diff options
421 files changed, 26615 insertions, 7987 deletions
diff --git a/include/lldb/API/SBHostOS.h b/include/lldb/API/SBHostOS.h index 52754ea4e829..e5fab6fe7849 100644 --- a/include/lldb/API/SBHostOS.h +++ b/include/lldb/API/SBHostOS.h @@ -30,7 +30,7 @@ public: static lldb::thread_t ThreadCreate (const char *name, - void *(*thread_function)(void *), + thread_func_t thread_function, void *thread_arg, lldb::SBError *err); @@ -43,7 +43,7 @@ public: lldb::SBError *err); static bool ThreadJoin (lldb::thread_t thread, - void **result, + thread_result_t *result, lldb::SBError *err); diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h index 784f362122a9..4ecaeaa49920 100644 --- a/include/lldb/API/SBProcess.h +++ b/include/lldb/API/SBProcess.h @@ -269,6 +269,38 @@ public: lldb::SBError UnloadImage (uint32_t image_token); + //------------------------------------------------------------------ + /// Return the number of different thread-origin extended backtraces + /// this process can support. + /// + /// When the process is stopped and you have an SBThread, lldb may be + /// able to show a backtrace of when that thread was originally created, + /// or the work item was enqueued to it (in the case of a libdispatch + /// queue). + /// + /// @return + /// The number of thread-origin extended backtrace types that may be + /// available. + //------------------------------------------------------------------ + uint32_t + GetNumExtendedBacktraceTypes (); + + //------------------------------------------------------------------ + /// Return the name of one of the thread-origin extended backtrace + /// methods. + /// + /// @param [in] idx + /// The index of the name to return. They will be returned in + /// the order that the user will most likely want to see them. + /// e.g. if the type at index 0 is not available for a thread, + /// see if the type at index 1 provides an extended backtrace. + /// + /// @return + /// The name at that index. + //------------------------------------------------------------------ + const char * + GetExtendedBacktraceTypeAtIndex (uint32_t idx); + protected: friend class SBAddress; friend class SBBreakpoint; diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h index 15aeed4b600c..7bcf91c16d77 100644 --- a/include/lldb/API/SBTarget.h +++ b/include/lldb/API/SBTarget.h @@ -747,6 +747,9 @@ public: lldb::SBType GetBasicType(lldb::BasicType type); + lldb::SBValue + CreateValueFromAddress (const char *name, lldb::SBAddress addr, lldb::SBType type); + SBSourceManager GetSourceManager(); diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h index 9645f925035e..d062d7121303 100644 --- a/include/lldb/API/SBThread.h +++ b/include/lldb/API/SBThread.h @@ -94,6 +94,9 @@ public: const char * GetQueueName() const; + lldb::queue_id_t + GetQueueID() const; + void StepOver (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); @@ -117,6 +120,9 @@ public: lldb::SBFileSpec &file_spec, uint32_t line); + SBError + JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line); + void RunToAddress (lldb::addr_t addr); @@ -195,6 +201,9 @@ public: bool GetStatus (lldb::SBStream &status) const; + SBThread + GetExtendedBacktrace (const char *type); + protected: friend class SBBreakpoint; friend class SBBreakpointLocation; diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h index bd11a1c91e21..30cc3314af3a 100644 --- a/include/lldb/Breakpoint/Breakpoint.h +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -576,6 +576,12 @@ public: InvokeCallback (StoppointCallbackContext *context, lldb::break_id_t bp_loc_id); + bool + IsHardware() const + { + return m_hardware; + } + protected: friend class Target; //------------------------------------------------------------------ @@ -590,7 +596,10 @@ protected: /// variants that make breakpoints for some common cases. //------------------------------------------------------------------ // This is the generic constructor - Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp); + Breakpoint(Target &target, + lldb::SearchFilterSP &filter_sp, + lldb::BreakpointResolverSP &resolver_sp, + bool hardware); friend class BreakpointLocation; // To call the following two when determining whether to stop. @@ -609,12 +618,13 @@ private: // For Breakpoint only //------------------------------------------------------------------ bool m_being_created; + bool m_hardware; // If this breakpoint is required to use a hardware breakpoint 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; + std::string m_kind_description; void SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind); diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h index 97eb2b46bc0c..c6708db118df 100644 --- a/include/lldb/Breakpoint/BreakpointList.h +++ b/include/lldb/Breakpoint/BreakpointList.h @@ -149,11 +149,17 @@ public: /// @param[in] module_list /// The module list that has changed. /// - /// @param[in] added + /// @param[in] load /// \b true if the modules are loaded, \b false if unloaded. + /// + /// @param[in] delete_locations + /// If \a load is \b false, then delete breakpoint locations when + /// when updating breakpoints. //------------------------------------------------------------------ void - UpdateBreakpoints (ModuleList &module_list, bool added); + UpdateBreakpoints (ModuleList &module_list, + bool load, + bool delete_locations); void UpdateBreakpointsWhenModuleIsReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp); diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h index 9ab0a79c6844..f4ba21a385f8 100644 --- a/include/lldb/Breakpoint/BreakpointLocation.h +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -324,7 +324,6 @@ public: protected: friend class BreakpointLocationList; - friend class CommandObjectBreakpointCommandAdd; friend class Process; //------------------------------------------------------------------ @@ -375,8 +374,8 @@ private: BreakpointLocation (lldb::break_id_t bid, Breakpoint &owner, const Address &addr, - lldb::tid_t tid = LLDB_INVALID_THREAD_ID, - bool hardware = false); + lldb::tid_t tid, + bool hardware); //------------------------------------------------------------------ // Data members: diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h index 3db3795453e8..184bdc950cbc 100644 --- a/include/lldb/Breakpoint/BreakpointResolver.h +++ b/include/lldb/Breakpoint/BreakpointResolver.h @@ -134,6 +134,13 @@ public: } protected: + //------------------------------------------------------------------ + /// SetSCMatchesByLine - Takes a symbol context list of matches which supposedly represent the same file and + /// line number in a CU, and find the nearest actual line number that matches, and then filter down the + /// matching addresses to unique entries, and skip the prologue if asked to do so, and then set + /// breakpoint locations in this breakpoint for all the resultant addresses. + void SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident); + Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. private: diff --git a/include/lldb/Breakpoint/BreakpointSiteList.h b/include/lldb/Breakpoint/BreakpointSiteList.h index 0d4dafc4baab..d7bb8fd777ef 100644 --- a/include/lldb/Breakpoint/BreakpointSiteList.h +++ b/include/lldb/Breakpoint/BreakpointSiteList.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include <map> +#include <functional> // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointSite.h" diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h index ccedc511951d..452c6388c82d 100644 --- a/include/lldb/Breakpoint/StoppointLocation.h +++ b/include/lldb/Breakpoint/StoppointLocation.h @@ -72,20 +72,20 @@ public: uint32_t GetHardwareIndex () const { - return m_hw_index; + return m_hardware_index; } bool - HardwarePreferred () const + HardwareRequired () const { - return m_hw_preferred; + return m_hardware; } virtual bool IsHardware () const { - return m_hw_index != LLDB_INVALID_INDEX32; + return m_hardware_index != LLDB_INVALID_INDEX32; } @@ -103,7 +103,7 @@ public: void SetHardwareIndex (uint32_t index) { - m_hw_index = index; + m_hardware_index = index; } @@ -120,8 +120,8 @@ protected: 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 + bool m_hardware; // True if this point has been is required to use hardware (which may fail due to lack of resources) + uint32_t m_hardware_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. diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h index 60cd4a86bd4a..da7cc5c03d38 100644 --- a/include/lldb/Core/Address.h +++ b/include/lldb/Core/Address.h @@ -540,6 +540,18 @@ protected: //------------------------------------------------------------------ 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... + + //------------------------------------------------------------------ + // Returns true if the m_section_wp once had a reference to a valid + // section shared pointer, but no longer does. This can happen if + // we have an address from a module that gets unloaded and deleted. + // This function should only be called if GetSection() returns an + // empty shared pointer and you want to know if this address used to + // have a valid section. + //------------------------------------------------------------------ + bool + SectionWasDeleted() const; + }; diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h index 3bfa96be0cee..7f2fd77a0934 100644 --- a/include/lldb/Core/ArchSpec.h +++ b/include/lldb/Core/ArchSpec.h @@ -41,6 +41,7 @@ public: eCore_arm_armv5e, eCore_arm_armv5t, eCore_arm_armv6, + eCore_arm_armv6m, eCore_arm_armv7, eCore_arm_armv7f, eCore_arm_armv7s, @@ -53,6 +54,7 @@ public: eCore_thumbv5, eCore_thumbv5e, eCore_thumbv6, + eCore_thumbv6m, eCore_thumbv7, eCore_thumbv7f, eCore_thumbv7s, @@ -60,6 +62,8 @@ public: eCore_thumbv7m, eCore_thumbv7em, + eCore_mips64, + eCore_ppc_generic, eCore_ppc_ppc601, eCore_ppc_ppc602, diff --git a/include/lldb/Core/ConnectionFileDescriptor.h b/include/lldb/Core/ConnectionFileDescriptor.h index fe704d4cadf7..3a2f0dd1ed0b 100644 --- a/include/lldb/Core/ConnectionFileDescriptor.h +++ b/include/lldb/Core/ConnectionFileDescriptor.h @@ -11,20 +11,27 @@ #define liblldb_ConnectionFileDescriptor_h_ // C Includes +#ifdef _WIN32 +typedef unsigned short in_port_t; +#else #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> +#endif // C++ Includes +#include <memory> + // 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 SocketAddress; + class ConnectionFileDescriptor : public Connection { @@ -70,6 +77,13 @@ public: GetWritePort () const; protected: + + typedef enum + { + eFDTypeFile, // Other FD requireing read/write + eFDTypeSocket, // Socket requiring send/recv + eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom + } FDType; void OpenCommandPipe (); @@ -96,20 +110,13 @@ protected: 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; + Close (int& fd, FDType type, Error *error); int m_fd_send; int m_fd_recv; FDType m_fd_send_type; FDType m_fd_recv_type; - SocketAddress m_udp_send_sockaddr; + std::unique_ptr<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 diff --git a/include/lldb/Core/ConnectionMachPort.h b/include/lldb/Core/ConnectionMachPort.h index 5613e7ee8008..04ec7f69136b 100644 --- a/include/lldb/Core/ConnectionMachPort.h +++ b/include/lldb/Core/ConnectionMachPort.h @@ -12,7 +12,8 @@ #define liblldb_ConnectionMachPort_h_ // C Includes -#include <mach/mach.h> +#include <mach/port.h> +#include <mach/kern_return.h> // C++ Includes #include <string> diff --git a/include/lldb/Core/ConstString.h b/include/lldb/Core/ConstString.h index e692d3b96e5d..684cc8f921ed 100644 --- a/include/lldb/Core/ConstString.h +++ b/include/lldb/Core/ConstString.h @@ -86,7 +86,7 @@ public: /// @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 + /// more characters than the length of the string, or the /// string can be part of another string and a new substring /// can be created. /// @@ -148,11 +148,11 @@ public: /// /b True this object contains a valid non-empty C string, \b /// false otherwise. //------------------------------------------------------------------ - operator bool() const + explicit operator bool() const { return m_string && m_string[0]; } - + //------------------------------------------------------------------ /// Assignment operator /// diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h index a8593043cb15..c9db2dab73d2 100644 --- a/include/lldb/Core/DataExtractor.h +++ b/include/lldb/Core/DataExtractor.h @@ -468,6 +468,27 @@ public: } //------------------------------------------------------------------ + /// Copy \a length bytes from \a *offset, without swapping bytes. + /// + /// @param[in] offset + /// The offset into this data from which to start copying + /// + /// @param[in] length + /// The length of the data to copy from this object + /// + /// @param[out] dst + /// The buffer to place the output data. + /// + /// @return + /// Returns the number of bytes that were copied, or zero if + /// anything goes wrong. + //------------------------------------------------------------------ + lldb::offset_t + CopyData (lldb::offset_t offset, + lldb::offset_t length, + void *dst) const; + + //------------------------------------------------------------------ /// 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. diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h index bed93fe02528..671b378df807 100644 --- a/include/lldb/Core/Debugger.h +++ b/include/lldb/Core/Debugger.h @@ -13,7 +13,6 @@ #include <stdint.h> -#include <unistd.h> #include <stack> @@ -323,6 +322,9 @@ public: GetDisassemblyLineCount () const; bool + GetAutoOneLineSummaries () const; + + bool GetNotifyVoid () const; diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h index d6e90071dc5b..f434d56943d4 100644 --- a/include/lldb/Core/Disassembler.h +++ b/include/lldb/Core/Disassembler.h @@ -270,7 +270,8 @@ public: const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, - const AddressRange &disasm_range); + const AddressRange &disasm_range, + bool prefer_file_cache); static lldb::DisassemblerSP DisassembleBytes (const ArchSpec &arch, diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h index 08b97e424913..19a3269ae374 100644 --- a/include/lldb/Core/EmulateInstruction.h +++ b/include/lldb/Core/EmulateInstruction.h @@ -69,14 +69,14 @@ /// 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 original breakpoint opcode, 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. +/// and emulating the instruction is just a bonus. //---------------------------------------------------------------------- namespace lldb_private { @@ -394,7 +394,7 @@ public: // Mandatory overrides //---------------------------------------------------------------------- virtual bool - SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; + SupportsEmulatingInstructionsOfType (InstructionType inst_type) = 0; virtual bool SetTargetTriple (const ArchSpec &arch) = 0; diff --git a/include/lldb/Core/Error.h b/include/lldb/Core/Error.h index 9e45d5f555d6..39c67f621c92 100644 --- a/include/lldb/Core/Error.h +++ b/include/lldb/Core/Error.h @@ -11,11 +11,10 @@ #define __DCError_h__ #if defined(__cplusplus) -#if defined (__APPLE__) -#include <mach/mach.h> -#endif -#include <stdint.h> -#include <stdio.h> +#include "llvm/Support/DataTypes.h" + +#include <cstdarg> +#include <cstdio> #include <string> #include "lldb/lldb-private.h" @@ -70,7 +69,7 @@ public: Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric); explicit - Error (const char* err_str); + Error (const char *format, ...) __attribute__ ((format (printf, 2, 3))); Error (const Error &rhs); //------------------------------------------------------------------ diff --git a/include/lldb/Core/Flags.h b/include/lldb/Core/Flags.h index 233f098ead23..5f4f8830456b 100644 --- a/include/lldb/Core/Flags.h +++ b/include/lldb/Core/Flags.h @@ -13,7 +13,6 @@ #include <stdint.h> -#include <unistd.h> namespace lldb_private { diff --git a/include/lldb/Core/Log.h b/include/lldb/Core/Log.h index ced6f2565d9a..b389946e264c 100644 --- a/include/lldb/Core/Log.h +++ b/include/lldb/Core/Log.h @@ -11,11 +11,10 @@ #define liblldb_Log_h_ // C Includes -#include <stdbool.h> +#include <stdarg.h> #include <stdint.h> #include <signal.h> #include <stdio.h> -#include <unistd.h> // C++ Includes // Other libraries and framework includes diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h index 9c135529f453..1473fb90cf85 100644 --- a/include/lldb/Core/Module.h +++ b/include/lldb/Core/Module.h @@ -347,6 +347,32 @@ public: SymbolContextList& sc_list); //------------------------------------------------------------------ + /// Find addresses by file/line + /// + /// @param[in] target_sp + /// The target the addresses are desired for. + /// + /// @param[in] file + /// Source file to locate. + /// + /// @param[in] line + /// Source line to locate. + /// + /// @param[in] function + /// Optional filter function. Addresses within this function will be + /// added to the 'local' list. All others will be added to the 'extern' list. + /// + /// @param[out] output_local + /// All matching addresses within 'function' + /// + /// @param[out] output_extern + /// All matching addresses not within 'function' + void FindAddressesForLine (const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, std::vector<Address> &output_extern); + + //------------------------------------------------------------------ /// Find global and static variables by name. /// /// @param[in] name @@ -723,8 +749,49 @@ public: bool ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr); + //------------------------------------------------------------------ + /// Resolve the symbol context for the given address. + /// + /// Tries to resolve the matching symbol context based on a lookup + /// from the current symbol vendor. If the lazy lookup fails, + /// an attempt is made to parse the eh_frame section to handle + /// stripped symbols. If this fails, an attempt is made to resolve + /// the symbol to the previous address to handle the case of a + /// function with a tail call. + /// + /// Use properties of the modified SymbolContext to inspect any + /// resolved target, module, compilation unit, symbol, function, + /// function block or line entry. Use the return value to determine + /// which of these properties have been modified. + /// + /// @param[in] so_addr + /// A load address to resolve. + /// + /// @param[in] resolve_scope + /// The scope that should be resolved (see SymbolContext::Scope). + /// A combination of flags from the enumeration SymbolContextItem + /// requesting a resolution depth. Note that the flags that are + /// actually resolved may be a superset of the requested flags. + /// For instance, eSymbolContextSymbol requires resolution of + /// eSymbolContextModule, and eSymbolContextFunction requires + /// eSymbolContextSymbol. + /// + /// @param[out] sc + /// The SymbolContext that is modified based on symbol resolution. + /// + /// @param[in] resolve_tail_call_address + /// Determines if so_addr should resolve to a symbol in the case + /// of a function whose last instruction is a call. In this case, + /// the PC can be one past the address range of the function. + /// + /// @return + /// The scope that has been resolved (see SymbolContext::Scope). + /// + /// @see SymbolContext::Scope + //------------------------------------------------------------------ uint32_t - ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc); + ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, + SymbolContext& sc, bool resolve_tail_call_address = false); //------------------------------------------------------------------ /// Resolve items in the symbol context for a given file and line. diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h index 1198e4196481..f03f79fb00ce 100644 --- a/include/lldb/Core/ModuleList.h +++ b/include/lldb/Core/ModuleList.h @@ -439,7 +439,35 @@ public: bool FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const; - + + + //------------------------------------------------------------------ + /// Find addresses by file/line + /// + /// @param[in] target_sp + /// The target the addresses are desired for. + /// + /// @param[in] file + /// Source file to locate. + /// + /// @param[in] line + /// Source line to locate. + /// + /// @param[in] function + /// Optional filter function. Addresses within this function will be + /// added to the 'local' list. All others will be added to the 'extern' list. + /// + /// @param[out] output_local + /// All matching addresses within 'function' + /// + /// @param[out] output_extern + /// All matching addresses not within 'function' + void FindAddressesForLine (const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, std::vector<Address> &output_extern); + + bool Remove (const lldb::ModuleSP &module_sp); diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h index 10e1ea9f17a9..dfeb7b73ca37 100644 --- a/include/lldb/Core/ModuleSpec.h +++ b/include/lldb/Core/ModuleSpec.h @@ -288,7 +288,7 @@ public: } - operator bool () const + explicit operator bool () const { if (m_file) return true; diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h index c07193b62059..fd80231a44e7 100644 --- a/include/lldb/Core/Opcode.h +++ b/include/lldb/Core/Opcode.h @@ -38,7 +38,7 @@ namespace lldb_private { eType64, eTypeBytes }; - + Opcode () : m_type (eTypeInvalid) { } @@ -78,7 +78,7 @@ namespace lldb_private { { return m_type; } - + uint8_t GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const { @@ -91,7 +91,6 @@ namespace lldb_private { case Opcode::eType32: break; case Opcode::eType64: break; case Opcode::eTypeBytes: break; - break; } return invalid_opcode; } @@ -157,7 +156,7 @@ namespace lldb_private { m_type = eType16; m_data.inst16 = inst; } - + void SetOpcode16_2 (uint32_t inst) { @@ -206,7 +205,7 @@ namespace lldb_private { return m_data.inst.bytes; return NULL; } - + uint32_t GetByteSize () const { @@ -222,7 +221,7 @@ namespace lldb_private { } return 0; } - + // Get the opcode exactly as it would be laid out in memory. uint32_t GetData (DataExtractor &data) const; @@ -246,7 +245,7 @@ namespace lldb_private { } return NULL; } - + lldb::ByteOrder GetDataByteOrder () const; @@ -257,7 +256,7 @@ namespace lldb_private { uint16_t inst16; uint32_t inst32; uint64_t inst64; - struct + struct { uint8_t bytes[16]; // This must be big enough to handle any opcode for any supported target. uint8_t length; diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h index 91f8fbb997f9..e02f43f4fa8b 100644 --- a/include/lldb/Core/PluginManager.h +++ b/include/lldb/Core/PluginManager.h @@ -132,6 +132,24 @@ public: //------------------------------------------------------------------ + // SystemRuntime + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + SystemRuntimeCreateInstance create_callback); + + static bool + UnregisterPlugin (SystemRuntimeCreateInstance create_callback); + + static SystemRuntimeCreateInstance + GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx); + + static SystemRuntimeCreateInstance + GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ // ObjectFile //------------------------------------------------------------------ static bool diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h index ee42467c18bf..d78504c7d285 100644 --- a/include/lldb/Core/RangeMap.h +++ b/include/lldb/Core/RangeMap.h @@ -592,7 +592,7 @@ namespace lldb_private { void Reserve (typename Collection::size_type size) { - m_entries.resize (size); + m_entries.reserve (size); } bool @@ -1229,16 +1229,11 @@ namespace lldb_private { typename Collection::const_iterator end = m_entries.end(); typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + while(pos != begin && pos[-1].Contains(addr)) + --pos; + 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; } @@ -1257,19 +1252,12 @@ namespace lldb_private { 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); + + while(pos != begin && pos[-1].Contains(addr)) + --pos; if (pos != end && pos->Contains(addr)) - { return &(*pos); - } - else if (pos != begin) - { - --pos; - if (pos->Contains(addr)) - { - return &(*pos); - } - } } return NULL; } @@ -1288,18 +1276,11 @@ namespace lldb_private { 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) - { + while(pos != begin && pos[-1].Contains(addr)) --pos; - if (pos->Contains(addr)) - { - return &(*pos); - } - } + + if (pos != end && pos->Contains(addr)) + return &(*pos); } return NULL; } @@ -1316,18 +1297,11 @@ namespace lldb_private { 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) - { + while(pos != begin && pos[-1].Contains(range)) --pos; - if (pos->Contains(range)) - { - return &(*pos); - } - } + + if (pos != end && pos->Contains(range)) + return &(*pos); } return NULL; } @@ -1501,12 +1475,15 @@ namespace lldb_private { typename Collection::iterator end = m_entries.end(); typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + while(pos != begin && pos[-1].addr == addr) + --pos; + if (pos != end) { if (pos->addr == addr || !exact_match_only) return &(*pos); } - } + } return NULL; } diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h index eeeb914bfa90..c116d439b94a 100644 --- a/include/lldb/Core/RegularExpression.h +++ b/include/lldb/Core/RegularExpression.h @@ -11,7 +11,36 @@ #define liblldb_DBRegex_h_ #if defined(__cplusplus) +#ifdef _WIN32 +#include "../lib/Support/regex_impl.h" + +typedef llvm_regmatch_t regmatch_t; +typedef llvm_regex_t regex_t; + +inline int regcomp(llvm_regex_t * a, const char *b, int c) +{ + return llvm_regcomp(a, b, c); +} + +inline size_t regerror(int a, const llvm_regex_t *b, char *c, size_t d) +{ + return llvm_regerror(a, b, c, d); +} + +inline int regexec(const llvm_regex_t * a, const char * b, size_t c, + llvm_regmatch_t d [], int e) +{ + return llvm_regexec(a, b, c, d, e); +} + +inline void regfree(llvm_regex_t * a) +{ + llvm_regfree(a); +} + +#else #include <regex.h> +#endif #include <stdint.h> #include <string> diff --git a/include/lldb/Core/StreamGDBRemote.h b/include/lldb/Core/StreamGDBRemote.h new file mode 100644 index 000000000000..3fdb6f6e7012 --- /dev/null +++ b/include/lldb/Core/StreamGDBRemote.h @@ -0,0 +1,54 @@ +//===-- StreamGDBRemote.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_StreamGDBRemote_h_ +#define liblldb_StreamGDBRemote_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes + +#include "lldb/Core/StreamString.h" + +namespace lldb_private { + + class StreamGDBRemote : public StreamString + { + public: + StreamGDBRemote (); + + StreamGDBRemote (uint32_t flags, + uint32_t addr_size, + lldb::ByteOrder byte_order); + + virtual + ~StreamGDBRemote (); + + //------------------------------------------------------------------ + /// Output a block of data to the stream performing GDB-remote escaping. + /// + /// @param[in] s + /// A block of data. + /// + /// @param[in] src_len + /// The amount of data to write. + /// + /// @return + /// Number of bytes written. + //------------------------------------------------------------------ + int + PutEscapedBytes (const void* s, + size_t src_len); + }; + +} // namespace lldb_private + +#endif // liblldb_StreamGDBRemote_h_ diff --git a/include/lldb/Core/UUID.h b/include/lldb/Core/UUID.h index fe72b8eb0c70..3bb14421b1e9 100644 --- a/include/lldb/Core/UUID.h +++ b/include/lldb/Core/UUID.h @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include <string> + // Other libraries and framework includes // Project includes diff --git a/include/lldb/Core/Value.h b/include/lldb/Core/Value.h index 5461ca73d082..c7d44322333c 100644 --- a/include/lldb/Core/Value.h +++ b/include/lldb/Core/Value.h @@ -114,7 +114,7 @@ public: #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; + else if (length >= 16) scalar = *(const uint64_t *)bytes; #endif } return scalar; diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h index 0d965d6ccc01..1ef421676ee1 100644 --- a/include/lldb/Core/ValueObject.h +++ b/include/lldb/Core/ValueObject.h @@ -12,7 +12,6 @@ // C Includes // C++ Includes -#include <initializer_list> #include <map> #include <vector> // Other libraries and framework includes @@ -217,229 +216,6 @@ public: } }; - - 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 { @@ -598,6 +374,10 @@ public: ClangASTType GetClangType (); + + // this vends a TypeImpl that is useful at the SB API layer + virtual TypeImpl + GetTypeImpl (); //------------------------------------------------------------------ // Sublasses must implement the functions below. @@ -725,6 +505,9 @@ public: virtual uint64_t GetValueAsUnsigned (uint64_t fail_value, bool *success = NULL); + virtual int64_t + GetValueAsSigned (int64_t fail_value, bool *success = NULL); + virtual bool SetValueFromCString (const char *value_str, Error& error); @@ -768,6 +551,23 @@ public: lldb::ValueObjectSP GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs, size_t* index_of_error = NULL); + + // this will always create the children if necessary + lldb::ValueObjectSP + GetChildAtNamePath (const std::initializer_list<ConstString> &names, + ConstString* name_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtNamePath (const std::vector<ConstString> &names, + ConstString* name_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names, + ConstString* name_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names, + ConstString* name_of_error = NULL); virtual lldb::ValueObjectSP GetChildMemberWithName (const ConstString &name, bool can_create); @@ -937,13 +737,12 @@ public: virtual SymbolContextScope * GetSymbolContextScope(); - static void - DumpValueObject (Stream &s, - ValueObject *valobj); - static void - DumpValueObject (Stream &s, - ValueObject *valobj, - const DumpValueObjectOptions& options); + void + Dump (Stream &s); + + void + Dump (Stream &s, + const DumpValueObjectOptions& options); static lldb::ValueObjectSP CreateValueObjectFromExpression (const char* name, @@ -962,13 +761,11 @@ public: const ExecutionContext& exe_ctx, ClangASTType type); - static void - LogValueObject (Log *log, - ValueObject *valobj); + void + LogValueObject (Log *log); - static void + void LogValueObject (Log *log, - ValueObject *valobj, const DumpValueObjectOptions& options); diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h index c0f6baade3fb..68f88c96e545 100644 --- a/include/lldb/Core/ValueObjectDynamicValue.h +++ b/include/lldb/Core/ValueObjectDynamicValue.h @@ -93,6 +93,9 @@ public: virtual bool SetData (DataExtractor &data, Error &error); + virtual TypeImpl + GetTypeImpl (); + protected: virtual bool UpdateValue (); @@ -116,6 +119,7 @@ protected: 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; + TypeImpl m_type_impl; private: friend class ValueObject; diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h index bf77125d86a8..91c8dfb9d0da 100644 --- a/include/lldb/Core/dwarf.h +++ b/include/lldb/Core/dwarf.h @@ -11,7 +11,6 @@ #define DebugBase_dwarf_h_ #include <stdint.h> -#include <stdbool.h> // Get the DWARF constant defintions from llvm #include "llvm/Support/Dwarf.h" diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h index 2f56c56810ab..433c2a3c407b 100644 --- a/include/lldb/DataFormatters/CXXFormatterFunctions.h +++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -868,6 +868,39 @@ namespace lldb_private { SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdUnorderedMapSyntheticFrontEnd (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 + ~LibcxxStdUnorderedMapSyntheticFrontEnd (); + private: + + ValueObject* m_tree; + size_t m_num_elements; + ValueObject* m_next_element; + std::map<size_t,lldb::ValueObjectSP> m_children; + std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache; + }; + + SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h index 499e0fe14d93..ca0714c29f84 100644 --- a/include/lldb/DataFormatters/DataVisualization.h +++ b/include/lldb/DataFormatters/DataVisualization.h @@ -36,40 +36,19 @@ public: 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 bool + ShouldPrintAsOneLiner (ValueObject& valobj); + + static lldb::TypeFormatImplSP + GetFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + + static lldb::TypeFormatImplSP + GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp); static lldb::TypeSummaryImplSP - GetSummaryFormat(ValueObject& valobj, - lldb::DynamicValueType use_dynamic); + GetSummaryFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); static lldb::TypeSummaryImplSP GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h index 941b96c1facc..bd9e20ccc9ee 100644 --- a/include/lldb/DataFormatters/FormatCache.h +++ b/include/lldb/DataFormatters/FormatCache.h @@ -27,23 +27,32 @@ private: struct Entry { private: + bool m_format_cached : 1; bool m_summary_cached : 1; bool m_synthetic_cached : 1; + lldb::TypeFormatImplSP m_format_sp; lldb::TypeSummaryImplSP m_summary_sp; lldb::SyntheticChildrenSP m_synthetic_sp; public: Entry (); + Entry (lldb::TypeFormatImplSP); Entry (lldb::TypeSummaryImplSP); Entry (lldb::SyntheticChildrenSP); - Entry (lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP); + Entry (lldb::TypeFormatImplSP,lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP); bool + IsFormatCached (); + + bool IsSummaryCached (); bool IsSyntheticCached (); + lldb::TypeFormatImplSP + GetFormat (); + lldb::TypeSummaryImplSP GetSummary (); @@ -51,6 +60,9 @@ private: GetSynthetic (); void + SetFormat (lldb::TypeFormatImplSP); + + void SetSummary (lldb::TypeSummaryImplSP); void @@ -70,12 +82,18 @@ public: FormatCache (); bool + GetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp); + + bool GetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp); bool GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp); void + SetFormat (const ConstString& type,lldb::TypeFormatImplSP& format_sp); + + void SetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp); void diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h index 48a8eda4ad43..6d9a50e8f2c5 100644 --- a/include/lldb/DataFormatters/FormatClasses.h +++ b/include/lldb/DataFormatters/FormatClasses.h @@ -12,7 +12,6 @@ // C Includes #include <stdint.h> -#include <unistd.h> // C++ Includes #include <string> @@ -61,7 +60,7 @@ public: if (type) { m_type.m_type_name.assign(type->GetName().GetCString()); - m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + m_type.m_type_pair.SetType(type); } } @@ -72,7 +71,7 @@ public: if (type.IsValid()) { m_type.m_type_name.assign(type.GetConstTypeName().GetCString()); - m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + m_type.m_type_pair.SetType(type); } } @@ -87,16 +86,16 @@ public: lldb::TypeSP GetTypeSP () { - if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) - return m_type.m_typeimpl_sp->GetTypeSP(); + if (m_type.m_type_pair.IsValid()) + return m_type.m_type_pair.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(); + if (m_type.m_type_pair.IsValid()) + return m_type.m_type_pair.GetClangASTType(); return ClangASTType(); } @@ -109,12 +108,11 @@ public: 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 + // whereas TypePair can also be backed by a ClangASTType struct TypeOrName { std::string m_type_name; - lldb::TypeImplSP m_typeimpl_sp; + TypePair m_type_pair; }; TypeOrName m_type; diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h index 162e25143f27..3c90c993e0c4 100644 --- a/include/lldb/DataFormatters/FormatManager.h +++ b/include/lldb/DataFormatters/FormatManager.h @@ -23,6 +23,8 @@ #include "lldb/DataFormatters/TypeCategory.h" #include "lldb/DataFormatters/TypeCategoryMap.h" +#include <atomic> + namespace lldb_private { // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization @@ -32,8 +34,6 @@ namespace lldb_private { class FormatManager : public IFormatChangeListener { - typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator; - typedef ValueNavigator::MapType ValueMap; typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap; typedef TypeCategoryMap::MapType::iterator CategoryMapIterator; public: @@ -42,12 +42,6 @@ public: FormatManager (); - ValueNavigator& - GetValueNavigator () - { - return m_value_nav; - } - NamedSummariesMap& GetNamedSummaryNavigator () { @@ -124,6 +118,9 @@ public: lldb::TypeCategoryImplSP GetCategory (const ConstString& category_name, bool can_create = true); + + lldb::TypeFormatImplSP + GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp); lldb::TypeSummaryImplSP GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); @@ -141,6 +138,10 @@ public: GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp); #endif + lldb::TypeFormatImplSP + GetFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + lldb::TypeSummaryImplSP GetSummaryFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic); @@ -188,10 +189,17 @@ public: static lldb::Format GetSingleItemFormat (lldb::Format vector_format); + // this returns true if the ValueObjectPrinter is *highly encouraged* + // to actually represent this ValueObject in one-liner format + // If this object has a summary formatter, however, we should not + // try and do one-lining, just let the summary do the right thing + bool + ShouldPrintAsOneLiner (ValueObject& valobj); + void Changed () { - __sync_add_and_fetch(&m_last_revision, +1); + ++m_last_revision; m_format_cache.Clear (); } @@ -207,9 +215,8 @@ public: private: FormatCache m_format_cache; - ValueNavigator m_value_nav; NamedSummariesMap m_named_summaries_map; - uint32_t m_last_revision; + std::atomic<uint32_t> m_last_revision; TypeCategoryMap m_categories_map; ConstString m_default_category_name; diff --git a/include/lldb/DataFormatters/FormatNavigator.h b/include/lldb/DataFormatters/FormatNavigator.h index a738cfd069e7..cd5f6824e199 100644 --- a/include/lldb/DataFormatters/FormatNavigator.h +++ b/include/lldb/DataFormatters/FormatNavigator.h @@ -76,7 +76,7 @@ GetValidTypeName_Impl (const ConstString& type) { int strip_len = 0; - if (type == false) + if ((bool)type == false) return type; const char* type_cstr = type.AsCString(); diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h index b76d84f4772f..6461c4e97e4e 100644 --- a/include/lldb/DataFormatters/TypeCategory.h +++ b/include/lldb/DataFormatters/TypeCategory.h @@ -24,6 +24,8 @@ namespace lldb_private { class TypeCategoryImpl { private: + typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator; + typedef FormatNavigator<lldb::RegularExpressionSP, TypeFormatImpl> RegexValueNavigator; typedef FormatNavigator<ConstString, TypeSummaryImpl> SummaryNavigator; typedef FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl> RegexSummaryNavigator; @@ -35,11 +37,16 @@ namespace lldb_private { typedef FormatNavigator<ConstString, ScriptedSyntheticChildren> SynthNavigator; typedef FormatNavigator<lldb::RegularExpressionSP, ScriptedSyntheticChildren> RegexSynthNavigator; #endif // #ifndef LLDB_DISABLE_PYTHON - + + typedef ValueNavigator::MapType ValueMap; + typedef RegexValueNavigator::MapType RegexValueMap; + 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; @@ -49,9 +56,13 @@ namespace lldb_private { typedef uint16_t FormatCategoryItems; static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; + + typedef ValueNavigator::SharedPointer ValueNavigatorSP; + typedef RegexValueNavigator::SharedPointer RegexValueNavigatorSP; typedef SummaryNavigator::SharedPointer SummaryNavigatorSP; typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP; + typedef FilterNavigator::SharedPointer FilterNavigatorSP; typedef RegexFilterNavigator::SharedPointer RegexFilterNavigatorSP; #ifndef LLDB_DISABLE_PYTHON @@ -62,6 +73,18 @@ namespace lldb_private { TypeCategoryImpl (IFormatChangeListener* clist, ConstString name); + ValueNavigatorSP + GetValueNavigator () + { + return ValueNavigatorSP(m_value_nav); + } + + RegexValueNavigatorSP + GetRegexValueNavigator () + { + return RegexValueNavigatorSP(m_regex_value_nav); + } + SummaryNavigatorSP GetSummaryNavigator () { @@ -85,6 +108,9 @@ namespace lldb_private { { return RegexFilterNavigatorSP(m_regex_filter_nav); } + + ValueNavigator::MapValueType + GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp); SummaryNavigator::MapValueType GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); @@ -98,7 +124,13 @@ namespace lldb_private { #endif lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForFormatAtIndex (size_t index); + + lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierForSummaryAtIndex (size_t index); + + ValueNavigator::MapValueType + GetFormatAtIndex (size_t index); SummaryNavigator::MapValueType GetSummaryAtIndex (size_t index); @@ -145,6 +177,13 @@ namespace lldb_private { return m_enabled_position; } + + bool + Get (ValueObject& valobj, + lldb::TypeFormatImplSP& entry, + lldb::DynamicValueType use_dynamic, + uint32_t* reason = NULL); + bool Get (ValueObject& valobj, lldb::TypeSummaryImplSP& entry, @@ -183,10 +222,15 @@ namespace lldb_private { typedef std::shared_ptr<TypeCategoryImpl> SharedPointer; private: + ValueNavigator::SharedPointer m_value_nav; + RegexValueNavigator::SharedPointer m_regex_value_nav; + 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; @@ -213,6 +257,9 @@ namespace lldb_private { friend class TypeCategoryMap; + friend class FormatNavigator<ConstString, TypeFormatImpl>; + friend class FormatNavigator<lldb::RegularExpressionSP, TypeFormatImpl>; + friend class FormatNavigator<ConstString, TypeSummaryImpl>; friend class FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl>; diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h index c2465ad13aa7..6bed18719893 100644 --- a/include/lldb/DataFormatters/TypeCategoryMap.h +++ b/include/lldb/DataFormatters/TypeCategoryMap.h @@ -93,6 +93,10 @@ namespace lldb_private { { return m_map.size(); } + + lldb::TypeFormatImplSP + GetFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); lldb::TypeSummaryImplSP GetSummaryFormat (ValueObject& valobj, diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h index 2183384b9d62..1c195ab2ba4d 100644 --- a/include/lldb/DataFormatters/TypeSummary.h +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -12,7 +12,6 @@ // C Includes #include <stdint.h> -#include <unistd.h> // C++ Includes #include <string> @@ -239,7 +238,7 @@ namespace lldb_private { } bool - IsOneliner () const + IsOneLiner () const { return m_flags.GetShowMembersOneLiner(); } @@ -281,7 +280,7 @@ namespace lldb_private { } void - SetIsOneliner (bool value) + SetIsOneLiner (bool value) { m_flags.SetShowMembersOneLiner(value); } diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h index a32f4b761175..18b9d011e96a 100644 --- a/include/lldb/DataFormatters/TypeSynthetic.h +++ b/include/lldb/DataFormatters/TypeSynthetic.h @@ -12,7 +12,6 @@ // C Includes #include <stdint.h> -#include <unistd.h> // C++ Includes #include <string> @@ -533,6 +532,12 @@ namespace lldb_private { FrontEnd (std::string pclass, ValueObject &backend); + bool + IsValid () + { + return m_wrapper_sp.get() != nullptr && m_wrapper_sp->operator bool() && m_interpreter != nullptr; + } + virtual ~FrontEnd (); @@ -582,8 +587,11 @@ namespace lldb_private { virtual SyntheticChildrenFrontEnd::AutoPointer GetFrontEnd(ValueObject &backend) { - return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); - } + auto synth_ptr = SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); + if (synth_ptr && ((FrontEnd*)synth_ptr.get())->IsValid()) + return synth_ptr; + return NULL; + } private: DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren); diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h new file mode 100644 index 000000000000..4e23ceedcc16 --- /dev/null +++ b/include/lldb/DataFormatters/ValueObjectPrinter.h @@ -0,0 +1,394 @@ +//===-- ValueObjectPrinter.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_ValueObjectPrinter_h_ +#define lldb_ValueObjectPrinter_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-public.h" + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" + +namespace lldb_private { + +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; + bool m_be_raw; + + 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" + m_be_raw(false) + {} + + 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), + m_be_raw(rhs.m_be_raw) + {} + + 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); + m_be_raw = true; + } + else + { + SetUseSyntheticValue(true); + SetOmitSummaryDepth(0); + SetIgnoreCap(false); + SetHideName(false); + SetHideValue(false); + m_be_raw = 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 ValueObjectPrinter +{ +public: + + ValueObjectPrinter (ValueObject* valobj, + Stream* s, + const DumpValueObjectOptions& options); + + ~ValueObjectPrinter () {} + + bool + PrintValueObject (); + + bool + PrintChildrenOneLiner (bool hide_names); + +protected: + + // only this class (and subclasses, if any) should ever be concerned with + // the depth mechanism + ValueObjectPrinter (ValueObject* valobj, + Stream* s, + const DumpValueObjectOptions& options, + uint32_t ptr_depth, + uint32_t curr_depth); + + // we should actually be using delegating constructors here + // but some versions of GCC still have trouble with those + void + Init (ValueObject* valobj, + Stream* s, + const DumpValueObjectOptions& options, + uint32_t ptr_depth, + uint32_t curr_depth); + + bool + GetDynamicValueIfNeeded (); + + const char* + GetDescriptionForDisplay (); + + const char* + GetRootNameForDisplay (const char* if_fail = nullptr); + + bool + ShouldPrintValueObject (); + + bool + IsNil (); + + bool + IsPtr (); + + bool + IsRef (); + + bool + IsAggregate (); + + bool + PrintLocationIfNeeded (); + + bool + PrintTypeIfNeeded (); + + bool + PrintNameIfNeeded (bool show_type); + + bool + CheckScopeIfNeeded (); + + TypeSummaryImpl* + GetSummaryFormatter (); + + void + GetValueSummaryError (std::string& value, + std::string& summary, + std::string& error); + + bool + PrintValueAndSummaryIfNeeded (bool& value_printed, + bool& summary_printed); + + bool + PrintObjectDescriptionIfNeeded (bool value_printed, + bool summary_printed); + + bool + ShouldPrintChildren (bool is_failed_description, + uint32_t& curr_ptr_depth); + + ValueObject* + GetValueObjectForChildrenGeneration (); + + void + PrintChildrenPreamble (); + + void + PrintChildrenPostamble (bool print_dotdotdot); + + void + PrintChild (lldb::ValueObjectSP child_sp, + uint32_t curr_ptr_depth); + + uint32_t + GetMaxNumChildrenToPrint (bool& print_dotdotdot); + + void + PrintChildren (uint32_t curr_ptr_depth); + + void + PrintChildrenIfNeeded (bool value_printed, + bool summary_printed); + +private: + + ValueObject *m_orig_valobj; + ValueObject *m_valobj; + Stream *m_stream; + DumpValueObjectOptions options; + Flags m_type_flags; + ClangASTType m_clang_type; + uint32_t m_ptr_depth; + uint32_t m_curr_depth; + LazyBool m_should_print; + LazyBool m_is_nil; + LazyBool m_is_ptr; + LazyBool m_is_ref; + LazyBool m_is_aggregate; + std::pair<TypeSummaryImpl*,bool> m_summary_formatter; + std::string m_value; + std::string m_summary; + std::string m_error; + + DISALLOW_COPY_AND_ASSIGN(ValueObjectPrinter); +}; + +} // namespace lldb_private + +#endif // lldb_ValueObjectPrinter_h_ diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h index b2a43e0ac75f..b04e1bd6f116 100644 --- a/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/include/lldb/Expression/ClangExpressionDeclMap.h @@ -291,6 +291,9 @@ public: /// @param[in] name /// The name of the symbol. /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// /// @return /// Valid load address for the symbol //------------------------------------------------------------------ @@ -298,7 +301,8 @@ public: GetSymbolAddress (Target &target, Process *process, const ConstString &name, - lldb::SymbolType symbol_type); + lldb::SymbolType symbol_type, + Module *module = NULL); lldb::addr_t GetSymbolAddress (const ConstString &name, @@ -504,12 +508,16 @@ private: /// @param[in] name /// The name as a plain C string. /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// /// @return /// The LLDB Symbol found, or NULL if none was found. - //--------------------------------------------------------- + //------------------------------------------------------------------ const Symbol * FindGlobalDataSymbol (Target &target, - const ConstString &name); + const ConstString &name, + Module *module = NULL); //------------------------------------------------------------------ /// Given a target, find a variable that matches the given name and diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h index 3f96f7bd3117..9cb22ed15cb5 100644 --- a/include/lldb/Expression/ClangFunction.h +++ b/include/lldb/Expression/ClangFunction.h @@ -67,8 +67,8 @@ class ClangFunction : public ClangExpression { friend class ASTStructExtractor; public: - //------------------------------------------------------------------ - /// Constructor + //------------------------------------------------------------------ + /// Constructor /// /// @param[in] exe_scope /// An execution context scope that gets us at least a target and @@ -84,14 +84,14 @@ public: /// @param[in] arg_value_list /// The default values to use when calling this function. Can /// be overridden using WriteFunctionArguments(). - //------------------------------------------------------------------ - ClangFunction (ExecutionContextScope &exe_scope, + //------------------------------------------------------------------ + ClangFunction (ExecutionContextScope &exe_scope, Function &function_ptr, ClangASTContext *ast_context, const ValueList &arg_value_list); //------------------------------------------------------------------ - /// Constructor + /// Constructor /// /// @param[in] exe_scope /// An execution context scope that gets us at least a target and @@ -110,32 +110,32 @@ public: /// @param[in] arg_value_list /// The default values to use when calling this function. Can /// be overridden using WriteFunctionArguments(). - //------------------------------------------------------------------ - ClangFunction (ExecutionContextScope &exe_scope, + //------------------------------------------------------------------ + ClangFunction (ExecutionContextScope &exe_scope, const ClangASTType &return_type, const Address& function_address, const ValueList &arg_value_list); //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - virtual + /// Destructor + //------------------------------------------------------------------ + virtual ~ClangFunction(); //------------------------------------------------------------------ - /// Compile the wrapper function + /// 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 + /// Insert the default function wrapper and its default argument struct /// /// @param[in] exe_ctx /// The execution context to insert the function and its arguments @@ -151,14 +151,14 @@ public: /// /// @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) + /// Insert the default function wrapper (using the JIT) /// /// @param[in] exe_ctx /// The execution context to insert the function and its arguments @@ -169,12 +169,12 @@ public: /// /// @return /// True on success; false otherwise. - //------------------------------------------------------------------ + //------------------------------------------------------------------ bool WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors); //------------------------------------------------------------------ - /// Insert the default function argument struct + /// Insert the default function argument struct /// /// @param[in] exe_ctx /// The execution context to insert the function and its arguments @@ -190,13 +190,13 @@ public: /// /// @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 + /// Insert an argument struct with a non-default function address and /// non-default argument values /// /// @param[in] exe_ctx @@ -219,7 +219,7 @@ public: /// /// @return /// True on success; false otherwise. - //------------------------------------------------------------------ + //------------------------------------------------------------------ bool WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, @@ -227,7 +227,7 @@ public: Stream &errors); //------------------------------------------------------------------ - /// [Static] Execute a function, passing it a single void* parameter. + /// [Static] Execute a function, passing it a single void* parameter. /// ClangFunction uses this to call the wrapper function. /// /// @param[in] exe_ctx @@ -266,7 +266,7 @@ public: /// /// @return /// Returns one of the ExecutionResults enum indicating function call status. - //------------------------------------------------------------------ + //------------------------------------------------------------------ static ExecutionResults ExecuteFunction (ExecutionContext &exe_ctx, lldb::addr_t function_address, @@ -446,7 +446,7 @@ public: /// /// @return /// A ThreadPlan for executing the function. - //------------------------------------------------------------------ + //------------------------------------------------------------------ static ThreadPlan * GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t func_addr, @@ -482,7 +482,7 @@ public: /// /// @return /// A ThreadPlan for executing the function. - //------------------------------------------------------------------ + //------------------------------------------------------------------ ThreadPlan * GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, @@ -514,7 +514,7 @@ public: /// /// @return /// True on success; false otherwise. - //------------------------------------------------------------------ + //------------------------------------------------------------------ bool FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value); @@ -528,7 +528,7 @@ public: /// /// @param[in] args_addr /// The address of the argument struct. - //------------------------------------------------------------------ + //------------------------------------------------------------------ void DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr); @@ -614,9 +614,9 @@ public: return m_arg_values; } private: - //------------------------------------------------------------------ - // For ClangFunction only - //------------------------------------------------------------------ + //------------------------------------------------------------------ + // For ClangFunction only + //------------------------------------------------------------------ std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function. std::unique_ptr<IRExecutionUnit> m_execution_unit_ap; @@ -624,17 +624,18 @@ private: 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. + std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct below. + bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below. - //------------------------------------------------------------------ - /// These values are populated by the ASTStructExtractor + //------------------------------------------------------------------ + /// 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. diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h index 47bfebb46648..b8c3c128acf4 100644 --- a/include/lldb/Expression/ClangUserExpression.h +++ b/include/lldb/Expression/ClangUserExpression.h @@ -126,13 +126,8 @@ public: /// 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] options + /// Expression evaluation options. /// /// @param[in] shared_ptr_to_me /// This is a shared pointer to this ClangUserExpression. This is @@ -145,29 +140,15 @@ public: /// 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, + const EvaluateExpressionOptions& options, ClangUserExpressionSP &shared_ptr_to_me, - lldb::ClangExpressionVariableSP &result, - bool try_all_threads, - uint32_t timeout_usec); + lldb::ClangExpressionVariableSP &result); ThreadPlan * GetThreadPlanToExecuteJITExpression (Stream &error_stream, @@ -300,25 +281,8 @@ public: /// @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] options + /// Expression evaluation options. /// /// @param[in] expr_cstr /// A C string containing the expression to be evaluated. @@ -330,45 +294,20 @@ public: /// @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. + /// @param[out] + /// Filled in with an error in case the expression evaluation + /// fails to parse, run, or evaluated. /// /// @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 EvaluateExpressionOptions& options, 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); + Error &error); static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. private: diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h index 2692831ecc84..5ecdf7fe9ee5 100644 --- a/include/lldb/Expression/DWARFExpression.h +++ b/include/lldb/Expression/DWARFExpression.h @@ -58,7 +58,8 @@ public: /// @param[in] data_length /// The byte length of the location expression. //------------------------------------------------------------------ - DWARFExpression(const DataExtractor& data, + DWARFExpression(lldb::ModuleSP module, + const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length); @@ -172,6 +173,9 @@ public: /// Make the expression parser read its location information from a /// given data source /// + /// @param[in] module_sp + /// The module that defines the DWARF expression. + /// /// @param[in] data /// A data extractor configured to read the DWARF location expression's /// bytecode. @@ -183,7 +187,7 @@ public: /// The byte length of the location expression. //------------------------------------------------------------------ void - SetOpcodeData(const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length); + SetOpcodeData(lldb::ModuleSP module_sp, const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length); //------------------------------------------------------------------ /// Copy the DWARF location expression into a local buffer. @@ -199,6 +203,9 @@ public: /// the data, it shouldn't amount to that much for the variables we /// end up parsing. /// + /// @param[in] module_sp + /// The module that defines the DWARF expression. + /// /// @param[in] data /// A data extractor configured to read and copy the DWARF /// location expression's bytecode. @@ -210,7 +217,8 @@ public: /// The byte length of the location expression. //------------------------------------------------------------------ void - CopyOpcodeData (const DataExtractor& data, + CopyOpcodeData (lldb::ModuleSP module_sp, + const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length); @@ -279,6 +287,9 @@ public: /// expression. The location expression may access the target's /// memory, especially if it comes from the expression parser. /// + /// @param[in] opcode_ctx + /// The module which defined the expression. + /// /// @param[in] opcodes /// This is a static method so the opcodes need to be provided /// explicitly. @@ -332,6 +343,7 @@ public: ClangExpressionVariableList *expr_locals, ClangExpressionDeclMap *decl_map, RegisterContext *reg_ctx, + lldb::ModuleSP opcode_ctx, const DataExtractor& opcodes, const lldb::offset_t offset, const lldb::offset_t length, @@ -410,7 +422,8 @@ protected: //------------------------------------------------------------------ /// Classes that inherit from DWARFExpression can see and modify these //------------------------------------------------------------------ - + + lldb::ModuleWP m_module_wp; ///< Module which defined this expression. 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 diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index 885b6516b0c6..2820317e108e 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -287,7 +287,8 @@ private: /// Allocated space. //------------------------------------------------------------------ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, + llvm::StringRef SectionName); //------------------------------------------------------------------ /// Allocate space for data, and add it to the m_spaceBlocks map @@ -308,7 +309,9 @@ private: /// Allocated space. //------------------------------------------------------------------ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, bool IsReadOnly); + unsigned SectionID, + llvm::StringRef SectionName, + bool IsReadOnly); //------------------------------------------------------------------ /// Allocate space for a global variable, and add it to the @@ -388,6 +391,10 @@ private: return m_default_mm_ap->GetNumStubSlabs(); } + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) { + return m_default_mm_ap->registerEHFrames(Addr, LoadAddr, Size); + } + //------------------------------------------------------------------ /// Passthrough interface stub //------------------------------------------------------------------ diff --git a/include/lldb/Expression/IRForTarget.h b/include/lldb/Expression/IRForTarget.h index 151bf2ab4774..566328772502 100644 --- a/include/lldb/Expression/IRForTarget.h +++ b/include/lldb/Expression/IRForTarget.h @@ -19,6 +19,7 @@ #include "llvm/Pass.h" #include <map> +#include <functional> namespace llvm { class BasicBlock; diff --git a/include/lldb/Host/Condition.h b/include/lldb/Host/Condition.h index 98439ee2ebdf..2f1858b75a56 100644 --- a/include/lldb/Host/Condition.h +++ b/include/lldb/Host/Condition.h @@ -12,7 +12,7 @@ #if defined(__cplusplus) -#include <pthread.h> +#include "lldb/lldb-types.h" #include "lldb/Host/Mutex.h" namespace lldb_private { @@ -105,7 +105,7 @@ protected: //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ - pthread_cond_t m_condition; ///< The condition variable. + lldb::condition_t m_condition; ///< The condition variable. //------------------------------------------------------------------ /// Get accessor to the pthread condition object. @@ -113,7 +113,7 @@ protected: /// @return /// A pointer to the condition variable owned by this object. //------------------------------------------------------------------ - pthread_cond_t * + lldb::condition_t * GetCondition (); }; diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h index 2d5d39baac3d..80616b747cf5 100644 --- a/include/lldb/Host/Config.h +++ b/include/lldb/Host/Config.h @@ -14,7 +14,7 @@ #include "lldb/Host/macosx/Config.h" -#elif defined(__linux__) +#elif defined(__linux__) || defined(__GNU__) #include "lldb/Host/linux/Config.h" @@ -26,6 +26,10 @@ #include "lldb/Host/mingw/Config.h" +#elif defined(_MSC_VER) + +#include "lldb/Host/msvc/Config.h" + #else #error undefined platform diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h index df7fe92cccba..7ca582402b32 100644 --- a/include/lldb/Host/File.h +++ b/include/lldb/Host/File.h @@ -11,7 +11,9 @@ #define liblldb_File_h_ #if defined(__cplusplus) +#include <stdarg.h> #include <stdio.h> +#include <sys/types.h> #include "lldb/lldb-private.h" @@ -41,17 +43,20 @@ public: eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist }; + static mode_t + ConvertOpenOptionsForPOSIXOpen (uint32_t open_options); + enum Permissions { - ePermissionsUserRead = (1u << 0), - ePermissionsUserWrite = (1u << 1), - ePermissionsUserExecute = (1u << 2), - ePermissionsGroupRead = (1u << 3), + ePermissionsUserRead = (1u << 8), + ePermissionsUserWrite = (1u << 7), + ePermissionsUserExecute = (1u << 6), + ePermissionsGroupRead = (1u << 5), ePermissionsGroupWrite = (1u << 4), - ePermissionsGroupExecute = (1u << 5), - ePermissionsWorldRead = (1u << 6), - ePermissionsWorldWrite = (1u << 7), - ePermissionsWorldExecute = (1u << 8), + ePermissionsGroupExecute = (1u << 3), + ePermissionsWorldRead = (1u << 2), + ePermissionsWorldWrite = (1u << 1), + ePermissionsWorldExecute = (1u << 0), ePermissionsUserRW = (ePermissionsUserRead | ePermissionsUserWrite | 0 ), ePermissionsUserRX = (ePermissionsUserRead | 0 | ePermissionsUserExecute ), @@ -117,6 +122,27 @@ public: uint32_t options, uint32_t permissions = ePermissionsDefault); + //------------------------------------------------------------------ + /// Constructor with FileSpec. + /// + /// Takes a FileSpec pointing 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 FileSpec for this 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 FileSpec& filespec, + uint32_t options, + uint32_t permissions = ePermissionsDefault); File (int fd, bool tranfer_ownership) : m_descriptor (fd), @@ -451,6 +477,19 @@ public: //------------------------------------------------------------------ Error Sync (); + + //------------------------------------------------------------------ + /// Get the permissions for a this file. + /// + /// @return + /// Bits logical OR'ed together from the permission bits defined + /// in lldb_private::File::Permissions. + //------------------------------------------------------------------ + uint32_t + GetPermissions(Error &error) const; + + static uint32_t + GetPermissions (const char *path, Error &error); //------------------------------------------------------------------ /// Output printf formatted output to the stream. diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h index c58be9ec09d5..dfc6b711ae4a 100644 --- a/include/lldb/Host/FileSpec.h +++ b/include/lldb/Host/FileSpec.h @@ -177,7 +177,7 @@ public: /// A pointer to this object if either the directory or filename /// is valid, NULL otherwise. //------------------------------------------------------------------ - operator bool() const; + explicit operator bool() const; //------------------------------------------------------------------ /// Logical NOT operator. @@ -624,6 +624,21 @@ public: static size_t Resolve (const char *src_path, char *dst_path, size_t dst_len); + FileSpec + CopyByAppendingPathComponent (const char *new_path) const; + + FileSpec + CopyByRemovingLastPathComponent () const; + + void + AppendPathComponent (const char *new_path); + + void + RemoveLastPathComponent (); + + const char* + GetLastPathComponent () const; + //------------------------------------------------------------------ /// 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 diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h index 547bdd5d637b..1d667dee5a20 100644 --- a/include/lldb/Host/Host.h +++ b/include/lldb/Host/Host.h @@ -18,6 +18,7 @@ #include "lldb/lldb-private.h" #include "lldb/Core/StringList.h" +#include "lldb/Host/File.h" namespace lldb_private { @@ -209,6 +210,9 @@ public: static lldb::pid_t GetCurrentProcessID (); + static void + Kill(lldb::pid_t pid, int signo); + //------------------------------------------------------------------ /// Get the thread ID for the calling thread in the current process. /// @@ -264,6 +268,17 @@ public: lldb::thread_result_t *thread_result_ptr, Error *error); + typedef void (*ThreadLocalStorageCleanupCallback) (void *p); + + static lldb::thread_key_t + ThreadLocalStorageCreate(ThreadLocalStorageCleanupCallback callback); + + static void* + ThreadLocalStorageGet(lldb::thread_key_t key); + + static void + ThreadLocalStorageSet(lldb::thread_key_t key, void *value); + //------------------------------------------------------------------ /// Gets the name of a thread in a process. /// @@ -458,7 +473,7 @@ public: 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"); + const char *shell = LLDB_DEFAULT_SHELL); static lldb::DataBufferSP GetAuxvData (lldb_private::Process *process); @@ -494,6 +509,45 @@ public: DynamicLibraryGetSymbol (void *dynamic_library_handle, const char *symbol_name, Error &error); + + static uint32_t + MakeDirectory (const char* path, mode_t mode); + + static lldb::user_id_t + OpenFile (const FileSpec& file_spec, + uint32_t flags, + mode_t mode, + Error &error); + + static bool + CloseFile (lldb::user_id_t fd, + Error &error); + + static uint64_t + WriteFile (lldb::user_id_t fd, + uint64_t offset, + const void* src, + uint64_t src_len, + Error &error); + + static uint64_t + ReadFile (lldb::user_id_t fd, + uint64_t offset, + void* dst, + uint64_t dst_len, + Error &error); + + static lldb::user_id_t + GetFileSize (const FileSpec& file_spec); + + static bool + GetFileExists (const FileSpec& file_spec); + + static bool + CalculateMD5 (const FileSpec& file_spec, + uint64_t &low, + uint64_t &high); + }; } // namespace lldb_private diff --git a/include/lldb/Host/Mutex.h b/include/lldb/Host/Mutex.h index 63f759efe366..496dd0496c13 100644 --- a/include/lldb/Host/Mutex.h +++ b/include/lldb/Host/Mutex.h @@ -11,7 +11,7 @@ #define liblldb_Mutex_h_ #if defined(__cplusplus) -#include <pthread.h> +#include "lldb/lldb-types.h" #include <assert.h> #ifdef LLDB_CONFIGURATION_DEBUG @@ -238,7 +238,7 @@ protected: //------------------------------------------------------------------ // 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. + lldb::mutex_t m_mutex; ///< The OS mutex object. private: //------------------------------------------------------------------ @@ -247,7 +247,7 @@ private: /// @return /// A pointer to the pthread mutex object owned by this object. //------------------------------------------------------------------ - pthread_mutex_t * + lldb::mutex_t * GetMutex(); Mutex(const Mutex&); diff --git a/include/lldb/Host/OptionParser.h b/include/lldb/Host/OptionParser.h new file mode 100644 index 000000000000..410e4d9f9468 --- /dev/null +++ b/include/lldb/Host/OptionParser.h @@ -0,0 +1,53 @@ +//===-- OptionParser.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_OptionParser_h_ +#define liblldb_OptionParser_h_ + +namespace lldb_private { + +typedef struct Option +{ + // name of long option + const char *name; + // one of no_argument, required_argument, and optional_argument: + // whether option takes an argument + int has_arg; + // if not NULL, set *flag to val when option found + int *flag; + // if flag not NULL, value to set *flag to; else return value + int val; +} Option; + +class OptionParser +{ +public: + enum OptionArgument + { + eNoArgument = 0, + eRequiredArgument, + eOptionalArgument + }; + + static void Prepare(); + + static void EnableError(bool error); + + static int Parse(int argc, char * const argv [], + const char *optstring, + const Option *longopts, int *longindex); + + static char* GetOptionArgument(); + static int GetOptionIndex(); + static int GetOptionErrorCause(); +}; + +} + +#endif // liblldb_OptionParser_h_ diff --git a/include/lldb/Host/ProcessRunLock.h b/include/lldb/Host/ProcessRunLock.h index f563be73fce0..eca1ad375fc6 100644 --- a/include/lldb/Host/ProcessRunLock.h +++ b/include/lldb/Host/ProcessRunLock.h @@ -11,9 +11,9 @@ #define liblldb_ProcessRunLock_h_ #if defined(__cplusplus) +#include "lldb/lldb-defines.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Condition.h" -#include <pthread.h> #include <stdint.h> #include <time.h> @@ -32,75 +32,14 @@ namespace lldb_private { 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; - } - + ProcessRunLock(); + ~ProcessRunLock(); + bool ReadTryLock (); + bool ReadUnlock (); + bool SetRunning (); + bool TrySetRunning (); + bool SetStopped (); +public: class ProcessRunLocker { public: @@ -153,7 +92,7 @@ public: }; protected: - pthread_rwlock_t m_rwlock; + lldb::rwlock_t m_rwlock; bool m_running; private: DISALLOW_COPY_AND_ASSIGN(ProcessRunLock); diff --git a/include/lldb/Host/SocketAddress.h b/include/lldb/Host/SocketAddress.h index e63b238c7994..5e79e94fa9ec 100644 --- a/include/lldb/Host/SocketAddress.h +++ b/include/lldb/Host/SocketAddress.h @@ -12,9 +12,18 @@ // C Includes #include <stdint.h> + +#ifdef _WIN32 +#include "lldb/Host/windows/windows.h" +#include <winsock2.h> +#include <WS2tcpip.h> +typedef ADDRESS_FAMILY sa_family_t; +typedef USHORT in_port_t; +#else #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> +#endif #if defined(__FreeBSD__) #include <sys/types.h> diff --git a/include/lldb/Host/Symbols.h b/include/lldb/Host/Symbols.h index 9db68e1ecf15..652a614e6355 100644 --- a/include/lldb/Host/Symbols.h +++ b/include/lldb/Host/Symbols.h @@ -12,7 +12,6 @@ // C Includes #include <stdint.h> -#include <sys/time.h> // C++ Includes // Other libraries and framework includes diff --git a/include/lldb/Host/Terminal.h b/include/lldb/Host/Terminal.h index b334717c796b..5ea88c515637 100644 --- a/include/lldb/Host/Terminal.h +++ b/include/lldb/Host/Terminal.h @@ -12,6 +12,7 @@ #if defined(__cplusplus) #include "lldb/lldb-private.h" +#include "lldb/Host/Config.h" struct termios; @@ -173,7 +174,9 @@ protected: //------------------------------------------------------------------ Terminal m_tty; ///< A terminal int m_tflags; ///< Cached tflags information. +#ifdef LLDB_CONFIG_TERMIOS_SUPPORTED std::unique_ptr<struct termios> m_termios_ap; ///< Cached terminal state information. +#endif lldb::pid_t m_process_group;///< Cached process group information. }; diff --git a/include/lldb/Host/TimeValue.h b/include/lldb/Host/TimeValue.h index 8c43d6d0e5ff..ba230045307f 100644 --- a/include/lldb/Host/TimeValue.h +++ b/include/lldb/Host/TimeValue.h @@ -12,6 +12,7 @@ // C Includes #include <stdint.h> +#ifndef _MSC_VER #include <sys/time.h> // BEGIN: MinGW work around @@ -19,6 +20,7 @@ #include <pthread.h> #endif // END: MinGW work around +#endif // C++ Includes // Other libraries and framework includes @@ -40,7 +42,7 @@ public: TimeValue(); TimeValue(const TimeValue& rhs); TimeValue(const struct timespec& ts); - TimeValue(const struct timeval& tv); + explicit TimeValue(uint32_t seconds, uint32_t nanos = 0); ~TimeValue(); //------------------------------------------------------------------ @@ -64,9 +66,6 @@ public: struct timespec GetAsTimeSpec () const; - struct timeval - GetAsTimeVal () const; - bool IsValid () const; @@ -85,6 +84,23 @@ public: void Dump (Stream *s, uint32_t width = 0) const; + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + uint32_t seconds() const { return m_nano_seconds / NanoSecPerSec; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + uint32_t nanoseconds() const { return m_nano_seconds % NanoSecPerSec; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return (m_nano_seconds % NanoSecPerSec) / NanoSecPerMicroSec; + } + protected: //------------------------------------------------------------------ // Classes that inherit from TimeValue can see and modify these diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h index d06c3e56aecd..27feca63e4ad 100644 --- a/include/lldb/Interpreter/Args.h +++ b/include/lldb/Interpreter/Args.h @@ -11,8 +11,6 @@ #define liblldb_Command_h_ // C Includes -#include <getopt.h> - // C++ Includes #include <list> #include <string> @@ -24,6 +22,7 @@ #include "lldb/lldb-private-types.h" #include "lldb/lldb-types.h" #include "lldb/Core/Error.h" +#include "lldb/Host/OptionParser.h" namespace lldb_private { @@ -319,7 +318,7 @@ public: ParseOptions (Options &options); size_t - FindArgumentIndexForOption (struct option *long_options, int long_options_index); + FindArgumentIndexForOption (Option *long_options, int long_options_index); bool IsPositionalArgument (const char *arg); diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h index 2bfab0a8ecc4..8544fd9f9c3f 100644 --- a/include/lldb/Interpreter/CommandObject.h +++ b/include/lldb/Interpreter/CommandObject.h @@ -42,7 +42,7 @@ public: return (*help_callback)(); } - operator bool() const + explicit operator bool() const { return (help_callback != NULL); } diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h index da05e127d5d1..c09528f9f514 100644 --- a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h +++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -62,8 +62,8 @@ public: ignore_cap == true; } - ValueObject::DumpValueObjectOptions - GetAsDumpOptions (bool objc_is_compact = false, + DumpValueObjectOptions + GetAsDumpOptions (LanguageRuntimeDescriptionDisplayVerbosity lang_descr_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull, lldb::Format format = lldb::eFormatDefault, lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP()); diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h index 2b935e9e03e6..e024f3a0f3db 100644 --- a/include/lldb/Interpreter/OptionValueBoolean.h +++ b/include/lldb/Interpreter/OptionValueBoolean.h @@ -92,7 +92,7 @@ public: /// /b True this object contains a valid namespace decl, \b /// false otherwise. //------------------------------------------------------------------ - operator bool() const + explicit operator bool() const { return m_current_value; } diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h index 012eeb68ac0e..68beddfce0d0 100644 --- a/include/lldb/Interpreter/OptionValueEnumeration.h +++ b/include/lldb/Interpreter/OptionValueEnumeration.h @@ -34,7 +34,7 @@ public: const char *description; }; typedef UniqueCStringMap<EnumeratorInfo> EnumerationMap; - typedef typename EnumerationMap::Entry EnumerationMapEntry; + typedef EnumerationMap::Entry EnumerationMapEntry; OptionValueEnumeration (const OptionEnumValueElement *enumerators, enum_type value); diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h index ac4daa8f579a..2b4ac1190557 100644 --- a/include/lldb/Interpreter/Options.h +++ b/include/lldb/Interpreter/Options.h @@ -11,7 +11,6 @@ #define liblldb_Options_h_ // C Includes -#include <getopt.h> // C++ Includes #include <set> @@ -141,7 +140,7 @@ public: /// @see Args::ParseOptions (Options&) /// @see man getopt_long_only //------------------------------------------------------------------ - struct option * + Option * GetLongOptions (); // This gets passed the short option as an integer... @@ -309,7 +308,7 @@ protected: typedef std::vector<OptionSet> OptionSetVector; CommandInterpreter &m_interpreter; - std::vector<struct option> m_getopt_table; + std::vector<Option> m_getopt_table; OptionSet m_seen_options; OptionSetVector m_required_options; OptionSetVector m_optional_options; @@ -448,6 +447,12 @@ protected: void Finalize (); + bool + DidFinalize () + { + return m_did_finalize; + } + virtual Error SetOptionValue (uint32_t option_idx, const char *option_arg); @@ -464,6 +469,10 @@ protected: assert (m_did_finalize); return &m_option_defs[0]; } + + const OptionGroup* + GetGroupWithOption (char short_opt); + struct OptionInfo { OptionInfo (OptionGroup* g, uint32_t i) : diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h index b2c9240db09f..a54318159d14 100644 --- a/include/lldb/Interpreter/PythonDataObjects.h +++ b/include/lldb/Interpreter/PythonDataObjects.h @@ -105,7 +105,7 @@ namespace lldb_private { PythonString Str (); - operator bool () const + explicit operator bool () const { return m_py_obj != NULL; } diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h index 9a66c775d47a..9f529b822910 100644 --- a/include/lldb/Interpreter/ScriptInterpreter.h +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -41,7 +41,7 @@ public: return m_object; } - operator bool () + explicit operator bool () { return m_object != NULL; } @@ -108,44 +108,47 @@ public: 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 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 lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (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 void* (*SWIGPython_GetDynamicSetting) (void* module, + const char* setting, + const lldb::TargetSP& target_sp); typedef enum { @@ -162,7 +165,8 @@ public: eScriptReturnTypeFloat, eScriptReturnTypeDouble, eScriptReturnTypeChar, - eScriptReturnTypeCharStrOrNone + eScriptReturnTypeCharStrOrNone, + eScriptReturnTypeOpaqueObject } ScriptReturnType; ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang); @@ -336,6 +340,22 @@ public: { return lldb::ScriptInterpreterObjectSP(); } + + virtual lldb::ScriptInterpreterObjectSP + LoadPluginModule (const FileSpec& file_spec, + lldb_private::Error& error) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, + Target* target, + const char* setting_name, + lldb_private::Error& error) + { + return lldb::ScriptInterpreterObjectSP(); + } virtual bool GenerateFunction(const char *signature, const StringList &input) @@ -473,7 +493,8 @@ public: LoadScriptingModule (const char* filename, bool can_reload, bool init_session, - lldb_private::Error& error) + lldb_private::Error& error, + lldb::ScriptInterpreterObjectSP* module_sp = nullptr) { error.SetErrorString("loading unimplemented"); return false; @@ -501,7 +522,26 @@ public: LanguageToString (lldb::ScriptLanguage language); static void - InitializeInterpreter (SWIGInitCallback python_swig_init_callback); + InitializeInterpreter (SWIGInitCallback python_swig_init_callback, + SWIGBreakpointCallbackFunction swig_breakpoint_callback, + SWIGWatchpointCallbackFunction swig_watchpoint_callback, + SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, + SWIGPythonCreateSyntheticProvider swig_synthetic_script, + SWIGPythonCalculateNumChildren swig_calc_children, + SWIGPythonGetChildAtIndex swig_get_child_index, + SWIGPythonGetIndexOfChildWithName swig_get_index_child, + SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , + SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, + SWIGPythonUpdateSynthProviderInstance swig_update_provider, + SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonCallCommand swig_call_command, + SWIGPythonCallModuleInit swig_call_module_init, + SWIGPythonCreateOSPlugin swig_create_os_plugin, + SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, + SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, + SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, + SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, + SWIGPython_GetDynamicSetting swig_plugin_get); static void TerminateInterpreter (); diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h index 2616f575d20e..4b3dc61f3ee8 100644 --- a/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -98,6 +98,16 @@ public: lldb::tid_t tid, lldb::addr_t context); + virtual lldb::ScriptInterpreterObjectSP + LoadPluginModule (const FileSpec& file_spec, + lldb_private::Error& error); + + virtual lldb::ScriptInterpreterObjectSP + GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp, + Target* target, + const char* setting_name, + lldb_private::Error& error); + virtual size_t CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor); @@ -200,7 +210,8 @@ public: LoadScriptingModule (const char* filename, bool can_reload, bool init_session, - lldb_private::Error& error); + lldb_private::Error& error, + lldb::ScriptInterpreterObjectSP* module_sp = nullptr); virtual lldb::ScriptInterpreterObjectSP MakeScriptObject (void* object); @@ -239,7 +250,26 @@ public: InitializePrivate (); static void - InitializeInterpreter (SWIGInitCallback python_swig_init_callback); + InitializeInterpreter (SWIGInitCallback python_swig_init_callback, + SWIGBreakpointCallbackFunction swig_breakpoint_callback, + SWIGWatchpointCallbackFunction swig_watchpoint_callback, + SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, + SWIGPythonCreateSyntheticProvider swig_synthetic_script, + SWIGPythonCalculateNumChildren swig_calc_children, + SWIGPythonGetChildAtIndex swig_get_child_index, + SWIGPythonGetIndexOfChildWithName swig_get_index_child, + SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , + SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, + SWIGPythonUpdateSynthProviderInstance swig_update_provider, + SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, + SWIGPythonCallCommand swig_call_command, + SWIGPythonCallModuleInit swig_call_module_init, + SWIGPythonCreateOSPlugin swig_create_os_plugin, + SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, + SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, + SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, + SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, + SWIGPython_GetDynamicSetting swig_plugin_get); protected: @@ -254,7 +284,7 @@ protected: void RestoreTerminalState (); - + private: class SynchronicityHandler @@ -282,7 +312,7 @@ private: Py_XINCREF(m_object); } - operator bool () + explicit operator bool () { return m_object && m_object != Py_None; } @@ -351,7 +381,7 @@ private: public: PythonInputReaderManager (ScriptInterpreterPython *interpreter); - operator bool() + explicit operator bool() { return m_error; } diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h index a2d703b9069c..4a305e3cbbec 100644 --- a/include/lldb/Symbol/Block.h +++ b/include/lldb/Symbol/Block.h @@ -17,6 +17,7 @@ #include "lldb/Core/UserID.h" #include "lldb/Symbol/LineEntry.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/ClangASTType.h" namespace lldb_private { diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h index 10df7da893a8..dc6ce6b5b95b 100644 --- a/include/lldb/Symbol/ClangASTImporter.h +++ b/include/lldb/Symbol/ClangASTImporter.h @@ -278,6 +278,8 @@ private: clang::Decl *Imported (clang::Decl *from, clang::Decl *to); + clang::Decl *GetOriginalDecl (clang::Decl *To); + std::set<clang::NamedDecl *> *m_decls_to_deport; std::set<clang::NamedDecl *> *m_decls_already_deported; ClangASTImporter &m_master; diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h index d9e754e8ceb9..19b5d6ec6727 100644 --- a/include/lldb/Symbol/ClangASTType.h +++ b/include/lldb/Symbol/ClangASTType.h @@ -98,7 +98,7 @@ public: // Tests //---------------------------------------------------------------------- - operator bool () const + explicit operator bool () const { return m_type != NULL && m_ast != NULL; } @@ -155,6 +155,12 @@ public: bool IsFunctionType (bool *is_variadic_ptr = NULL) const; + size_t + GetNumberOfFunctionArguments () const; + + ClangASTType + GetFunctionArgumentAtIndex (const size_t index); + bool IsVariadicFunctionType () const; @@ -195,6 +201,9 @@ public: IsPointerToScalarType () const; bool + IsRuntimeGeneratedType () const; + + bool IsPointerType (ClangASTType *pointee_type = NULL) const; bool @@ -249,7 +258,7 @@ public: ConstString GetConstTypeName () const; - std::string + ConstString GetTypeName () const; uint32_t diff --git a/include/lldb/Symbol/ClangNamespaceDecl.h b/include/lldb/Symbol/ClangNamespaceDecl.h index d10ab2a29665..13a4c0011aff 100644 --- a/include/lldb/Symbol/ClangNamespaceDecl.h +++ b/include/lldb/Symbol/ClangNamespaceDecl.h @@ -10,6 +10,8 @@ #ifndef liblldb_ClangNamespaceDecl_h_ #define liblldb_ClangNamespaceDecl_h_ +#include <string> + #include "lldb/lldb-public.h" #include "lldb/Core/ClangForward.h" @@ -60,7 +62,7 @@ public: /// /b True this object contains a valid namespace decl, \b /// false otherwise. //------------------------------------------------------------------ - operator bool() const + explicit operator bool() const { return m_ast != NULL && m_namespace_decl != NULL; } diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h index 8934c31bb988..ad500f5413b8 100644 --- a/include/lldb/Symbol/ObjectFile.h +++ b/include/lldb/Symbol/ObjectFile.h @@ -368,6 +368,34 @@ public: GetSymtab () = 0; //------------------------------------------------------------------ + /// Appends a Symbol for the specified so_addr to the symbol table. + /// + /// If verify_unique is false, the symbol table is not searched + /// to determine if a Symbol found at this address has already been + /// added to the symbol table. When verify_unique is true, this + /// method resolves the Symbol as the first match in the SymbolTable + /// and appends a Symbol only if required/found. + /// + /// @return + /// The resolved symbol or nullptr. Returns nullptr if a + /// a Symbol could not be found for the specified so_addr. + //------------------------------------------------------------------ + virtual Symbol * + ResolveSymbolForAddress(const Address &so_addr, bool verify_unique) + { + // Typically overridden to lazily add stripped symbols recoverable from + // the exception handling unwind information (i.e. without parsing + // the entire eh_frame section. + // + // The availability of LC_FUNCTION_STARTS allows ObjectFileMachO + // to efficiently add stripped symbols when the symbol table is + // first constructed. Poorer cousins are PECoff and ELF. + return nullptr; + } + + //------------------------------------------------------------------ + /// Detect if this object file has been stripped of local symbols. + //------------------------------------------------------------------ /// Detect if this object file has been stripped of local symbols. /// /// @return @@ -478,7 +506,7 @@ public: /// 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(); } + GetImageInfoAddress (Target *target) { return Address(); } //------------------------------------------------------------------ /// Returns the address of the Entry Point in this object file - if @@ -612,6 +640,72 @@ public: } return 0; } + + //------------------------------------------------------------------ + /// Get the minimum OS version this object file can run on. + /// + /// Some object files have information that specifies the minimum OS + /// version that they can be used on. + /// + /// 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 + GetMinimumOSVersion (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; + } + + //------------------------------------------------------------------ + /// Get the SDK OS version this object file was built with. + /// + /// The versions arguments and returns values are the same as the + /// GetMinimumOSVersion() + //------------------------------------------------------------------ + virtual uint32_t + GetSDKVersion (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 diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h index 11c1cc7af9ab..75e0900ab640 100644 --- a/include/lldb/Symbol/Symbol.h +++ b/include/lldb/Symbol/Symbol.h @@ -122,6 +122,21 @@ public: return m_mangled; } + ConstString + GetReExportedSymbolName() const; + + FileSpec + GetReExportedSymbolSharedLibrary () const; + + bool + SetReExportedSymbolName(const ConstString &name); + + bool + SetReExportedSymbolSharedLibrary (const FileSpec &fspec); + + Symbol * + ResolveReExportedSymbol (Target &target); + uint32_t GetSiblingIndex () const; @@ -238,24 +253,6 @@ public: 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 diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h index 5b12adebf5f5..a0501440f18c 100644 --- a/include/lldb/Symbol/SymbolContext.h +++ b/include/lldb/Symbol/SymbolContext.h @@ -16,7 +16,6 @@ #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 { diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h index 666c3b5686b9..5dfb1c822d51 100644 --- a/include/lldb/Symbol/Symtab.h +++ b/include/lldb/Symbol/Symtab.h @@ -95,6 +95,10 @@ public: bool add_mangled, NameToIndexMap &name_to_index_map) const; + ObjectFile * GetObjectFile() + { + return m_objfile; + } protected: typedef std::vector<Symbol> collection; typedef collection::iterator iterator; diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h index 50b22fe96b9d..920f571fa1e9 100644 --- a/include/lldb/Symbol/Type.h +++ b/include/lldb/Symbol/Type.h @@ -304,147 +304,236 @@ protected: ResolveClangType (ResolveState clang_type_resolve_state); }; +// these classes are used to back the SBType* objects -/// -/// 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); +class TypePair { +private: + ClangASTType clang_type; + lldb::TypeSP type_sp; - TypeAndOrName & - operator= (const TypeAndOrName &rhs); +public: + TypePair () : clang_type(), type_sp() {} + TypePair (ClangASTType type) : + clang_type(type), + type_sp() + { + } - bool - operator==(const TypeAndOrName &other) const; + TypePair (lldb::TypeSP type) : + clang_type(), + type_sp(type) + { + clang_type = type_sp->GetClangForwardType(); + } bool - operator!=(const TypeAndOrName &other) const; - - ConstString GetName () const; - - lldb::TypeSP - GetTypeSP () const + IsValid () const { - return m_type_sp; + return clang_type.IsValid() || (type_sp.get() != nullptr); } - void - SetName (const ConstString &type_name); - - void - SetName (const char *type_name_cstr); - - void - SetTypeSP (lldb::TypeSP type_sp); - - bool - IsEmpty (); + explicit operator bool () const + { + return IsValid(); + } bool - HasName (); + operator == (const TypePair& rhs) const + { + return clang_type == rhs.clang_type && + type_sp.get() == rhs.type_sp.get(); + } bool - HasTypeSP (); + operator != (const TypePair& rhs) const + { + return clang_type != rhs.clang_type || + type_sp.get() != rhs.type_sp.get(); + } void - Clear (); + Clear () + { + clang_type.Clear(); + type_sp.reset(); + } - operator - bool () + ConstString + GetName () const { - return !IsEmpty(); + if (type_sp) + return type_sp->GetName(); + if (clang_type) + return clang_type.GetTypeName(); + return ConstString (); } -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 + void + SetType (ClangASTType type) + { + type_sp.reset(); + clang_type = type; + } -class TypeImpl -{ -public: + void + SetType (lldb::TypeSP type) + { + type_sp = type; + clang_type = type_sp->GetClangForwardType(); + } - TypeImpl() : - m_clang_ast_type(), - m_type_sp() + lldb::TypeSP + GetTypeSP () const { + return type_sp; } - TypeImpl(const TypeImpl& rhs) : - m_clang_ast_type(rhs.m_clang_ast_type), - m_type_sp(rhs.m_type_sp) + ClangASTType + GetClangASTType () const { + return clang_type; } - TypeImpl(const lldb_private::ClangASTType& type); + ClangASTType + GetPointerType () const + { + if (type_sp) + return type_sp->GetClangLayoutType().GetPointerType(); + return clang_type.GetPointerType(); + } - TypeImpl(const lldb::TypeSP& type); + ClangASTType + GetPointeeType () const + { + if (type_sp) + return type_sp->GetClangFullType().GetPointeeType(); + return clang_type.GetPointeeType(); + } - TypeImpl& - operator = (const TypeImpl& rhs); + ClangASTType + GetReferenceType () const + { + if (type_sp) + return type_sp->GetClangLayoutType().GetLValueReferenceType(); + return clang_type.GetLValueReferenceType(); + } - bool - operator == (const TypeImpl& rhs) + ClangASTType + GetDereferencedType () const { - return m_clang_ast_type == rhs.m_clang_ast_type && m_type_sp.get() == rhs.m_type_sp.get(); + if (type_sp) + return type_sp->GetClangFullType().GetNonReferenceType(); + return clang_type.GetNonReferenceType(); } - - bool - operator != (const TypeImpl& rhs) + + ClangASTType + GetUnqualifiedType () const { - return m_clang_ast_type != rhs.m_clang_ast_type || m_type_sp.get() != rhs.m_type_sp.get(); + if (type_sp) + return type_sp->GetClangLayoutType().GetFullyUnqualifiedType(); + return clang_type.GetFullyUnqualifiedType(); } - bool - IsValid() + ClangASTType + GetCanonicalType () const { - return m_type_sp.get() != NULL || m_clang_ast_type.IsValid(); + if (type_sp) + return type_sp->GetClangFullType().GetCanonicalType(); + return clang_type.GetCanonicalType(); } - const lldb_private::ClangASTType & - GetClangASTType() const + clang::ASTContext * + GetClangASTContext () const { - return m_clang_ast_type; + return clang_type.GetASTContext(); } +}; - clang::ASTContext* - GetASTContext(); +class TypeImpl +{ +public: + + TypeImpl(); + + ~TypeImpl () {} + + TypeImpl(const TypeImpl& rhs); + + TypeImpl (lldb::TypeSP type_sp); + + TypeImpl (ClangASTType clang_type); - lldb::clang_type_t - GetOpaqueQualType(); + TypeImpl (lldb::TypeSP type_sp, ClangASTType dynamic); + + TypeImpl (ClangASTType clang_type, ClangASTType dynamic); + + TypeImpl (TypePair pair, ClangASTType dynamic); - lldb::TypeSP - GetTypeSP () - { - return m_type_sp; - } + void + SetType (lldb::TypeSP type_sp); + + void + SetType (ClangASTType clang_type); + + void + SetType (lldb::TypeSP type_sp, ClangASTType dynamic); + + void + SetType (ClangASTType clang_type, ClangASTType dynamic); + + void + SetType (TypePair pair, ClangASTType dynamic); + + TypeImpl& + operator = (const TypeImpl& rhs); + + bool + operator == (const TypeImpl& rhs) const; + + bool + operator != (const TypeImpl& rhs) const; + + bool + IsValid() const; + + explicit operator bool () const; + + void Clear(); ConstString - GetName (); - + GetName () const; + + TypeImpl + GetPointerType () const; + + TypeImpl + GetPointeeType () const; + + TypeImpl + GetReferenceType () const; + + TypeImpl + GetDereferencedType () const; + + TypeImpl + GetUnqualifiedType() const; + + TypeImpl + GetCanonicalType() const; + + ClangASTType + GetClangASTType (bool prefer_dynamic); + + clang::ASTContext * + GetClangASTContext (bool prefer_dynamic); + 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; + TypePair m_static_type; + ClangASTType m_dynamic_type; }; class TypeListImpl @@ -590,6 +679,89 @@ protected: }; +/// +/// 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 ClangASTType &clang_type); + 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_pair.GetTypeSP(); + } + + ClangASTType + GetClangASTType () const + { + return m_type_pair.GetClangASTType(); + } + + void + SetName (const ConstString &type_name); + + void + SetName (const char *type_name_cstr); + + void + SetTypeSP (lldb::TypeSP type_sp); + + void + SetClangASTType (ClangASTType clang_type); + + bool + IsEmpty () const; + + bool + HasName () const; + + bool + HasTypeSP () const; + + bool + HasClangASTType () const; + + bool + HasType () const + { + return HasTypeSP() || HasClangASTType(); + } + + void + Clear (); + + explicit operator bool () + { + return !IsEmpty(); + } + +private: + TypePair m_type_pair; + ConstString m_type_name; +}; + } // namespace lldb_private #endif // liblldb_Type_h_ diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h index 9c74db6bf1f4..be7d35482da0 100644 --- a/include/lldb/Symbol/TypeList.h +++ b/include/lldb/Symbol/TypeList.h @@ -13,6 +13,7 @@ #include "lldb/lldb-private.h" #include "lldb/Symbol/Type.h" #include <map> +#include <functional> namespace lldb_private { diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h index 6b76e5891ae8..272f64f33113 100644 --- a/include/lldb/Target/DynamicLoader.h +++ b/include/lldb/Target/DynamicLoader.h @@ -224,6 +224,26 @@ public: return false; } + //------------------------------------------------------------------ + /// Retrieves the per-module TLS block for a given thread. + /// + /// @param[in] module + /// The module to query TLS data for. + /// + /// @param[in] thread + /// The specific thread to query TLS data for. + /// + /// @return + /// If the given thread has TLS data allocated for the + /// module, the address of the TLS block. Otherwise + /// LLDB_INVALID_ADDRESS is returned. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread) + { + return LLDB_INVALID_ADDRESS; + } + protected: //------------------------------------------------------------------ // Member variables. diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h index de5fe14934a7..4038e70b0c56 100644 --- a/include/lldb/Target/ExecutionContext.h +++ b/include/lldb/Target/ExecutionContext.h @@ -461,6 +461,9 @@ public: uint32_t GetAddressByteSize() const; + + lldb::ByteOrder + GetByteOrder() const; //------------------------------------------------------------------ /// Returns a pointer to the target object. diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h index b0a07946e74e..93cd67d66659 100644 --- a/include/lldb/Target/Platform.h +++ b/include/lldb/Target/Platform.h @@ -22,6 +22,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Host/Mutex.h" namespace lldb_private { @@ -459,6 +460,15 @@ namespace lldb_private { virtual lldb::BreakpointSP SetThreadCreationBreakpoint (Target &target); + //------------------------------------------------------------------ + // Given a target, find the local SDK directory if one exists on the + // current host. + //------------------------------------------------------------------ + virtual lldb_private::ConstString + GetSDKDirectory (lldb_private::Target &target) + { + return lldb_private::ConstString(); + } const std::string & GetRemoteURL () const @@ -542,9 +552,249 @@ namespace lldb_private { return false; } + virtual uint32_t + MakeDirectory (const std::string &path, + mode_t mode) + { + return UINT32_MAX; + } + + // this need not be virtual: the core behavior is in + // MakeDirectory(std::string,mode_t) + uint32_t + MakeDirectory (const FileSpec &spec, + mode_t mode); + + virtual lldb::user_id_t + OpenFile (const FileSpec& file_spec, + uint32_t flags, + mode_t mode, + Error &error) + { + return UINT64_MAX; + } + + virtual bool + CloseFile (lldb::user_id_t fd, + Error &error) + { + return false; + } + + virtual lldb::user_id_t + GetFileSize (const FileSpec& file_spec) + { + return UINT64_MAX; + } + + virtual uint64_t + ReadFile (lldb::user_id_t fd, + uint64_t offset, + void *dst, + uint64_t dst_len, + Error &error) + { + error.SetErrorStringWithFormat ("Platform::ReadFile() is not supported in the %s platform", GetName().GetCString()); + return -1; + } + + virtual uint64_t + WriteFile (lldb::user_id_t fd, + uint64_t offset, + const void* src, + uint64_t src_len, + Error &error) + { + error.SetErrorStringWithFormat ("Platform::ReadFile() is not supported in the %s platform", GetName().GetCString()); + return -1; + } + + virtual Error + PutFile (const FileSpec& source, + const FileSpec& destination, + uint32_t uid = UINT32_MAX, + uint32_t gid = UINT32_MAX); + virtual size_t GetEnvironment (StringList &environment); + virtual Error + GetFile (const FileSpec& source, + const FileSpec& destination); + + virtual bool + GetFileExists (const lldb_private::FileSpec& file_spec); + + virtual uint32_t + GetFilePermissions (const lldb_private::FileSpec &file_spec, + Error &error) + { + error.SetErrorStringWithFormat ("Platform::GetFilePermissions() is not supported in the %s platform", GetName().GetCString()); + return 0; + } + + virtual bool + GetSupportsRSync () + { + return m_supports_rsync; + } + + virtual void + SetSupportsRSync(bool flag) + { + m_supports_rsync = flag; + } + + virtual const char* + GetRSyncOpts () + { + return m_rsync_opts.c_str(); + } + + virtual void + SetRSyncOpts (const char* opts) + { + m_rsync_opts.assign(opts); + } + + virtual const char* + GetRSyncPrefix () + { + return m_rsync_prefix.c_str(); + } + + virtual void + SetRSyncPrefix (const char* prefix) + { + m_rsync_prefix.assign(prefix); + } + + virtual bool + GetSupportsSSH () + { + return m_supports_ssh; + } + + virtual void + SetSupportsSSH(bool flag) + { + m_supports_ssh = flag; + } + + virtual const char* + GetSSHOpts () + { + return m_ssh_opts.c_str(); + } + + virtual void + SetSSHOpts (const char* opts) + { + m_ssh_opts.assign(opts); + } + + virtual bool + GetIgnoresRemoteHostname () + { + return m_ignores_remote_hostname; + } + + virtual void + SetIgnoresRemoteHostname(bool flag) + { + m_ignores_remote_hostname = flag; + } + + virtual lldb_private::OptionGroupOptions * + GetConnectionOptions (CommandInterpreter& interpreter) + { + return NULL; + } + + virtual lldb_private::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); // Timeout in seconds to wait for shell program to finish + + virtual void + SetLocalCacheDirectory (const char* local); + + virtual const char* + GetLocalCacheDirectory (); + + virtual std::string + GetPlatformSpecificConnectionInformation() + { + return ""; + } + + virtual bool + CalculateMD5 (const FileSpec& file_spec, + uint64_t &low, + uint64_t &high); + + virtual int32_t + GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info) + { + return 1; + } + + //------------------------------------------------------------------ + /// Locate a queue name given a thread's qaddr + /// + /// On a system using libdispatch ("Grand Central Dispatch") style + /// queues, a thread may be associated with a GCD queue or not, + /// and a queue may be associated with multiple threads. + /// The process/thread must provide a way to find the "dispatch_qaddr" + /// for each thread, and from that dispatch_qaddr this Platform method + /// will locate the queue name and provide that. + /// + /// @param[in] process + /// A process is required for reading memory. + /// + /// @param[in] dispatch_qaddr + /// The dispatch_qaddr for this thread. + /// + /// @return + /// The name of the queue, if there is one. An empty string + /// means that this thread is not associated with a dispatch + /// queue. + //------------------------------------------------------------------ + virtual std::string + GetQueueNameForThreadQAddress (Process *process, lldb::addr_t dispatch_qaddr) + { + return ""; + } + + //------------------------------------------------------------------ + /// Locate a queue ID given a thread's qaddr + /// + /// On a system using libdispatch ("Grand Central Dispatch") style + /// queues, a thread may be associated with a GCD queue or not, + /// and a queue may be associated with multiple threads. + /// The process/thread must provide a way to find the "dispatch_qaddr" + /// for each thread, and from that dispatch_qaddr this Platform method + /// will locate the queue ID and provide that. + /// + /// @param[in] process + /// A process is required for reading memory. + /// + /// @param[in] dispatch_qaddr + /// The dispatch_qaddr for this thread. + /// + /// @return + /// The queue_id for this thread, if this thread is associated + /// with a dispatch queue. Else LLDB_INVALID_QUEUE_ID is returned. + //------------------------------------------------------------------ + virtual lldb::queue_id_t + GetQueueIDForThreadQAddress (Process *process, lldb::addr_t dispatch_qaddr) + { + return LLDB_INVALID_QUEUE_ID; + } + protected: bool m_is_host; // Set to true when we are able to actually set the OS version while @@ -569,7 +819,14 @@ namespace lldb_private { IDToNameMap m_gid_map; size_t m_max_uid_name_len; size_t m_max_gid_name_len; - + bool m_supports_rsync; + std::string m_rsync_opts; + std::string m_rsync_prefix; + bool m_supports_ssh; + std::string m_ssh_opts; + bool m_ignores_remote_hostname; + std::string m_local_cache_directory; + const char * GetCachedUserName (uint32_t uid) { @@ -750,6 +1007,110 @@ namespace lldb_private { private: DISALLOW_COPY_AND_ASSIGN (PlatformList); }; + + class OptionGroupPlatformRSync : public lldb_private::OptionGroup + { + public: + OptionGroupPlatformRSync (); + + virtual + ~OptionGroupPlatformRSync (); + + virtual lldb_private::Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + void + OptionParsingStarting (CommandInterpreter &interpreter); + + const lldb_private::OptionDefinition* + GetDefinitions (); + + virtual uint32_t + GetNumDefinitions (); + + // Options table: Required for subclasses of Options. + + static lldb_private::OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_rsync; + std::string m_rsync_opts; + std::string m_rsync_prefix; + bool m_ignores_remote_hostname; + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformRSync); + }; + + class OptionGroupPlatformSSH : public lldb_private::OptionGroup + { + public: + OptionGroupPlatformSSH (); + + virtual + ~OptionGroupPlatformSSH (); + + virtual lldb_private::Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + void + OptionParsingStarting (CommandInterpreter &interpreter); + + virtual uint32_t + GetNumDefinitions (); + + const lldb_private::OptionDefinition* + GetDefinitions (); + + // Options table: Required for subclasses of Options. + + static lldb_private::OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_ssh; + std::string m_ssh_opts; + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformSSH); + }; + + class OptionGroupPlatformCaching : public lldb_private::OptionGroup + { + public: + OptionGroupPlatformCaching (); + + virtual + ~OptionGroupPlatformCaching (); + + virtual lldb_private::Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + void + OptionParsingStarting (CommandInterpreter &interpreter); + + virtual uint32_t + GetNumDefinitions (); + + const lldb_private::OptionDefinition* + GetDefinitions (); + + // Options table: Required for subclasses of Options. + + static lldb_private::OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + std::string m_cache_dir; + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupPlatformCaching); + }; + } // namespace lldb_private #endif // liblldb_Platform_h_ diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h index ef89a1eb1418..aa7b5edc5af1 100644 --- a/include/lldb/Target/Process.h +++ b/include/lldb/Target/Process.h @@ -10,9 +10,10 @@ #ifndef liblldb_Process_h_ #define liblldb_Process_h_ +#include "lldb/Host/Config.h" + // C Includes #include <limits.h> -#include <spawn.h> // C++ Includes #include <list> @@ -239,6 +240,12 @@ public: return m_arch; } + void + SetArchitecture (ArchSpec arch) + { + m_arch = arch; + } + lldb::pid_t GetProcessID () const { @@ -475,11 +482,13 @@ public: bool Open (int fd, const char *path, bool read, bool write); +#ifndef LLDB_DISABLE_POSIX static bool - AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions, + AddPosixSpawnFileAction (void *file_actions, const FileAction *info, Log *log, Error& error); +#endif int GetFD () const @@ -777,7 +786,8 @@ public: ConvertArgumentsForLaunchingInShell (Error &error, bool localhost, bool will_debug, - bool first_arg_is_full_shell_command); + bool first_arg_is_full_shell_command, + int32_t num_resumes); void SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback, @@ -1358,9 +1368,7 @@ class Process : { friend class ThreadList; friend class ClangFunction; // For WaitForStateChangeEventsPrivate -friend class CommandObjectProcessLaunch; friend class ProcessEventData; -friend class CommandObjectBreakpointCommand; friend class StopInfo; public: @@ -1749,7 +1757,7 @@ public: error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetPluginName().GetCString()); return error; } - + //------------------------------------------------------------------ /// Get the dynamic loader plug-in for this process. /// @@ -1763,6 +1771,16 @@ public: GetDynamicLoader (); //------------------------------------------------------------------ + /// Get the system runtime plug-in for this process. + /// + /// @return + /// Returns a pointer to the SystemRuntime plugin for this Process + /// if one is available. Else returns NULL. + //------------------------------------------------------------------ + virtual SystemRuntime * + GetSystemRuntime (); + + //------------------------------------------------------------------ /// Attach to an existing process using the process attach info. /// /// This function is not meant to be overridden by Process @@ -3308,8 +3326,11 @@ public: lldb::StateType GetNextEvent (lldb::EventSP &event_sp); + // Returns the process state when it is stopped. If specified, event_sp_ptr + // is set to the event which triggered the stop. If wait_always = false, + // and the process is already stopped, this function returns immediately. lldb::StateType - WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL); + WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL, bool wait_always = true); lldb::StateType WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp); @@ -3656,6 +3677,7 @@ protected: 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; + std::unique_ptr<SystemRuntime> m_system_runtime_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; @@ -3711,10 +3733,10 @@ protected: void ResumePrivateStateThread (); - static void * + static lldb::thread_result_t PrivateStateThread (void *arg); - void * + lldb::thread_result_t RunPrivateStateThread (); void diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h index dd0e73fc7eb3..7da462700110 100644 --- a/include/lldb/Target/RegisterContext.h +++ b/include/lldb/Target/RegisterContext.h @@ -123,12 +123,17 @@ public: const RegisterInfo * GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0); + const RegisterInfo * + GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num); + uint64_t GetPC (uint64_t fail_value = LLDB_INVALID_ADDRESS); bool SetPC (uint64_t pc); + bool SetPC (Address addr); + uint64_t GetSP (uint64_t fail_value = LLDB_INVALID_ADDRESS); diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h index 877bd8ce661b..e7b57cd26ac9 100644 --- a/include/lldb/Target/StackFrame.h +++ b/include/lldb/Target/StackFrame.h @@ -26,9 +26,21 @@ namespace lldb_private { +/// @class StackFrame StackFrame.h "lldb/Target/StackFrame.h" +/// +/// @brief This base class provides an interface to stack frames. +/// +/// StackFrames may have a Canonical Frame Address (CFA) or not. +/// A frame may have a plain pc value or it may have a pc value + stop_id +/// to indicate a specific point in the debug session so the correct section +/// load list is used for symbolication. +/// +/// Local variables may be available, or not. A register context may be +/// available, or not. + class StackFrame : - public std::enable_shared_from_this<StackFrame>, - public ExecutionContextScope + public ExecutionContextScope, + public std::enable_shared_from_this<StackFrame> { public: enum ExpressionPathOption @@ -39,14 +51,72 @@ public: eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3), eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4) }; + //------------------------------------------------------------------ - // Constructors and Destructors + /// Construct a StackFrame object without supplying a RegisterContextSP. + /// + /// This is the one constructor that doesn't take a RegisterContext + /// parameter. This ctor may be called when creating a history StackFrame; + /// these are used if we've collected a stack trace of pc addresses at + /// some point in the past. We may only have pc values. We may have pc + /// values and the stop_id when the stack trace was recorded. We may have a + /// CFA, or more likely, we won't. + /// + /// @param [in] thread_sp + /// The Thread that this frame belongs to. + /// + /// @param [in] frame_idx + /// This StackFrame's frame index number in the Thread. If inlined stack + /// frames are being created, this may differ from the concrete_frame_idx + /// which is the frame index without any inlined stack frames. + /// + /// @param [in] concrete_frame_idx + /// The StackFrame's frame index number in the Thread without any inlined + /// stack frames being included in the index. + /// + /// @param [in] cfa + /// The Canonical Frame Address (this terminology from DWARF) for this + /// stack frame. The CFA for a stack frame does not change over the + /// span of the stack frame's existence. It is often the value of the + /// caller's stack pointer before the call instruction into this frame's + /// function. It is usually not the same as the frame pointer register's + /// value. + /// + /// @param [in] cfa_is_valid + /// A history stack frame may not have a CFA value collected. We want to + /// distinguish between "no CFA available" and a CFA of + /// LLDB_INVALID_ADDRESS. + /// + /// @param [in] pc + /// The current pc value of this stack frame. + /// + /// @param [in] stop_id + /// The stop_id which should be used when looking up symbols for the pc value, + /// if appropriate. This argument is ignored if stop_id_is_valid is false. + /// + /// @param [in] stop_id_is_valid + /// If the stop_id argument provided is not needed for this StackFrame, this + /// should be false. If this is a history stack frame and we know the stop_id + /// when the pc value was collected, that stop_id should be provided and this + /// will be true. + /// + /// @param [in] is_history_frame + /// If this is a historical stack frame -- possibly without CFA or registers or + /// local variables -- then this should be set to true. + /// + /// @param [in] sc_ptr + /// Optionally seed the StackFrame with the SymbolContext information that has + /// already been discovered. //------------------------------------------------------------------ StackFrame (const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx, lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa, + bool cfa_is_valid, lldb::addr_t pc, + uint32_t stop_id, + bool stop_id_is_valid, + bool is_history_frame, const SymbolContext *sc_ptr); StackFrame (const lldb::ThreadSP &thread_sp, @@ -76,21 +146,103 @@ public: StackID& GetStackID(); + //------------------------------------------------------------------ + /// Get an Address for the current pc value in this StackFrame. + /// + /// May not be the same as the actual PC value for inlined stack frames. + /// + /// @return + /// The Address object set to the current PC value. + //------------------------------------------------------------------ const Address& GetFrameCodeAddress(); - - void + + //------------------------------------------------------------------ + /// Change the pc value for a given thread. + /// + /// Change the current pc value for the frame on this thread. + /// + /// @param[in] pc + /// The load address that the pc will be set to. + /// + /// @return + /// true if the pc was changed. false if this failed -- possibly + /// because this frame is not a live StackFrame. + //------------------------------------------------------------------ + bool ChangePC (lldb::addr_t pc); + //------------------------------------------------------------------ + /// Provide a SymbolContext for this StackFrame's current pc value. + /// + /// The StackFrame maintains this SymbolContext and adds additional information + /// to it on an as-needed basis. This helps to avoid different functions + /// looking up symbolic information for a given pc value multple times. + /// + /// @params [in] resolve_scope + /// Flags from the SymbolContextItem enumerated type which specify what + /// type of symbol context is needed by this caller. + /// + /// @return + /// A SymbolContext reference which includes the types of information + /// requested by resolve_scope, if they are available. + //------------------------------------------------------------------ const SymbolContext& GetSymbolContext (uint32_t resolve_scope); + //------------------------------------------------------------------ + /// Return the Canonical Frame Address (DWARF term) for this frame. + /// + /// The CFA is typically the value of the stack pointer register before + /// the call invocation is made. It will not change during the lifetime + /// of a stack frame. It is often not the same thing as the frame pointer + /// register value. + /// + /// Live StackFrames will always have a CFA but other types of frames may + /// not be able to supply one. + /// + /// @param [out] value + /// The address of the CFA for this frame, if available. + /// + /// @param [out] error_ptr + /// If there is an error determining the CFA address, this may contain a + /// string explaining the failure. + /// + /// @return + /// Returns true if the CFA value was successfully set in value. Some + /// frames may be unable to provide this value; they will return false. + //------------------------------------------------------------------ bool GetFrameBaseValue(Scalar &value, Error *error_ptr); + //------------------------------------------------------------------ + /// Get the current lexical scope block for this StackFrame, if possible. + /// + /// If debug information is available for this stack frame, return a + /// pointer to the innermost lexical Block that the frame is currently + /// executing. + /// + /// @return + /// A pointer to the current Block. NULL is returned if this can + /// not be provided. + //------------------------------------------------------------------ Block * GetFrameBlock (); + //------------------------------------------------------------------ + /// Get the RegisterContext for this frame, if possible. + /// + /// Returns a shared pointer to the RegisterContext for this stack frame. + /// Only a live StackFrame object will be able to return a RegisterContext - + /// callers must be prepared for an empty shared pointer being returned. + /// + /// Even a live StackFrame RegisterContext may not be able to provide all + /// registers. Only the currently executing frame (frame 0) can reliably + /// provide every register in the register context. + /// + /// @return + /// The RegisterContext shared point for this frame. + //------------------------------------------------------------------ lldb::RegisterContextSP GetRegisterContext (); @@ -100,73 +252,237 @@ public: return m_reg_context_sp; } + //------------------------------------------------------------------ + /// Retrieve the list of variables that are in scope at this StackFrame's pc. + /// + /// A frame that is not live may return an empty VariableList for a given + /// pc value even though variables would be available at this point if + /// it were a live stack frame. + /// + /// @param[in] get_file_globals + /// Whether to also retrieve compilation-unit scoped variables + /// that are visisble to the entire compilation unit (e.g. file + /// static in C, globals that are homed in this CU). + /// + /// @return + /// A pointer to a list of variables. + //------------------------------------------------------------------ VariableList * GetVariableList (bool get_file_globals); + //------------------------------------------------------------------ + /// Retrieve the list of variables that are in scope at this StackFrame's pc. + /// + /// A frame that is not live may return an empty VariableListSP for a + /// given pc value even though variables would be available at this point + /// if it were a live stack frame. + /// + /// @param[in] get_file_globals + /// Whether to also retrieve compilation-unit scoped variables + /// that are visisble to the entire compilation unit (e.g. file + /// static in C, globals that are homed in this CU). + /// + /// @return + /// A pointer to a list of variables. + //------------------------------------------------------------------ lldb::VariableListSP GetInScopeVariableList (bool get_file_globals); - // See ExpressionPathOption enumeration for "options" values + //------------------------------------------------------------------ + /// Create a ValueObject for a variable name / pathname, possibly + /// including simple dereference/child selection syntax. + /// + /// @param[in] var_expr + /// The string specifying a variable to base the VariableObject off + /// of. + /// + /// @param[in] use_dynamic + /// Whether the correct dynamic type of an object pointer should be + /// determined before creating the object, or if the static type is + /// sufficient. One of the DynamicValueType enumerated values. + /// + /// @param[in] options + /// An unsigned integer of flags, values from StackFrame::ExpressionPathOption + /// enum. + /// @param[in] var_sp + /// A VariableSP that will be set to the variable described in the + /// var_expr path. + /// + /// @param[in] error + /// Record any errors encountered while evaluating var_expr. + /// + /// @return + /// A shared pointer to the ValueObject described by var_expr. + //------------------------------------------------------------------ lldb::ValueObjectSP - GetValueForVariableExpressionPath (const char *var_expr, - lldb::DynamicValueType use_dynamic, + GetValueForVariableExpressionPath (const char *var_expr, + lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Error &error); + //------------------------------------------------------------------ + /// Determine whether this StackFrame has debug information available or not + /// + /// @return + // true if debug information is available for this frame (function, + // compilation unit, block, etc.) + //------------------------------------------------------------------ bool HasDebugInformation (); + //------------------------------------------------------------------ + /// Return the disassembly for the instructions of this StackFrame's function + /// as a single C string. + /// + /// @return + // C string with the assembly instructions for this function. + //------------------------------------------------------------------ const char * Disassemble (); + //------------------------------------------------------------------ + /// Print a description for this frame using the frame-format formatter settings. + /// + /// @param [in] strm + /// The Stream to print the description to. + /// + /// @param [in] frame_marker + /// Optional string that will be prepended to the frame output description. + //------------------------------------------------------------------ void - DumpUsingSettingsFormat (Stream *strm); - + DumpUsingSettingsFormat (Stream *strm, const char *frame_marker = NULL); + + //------------------------------------------------------------------ + /// Print a description for this frame using a default format. + /// + /// @param [in] strm + /// The Stream to print the description to. + /// + /// @param [in] show_frame_index + /// Whether to print the frame number or not. + /// + /// @param [in] show_fullpaths + /// Whether to print the full source paths or just the file base name. + //------------------------------------------------------------------ void Dump (Stream *strm, bool show_frame_index, bool show_fullpaths); - + + //------------------------------------------------------------------ + /// Print a description of this stack frame and/or the source context/assembly + /// for this stack frame. + /// + /// @param[in] strm + /// The Stream to send the output to. + /// + /// @param[in] show_frame_info + /// If true, print the frame info by calling DumpUsingSettingsFormat(). + /// + /// @param[in] show_source + /// If true, print source or disassembly as per the user's settings. + /// + /// @param[in] frame_marker + /// Passed to DumpUsingSettingsFormat() for the frame info printing. + /// + /// @return + /// Returns true if successful. + //------------------------------------------------------------------ + bool + GetStatus (Stream &strm, + bool show_frame_info, + bool show_source, + const char *frame_marker = NULL); + + //------------------------------------------------------------------ + /// Query whether this frame is a concrete frame on the call stack, + /// or if it is an inlined frame derived from the debug information + /// and presented by the debugger. + /// + /// @return + /// true if this is an inlined frame. + //------------------------------------------------------------------ bool IsInlined (); + //------------------------------------------------------------------ + /// Query this frame to find what frame it is in this Thread's StackFrameList. + /// + /// @return + /// StackFrame index 0 indicates the currently-executing function. Inline + /// frames are included in this frame index count. + //------------------------------------------------------------------ uint32_t GetFrameIndex () const; + //------------------------------------------------------------------ + /// Query this frame to find what frame it is in this Thread's StackFrameList, + /// not counting inlined frames. + /// + /// @return + /// StackFrame index 0 indicates the currently-executing function. Inline + /// frames are not included in this frame index count; their concrete + /// frame index will be the same as the concrete frame that they are + /// derived from. + //------------------------------------------------------------------ uint32_t GetConcreteFrameIndex () const { return m_concrete_frame_index; } - + + //------------------------------------------------------------------ + /// Create a ValueObject for a given Variable in this StackFrame. + /// + /// @params [in] variable_sp + /// The Variable to base this ValueObject on + /// + /// @params [in] use_dynamic + /// Whether the correct dynamic type of the variable should be + /// determined before creating the ValueObject, or if the static type + /// is sufficient. One of the DynamicValueType enumerated values. + /// + /// @return + // A ValueObject for this variable. + //------------------------------------------------------------------ lldb::ValueObjectSP GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic); + //------------------------------------------------------------------ + /// Add an arbitrary Variable object (e.g. one that specifics a global or static) + /// to a StackFrame's list of ValueObjects. + /// + /// @params [in] variable_sp + /// The Variable to base this ValueObject on + /// + /// @params [in] use_dynamic + /// Whether the correct dynamic type of the variable should be + /// determined before creating the ValueObject, or if the static type + /// is sufficient. One of the DynamicValueType enumerated values. + /// + /// @return + // A ValueObject for this variable. + //------------------------------------------------------------------ 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 + void CalculateExecutionContext (ExecutionContext &exe_ctx); - - bool - GetStatus (Stream &strm, - bool show_frame_info, - bool show_source); - + protected: friend class StackFrameList; @@ -175,7 +491,7 @@ protected: void UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame); - + void UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame); @@ -196,6 +512,10 @@ private: Flags m_flags; Scalar m_frame_base; Error m_frame_base_error; + bool m_cfa_is_valid; // Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS + uint32_t m_stop_id; + bool m_stop_id_is_valid; // Does this frame have a stop_id? Use it when referring to the m_frame_code_addr. + bool m_is_history_frame; 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; diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h index b2689d0391e9..2680be3e5a68 100644 --- a/include/lldb/Target/StackFrameList.h +++ b/include/lldb/Target/StackFrameList.h @@ -88,7 +88,8 @@ public: uint32_t first_frame, uint32_t num_frames, bool show_frame_info, - uint32_t num_frames_with_source); + uint32_t num_frames_with_source, + const char *frame_marker = NULL); protected: diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h index 7e713c73d972..75ad8ab38903 100644 --- a/include/lldb/Target/StackID.h +++ b/include/lldb/Target/StackID.h @@ -110,13 +110,18 @@ public: protected: friend class StackFrame; - + void SetPC (lldb::addr_t pc) { m_pc = pc; } + void + SetCFA (lldb::addr_t cfa) + { + m_cfa = cfa; + } //------------------------------------------------------------------ // Classes that inherit from StackID can see and modify these diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h new file mode 100644 index 000000000000..6c0a4205d5f2 --- /dev/null +++ b/include/lldb/Target/SystemRuntime.h @@ -0,0 +1,174 @@ +//===-- SystemRuntime.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_SystemRuntime_h_ +#define liblldb_SystemRuntime_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include <vector> + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/lldb-private.h" + + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class SystemRuntime SystemRuntime.h "lldb/Target/SystemRuntime.h" +/// @brief A plug-in interface definition class for system runtimes. +/// +/// The system runtime plugins can collect information from the system +/// libraries during a Process' lifetime and provide information about +/// how objects/threads were originated. +/// +/// For instance, a system runtime plugin use a breakpoint when threads +/// are created to record the backtrace of where that thread was created. +/// Later, when backtracing the created thread, it could extend the backtrace +/// to show where it was originally created from. +/// +/// The plugin will insert its own breakpoint when Created and start collecting +/// information. Later when it comes time to augment a Thread, it can be +/// asked to provide that information. +/// +//---------------------------------------------------------------------- + +class SystemRuntime : + public PluginInterface +{ +public: + //------------------------------------------------------------------ + /// Find a system runtime plugin for a given process. + /// + /// Scans the installed SystemRuntime plugins 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 system runtime + /// plugin instance. + //------------------------------------------------------------------ + static SystemRuntime* + FindPlugin (Process *process); + + //------------------------------------------------------------------ + /// Construct with a process. + // ----------------------------------------------------------------- + SystemRuntime(lldb_private::Process *process); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~SystemRuntime(); + + //------------------------------------------------------------------ + /// Called after attaching to a process. + /// + /// Allow the SystemRuntime plugin to execute some code after attaching + /// to a process. + //------------------------------------------------------------------ + virtual void + DidAttach (); + + //------------------------------------------------------------------ + /// Called after launching a process. + /// + /// Allow the SystemRuntime plugin to execute some code after launching + /// a process. + //------------------------------------------------------------------ + virtual void + DidLaunch(); + + //------------------------------------------------------------------ + /// Called when modules have been loaded in the process. + /// + /// Allow the SystemRuntime plugin to enable logging features in the + /// system runtime libraries. + //------------------------------------------------------------------ + virtual void + ModulesDidLoad(lldb_private::ModuleList &module_list); + + + //------------------------------------------------------------------ + /// Return a list of thread origin extended backtraces that may + /// be available. + /// + /// A System Runtime may be able to provide a backtrace of when this + /// thread was originally created. Furthermore, it may be able to + /// provide that extended backtrace for different styles of creation. + /// On a system with both pthreads and libdispatch, aka Grand Central + /// Dispatch, queues, the system runtime may be able to provide the + /// pthread creation of the thread and it may also be able to provide + /// the backtrace of when this GCD queue work block was enqueued. + /// The caller may request these different origins by name. + /// + /// The names will be provided in the order that they are most likely + /// to be requested. For instance, a most natural order may be to + /// request the GCD libdispatch queue origin. If there is none, then + /// request the pthread origin. + /// + /// @return + /// A vector of ConstStrings with names like "pthread" or "libdispatch". + /// An empty vector may be returned if no thread origin extended + /// backtrace capabilities are available. + //------------------------------------------------------------------ + virtual std::vector<ConstString> + GetExtendedBacktraceTypes (); + + //------------------------------------------------------------------ + /// Return a Thread which shows the origin of this thread's creation. + /// + /// This likely returns a HistoryThread which shows how thread was + /// originally created (e.g. "pthread" type), or how the work that + /// is currently executing on it was originally enqueued (e.g. + /// "libdispatch" type). + /// + /// There may be a chain of thread-origins; it may be informative to + /// the end user to query the returned ThreadSP for its origins as + /// well. + /// + /// @param [in] thread + /// The thread to examine. + /// + /// @param [in] type + /// The type of thread origin being requested. The types supported + /// are returned from SystemRuntime::GetExtendedBacktraceTypes. + /// + /// @return + /// A ThreadSP which will have a StackList of frames. This Thread will + /// not appear in the Process' list of current threads. Normal thread + /// operations like stepping will not be available. This is a historical + /// view thread and may be only useful for showing a backtrace. + /// + /// An empty ThreadSP will be returned if no thread origin is available. + //------------------------------------------------------------------ + virtual lldb::ThreadSP + GetExtendedBacktrace (lldb::ThreadSP thread, ConstString type); + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Process *m_process; +private: + DISALLOW_COPY_AND_ASSIGN (SystemRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_SystemRuntime_h_ diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h index 87fa57b3a299..1c90ea6f15eb 100644 --- a/include/lldb/Target/Target.h +++ b/include/lldb/Target/Target.h @@ -184,11 +184,13 @@ public: static const uint32_t default_timeout = 500000; EvaluateExpressionOptions() : m_execution_policy(eExecutionPolicyOnlyWhenNeeded), + m_language (lldb::eLanguageTypeUnknown), m_coerce_to_id(false), m_unwind_on_error(true), m_ignore_breakpoints (false), m_keep_in_memory(false), m_run_others(true), + m_debug(false), m_use_dynamic(lldb::eNoDynamicValues), m_timeout_usec(default_timeout) {} @@ -206,6 +208,19 @@ public: return *this; } + lldb::LanguageType + GetLanguage() const + { + return m_language; + } + + EvaluateExpressionOptions& + SetLanguage(lldb::LanguageType language) + { + m_language = language; + return *this; + } + bool DoesCoerceToId () const { @@ -297,13 +312,28 @@ public: return *this; } + bool + GetDebug() const + { + return m_debug; + } + + EvaluateExpressionOptions& + SetDebug(bool b) + { + m_debug = b; + return *this; + } + private: ExecutionPolicy m_execution_policy; + lldb::LanguageType m_language; bool m_coerce_to_id; bool m_unwind_on_error; bool m_ignore_breakpoints; bool m_keep_in_memory; bool m_run_others; + bool m_debug; lldb::DynamicValueType m_use_dynamic; uint32_t m_timeout_usec; }; @@ -503,26 +533,30 @@ public: CreateBreakpoint (const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, - LazyBool check_inlines = eLazyBoolCalculate, - LazyBool skip_prologue = eLazyBoolCalculate, - bool internal = false); + LazyBool check_inlines, + LazyBool skip_prologue, + bool internal, + bool request_hardware); // 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); + bool internal, + bool request_hardware); // Use this to create a breakpoint from a load address lldb::BreakpointSP CreateBreakpoint (lldb::addr_t load_addr, - bool internal = false); + bool internal, + bool request_hardware); // Use this to create Address breakpoints: lldb::BreakpointSP CreateBreakpoint (Address &addr, - bool internal = false); + bool internal, + bool request_hardware); // 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 @@ -531,8 +565,9 @@ public: CreateFuncRegexBreakpoint (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles, RegularExpression &func_regexp, - LazyBool skip_prologue = eLazyBoolCalculate, - bool internal = false); + LazyBool skip_prologue, + bool internal, + bool request_hardware); // 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 @@ -542,11 +577,12 @@ public: const FileSpecList *containingSourceFiles, const char *func_name, uint32_t func_name_type_mask, - LazyBool skip_prologue = eLazyBoolCalculate, - bool internal = false); + LazyBool skip_prologue, + bool internal, + bool request_hardware); lldb::BreakpointSP - CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal = false); + CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal); // 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 @@ -557,23 +593,26 @@ public: const char *func_names[], size_t num_names, uint32_t func_name_type_mask, - LazyBool skip_prologue = eLazyBoolCalculate, - bool internal = false); + LazyBool skip_prologue, + bool internal, + bool request_hardware); 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); + LazyBool skip_prologue, + bool internal, + bool request_hardware); // Use this to create a general breakpoint: lldb::BreakpointSP CreateBreakpoint (lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp, - bool internal = false); + bool internal, + bool request_hardware); // Use this to create a watchpoint: lldb::WatchpointSP @@ -696,11 +735,14 @@ public: ModulesDidLoad (ModuleList &module_list); void - ModulesDidUnload (ModuleList &module_list); + ModulesDidUnload (ModuleList &module_list, bool delete_locations); void SymbolsDidLoad (ModuleList &module_list); + void + ClearModules(); + //------------------------------------------------------------------ /// Gets the module for the main executable. /// @@ -1095,21 +1137,7 @@ public: { 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); // diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index e4e532e4b331..7dac37caa200 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -339,6 +339,12 @@ public: return NULL; } + virtual lldb::queue_id_t + GetQueueID () + { + return LLDB_INVALID_QUEUE_ID; + } + virtual const char * GetQueueName () { @@ -377,7 +383,10 @@ public: Error ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false); - + + Error + JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = NULL); + virtual lldb::StackFrameSP GetFrameWithStackID (const StackID &stack_id) { @@ -452,6 +461,33 @@ public: DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); //------------------------------------------------------------------ + /// Retrieves the per-thread data area. + /// Most OSs maintain a per-thread pointer (e.g. the FS register on + /// x64), which we return the value of here. + /// + /// @return + /// LLDB_INVALID_ADDRESS if not supported, otherwise the thread + /// pointer value. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetThreadPointer (); + + //------------------------------------------------------------------ + /// Retrieves the per-module TLS block for a thread. + /// + /// @param[in] module + /// The module to query TLS data for. + /// + /// @return + /// If the thread has TLS data allocated for the + /// module, the address of the TLS block. Otherwise + /// LLDB_INVALID_ADDRESS is returned. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetThreadLocalData (const lldb::ModuleSP module); + + + //------------------------------------------------------------------ // 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 diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h index d747706c6393..7b8efb60b880 100644 --- a/include/lldb/Target/ThreadPlanCallFunction.h +++ b/include/lldb/Target/ThreadPlanCallFunction.h @@ -136,7 +136,13 @@ public: virtual bool RestoreThreadState(); - + + virtual void + ThreadDestroyed () + { + m_takedown_done = true; + } + protected: void ReportRegisterState (const char *message); diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h index de9e66829dc7..2cb5288272ea 100644 --- a/include/lldb/Target/ThreadPlanStepOverRange.h +++ b/include/lldb/Target/ThreadPlanStepOverRange.h @@ -41,6 +41,8 @@ protected: private: + bool IsEquivalentContext(const SymbolContext &context); + bool m_first_resume; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange); diff --git a/include/lldb/Utility/RefCounter.h b/include/lldb/Utility/RefCounter.h deleted file mode 100644 index 6daed5498eb8..000000000000 --- a/include/lldb/Utility/RefCounter.h +++ /dev/null @@ -1,56 +0,0 @@ -//===-- 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/SharingPtr.h b/include/lldb/Utility/SharingPtr.h index 814b54b5cfe6..c451ee6e3593 100644 --- a/include/lldb/Utility/SharingPtr.h +++ b/include/lldb/Utility/SharingPtr.h @@ -13,6 +13,15 @@ #include <algorithm> #include <memory> +// Microsoft Visual C++ currently does not enable std::atomic to work +// in CLR mode - as such we need to "hack around it" for MSVC++ builds only +// using Windows specific instrinsics instead of the C++11 atomic support +#ifdef _MSC_VER +#include <intrin.h> +#else +#include <atomic> +#endif + //#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT #if defined (ENABLE_SP_LOGGING) @@ -24,27 +33,17 @@ 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: +#ifdef _MSC_VER long shared_owners_; +#else + std::atomic<long> shared_owners_; +#endif virtual ~shared_count(); private: virtual void on_zero_shared() = 0; @@ -592,14 +591,22 @@ private: void lldb_private::ReferenceCountedBase<T>::add_shared() { - imp::increment(shared_owners_); +#ifdef _MSC_VER + _InterlockedIncrement(&shared_owners_); +#else + ++shared_owners_; +#endif } template <class T> void lldb_private::ReferenceCountedBase<T>::release_shared() { - if (imp::decrement(shared_owners_) == -1) +#ifdef _MSC_VER + if (_InterlockedDecrement(&shared_owners_) == -1) +#else + if (--shared_owners_ == -1) +#endif delete static_cast<T*>(this); } @@ -713,7 +720,7 @@ public: return ptr_; } - operator bool() const + explicit operator bool() const { return ptr_ != 0; } diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h index 3318aa15f5ac..82307d2f5310 100644 --- a/include/lldb/lldb-defines.h +++ b/include/lldb/lldb-defines.h @@ -33,6 +33,7 @@ // LLDB defines //---------------------------------------------------------------------- #define LLDB_GENERIC_ERROR UINT32_MAX +#define LLDB_DEFAULT_SHELL "/bin/sh" //---------------------------------------------------------------------- // Breakpoints @@ -81,6 +82,8 @@ #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 +#define LLDB_INVALID_LINE_NUMBER UINT32_MAX +#define LLDB_INVALID_QUEUE_ID 0 //---------------------------------------------------------------------- /// CPU Type defintions @@ -109,6 +112,15 @@ #define LLDB_OPT_SET_10 (1U << 9) #define LLDB_OPT_SET_FROM_TO(A, B) (((1U << (B)) - 1) ^ (((1U << (A))-1) >> 1)) +#ifdef _WIN32 +#define MAX_PATH 260 +#endif + +#ifdef _MSC_VER +// ignore GCC function attributes +#define __attribute__(X) +#endif + #if defined(__cplusplus) //---------------------------------------------------------------------- diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h index 6ec5ed6a35e2..ae8c92be900b 100644 --- a/include/lldb/lldb-enumerations.h +++ b/include/lldb/lldb-enumerations.h @@ -380,6 +380,7 @@ namespace lldb { eArgTypeClassName, eArgTypeCommandName, eArgTypeCount, + eArgTypeDescriptionVerbosity, eArgTypeDirectoryName, eArgTypeDisassemblyFlavor, eArgTypeEndAddress, @@ -406,6 +407,9 @@ namespace lldb { eArgTypeOffset, eArgTypeOldPathPrefix, eArgTypeOneLiner, + eArgTypePath, + eArgTypePermissionsNumber, + eArgTypePermissionsString, eArgTypePid, eArgTypePlugin, eArgTypeProcessName, @@ -480,7 +484,8 @@ namespace lldb { eSymbolTypeUndefined, eSymbolTypeObjCClass, eSymbolTypeObjCMetaClass, - eSymbolTypeObjCIVar + eSymbolTypeObjCIVar, + eSymbolTypeReExported } SymbolType; typedef enum SectionType diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h index 84af8b646901..cd8a5c2e8130 100644 --- a/include/lldb/lldb-forward.h +++ b/include/lldb/lldb-forward.h @@ -79,6 +79,7 @@ class DataExtractor; class Debugger; class Declaration; class Disassembler; +struct DumpValueObjectOptions; class DynamicLibrary; class DynamicLoader; class EmulateInstruction; @@ -90,6 +91,7 @@ class ExecutionContext; class ExecutionContextRef; class ExecutionContextRefLocker; class ExecutionContextScope; +class File; class FileSpec; class FileSpecList; class Flags; @@ -104,6 +106,7 @@ class Instruction; class InstructionList; class IRExecutionUnit; class LanguageRuntime; +class SystemRuntime; class LineTable; class Listener; class Log; @@ -119,6 +122,7 @@ struct NameSearchContext; class ObjCLanguageRuntime; class ObjectContainer; class OptionGroup; +class OptionGroupOptions; class OptionGroupPlatform; class ObjectFile; class OperatingSystem; @@ -224,13 +228,14 @@ class ThreadPlanTracer; class ThreadSpec; class TimeValue; class Type; +class TypeAndOrName; class TypeCategoryMap; class TypeImpl; -class TypeAndOrName; class TypeList; class TypeListImpl; class TypeMemberImpl; class TypeNameSpecifierImpl; +class TypePair; class UUID; class Unwind; class UnwindAssembly; @@ -246,6 +251,7 @@ class ValueObjectConstResult; class ValueObjectConstResultChild; class ValueObjectConstResultImpl; class ValueObjectList; +class ValueObjectPrinter; class Variable; class VariableList; class Watchpoint; @@ -285,12 +291,14 @@ namespace lldb { 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::File> FileSP; 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::SystemRuntime> SystemRuntimeSP; typedef std::shared_ptr<lldb_private::LineTable> LineTableSP; typedef std::shared_ptr<lldb_private::Listener> ListenerSP; typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP; diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h index 60c90907145f..e523b912eac6 100644 --- a/include/lldb/lldb-private-enumerations.h +++ b/include/lldb/lldb-private-enumerations.h @@ -51,6 +51,7 @@ typedef enum ArchitectureType eArchTypeInvalid, eArchTypeMachO, eArchTypeELF, + eArchTypeCOFF, kNumArchTypes } ArchitectureType; @@ -191,7 +192,9 @@ typedef enum FormatCategoryItem eFormatCategoryItemFilter = 0x0004, eFormatCategoryItemRegexFilter = 0x0008, eFormatCategoryItemSynth = 0x0010, - eFormatCategoryItemRegexSynth = 0x0020 + eFormatCategoryItemRegexSynth = 0x0020, + eFormatCategoryItemValue = 0x0040, + eFormatCategoryItemRegexValue = 0x0080 } FormatCategoryItem; //------------------------------------------------------------------ @@ -228,6 +231,14 @@ typedef enum ScriptedCommandSynchronicity eScriptedCommandSynchronicityCurrentValue // use whatever the current synchronicity is } ScriptedCommandSynchronicity; +//---------------------------------------------------------------------- +// Verbosity mode of "po" output +//---------------------------------------------------------------------- +typedef enum LanguageRuntimeDescriptionDisplayVerbosity +{ + eLanguageRuntimeDescriptionDisplayVerbosityCompact, // only print the description string, if any + eLanguageRuntimeDescriptionDisplayVerbosityFull, // print the full-blown output +} LanguageRuntimeDescriptionDisplayVerbosity; //---------------------------------------------------------------------- // Loading modules from memory diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h index 949cafed98b3..5a2da8989f35 100644 --- a/include/lldb/lldb-private-interfaces.h +++ b/include/lldb/lldb-private-interfaces.h @@ -27,6 +27,7 @@ namespace lldb_private 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 SystemRuntime *(*SystemRuntimeCreateInstance) (Process *process); 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); diff --git a/include/lldb/lldb-private-log.h b/include/lldb/lldb-private-log.h index 31a1c23c5e67..48cce69d36cc 100644 --- a/include/lldb/lldb-private-log.h +++ b/include/lldb/lldb-private-log.h @@ -44,6 +44,7 @@ #define LIBLLDB_LOG_TARGET (1u << 22) #define LIBLLDB_LOG_MMAP (1u << 23) #define LIBLLDB_LOG_OS (1u << 24) +#define LIBLLDB_LOG_PLATFORM (1u << 25) #define LIBLLDB_LOG_ALL (UINT32_MAX) #define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\ LIBLLDB_LOG_THREAD |\ diff --git a/include/lldb/lldb-private.h b/include/lldb/lldb-private.h index 90590601d945..05b2c4fd6381 100644 --- a/include/lldb/lldb-private.h +++ b/include/lldb/lldb-private.h @@ -12,6 +12,10 @@ #if defined(__cplusplus) +#ifdef _WIN32 +#include "lldb/Host/windows/win32.h" +#endif + #include "lldb/lldb-public.h" #include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-private-interfaces.h" diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h index 2693c0c822bb..5851b5d3f923 100644 --- a/include/lldb/lldb-types.h +++ b/include/lldb/lldb-types.h @@ -14,11 +14,8 @@ #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: @@ -38,13 +35,42 @@ // things should be defined. Currently MacOSX is being assumed by default // since that is what lldb was first developed for. +#ifndef _MSC_VER +#include <stdbool.h> +#include <unistd.h> +#endif + +#ifdef _WIN32 + +#include <process.h> + +namespace lldb +{ + typedef void* mutex_t; + typedef void* condition_t; + typedef void* rwlock_t; + typedef uintptr_t thread_t; // Host thread type + typedef uint32_t thread_key_t; + typedef void * thread_arg_t; // Host thread argument type + typedef unsigned thread_result_t; // Host thread result type + typedef thread_result_t (*thread_func_t)(void *); // Host thread function type + typedef void (*LogOutputCallback) (const char *, void *baton); + typedef bool (*CommandOverrideCallback)(void *baton, const char **argv); +} + +#else + +#include <pthread.h> + namespace lldb { //---------------------------------------------------------------------- // MacOSX Types //---------------------------------------------------------------------- typedef ::pthread_mutex_t mutex_t; typedef pthread_cond_t condition_t; + typedef pthread_rwlock_t rwlock_t; typedef pthread_t thread_t; // Host thread type + typedef pthread_key_t thread_key_t; 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 @@ -52,19 +78,11 @@ namespace lldb { 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 +#endif #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 @@ -77,6 +95,7 @@ namespace lldb typedef int32_t break_id_t; typedef int32_t watch_id_t; typedef void * clang_type_t; + typedef uint64_t queue_id_t; } diff --git a/include/lldb/lldb-versioning.h b/include/lldb/lldb-versioning.h index 8ccc67d8e9c0..d0498a569f58 100644 --- a/include/lldb/lldb-versioning.h +++ b/include/lldb/lldb-versioning.h @@ -1604,4 +1604,4 @@ #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 +#endif // LLDB_lldb_versioning_h_ diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp index 0c839004601c..ac77e2e41126 100644 --- a/source/API/SBCommandInterpreter.cpp +++ b/source/API/SBCommandInterpreter.cpp @@ -384,15 +384,103 @@ SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, extern "C" void init_lldb(void); -#else +// these are the Pythonic implementations of the required callbacks +// these are scripting-language specific, which is why they belong here +// we still need to use function pointers to them instead of relying +// on linkage-time resolution because the SWIG stuff and this file +// get built at different times +extern "C" bool +LLDBSwigPythonBreakpointCallbackFunction (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& sb_frame, + const lldb::BreakpointLocationSP& sb_bp_loc); + +extern "C" bool +LLDBSwigPythonWatchpointCallbackFunction (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& sb_frame, + const lldb::WatchpointSP& sb_wp); + +extern "C" bool +LLDBSwigPythonCallTypeScript (const char *python_function_name, + void *session_dictionary, + const lldb::ValueObjectSP& valobj_sp, + void** pyfunct_wrapper, + std::string& retval); + +extern "C" void* +LLDBSwigPythonCreateSyntheticProvider (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + + +extern "C" uint32_t +LLDBSwigPython_CalculateNumChildren (void *implementor); + +extern "C" void * +LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); + +extern "C" int +LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); + +extern "C" void * +LLDBSWIGPython_CastPyObjectToSBValue (void* data); + +extern lldb::ValueObjectSP +LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data); + +extern "C" bool +LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); + +extern "C" bool +LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor); + +extern "C" bool +LLDBSwigPythonCallCommand (const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject &cmd_retobj); + +extern "C" bool +LLDBSwigPythonCallModuleInit (const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger); + +extern "C" void* +LLDBSWIGPythonCreateOSPlugin (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP& process_sp); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordProcess (const char* python_function_name, + const char* session_dictionary_name, + lldb::ProcessSP& process, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordThread (const char* python_function_name, + const char* session_dictionary_name, + lldb::ThreadSP& thread, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordTarget (const char* python_function_name, + const char* session_dictionary_name, + lldb::TargetSP& target, + std::string& output); + +extern "C" bool +LLDBSWIGPythonRunScriptKeywordFrame (const char* python_function_name, + const char* session_dictionary_name, + lldb::StackFrameSP& frame, + std::string& output); + +extern "C" void* +LLDBSWIGPython_GetDynamicSetting (void* module, + const char* setting, + const lldb::TargetSP& target_sp); -extern "C" void init_lldb(void); - -// Usually defined in the SWIG source file, but we have sripting disabled -extern "C" void -init_lldb(void) -{ -} #endif @@ -404,7 +492,26 @@ SBCommandInterpreter::InitializeSWIG () { g_initialized = true; #ifndef LLDB_DISABLE_PYTHON - ScriptInterpreter::InitializeInterpreter (init_lldb); + ScriptInterpreter::InitializeInterpreter (init_lldb, + LLDBSwigPythonBreakpointCallbackFunction, + LLDBSwigPythonWatchpointCallbackFunction, + LLDBSwigPythonCallTypeScript, + LLDBSwigPythonCreateSyntheticProvider, + LLDBSwigPython_CalculateNumChildren, + LLDBSwigPython_GetChildAtIndex, + LLDBSwigPython_GetIndexOfChildWithName, + LLDBSWIGPython_CastPyObjectToSBValue, + LLDBSWIGPython_GetValueObjectSPFromSBValue, + LLDBSwigPython_UpdateSynthProviderInstance, + LLDBSwigPython_MightHaveChildrenSynthProviderInstance, + LLDBSwigPythonCallCommand, + LLDBSwigPythonCallModuleInit, + LLDBSWIGPythonCreateOSPlugin, + LLDBSWIGPythonRunScriptKeywordProcess, + LLDBSWIGPythonRunScriptKeywordThread, + LLDBSWIGPythonRunScriptKeywordTarget, + LLDBSWIGPythonRunScriptKeywordFrame, + LLDBSWIGPython_GetDynamicSetting); #endif } } diff --git a/source/API/SBData.cpp b/source/API/SBData.cpp index 5b2f075158b8..06dcfc12af41 100644 --- a/source/API/SBData.cpp +++ b/source/API/SBData.cpp @@ -122,7 +122,7 @@ SBData::GetByteSize () value = m_opaque_sp->GetByteSize(); if (log) log->Printf ("SBData::GetByteSize () => " - "(%lu)", value); + "(%zu)", value); return value; } @@ -479,7 +479,7 @@ SBData::ReadRawData (lldb::SBError& error, error.SetErrorString("unable to read data"); } if (log) - log->Printf ("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%lu) => " + log->Printf ("SBData::ReadRawData (error=%p,offset=%" PRIu64 ",buf=%p,size=%zu) => " "(%p)", error.get(), offset, buf, size, ok); return ok ? size : 0; } @@ -497,7 +497,7 @@ SBData::SetData (lldb::SBError& error, else m_opaque_sp->SetData(buf, size, endian); if (log) - log->Printf ("SBData::SetData (error=%p,buf=%p,size=%lu,endian=%d,addr_size=%c) => " + log->Printf ("SBData::SetData (error=%p,buf=%p,size=%zu,endian=%d,addr_size=%c) => " "(%p)", error.get(), buf, size, endian, addr_size, m_opaque_sp.get()); } @@ -647,7 +647,7 @@ SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len) if (!array || array_len == 0) { if (log) - log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => " "false", array, array_len); return false; } @@ -662,7 +662,7 @@ SBData::SetDataFromUInt64Array (uint64_t* array, size_t array_len) m_opaque_sp->SetData(buffer_sp); if (log) - log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromUInt64Array (array=%p, array_len = %zu) => " "true", array, array_len); return true; @@ -676,7 +676,7 @@ SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len) if (!array || array_len == 0) { if (log) - log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => " "false", array, array_len); return false; } @@ -691,7 +691,7 @@ SBData::SetDataFromUInt32Array (uint32_t* array, size_t array_len) m_opaque_sp->SetData(buffer_sp); if (log) - log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromUInt32Array (array=%p, array_len = %zu) => " "true", array, array_len); return true; @@ -705,7 +705,7 @@ SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len) if (!array || array_len == 0) { if (log) - log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => " "false", array, array_len); return false; } @@ -720,7 +720,7 @@ SBData::SetDataFromSInt64Array (int64_t* array, size_t array_len) m_opaque_sp->SetData(buffer_sp); if (log) - log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromSInt64Array (array=%p, array_len = %zu) => " "true", array, array_len); return true; @@ -734,7 +734,7 @@ SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len) if (!array || array_len == 0) { if (log) - log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => " "false", array, array_len); return false; } @@ -749,7 +749,7 @@ SBData::SetDataFromSInt32Array (int32_t* array, size_t array_len) m_opaque_sp->SetData(buffer_sp); if (log) - log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromSInt32Array (array=%p, array_len = %zu) => " "true", array, array_len); return true; @@ -763,7 +763,7 @@ SBData::SetDataFromDoubleArray (double* array, size_t array_len) if (!array || array_len == 0) { if (log) - log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => " "false", array, array_len); return false; } @@ -778,7 +778,7 @@ SBData::SetDataFromDoubleArray (double* array, size_t array_len) m_opaque_sp->SetData(buffer_sp); if (log) - log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %lu) => " + log->Printf ("SBData::SetDataFromDoubleArray (array=%p, array_len = %zu) => " "true", array, array_len); return true; diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp index f5e71d5f1a07..88c991b72054 100644 --- a/source/API/SBDebugger.cpp +++ b/source/API/SBDebugger.cpp @@ -480,7 +480,7 @@ SBDebugger::GetScriptingLanguage (const char *script_language_name) const char * SBDebugger::GetVersionString () { - return GetVersion(); + return lldb_private::GetVersion(); } const char * @@ -711,7 +711,7 @@ SBDebugger::GetIndexOfTarget (lldb::SBTarget target) } SBTarget -SBDebugger::FindTargetWithProcessID (pid_t pid) +SBDebugger::FindTargetWithProcessID (lldb::pid_t pid) { SBTarget sb_target; if (m_opaque_sp) diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp index 4413689501a8..fc207d071dbc 100644 --- a/source/API/SBFileSpec.cpp +++ b/source/API/SBFileSpec.cpp @@ -61,7 +61,7 @@ SBFileSpec::operator = (const SBFileSpec &rhs) bool SBFileSpec::IsValid() const { - return *m_opaque_ap; + return m_opaque_ap->operator bool(); } bool diff --git a/source/API/SBFunction.cpp b/source/API/SBFunction.cpp index 914d2d77f3ec..bb7ea2e9f202 100644 --- a/source/API/SBFunction.cpp +++ b/source/API/SBFunction.cpp @@ -143,11 +143,13 @@ SBFunction::GetInstructions (SBTarget target, const char *flavor) ModuleSP module_sp (m_opaque_ptr->GetAddressRange().GetBaseAddress().GetModule()); if (module_sp) { + const bool prefer_file_cache = false; sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture(), NULL, flavor, exe_ctx, - m_opaque_ptr->GetAddressRange())); + m_opaque_ptr->GetAddressRange(), + prefer_file_cache)); } } return sb_instructions; diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp index a8f7db90a150..166403103ad5 100644 --- a/source/API/SBHostOS.cpp +++ b/source/API/SBHostOS.cpp @@ -42,7 +42,7 @@ lldb::thread_t SBHostOS::ThreadCreate ( const char *name, - void *(*thread_function)(void *), + thread_func_t thread_function, void *thread_arg, SBError *error_ptr ) @@ -77,7 +77,7 @@ SBHostOS::ThreadDetach (lldb::thread_t thread, SBError *error_ptr) } bool -SBHostOS::ThreadJoin (lldb::thread_t thread, void **result, SBError *error_ptr) +SBHostOS::ThreadJoin (lldb::thread_t thread, thread_result_t *result, SBError *error_ptr) { return Host::ThreadJoin (thread, result, error_ptr ? error_ptr->get() : NULL); } diff --git a/source/API/SBModuleSpec.cpp b/source/API/SBModuleSpec.cpp index 654a8ca6ec86..17c83abb4f24 100644 --- a/source/API/SBModuleSpec.cpp +++ b/source/API/SBModuleSpec.cpp @@ -44,7 +44,7 @@ SBModuleSpec::~SBModuleSpec () bool SBModuleSpec::IsValid () const { - return *m_opaque_ap; + return m_opaque_ap->operator bool(); } void diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp index 259eb5e97034..d690da7eed87 100644 --- a/source/API/SBProcess.cpp +++ b/source/API/SBProcess.cpp @@ -11,6 +11,9 @@ #include "lldb/API/SBProcess.h" +// C Includes +#include <inttypes.h> + #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" @@ -23,6 +26,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" @@ -334,7 +338,7 @@ SBProcess::PutSTDIN (const char *src, size_t src_len) } if (log) - log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %lu", + log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %zu", process_sp.get(), src, (uint32_t) src_len, @@ -1254,3 +1258,37 @@ SBProcess::UnloadImage (uint32_t image_token) sb_error.SetErrorString("invalid process"); return sb_error; } + +uint32_t +SBProcess::GetNumExtendedBacktraceTypes () +{ + ProcessSP process_sp(GetSP()); + if (process_sp && process_sp->GetSystemRuntime()) + { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + return runtime->GetExtendedBacktraceTypes().size(); + } + return 0; +} + +const char * +SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx) +{ + ProcessSP process_sp(GetSP()); + if (process_sp && process_sp->GetSystemRuntime()) + { + SystemRuntime *runtime = process_sp->GetSystemRuntime(); + std::vector<ConstString> names = runtime->GetExtendedBacktraceTypes(); + if (idx < names.size()) + { + return names[idx].AsCString(); + } + else + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => error: requested extended backtrace name out of bounds", process_sp.get()); + } + } + return NULL; +} diff --git a/source/API/SBSymbol.cpp b/source/API/SBSymbol.cpp index dd057e81a559..ef3d0764c963 100644 --- a/source/API/SBSymbol.cpp +++ b/source/API/SBSymbol.cpp @@ -139,11 +139,13 @@ SBSymbol::GetInstructions (SBTarget target, const char *flavor_string) if (module_sp) { AddressRange symbol_range (m_opaque_ptr->GetAddress(), m_opaque_ptr->GetByteSize()); + const bool prefer_file_cache = false; sb_instructions.SetDisassembler (Disassembler::DisassembleRange (module_sp->GetArchitecture (), NULL, flavor_string, exe_ctx, - symbol_range)); + symbol_range, + prefer_file_cache)); } } } diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp index f37c8f8a614b..cff6e4e2de36 100644 --- a/source/API/SBTarget.cpp +++ b/source/API/SBTarget.cpp @@ -41,6 +41,7 @@ #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Section.h" #include "lldb/Core/STLUtils.h" +#include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectList.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Host/FileSpec.h" @@ -1260,7 +1261,8 @@ SBTarget::ResolveLoadAddress (lldb::addr_t vm_addr) } SBSymbolContext -SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolve_scope) +SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, + uint32_t resolve_scope) { SBSymbolContext sc; if (addr.IsValid()) @@ -1274,13 +1276,15 @@ SBTarget::ResolveSymbolContextForAddress (const SBAddress& addr, uint32_t resolv SBBreakpoint -SBTarget::BreakpointCreateByLocation (const char *file, uint32_t line) +SBTarget::BreakpointCreateByLocation (const char *file, + uint32_t line) { return SBBreakpoint(BreakpointCreateByLocation (SBFileSpec (file, false), line)); } SBBreakpoint -SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t line) +SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, + uint32_t line) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1293,7 +1297,8 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t l const LazyBool check_inlines = eLazyBoolCalculate; const LazyBool skip_prologue = eLazyBoolCalculate; const bool internal = false; - *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal); + const bool hardware = false; + *sb_bp = target_sp->CreateBreakpoint (NULL, *sb_file_spec, line, check_inlines, skip_prologue, internal, hardware); } if (log) @@ -1314,7 +1319,8 @@ SBTarget::BreakpointCreateByLocation (const SBFileSpec &sb_file_spec, uint32_t l } SBBreakpoint -SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_name) +SBTarget::BreakpointCreateByName (const char *symbol_name, + const char *module_name) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1325,16 +1331,17 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na Mutex::Locker api_locker (target_sp->GetAPIMutex()); const bool internal = false; + const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; if (module_name && module_name[0]) { FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal); + *sb_bp = target_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware); } else { - *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal); + *sb_bp = target_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, skip_prologue, internal, hardware); } } @@ -1349,8 +1356,8 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na lldb::SBBreakpoint SBTarget::BreakpointCreateByName (const char *symbol_name, - const SBFileSpecList &module_list, - const SBFileSpecList &comp_unit_list) + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { uint32_t name_type_mask = eFunctionNameTypeAuto; return BreakpointCreateByName (symbol_name, name_type_mask, module_list, comp_unit_list); @@ -1358,9 +1365,9 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, lldb::SBBreakpoint SBTarget::BreakpointCreateByName (const char *symbol_name, - uint32_t name_type_mask, - const SBFileSpecList &module_list, - const SBFileSpecList &comp_unit_list) + uint32_t name_type_mask, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1369,14 +1376,16 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, if (target_sp && symbol_name && symbol_name[0]) { const bool internal = false; + const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; Mutex::Locker api_locker (target_sp->GetAPIMutex()); *sb_bp = target_sp->CreateBreakpoint (module_list.get(), - comp_unit_list.get(), - symbol_name, - name_type_mask, - skip_prologue, - internal); + comp_unit_list.get(), + symbol_name, + name_type_mask, + skip_prologue, + internal, + hardware); } if (log) @@ -1403,6 +1412,7 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], { Mutex::Locker api_locker (target_sp->GetAPIMutex()); const bool internal = false; + const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; *sb_bp = target_sp->CreateBreakpoint (module_list.get(), comp_unit_list.get(), @@ -1410,7 +1420,8 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], num_names, name_type_mask, skip_prologue, - internal); + internal, + hardware); } if (log) @@ -1436,7 +1447,8 @@ SBTarget::BreakpointCreateByNames (const char *symbol_names[], } SBBreakpoint -SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name) +SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, + const char *module_name) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1447,6 +1459,7 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo Mutex::Locker api_locker (target_sp->GetAPIMutex()); RegularExpression regexp(symbol_name_regex); const bool internal = false; + const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; if (module_name && module_name[0]) @@ -1454,11 +1467,11 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal); + *sb_bp = target_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, skip_prologue, internal, hardware); } else { - *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal); + *sb_bp = target_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, skip_prologue, internal, hardware); } } @@ -1473,8 +1486,8 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo lldb::SBBreakpoint SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, - const SBFileSpecList &module_list, - const SBFileSpecList &comp_unit_list) + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1485,9 +1498,10 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, Mutex::Locker api_locker (target_sp->GetAPIMutex()); RegularExpression regexp(symbol_name_regex); const bool internal = false; + const bool hardware = false; const LazyBool skip_prologue = eLazyBoolCalculate; - *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal); + *sb_bp = target_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, skip_prologue, internal, hardware); } if (log) @@ -1509,7 +1523,8 @@ SBTarget::BreakpointCreateByAddress (addr_t address) if (target_sp) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); - *sb_bp = target_sp->CreateBreakpoint (address, false); + const bool hardware = false; + *sb_bp = target_sp->CreateBreakpoint (address, false, hardware); } if (log) @@ -1521,7 +1536,9 @@ SBTarget::BreakpointCreateByAddress (addr_t address) } lldb::SBBreakpoint -SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name) +SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, + const lldb::SBFileSpec &source_file, + const char *module_name) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1532,6 +1549,7 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S Mutex::Locker api_locker (target_sp->GetAPIMutex()); RegularExpression regexp(source_regex); FileSpecList source_file_spec_list; + const bool hardware = false; source_file_spec_list.Append (source_file.ref()); if (module_name && module_name[0]) @@ -1539,11 +1557,11 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false, hardware); } else { - *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false, hardware); } } @@ -1560,8 +1578,8 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S lldb::SBBreakpoint SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, - const SBFileSpecList &module_list, - const lldb::SBFileSpecList &source_file_list) + const SBFileSpecList &module_list, + const lldb::SBFileSpecList &source_file_list) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1570,8 +1588,9 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, if (target_sp && source_regex && source_regex[0]) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); + const bool hardware = false; RegularExpression regexp(source_regex); - *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false); + *sb_bp = target_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false, hardware); } if (log) @@ -1585,8 +1604,8 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, lldb::SBBreakpoint SBTarget::BreakpointCreateForException (lldb::LanguageType language, - bool catch_bp, - bool throw_bp) + bool catch_bp, + bool throw_bp) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -1595,7 +1614,8 @@ SBTarget::BreakpointCreateForException (lldb::LanguageType language, if (target_sp) { Mutex::Locker api_locker (target_sp->GetAPIMutex()); - *sb_bp = target_sp->CreateExceptionBreakpoint (language, catch_bp, throw_bp); + const bool hardware = false; + *sb_bp = target_sp->CreateExceptionBreakpoint (language, catch_bp, throw_bp, hardware); } if (log) @@ -1862,6 +1882,50 @@ SBTarget::DisableAllWatchpoints () return false; } +SBValue +SBTarget::CreateValueFromAddress (const char *name, SBAddress addr, SBType type) +{ + SBValue sb_value; + lldb::ValueObjectSP new_value_sp; + if (IsValid() && name && *name && addr.IsValid() && type.IsValid()) + { + lldb::addr_t address(addr.GetLoadAddress(*this)); + lldb::TypeImplSP type_impl_sp (type.GetSP()); + ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(true).GetPointerType ()); + if (pointer_ast_type) + { + lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); + + ExecutionContext exe_ctx (ExecutionContextRef(ExecutionContext(m_opaque_sp.get(),false))); + ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), + pointer_ast_type, + ConstString(name), + buffer, + exe_ctx.GetByteOrder(), + exe_ctx.GetAddressByteSize())); + + if (ptr_result_valobj_sp) + { + ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); + Error err; + new_value_sp = ptr_result_valobj_sp->Dereference(err); + if (new_value_sp) + new_value_sp->SetName(ConstString(name)); + } + } + } + sb_value.SetSP(new_value_sp); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + { + if (new_value_sp) + log->Printf ("SBTarget(%p)::CreateValueFromAddress => \"%s\"", m_opaque_sp.get(), new_value_sp->GetName().AsCString()); + else + log->Printf ("SBTarget(%p)::CreateValueFromAddress => NULL", m_opaque_sp.get()); + } + return sb_value; +} + bool SBTarget::DeleteAllWatchpoints () { @@ -1905,6 +1969,8 @@ SBTarget::AddModule (const char *path, if (triple) module_spec.GetArchitecture().SetTriple (triple, target_sp->GetPlatform ().get()); + else + module_spec.GetArchitecture() = target_sp->GetArchitecture(); if (symfile) module_spec.GetSymbolFileSpec ().SetFile(symfile, false); diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index 2752620c9baf..4b54b1c0c1c6 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Thread.h" #include "lldb/Target/Process.h" #include "lldb/Symbol/SymbolContext.h" @@ -507,6 +508,34 @@ SBThread::GetQueueName () const return name; } +lldb::queue_id_t +SBThread::GetQueueID () const +{ + queue_id_t id = LLDB_INVALID_QUEUE_ID; + Mutex::Locker api_locker; + ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (exe_ctx.HasThreadScope()) + { + Process::StopLocker stop_locker; + if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) + { + id = exe_ctx.GetThreadPtr()->GetQueueID(); + } + else + { + if (log) + log->Printf ("SBThread(%p)::GetQueueID() => error: process is running", exe_ctx.GetThreadPtr()); + } + } + + if (log) + log->Printf ("SBThread(%p)::GetQueueID () => 0x%" PRIx64, exe_ctx.GetThreadPtr(), id); + + return id; +} + SBError SBThread::ResumeNewPlan (ExecutionContext &exe_ctx, ThreadPlan *new_plan) { @@ -910,6 +939,31 @@ SBThread::StepOverUntil (lldb::SBFrame &sb_frame, } SBError +SBThread::JumpToLine (lldb::SBFileSpec &file_spec, uint32_t line) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + SBError sb_error; + + Mutex::Locker api_locker; + ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); + + if (log) + log->Printf ("SBThread(%p)::JumpToLine (file+line = %s:%u)", exe_ctx.GetThreadPtr(), file_spec->GetPath().c_str(), line); + + if (!exe_ctx.HasThreadScope()) + { + sb_error.SetErrorString("this SBThread object is invalid"); + return sb_error; + } + + Thread *thread = exe_ctx.GetThreadPtr(); + + Error err = thread->JumpToLine (file_spec.get(), line, true); + sb_error.SetError (err); + return sb_error; +} + +SBError SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value) { SBError sb_error; @@ -1227,3 +1281,38 @@ SBThread::GetDescription (SBStream &description) const return true; } + +SBThread +SBThread::GetExtendedBacktrace (const char *type) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + Mutex::Locker api_locker; + ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker); + SBThread sb_origin_thread; + + if (exe_ctx.HasThreadScope()) + { + Process::StopLocker stop_locker; + if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) + { + ThreadSP real_thread(exe_ctx.GetThreadPtr()); + if (real_thread) + { + ConstString type_const (type); + SystemRuntime *runtime = exe_ctx.GetProcessPtr()->GetSystemRuntime(); + if (runtime) + { + ThreadSP origin_thread = runtime->GetExtendedBacktrace (real_thread, type_const); + sb_origin_thread.SetThread (origin_thread); + } + } + } + else + { + if (log) + log->Printf ("SBThread(%p)::GetExtendedBacktrace() => error: process is running", exe_ctx.GetThreadPtr()); + } + } + + return sb_origin_thread; +} diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp index 372d073acf12..3055c2752083 100644 --- a/source/API/SBType.cpp +++ b/source/API/SBType.cpp @@ -7,12 +7,6 @@ // //===----------------------------------------------------------------------===// -#include <string.h> - -#include "clang/AST/ASTContext.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" - #include "lldb/API/SBDefines.h" #include "lldb/API/SBType.h" #include "lldb/API/SBStream.h" @@ -69,8 +63,10 @@ SBType::operator == (SBType &rhs) if (IsValid() == false) return !rhs.IsValid(); - return (rhs.m_opaque_sp->GetASTContext() == m_opaque_sp->GetASTContext()) && - (rhs.m_opaque_sp->GetOpaqueQualType() == m_opaque_sp->GetOpaqueQualType()); + if (rhs.IsValid() == false) + return false; + + return *m_opaque_sp.get() == *rhs.m_opaque_sp.get(); } bool @@ -78,9 +74,11 @@ SBType::operator != (SBType &rhs) { if (IsValid() == false) return rhs.IsValid(); - - return (rhs.m_opaque_sp->GetASTContext() != m_opaque_sp->GetASTContext()) || - (rhs.m_opaque_sp->GetOpaqueQualType() != m_opaque_sp->GetOpaqueQualType()); + + if (rhs.IsValid() == false) + return true; + + return *m_opaque_sp.get() != *rhs.m_opaque_sp.get(); } lldb::TypeImplSP @@ -142,7 +140,7 @@ SBType::GetByteSize() if (!IsValid()) return 0; - return m_opaque_sp->GetClangASTType().GetByteSize(); + return m_opaque_sp->GetClangASTType(false).GetByteSize(); } @@ -151,7 +149,7 @@ SBType::IsPointerType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsPointerType(); + return m_opaque_sp->GetClangASTType(true).IsPointerType(); } bool @@ -159,7 +157,7 @@ SBType::IsReferenceType() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsReferenceType(); + return m_opaque_sp->GetClangASTType(true).IsReferenceType(); } SBType @@ -168,7 +166,7 @@ SBType::GetPointerType() if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointerType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType()))); } SBType @@ -176,7 +174,7 @@ SBType::GetPointeeType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetPointeeType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType()))); } SBType @@ -184,7 +182,7 @@ SBType::GetReferenceType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetLValueReferenceType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType()))); } SBType @@ -192,7 +190,7 @@ SBType::GetDereferencedType() { if (!IsValid()) return SBType(); - return SBType(ClangASTType(m_opaque_sp->GetClangASTType().GetNonReferenceType())); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType()))); } bool @@ -200,7 +198,7 @@ SBType::IsFunctionType () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsFunctionType(); + return m_opaque_sp->GetClangASTType(true).IsFunctionType(); } bool @@ -208,7 +206,7 @@ SBType::IsPolymorphicClass () { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsPolymorphicClass(); + return m_opaque_sp->GetClangASTType(true).IsPolymorphicClass(); } @@ -218,7 +216,7 @@ SBType::GetFunctionReturnType () { if (IsValid()) { - ClangASTType return_clang_type (m_opaque_sp->GetClangASTType().GetFunctionReturnType()); + ClangASTType return_clang_type (m_opaque_sp->GetClangASTType(true).GetFunctionReturnType()); if (return_clang_type.IsValid()) return SBType(return_clang_type); } @@ -231,13 +229,13 @@ SBType::GetFunctionArgumentTypes () SBTypeList sb_type_list; if (IsValid()) { - QualType qual_type(QualType::getFromOpaquePtr(m_opaque_sp->GetOpaqueQualType())); - const FunctionProtoType* func = dyn_cast<FunctionProtoType>(qual_type.getTypePtr()); - if (func) + ClangASTType func_type(m_opaque_sp->GetClangASTType(true)); + size_t count = func_type.GetNumberOfFunctionArguments(); + for (size_t i = 0; + i < count; + i++) { - const uint32_t num_args = func->getNumArgs(); - for (uint32_t i=0; i<num_args; ++i) - sb_type_list.Append (SBType(ClangASTType(m_opaque_sp->GetASTContext(), func->getArgType(i).getAsOpaquePtr()))); + sb_type_list.Append(SBType(func_type.GetFunctionArgumentAtIndex(i))); } } return sb_type_list; @@ -248,14 +246,14 @@ SBType::GetUnqualifiedType() { if (!IsValid()) return SBType(); - return SBType(m_opaque_sp->GetClangASTType().GetFullyUnqualifiedType()); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType()))); } lldb::SBType SBType::GetCanonicalType() { if (IsValid()) - return SBType(m_opaque_sp->GetClangASTType().GetCanonicalType()); + return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType()))); return SBType(); } @@ -264,7 +262,7 @@ lldb::BasicType SBType::GetBasicType() { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetBasicTypeEnumeration (); + return m_opaque_sp->GetClangASTType(false).GetBasicTypeEnumeration (); return eBasicTypeInvalid; } @@ -272,7 +270,7 @@ SBType SBType::GetBasicType(lldb::BasicType basic_type) { if (IsValid()) - return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetASTContext(), basic_type)); + return SBType (ClangASTContext::GetBasicType (m_opaque_sp->GetClangASTContext(false), basic_type)); return SBType(); } @@ -280,7 +278,7 @@ uint32_t SBType::GetNumberOfDirectBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumDirectBaseClasses(); + return m_opaque_sp->GetClangASTType(true).GetNumDirectBaseClasses(); return 0; } @@ -288,7 +286,7 @@ uint32_t SBType::GetNumberOfVirtualBaseClasses () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumVirtualBaseClasses(); + return m_opaque_sp->GetClangASTType(true).GetNumVirtualBaseClasses(); return 0; } @@ -296,7 +294,7 @@ uint32_t SBType::GetNumberOfFields () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumFields(); + return m_opaque_sp->GetClangASTType(false).GetNumFields(); return 0; } @@ -323,7 +321,7 @@ SBType::GetDirectBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); if (this_type.IsValid()) { uint32_t bit_offset = 0; @@ -344,7 +342,7 @@ SBType::GetVirtualBaseClassAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (true)); if (this_type.IsValid()) { uint32_t bit_offset = 0; @@ -364,7 +362,7 @@ SBType::GetFieldAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - ClangASTType this_type (m_opaque_sp->GetClangASTType ()); + ClangASTType this_type (m_opaque_sp->GetClangASTType (false)); if (this_type.IsValid()) { uint64_t bit_offset = 0; @@ -397,7 +395,7 @@ SBType::IsTypeComplete() { if (!IsValid()) return false; - return m_opaque_sp->GetClangASTType().IsCompleteType(); + return m_opaque_sp->GetClangASTType(false).IsCompleteType(); } const char* @@ -405,14 +403,14 @@ SBType::GetName() { if (!IsValid()) return ""; - return m_opaque_sp->GetClangASTType().GetConstTypeName().GetCString(); + return m_opaque_sp->GetName().GetCString(); } lldb::TypeClass SBType::GetTypeClass () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetTypeClass(); + return m_opaque_sp->GetClangASTType(false).GetTypeClass(); return lldb::eTypeClassInvalid; } @@ -420,7 +418,7 @@ uint32_t SBType::GetNumberOfTemplateArguments () { if (IsValid()) - return m_opaque_sp->GetClangASTType().GetNumTemplateArguments(); + return m_opaque_sp->GetClangASTType(false).GetNumTemplateArguments(); return 0; } @@ -430,7 +428,7 @@ SBType::GetTemplateArgumentType (uint32_t idx) if (IsValid()) { TemplateArgumentKind kind = eTemplateArgumentKindNull; - ClangASTType template_arg_type = m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); + ClangASTType template_arg_type = m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); if (template_arg_type.IsValid()) return SBType(template_arg_type); } @@ -443,7 +441,7 @@ SBType::GetTemplateArgumentKind (uint32_t idx) { TemplateArgumentKind kind = eTemplateArgumentKindNull; if (IsValid()) - m_opaque_sp->GetClangASTType().GetTemplateArgument (idx, kind); + m_opaque_sp->GetClangASTType(false).GetTemplateArgument (idx, kind); return kind; } diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp index e3978693c81c..08fdefad1be8 100644 --- a/source/API/SBTypeCategory.cpp +++ b/source/API/SBTypeCategory.cpp @@ -84,10 +84,10 @@ SBTypeCategory::GetName() uint32_t SBTypeCategory::GetNumFormats () { - if (!IsDefaultCategory()) + if (!IsValid()) return 0; - return DataVisualization::ValueFormats::GetCount(); + return m_opaque_sp->GetValueNavigator()->GetCount() + m_opaque_sp->GetRegexValueNavigator()->GetCount(); } uint32_t @@ -127,9 +127,9 @@ SBTypeCategory::GetTypeNameSpecifierForFilterAtIndex (uint32_t index) lldb::SBTypeNameSpecifier SBTypeCategory::GetTypeNameSpecifierForFormatAtIndex (uint32_t index) { - if (!IsDefaultCategory()) + if (!IsValid()) return SBTypeNameSpecifier(); - return SBTypeNameSpecifier(DataVisualization::ValueFormats::GetTypeNameSpecifierForFormatAtIndex(index)); + return SBTypeNameSpecifier(m_opaque_sp->GetTypeNameSpecifierForFormatAtIndex(index)); } lldb::SBTypeNameSpecifier @@ -177,16 +177,23 @@ SBTypeCategory::GetFilterForType (SBTypeNameSpecifier spec) SBTypeFormat SBTypeCategory::GetFormatForType (SBTypeNameSpecifier spec) { - if (!IsDefaultCategory()) + if (!IsValid()) return SBTypeFormat(); if (!spec.IsValid()) return SBTypeFormat(); + lldb::TypeFormatImplSP format_sp; + if (spec.IsRegex()) - return SBTypeFormat(); + m_opaque_sp->GetRegexValueNavigator()->GetExact(ConstString(spec.GetName()), format_sp); + else + m_opaque_sp->GetValueNavigator()->GetExact(ConstString(spec.GetName()), format_sp); - return SBTypeFormat(DataVisualization::ValueFormats::GetFormat(ConstString(spec.GetName()))); + if (!format_sp) + return lldb::SBTypeFormat(); + + return lldb::SBTypeFormat(format_sp); } #ifndef LLDB_DISABLE_PYTHON @@ -259,9 +266,9 @@ SBTypeCategory::GetFilterAtIndex (uint32_t index) SBTypeFormat SBTypeCategory::GetFormatAtIndex (uint32_t index) { - if (!IsDefaultCategory()) + if (!IsValid()) return SBTypeFormat(); - return SBTypeFormat(DataVisualization::ValueFormats::GetFormatAtIndex((index))); + return SBTypeFormat(m_opaque_sp->GetFormatAtIndex((index))); } #ifndef LLDB_DISABLE_PYTHON @@ -295,7 +302,7 @@ bool SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name, SBTypeFormat format) { - if (!IsDefaultCategory()) + if (!IsValid()) return false; if (!type_name.IsValid()) @@ -305,9 +312,9 @@ SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name, return false; if (type_name.IsRegex()) - return false; - - DataVisualization::ValueFormats::Add(ConstString(type_name.GetName()), format.GetSP()); + m_opaque_sp->GetRegexValueNavigator()->Add(lldb::RegularExpressionSP(new RegularExpression(type_name.GetName())), format.GetSP()); + else + m_opaque_sp->GetValueNavigator()->Add(ConstString(type_name.GetName()), format.GetSP()); return true; } @@ -315,16 +322,16 @@ SBTypeCategory::AddTypeFormat (SBTypeNameSpecifier type_name, bool SBTypeCategory::DeleteTypeFormat (SBTypeNameSpecifier type_name) { - if (!IsDefaultCategory()) + if (!IsValid()) return false; if (!type_name.IsValid()) return false; if (type_name.IsRegex()) - return false; - - return DataVisualization::ValueFormats::Delete(ConstString(type_name.GetName())); + return m_opaque_sp->GetRegexValueNavigator()->Delete(ConstString(type_name.GetName())); + else + return m_opaque_sp->GetValueNavigator()->Delete(ConstString(type_name.GetName())); } #ifndef LLDB_DISABLE_PYTHON diff --git a/source/API/SBTypeNameSpecifier.cpp b/source/API/SBTypeNameSpecifier.cpp index d417499ecbd3..3d03c6a0c539 100644 --- a/source/API/SBTypeNameSpecifier.cpp +++ b/source/API/SBTypeNameSpecifier.cpp @@ -36,7 +36,7 @@ SBTypeNameSpecifier::SBTypeNameSpecifier (SBType type) : m_opaque_sp() { if (type.IsValid()) - m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType())); + m_opaque_sp = TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(type.m_opaque_sp->GetClangASTType(true))); } SBTypeNameSpecifier::SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs) : diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp index aa9b23ac7c69..51b6790dd2b8 100644 --- a/source/API/SBValue.cpp +++ b/source/API/SBValue.cpp @@ -63,20 +63,20 @@ public: lldb::DynamicValueType use_dynamic, bool use_synthetic, const char *name = NULL) : - m_valobj_sp(in_valobj_sp), - m_use_dynamic(use_dynamic), - m_use_synthetic(use_synthetic), - m_name (name) + m_valobj_sp(in_valobj_sp), + m_use_dynamic(use_dynamic), + m_use_synthetic(use_synthetic), + m_name (name) { if (!m_name.IsEmpty() && m_valobj_sp) m_valobj_sp->SetName(m_name); } ValueImpl (const ValueImpl& rhs) : - m_valobj_sp(rhs.m_valobj_sp), - m_use_dynamic(rhs.m_use_dynamic), - m_use_synthetic(rhs.m_use_synthetic), - m_name (rhs.m_name) + m_valobj_sp(rhs.m_valobj_sp), + m_use_dynamic(rhs.m_use_dynamic), + m_use_synthetic(rhs.m_use_synthetic), + m_name (rhs.m_name) { } @@ -120,7 +120,7 @@ public: Target *target = value_sp->GetTargetSP().get(); if (target) api_locker.Lock(target->GetAPIMutex()); - + ProcessSP process_sp(value_sp->GetProcessSP()); if (process_sp && !stop_locker.TryLock (&process_sp->GetRunLock())) { @@ -131,7 +131,7 @@ public: error.SetErrorString ("process must be stopped."); return ValueObjectSP(); } - + if (value_sp->GetDynamicValue(m_use_dynamic)) value_sp = value_sp->GetDynamicValue(m_use_dynamic); if (value_sp->GetSyntheticValue(m_use_synthetic)) @@ -167,7 +167,7 @@ public: { return m_use_synthetic; } - + // All the derived values that we would make from the m_valobj_sp will share // the ExecutionContext with m_valobj_sp, so we don't need to do the calculations // in GetSP to return the Target, Process, Thread or Frame. It is convenient to @@ -207,7 +207,7 @@ public: else return StackFrameSP(); } - + private: lldb::ValueObjectSP m_valobj_sp; lldb::DynamicValueType m_use_dynamic; @@ -227,7 +227,7 @@ public: { return in_value.GetSP(m_stop_locker, m_api_locker, m_lock_error); } - + Error & GetError() { @@ -238,11 +238,11 @@ private: Process::StopLocker m_stop_locker; Mutex::Locker m_api_locker; Error m_lock_error; - + }; SBValue::SBValue () : - m_opaque_sp () +m_opaque_sp () { } @@ -318,7 +318,7 @@ SBValue::GetName() lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) name = value_sp->GetName().GetCString(); - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) { @@ -327,7 +327,7 @@ SBValue::GetName() else log->Printf ("SBValue(%p)::GetName () => NULL", value_sp.get()); } - + return name; } @@ -350,7 +350,7 @@ SBValue::GetTypeName () else log->Printf ("SBValue(%p)::GetTypeName () => NULL", value_sp.get()); } - + return name; } @@ -359,17 +359,17 @@ SBValue::GetByteSize () { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); size_t result = 0; - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { result = value_sp->GetByteSize(); } - + if (log) log->Printf ("SBValue(%p)::GetByteSize () => %" PRIu64, value_sp.get(), (uint64_t)result); - + return result; } @@ -377,18 +377,18 @@ bool SBValue::IsInScope () { bool result = false; - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { result = value_sp->IsInScope (); } - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBValue(%p)::IsInScope () => %i", value_sp.get(), result); - + return result; } @@ -396,7 +396,7 @@ const char * SBValue::GetValue () { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - + const char *cstr = NULL; ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); @@ -411,7 +411,7 @@ SBValue::GetValue () else log->Printf ("SBValue(%p)::GetValue() => NULL", value_sp.get()); } - + return cstr; } @@ -429,14 +429,14 @@ SBValue::GetValueType () { switch (result) { - case eValueTypeInvalid: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", value_sp.get()); break; - case eValueTypeVariableGlobal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", value_sp.get()); break; - case eValueTypeVariableStatic: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", value_sp.get()); break; - case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", value_sp.get()); break; - case eValueTypeVariableLocal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", value_sp.get()); break; - case eValueTypeRegister: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", value_sp.get()); break; - case eValueTypeRegisterSet: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", value_sp.get()); break; - case eValueTypeConstResult: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", value_sp.get()); break; + case eValueTypeInvalid: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeInvalid", value_sp.get()); break; + case eValueTypeVariableGlobal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableGlobal", value_sp.get()); break; + case eValueTypeVariableStatic: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableStatic", value_sp.get()); break; + case eValueTypeVariableArgument:log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableArgument", value_sp.get()); break; + case eValueTypeVariableLocal: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeVariableLocal", value_sp.get()); break; + case eValueTypeRegister: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegister", value_sp.get()); break; + case eValueTypeRegisterSet: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeRegisterSet", value_sp.get()); break; + case eValueTypeConstResult: log->Printf ("SBValue(%p)::GetValueType () => eValueTypeConstResult", value_sp.get()); break; } } return result; @@ -473,7 +473,7 @@ SBValue::GetType() TypeImplSP type_sp; if (value_sp) { - type_sp.reset (new TypeImpl(value_sp->GetClangType())); + type_sp.reset (new TypeImpl(value_sp->GetTypeImpl())); sb_type.SetSP(type_sp); } if (log) @@ -499,7 +499,7 @@ SBValue::GetValueDidChange () } if (log) log->Printf ("SBValue(%p)::GetValueDidChange() => %i", value_sp.get(), result); - + return result; } @@ -571,7 +571,7 @@ SBValue::SetValueFromCString (const char *value_str, lldb::SBError& error) if (log) log->Printf ("SBValue(%p)::SetValueFromCString(\"%s\") => %i", value_sp.get(), value_str, success); - + return success; } @@ -671,7 +671,7 @@ SBValue::CreateChildAtOffset (const char *name, uint32_t offset, SBType type) TypeImplSP type_sp (type.GetSP()); if (type.IsValid()) { - sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); + sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(false), true),GetPreferDynamicValue(),GetPreferSyntheticValue(), name); } } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -696,7 +696,7 @@ SBValue::Cast (SBType type) lldb::ValueObjectSP value_sp(GetSP(locker)); TypeImplSP type_sp (type.GetSP()); if (value_sp && type_sp) - sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType()),GetPreferDynamicValue(),GetPreferSyntheticValue()); + sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType(false)),GetPreferDynamicValue(),GetPreferSyntheticValue()); return sb_value; } @@ -761,19 +761,19 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType s lldb::TypeImplSP type_impl_sp (sb_type.GetSP()); if (value_sp && type_impl_sp) { - ClangASTType pointee_ast_type(type_impl_sp->GetClangASTType().GetPointerType ()); - if (pointee_ast_type) + ClangASTType pointer_ast_type(type_impl_sp->GetClangASTType(false).GetPointerType ()); + if (pointer_ast_type) { lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); - + ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - pointee_ast_type, + pointer_ast_type, ConstString(name), buffer, - lldb::endian::InlHostByteOrder(), + exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize())); - + if (ptr_result_valobj_sp) { ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); @@ -806,9 +806,9 @@ SBValue::CreateValueFromData (const char* name, SBData data, SBType type) if (value_sp) { ExecutionContext exe_ctx (value_sp->GetExecutionContextRef()); - + new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - type.m_opaque_sp->GetClangASTType(), + type.m_opaque_sp->GetClangASTType(false), ConstString(name), *data.m_opaque_sp, LLDB_INVALID_ADDRESS); @@ -837,7 +837,7 @@ SBValue::GetChildAtIndex (uint32_t idx) if (target_sp) use_dynamic = target_sp->GetPreferDynamicValue(); - + return GetChildAtIndex (idx, use_dynamic, can_create_synthetic); } @@ -846,7 +846,7 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool { lldb::ValueObjectSP child_sp; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) @@ -870,7 +870,7 @@ SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool sb_value.SetSP (child_sp, use_dynamic, GetPreferSyntheticValue()); if (log) log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", value_sp.get(), idx, value_sp.get()); - + return sb_value; } @@ -913,9 +913,9 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy { lldb::ValueObjectSP child_sp; const ConstString str_name (name); - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) @@ -925,10 +925,10 @@ SBValue::GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dy SBValue sb_value; sb_value.SetSP(child_sp, use_dynamic_value, GetPreferSyntheticValue()); - + if (log) log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", value_sp.get(), name, value_sp.get()); - + return sb_value; } @@ -1048,11 +1048,12 @@ SBValue::GetValueAsSigned(SBError& error, int64_t fail_value) lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - Scalar scalar; - if (value_sp->ResolveValue (scalar)) - return scalar.SLongLong (fail_value); - else - error.SetErrorString ("could not resolve value"); + bool success = true; + uint64_t ret_val = fail_value; + ret_val = value_sp->GetValueAsSigned(fail_value, &success); + if (!success) + error.SetErrorString("could not resolve value"); + return ret_val; } else error.SetErrorStringWithFormat ("could not get SBValue: %s", locker.GetError().AsCString()); @@ -1068,11 +1069,12 @@ SBValue::GetValueAsUnsigned(SBError& error, uint64_t fail_value) lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - Scalar scalar; - if (value_sp->ResolveValue (scalar)) - return scalar.ULongLong(fail_value); - else + bool success = true; + uint64_t ret_val = fail_value; + ret_val = value_sp->GetValueAsUnsigned(fail_value, &success); + if (!success) error.SetErrorString("could not resolve value"); + return ret_val; } else error.SetErrorStringWithFormat ("could not get SBValue: %s", locker.GetError().AsCString()); @@ -1087,9 +1089,7 @@ SBValue::GetValueAsSigned(int64_t fail_value) lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - Scalar scalar; - if (value_sp->ResolveValue (scalar)) - return scalar.SLongLong(fail_value); + return value_sp->GetValueAsSigned(fail_value); } return fail_value; } @@ -1101,9 +1101,7 @@ SBValue::GetValueAsUnsigned(uint64_t fail_value) lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - Scalar scalar; - if (value_sp->ResolveValue (scalar)) - return scalar.ULongLong(fail_value); + return value_sp->GetValueAsUnsigned(fail_value); } return fail_value; } @@ -1117,7 +1115,7 @@ SBValue::MightHaveChildren () lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) has_children = value_sp->MightHaveChildren(); - + if (log) log->Printf ("SBValue(%p)::MightHaveChildren() => %i", value_sp.get(), has_children); return has_children; @@ -1127,16 +1125,16 @@ uint32_t SBValue::GetNumChildren () { uint32_t num_children = 0; - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) num_children = value_sp->GetNumChildren(); - + if (log) log->Printf ("SBValue(%p)::GetNumChildren () => %u", value_sp.get(), num_children); - + return num_children; } @@ -1149,13 +1147,13 @@ SBValue::Dereference () lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) { - Error error; - sb_value = value_sp->Dereference (error); + Error error; + sb_value = value_sp->Dereference (error); } Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBValue(%p)::Dereference () => SBValue(%p)", value_sp.get(), value_sp.get()); - + return sb_value; } @@ -1163,17 +1161,17 @@ bool SBValue::TypeIsPointerType () { bool is_ptr_type = false; - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) is_ptr_type = value_sp->IsPointerType(); - + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); if (log) log->Printf ("SBValue(%p)::TypeIsPointerType () => %i", value_sp.get(), is_ptr_type); - - + + return is_ptr_type; } @@ -1390,16 +1388,14 @@ bool SBValue::GetDescription (SBStream &description) { Stream &strm = description.ref(); - + ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) - { - ValueObject::DumpValueObject (strm, value_sp.get()); - } + value_sp->Dump(strm); else strm.PutCString ("No value"); - + return true; } @@ -1653,7 +1649,7 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error) size_t byte_size = GetByteSize(); if (byte_size == 0) return sb_watchpoint; - + uint32_t watch_type = 0; if (read) watch_type |= LLDB_WATCH_TYPE_READ; @@ -1664,14 +1660,14 @@ SBValue::Watch (bool resolve_location, bool read, bool write, SBError &error) ClangASTType type (value_sp->GetClangType()); WatchpointSP watchpoint_sp = target_sp->CreateWatchpoint(addr, byte_size, &type, watch_type, rc); error.SetError(rc); - - if (watchpoint_sp) + + if (watchpoint_sp) { sb_watchpoint.SetSP (watchpoint_sp); Declaration decl; if (value_sp->GetDeclaration (decl)) { - if (decl.GetFile()) + if (decl.GetFile()) { StreamString ss; // True to show fullpath for declaration file. diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp index 9bc43814b48a..e07205e360b1 100644 --- a/source/Breakpoint/Breakpoint.cpp +++ b/source/Breakpoint/Breakpoint.cpp @@ -45,8 +45,9 @@ Breakpoint::GetEventIdentifier () //---------------------------------------------------------------------- // Breakpoint constructor //---------------------------------------------------------------------- -Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) : +Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp, bool hardware) : m_being_created(true), + m_hardware(hardware), m_target (target), m_filter_sp (filter_sp), m_resolver_sp (resolver_sp), @@ -558,7 +559,7 @@ Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_l { s->Printf(", locations = %" PRIu64, (uint64_t)num_locations); if (num_resolved_locations > 0) - s->Printf(", resolved = %" PRIu64, (uint64_t)num_resolved_locations); + s->Printf(", resolved = %" PRIu64 ", hit count = %d", (uint64_t)num_resolved_locations, GetHitCount()); } else { diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp index 5926663af7b1..c6030d60ca04 100644 --- a/source/Breakpoint/BreakpointList.cpp +++ b/source/Breakpoint/BreakpointList.cpp @@ -204,13 +204,13 @@ BreakpointList::GetBreakpointAtIndex (size_t i) const } void -BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added) +BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations) { Mutex::Locker locker(m_mutex); bp_collection::iterator end = m_breakpoints.end(); bp_collection::iterator pos; for (pos = m_breakpoints.begin(); pos != end; ++pos) - (*pos)->ModulesChanged (module_list, added); + (*pos)->ModulesChanged (module_list, added, delete_locations); } diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp index 1ec726dd52b1..17568c28b507 100644 --- a/source/Breakpoint/BreakpointLocation.cpp +++ b/source/Breakpoint/BreakpointLocation.cpp @@ -291,9 +291,11 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) // constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; - const bool unwind_on_error = true; - const bool ignore_breakpoints = true; - const bool try_all_threads = true; + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetIgnoreBreakpoints(true); + options.SetRunOthers(true); Error expr_error; @@ -304,12 +306,9 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) ExecutionResults result_code = m_user_expression_sp->Execute(execution_errors, exe_ctx, - unwind_on_error, - ignore_breakpoints, + options, m_user_expression_sp, - result_variable_sp, - try_all_threads, - ClangUserExpression::kDefaultTimeout); + result_variable_sp); bool ret; @@ -484,7 +483,7 @@ BreakpointLocation::ResolveBreakpointSite () if (process == NULL) return false; - lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), false); + lldb::break_id_t new_id = process->CreateBreakpointSite (shared_from_this(), m_owner.IsHardware()); if (new_id == LLDB_INVALID_BREAK_ID) { diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp index 22a4ff0c68ee..341b09716301 100644 --- a/source/Breakpoint/BreakpointLocationList.cpp +++ b/source/Breakpoint/BreakpointLocationList.cpp @@ -41,7 +41,7 @@ BreakpointLocationList::Create (const Address &addr) Mutex::Locker locker (m_mutex); // The location ID is just the size of the location list + 1 lldb::break_id_t bp_loc_id = ++m_next_id; - BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr)); + BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware())); m_locations.push_back (bp_loc_sp); m_address_to_location[addr] = bp_loc_sp; return bp_loc_sp; diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp index b22fa1e6dbcc..33b0ff40e35f 100644 --- a/source/Breakpoint/BreakpointResolver.cpp +++ b/source/Breakpoint/BreakpointResolver.cpp @@ -23,9 +23,12 @@ #include "lldb/Core/StreamString.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" #include "lldb/lldb-private-log.h" using namespace lldb_private; +using namespace lldb; //---------------------------------------------------------------------- // BreakpointResolver: @@ -59,3 +62,144 @@ BreakpointResolver::ResolveBreakpoint (SearchFilter &filter) filter.Search (*this); } +void +BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + + while (sc_list.GetSize() > 0) + { + SymbolContextList tmp_sc_list; + unsigned current_idx = 0; + SymbolContext sc; + bool first_entry = true; + + FileSpec match_file_spec; + uint32_t closest_line_number = UINT32_MAX; + + // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list. + while (current_idx < sc_list.GetSize()) + { + bool matches; + + sc_list.GetContextAtIndex (current_idx, sc); + if (first_entry) + { + match_file_spec = sc.line_entry.file; + matches = true; + first_entry = false; + } + else + matches = (sc.line_entry.file == match_file_spec); + + if (matches) + { + tmp_sc_list.Append (sc); + sc_list.RemoveContextAtIndex(current_idx); + + // ResolveSymbolContext will always return a number that is >= the line number you pass in. + // So the smaller line number is always better. + if (sc.line_entry.line < closest_line_number) + closest_line_number = sc.line_entry.line; + } + else + current_idx++; + } + + // Okay, we've found the closest line number match, now throw away all the others: + + current_idx = 0; + while (current_idx < tmp_sc_list.GetSize()) + { + if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) + { + if (sc.line_entry.line != closest_line_number) + tmp_sc_list.RemoveContextAtIndex(current_idx); + else + current_idx++; + } + } + + // Next go through and see if there are line table entries that are contiguous, and if so keep only the + // first of the contiguous range: + + current_idx = 0; + std::map<Block *, lldb::addr_t> blocks_with_breakpoints; + + while (current_idx < tmp_sc_list.GetSize()) + { + if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) + { + if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end()) + tmp_sc_list.RemoveContextAtIndex(current_idx); + else + { + blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress())); + current_idx++; + } + } + } + + // and make breakpoints out of the closest line number match. + + uint32_t tmp_sc_list_size = tmp_sc_list.GetSize(); + + for (uint32_t i = 0; i < tmp_sc_list_size; i++) + { + if (tmp_sc_list.GetContextAtIndex(i, sc)) + { + Address line_start = sc.line_entry.range.GetBaseAddress(); + if (line_start.IsValid()) + { + if (filter.AddressPasses(line_start)) + { + // If the line number is before the prologue end, move it there... + bool skipped_prologue = false; + if (skip_prologue) + { + if (sc.function) + { + Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress()); + if (prologue_addr.IsValid() && (line_start == prologue_addr)) + { + const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); + if (prologue_byte_size) + { + prologue_addr.Slide(prologue_byte_size); + + if (filter.AddressPasses(prologue_addr)) + { + skipped_prologue = true; + line_start = prologue_addr; + } + } + } + } + } + + BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); + if (log && bp_loc_sp && !m_breakpoint->IsInternal()) + { + StreamString s; + bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); + log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData()); + } + } + else if (log) + { + log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n", + log_ident ? log_ident : "", + line_start.GetFileAddress()); + } + } + else + { + if (log) + log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n", + log_ident ? log_ident : "", + line_start.GetFileAddress()); + } + } + } + } +} diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp index 91a218fdb80a..dcee2fd54125 100644 --- a/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -59,7 +59,6 @@ BreakpointResolverFileLine::SearchCallback SymbolContextList sc_list; assert (m_breakpoint != NULL); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); // There is a tricky bit here. You can have two compilation units that #include the same file, and // in one of them the function at m_line_number is used (and so code and a line entry for it is generated) but in the @@ -83,146 +82,13 @@ BreakpointResolverFileLine::SearchCallback cu_sp->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, sc_list); } } - - while (sc_list.GetSize() > 0) - { - SymbolContextList tmp_sc_list; - unsigned current_idx = 0; - SymbolContext sc; - bool first_entry = true; - - FileSpec match_file_spec; - uint32_t closest_line_number = UINT32_MAX; + StreamString s; + s.Printf ("for %s:%d ", + m_file_spec.GetFilename().AsCString("<Unknown>"), + m_line_number); - // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list. - while (current_idx < sc_list.GetSize()) - { - bool matches; - - sc_list.GetContextAtIndex (current_idx, sc); - if (first_entry) - { - match_file_spec = sc.line_entry.file; - matches = true; - first_entry = false; - } - else - matches = (sc.line_entry.file == match_file_spec); - - if (matches) - { - tmp_sc_list.Append (sc); - sc_list.RemoveContextAtIndex(current_idx); - - // ResolveSymbolContext will always return a number that is >= the line number you pass in. - // So the smaller line number is always better. - if (sc.line_entry.line < closest_line_number) - closest_line_number = sc.line_entry.line; - } - else - current_idx++; - } - - // Okay, we've found the closest line number match, now throw away all the others: - - current_idx = 0; - while (current_idx < tmp_sc_list.GetSize()) - { - if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) - { - if (sc.line_entry.line != closest_line_number) - tmp_sc_list.RemoveContextAtIndex(current_idx); - else - current_idx++; - } - } - - // Next go through and see if there are line table entries that are contiguous, and if so keep only the - // first of the contiguous range: - - lldb::addr_t last_end_addr = LLDB_INVALID_ADDRESS; - current_idx = 0; - while (current_idx < tmp_sc_list.GetSize()) - { - if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) - { - lldb::addr_t start_file_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress(); - lldb::addr_t end_file_addr = start_file_addr + sc.line_entry.range.GetByteSize(); - - if (start_file_addr == last_end_addr) - tmp_sc_list.RemoveContextAtIndex(current_idx); - else - current_idx++; + SetSCMatchesByLine (filter, sc_list, m_skip_prologue, s.GetData()); - last_end_addr = end_file_addr; - } - } - - // and make breakpoints out of the closest line number match. - - uint32_t tmp_sc_list_size = tmp_sc_list.GetSize(); - - for (uint32_t i = 0; i < tmp_sc_list_size; i++) - { - if (tmp_sc_list.GetContextAtIndex(i, sc)) - { - Address line_start = sc.line_entry.range.GetBaseAddress(); - if (line_start.IsValid()) - { - if (filter.AddressPasses(line_start)) - { - // If the line number is before the prologue end, move it there... - bool skipped_prologue = false; - if (m_skip_prologue) - { - if (sc.function) - { - Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress()); - if (prologue_addr.IsValid() && (line_start == prologue_addr)) - { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); - if (prologue_byte_size) - { - prologue_addr.Slide(prologue_byte_size); - - if (filter.AddressPasses(prologue_addr)) - { - skipped_prologue = true; - line_start = prologue_addr; - } - } - } - } - } - - BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); - if (log && bp_loc_sp && !m_breakpoint->IsInternal()) - { - StreamString s; - bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); - log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData()); - } - } - else if (log) - { - log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass the filter.\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString("<Unknown>"), - m_line_number); - } - } - else - { - if (log) - log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString("<Unknown>"), - m_line_number); - } - } - } - } - return Searcher::eCallbackReturnContinue; } diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp index de974d04894a..01aecee7b9c2 100644 --- a/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -54,60 +54,23 @@ BreakpointResolverFileRegex::SearchCallback assert (m_breakpoint != NULL); if (!context.target_sp) return eCallbackReturnContinue; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); CompileUnit *cu = context.comp_unit; FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu)); std::vector<uint32_t> line_matches; - context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); + context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); + uint32_t num_matches = line_matches.size(); for (uint32_t i = 0; i < num_matches; i++) { - uint32_t start_idx = 0; - bool exact = false; - while (1) - { - LineEntry line_entry; + SymbolContextList sc_list; + const bool search_inlines = false; + const bool exact = false; - // Cycle through all the line entries that might match this one: - start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry); - if (start_idx == UINT32_MAX) - break; - exact = true; - start_idx++; - - Address line_start = line_entry.range.GetBaseAddress(); - if (line_start.IsValid()) - { - if (filter.AddressPasses(line_start)) - { - BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); - if (log && bp_loc_sp && !m_breakpoint->IsInternal()) - { - StreamString s; - bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); - log->Printf ("Added location: %s\n", s.GetData()); - } - } - else if (log) - { - log->Printf ("Breakpoint at file address 0x%" PRIx64 " for %s:%d didn't pass filter.\n", - line_start.GetFileAddress(), - cu_file_spec.GetFilename().AsCString("<Unknown>"), - line_matches[i]); - } - } - else - { - if (log) - log->Printf ("error: Unable to set breakpoint at file address 0x%" PRIx64 " for %s:%d\n", - line_start.GetFileAddress(), - cu_file_spec.GetFilename().AsCString("<Unknown>"), - line_matches[i]); - } - - } + cu->ResolveSymbolContext (cu_file_spec, line_matches[i], search_inlines, exact, eSymbolContextEverything, sc_list); + const bool skip_prologue = true; + + BreakpointResolver::SetSCMatchesByLine (filter, sc_list, skip_prologue, m_regex.GetText()); } assert (m_breakpoint != NULL); diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp index 27f85653d648..c82dd5ee050b 100644 --- a/source/Breakpoint/BreakpointResolverName.cpp +++ b/source/Breakpoint/BreakpointResolverName.cpp @@ -289,7 +289,17 @@ BreakpointResolverName::SearchCallback } else if (sc.symbol) { - break_addr = sc.symbol->GetAddress(); + if (sc.symbol->GetType() == eSymbolTypeReExported) + { + const Symbol *actual_symbol = sc.symbol->ResolveReExportedSymbol(m_breakpoint->GetTarget()); + if (actual_symbol) + break_addr = actual_symbol->GetAddress(); + } + else + { + break_addr = sc.symbol->GetAddress(); + } + if (m_skip_prologue && break_addr.IsValid()) { const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); diff --git a/source/Breakpoint/StoppointLocation.cpp b/source/Breakpoint/StoppointLocation.cpp index 092caa5a9322..9d8d9241253a 100644 --- a/source/Breakpoint/StoppointLocation.cpp +++ b/source/Breakpoint/StoppointLocation.cpp @@ -23,8 +23,8 @@ using namespace lldb_private; StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, bool hardware) : m_loc_id(bid), m_addr(addr), - m_hw_preferred(hardware), - m_hw_index(LLDB_INVALID_INDEX32), + m_hardware(hardware), + m_hardware_index(LLDB_INVALID_INDEX32), m_byte_size(0), m_hit_count(0) { @@ -33,8 +33,8 @@ StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, bool hardware StoppointLocation::StoppointLocation (break_id_t bid, addr_t addr, uint32_t byte_size, bool hardware) : m_loc_id(bid), m_addr(addr), - m_hw_preferred(hardware), - m_hw_index(LLDB_INVALID_INDEX32), + m_hardware(hardware), + m_hardware_index(LLDB_INVALID_INDEX32), m_byte_size(byte_size), m_hit_count(0) { diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index a9d2f21b9bac..970aa692bd27 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -11,7 +11,6 @@ // C Includes #include <sys/stat.h> -#include <dirent.h> #if defined(__APPLE__) || defined(__linux__) #include <pwd.h> #endif @@ -121,6 +120,71 @@ CommandCompletions::SourceFiles return matches.GetSize(); } +typedef struct DiskFilesOrDirectoriesBaton +{ + const char *remainder; + char *partial_name_copy; + bool only_directories; + bool *saw_directory; + StringList *matches; + char *end_ptr; + size_t baselen; +} DiskFilesOrDirectoriesBaton; + +FileSpec::EnumerateDirectoryResult DiskFilesOrDirectoriesCallback(void *baton, FileSpec::FileType file_type, const FileSpec &spec) +{ + const char *name = spec.GetFilename().AsCString(); + + const DiskFilesOrDirectoriesBaton *parameters = (DiskFilesOrDirectoriesBaton*)baton; + char *end_ptr = parameters->end_ptr; + char *partial_name_copy = parameters->partial_name_copy; + const char *remainder = parameters->remainder; + + // Omit ".", ".." and any . files if the match string doesn't start with . + if (name[0] == '.') + { + if (name[1] == '\0') + return FileSpec::eEnumerateDirectoryResultNext; + else if (name[1] == '.' && name[2] == '\0') + return FileSpec::eEnumerateDirectoryResultNext; + else if (remainder[0] != '.') + return FileSpec::eEnumerateDirectoryResultNext; + } + + // If we found a directory, we put a "/" at the end of the name. + + if (remainder[0] == '\0' || strstr(name, remainder) == name) + { + if (strlen(name) + parameters->baselen >= PATH_MAX) + return FileSpec::eEnumerateDirectoryResultNext; + + strcpy(end_ptr, name); + + bool isa_directory = false; + if (file_type == FileSpec::eFileTypeDirectory) + isa_directory = true; + else if (file_type == FileSpec::eFileTypeSymbolicLink) + { + struct stat stat_buf; + if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) + isa_directory = true; + } + + if (isa_directory) + { + *parameters->saw_directory = true; + size_t len = strlen(parameters->partial_name_copy); + partial_name_copy[len] = '/'; + partial_name_copy[len + 1] = '\0'; + } + if (parameters->only_directories && !isa_directory) + return FileSpec::eEnumerateDirectoryResultNext; + parameters->matches->AppendString(partial_name_copy); + } + + return FileSpec::eEnumerateDirectoryResultNext; +} + static int DiskFilesOrDirectories ( @@ -239,60 +303,18 @@ DiskFilesOrDirectories // Okay, containing_part is now the directory we want to open and look for files: - lldb_utility::CleanUp <DIR *, int> dir_stream (opendir(containing_part), NULL, closedir); - if (!dir_stream.is_valid()) - return matches.GetSize(); - - struct dirent *dirent_buf; - size_t baselen = end_ptr - partial_name_copy; - while ((dirent_buf = readdir(dir_stream.get())) != NULL) - { - char *name = dirent_buf->d_name; - - // Omit ".", ".." and any . files if the match string doesn't start with . - if (name[0] == '.') - { - if (name[1] == '\0') - continue; - else if (name[1] == '.' && name[2] == '\0') - continue; - else if (remainder[0] != '.') - continue; - } - - // If we found a directory, we put a "/" at the end of the name. - - if (remainder[0] == '\0' || strstr(dirent_buf->d_name, remainder) == name) - { - if (strlen(name) + baselen >= PATH_MAX) - continue; - - strcpy(end_ptr, name); - - bool isa_directory = false; - if (dirent_buf->d_type & DT_DIR) - isa_directory = true; - else if (dirent_buf->d_type & DT_LNK) - { - struct stat stat_buf; - if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) - isa_directory = true; - } - - if (isa_directory) - { - saw_directory = true; - size_t len = strlen(partial_name_copy); - partial_name_copy[len] = '/'; - partial_name_copy[len + 1] = '\0'; - } - if (only_directories && !isa_directory) - continue; - matches.AppendString(partial_name_copy); - } - } + DiskFilesOrDirectoriesBaton parameters; + parameters.remainder = remainder; + parameters.partial_name_copy = partial_name_copy; + parameters.only_directories = only_directories; + parameters.saw_directory = &saw_directory; + parameters.matches = &matches; + parameters.end_ptr = end_ptr; + parameters.baselen = baselen; + + FileSpec::EnumerateDirectory(containing_part, true, true, true, DiskFilesOrDirectoriesCallback, ¶meters); return matches.GetSize(); } diff --git a/source/Commands/CommandObjectArgs.cpp b/source/Commands/CommandObjectArgs.cpp index 05fd53bbe89a..3b919d11a566 100644 --- a/source/Commands/CommandObjectArgs.cpp +++ b/source/Commands/CommandObjectArgs.cpp @@ -266,7 +266,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result) OptionDefinition CommandObjectArgs::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, + { LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose debug logging of the expression parsing and evaluation."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index cb70c99a1955..c20da7f3ec5c 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -106,6 +106,7 @@ public: m_queue_name(), m_catch_bp (false), m_throw_bp (true), + m_hardware (false), m_language (eLanguageTypeUnknown), m_skip_prologue (eLazyBoolCalculate), m_one_shot (false) @@ -183,13 +184,18 @@ public: break; case 'h': - { - bool success; - m_catch_bp = Args::StringToBoolean (option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg); - } - break; + { + bool success; + m_catch_bp = Args::StringToBoolean (option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg); + } + break; + + case 'H': + m_hardware = true; + break; + case 'i': { m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); @@ -311,6 +317,7 @@ public: m_queue_name.clear(); m_catch_bp = false; m_throw_bp = true; + m_hardware = false; m_language = eLanguageTypeUnknown; m_skip_prologue = eLazyBoolCalculate; m_one_shot = false; @@ -345,6 +352,7 @@ public: std::string m_queue_name; bool m_catch_bp; bool m_throw_bp; + bool m_hardware; // Request to use hardware breakpoints lldb::LanguageType m_language; LazyBool m_skip_prologue; bool m_one_shot; @@ -423,12 +431,15 @@ protected: m_options.m_line_num, check_inlines, m_options.m_skip_prologue, - internal).get(); + internal, + m_options.m_hardware).get(); } break; case eSetTypeAddress: // Breakpoint by address - bp = target->CreateBreakpoint (m_options.m_load_addr, false).get(); + bp = target->CreateBreakpoint (m_options.m_load_addr, + internal, + m_options.m_hardware).get(); break; case eSetTypeFunctionName: // Breakpoint by function name @@ -443,7 +454,8 @@ protected: m_options.m_func_names, name_type_mask, m_options.m_skip_prologue, - internal).get(); + internal, + m_options.m_hardware).get(); } break; @@ -464,7 +476,8 @@ protected: &(m_options.m_filenames), regexp, m_options.m_skip_prologue, - internal).get(); + internal, + m_options.m_hardware).get(); } break; case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. @@ -496,12 +509,19 @@ protected: result.SetStatus (eReturnStatusFailed); return false; } - bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get(); + bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), + &(m_options.m_filenames), + regexp, + internal, + m_options.m_hardware).get(); } break; case eSetTypeException: { - bp = target->CreateExceptionBreakpoint (m_options.m_language, m_options.m_catch_bp, m_options.m_throw_bp).get(); + bp = target->CreateExceptionBreakpoint (m_options.m_language, + m_options.m_catch_bp, + m_options.m_throw_bp, + m_options.m_hardware).get(); } break; default: @@ -603,84 +623,87 @@ private: OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { - { LLDB_OPT_NOT_10, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, + { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. " "Can repeat this option multiple times to specify multiple shared libraries."}, - { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, + { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_ALL, false, "one-shot", 'o', no_argument, NULL, 0, eArgTypeNone, + { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." }, - { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression, + { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex, + { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument."}, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, 0, eArgTypeThreadID, + { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, 0, eArgTypeThreadName, + { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."}, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, 0, eArgTypeQueueName, + { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, + "Require the breakpoint to use hardware breakpoints."}, + + { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, - { LLDB_OPT_FILE, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. " "Note, by default lldb only looks for files that are #included if they use the standard include file extensions. " "To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy" " to \"always\"."}, - { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint."}, // Comment out this option for the moment, as we don't actually use it, but will in the future. // This way users won't see it, but the infrastructure is left in place. - // { 0, false, "column", 'C', required_argument, NULL, "<column>", + // { 0, false, "column", 'C', OptionParser::eRequiredArgument, NULL, "<column>", // "Set the breakpoint by source location at this particular column."}, - { LLDB_OPT_SET_2, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, + { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Set the breakpoint by address, at the specified address."}, - { LLDB_OPT_SET_3, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, + { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" }, - { LLDB_OPT_SET_4, true, "fullname", 'F', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName, + { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and " "for Objective C this means a full function prototype with class and selector. " "Can be repeated multiple times to make one breakpoint for multiple names." }, - { LLDB_OPT_SET_5, true, "selector", 'S', required_argument, NULL, 0, eArgTypeSelector, + { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." }, - { LLDB_OPT_SET_6, true, "method", 'M', required_argument, NULL, 0, eArgTypeMethod, + { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, NULL, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to make one breakpoint for multiple methods." }, - { LLDB_OPT_SET_7, true, "func-regex", 'r', required_argument, NULL, 0, eArgTypeRegularExpression, + { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." }, - { LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, + { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). " "Can be repeated multiple times to make one breakpoint for multiple symbols." }, - { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', required_argument, NULL, 0, eArgTypeRegularExpression, + { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files " "specified with the -f option. The -f option can be specified more than once. " "If no source files are specified, uses the current \"default source file\"" }, - { LLDB_OPT_SET_10, true, "language-exception", 'E', required_argument, NULL, 0, eArgTypeLanguage, + { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" }, - { LLDB_OPT_SET_10, false, "on-throw", 'w', required_argument, NULL, 0, eArgTypeBoolean, + { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, - { LLDB_OPT_SET_10, false, "on-catch", 'h', required_argument, NULL, 0, eArgTypeBoolean, + { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, - { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', required_argument, NULL, 0, eArgTypeBoolean, + { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } @@ -989,15 +1012,15 @@ private: OptionDefinition CommandObjectBreakpointModify::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, -{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', required_argument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, -{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."}, -{ LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, -{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."}, -{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, -{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, -{ LLDB_OPT_SET_1, false, "enable", 'e', no_argument, NULL, 0, eArgTypeNone, "Enable the breakpoint."}, -{ LLDB_OPT_SET_2, false, "disable", 'd', no_argument, NULL, 0, eArgTypeNone, "Disable the breakpoint."}, +{ LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, +{ LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, +{ LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."}, +{ LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, +{ LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."}, +{ LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, +{ LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, +{ LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable the breakpoint."}, +{ LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Disable the breakpoint."}, { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1055,7 +1078,7 @@ protected: { // No breakpoint selected; enable all currently set breakpoints. target->EnableAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints enabled. (%lu breakpoints)\n", num_breakpoints); + result.AppendMessageWithFormat ("All breakpoints enabled. (%zu breakpoints)\n", num_breakpoints); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -1174,7 +1197,7 @@ protected: { // No breakpoint selected; disable all currently set breakpoints. target->DisableAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints disabled. (%lu breakpoints)\n", num_breakpoints); + result.AppendMessageWithFormat ("All breakpoints disabled. (%zu breakpoints)\n", num_breakpoints); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else @@ -1398,18 +1421,18 @@ private: OptionDefinition CommandObjectBreakpointList::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "internal", 'i', no_argument, NULL, 0, eArgTypeNone, + { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show debugger internal breakpoints" }, - { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone, + { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)."}, // FIXME: We need to add an "internal" command, and then add this sort of thing to it. // But I need to see it for now, and don't want to wait. - { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone, + { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations."}, - { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, + { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } @@ -1609,10 +1632,10 @@ private: OptionDefinition CommandObjectBreakpointClear::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file."}, - { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, + { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } @@ -1676,7 +1699,7 @@ protected: else { target->RemoveAllBreakpoints (); - result.AppendMessageWithFormat ("All breakpoints removed. (%lu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint"); + result.AppendMessageWithFormat ("All breakpoints removed. (%zu %s)\n", num_breakpoints, num_breakpoints > 1 ? "breakpoints" : "breakpoint"); } result.SetStatus (eReturnStatusSuccessFinishNoResult); } diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index c4504a4c6516..e540461dadae 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -640,16 +640,16 @@ g_script_option_enumeration[4] = OptionDefinition CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner, + { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, + { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, - { LLDB_OPT_SET_ALL, false, "script-type", 's', required_argument, g_script_option_enumeration, 0, eArgTypeNone, + { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."}, - { LLDB_OPT_SET_2, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, + { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index 4699aa6d9c4a..6824ead0d9e0 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -156,9 +156,9 @@ protected: } else { - std::pair<bool,uint64_t> start_idx = {m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()}; - std::pair<bool,uint64_t> stop_idx = {m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()}; - std::pair<bool,uint64_t> count = {m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()}; + std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue()); + std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue()); + std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue()); const CommandHistory& history(m_interpreter.GetCommandHistory()); @@ -227,10 +227,10 @@ protected: OptionDefinition CommandObjectCommandsHistory::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, -{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."}, -{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, -{ LLDB_OPT_SET_2, false, "clear", 'C', no_argument, NULL, 0, eArgTypeBoolean, "Clears the current command history."}, +{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, +{ LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."}, +{ LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, +{ LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, NULL, 0, eArgTypeBoolean, "Clears the current command history."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -410,9 +410,9 @@ protected: OptionDefinition CommandObjectCommandsSource::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, -{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, -{ LLDB_OPT_SET_ALL, false, "silent-run", 's', required_argument, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, +{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, +{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, +{ LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1243,8 +1243,8 @@ private: OptionDefinition CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."}, -{ LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, +{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "The help text to display for this command."}, +{ LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL } }; @@ -1517,7 +1517,7 @@ protected: OptionDefinition CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "allow-reload", 'r', no_argument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."}, + { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1828,8 +1828,8 @@ static OptionEnumValueElement g_script_synchro_type[] = OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, - { LLDB_OPT_SET_1, false, "synchronicity", 's', required_argument, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, + { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, + { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 0d40fcd7c0b5..fc148b1899f6 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -231,28 +231,28 @@ CommandObjectDisassemble::CommandOptions::GetDefinitions () OptionDefinition CommandObjectDisassemble::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', no_argument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, -{ LLDB_OPT_SET_ALL, false, "context" , 'C', required_argument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."}, -{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', no_argument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."}, -{ LLDB_OPT_SET_ALL, false, "raw" , 'r', no_argument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, -{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', required_argument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, -{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', required_argument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " +{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."}, +{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."}, +{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."}, +{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."}, +{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."}, +{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , NULL, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " "Currently the only valid options are default, and for Intel" " architectures, att and intel."}, -{ LLDB_OPT_SET_ALL, false, "arch" , 'A', required_argument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, +{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."}, { LLDB_OPT_SET_1 | - LLDB_OPT_SET_2 , true , "start-address", 's', required_argument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, -{ LLDB_OPT_SET_1 , false, "end-address" , 'e', required_argument , NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."}, + LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."}, +{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | - LLDB_OPT_SET_5 , false, "count" , 'c', required_argument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."}, -{ LLDB_OPT_SET_3 , false, "name" , 'n', required_argument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, + LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."}, +{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."}, -{ LLDB_OPT_SET_4 , false, "frame" , 'f', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, -{ LLDB_OPT_SET_5 , false, "pc" , 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."}, -{ LLDB_OPT_SET_6 , false, "line" , 'l', no_argument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there debug line table information, else disasemble around the pc."}, -{ LLDB_OPT_SET_7 , false, "address" , 'a', required_argument , NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, +{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."}, +{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble around the current pc."}, +{ LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."}, +{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , NULL, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."}, { 0 , false, NULL , 0, 0 , NULL, 0, eArgTypeNone, NULL } }; @@ -453,7 +453,9 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result) { ModuleSP module_sp (symbol_containing_address.GetModule()); SymbolContext sc; - module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc); + bool resolve_tail_call_address = true; // PC can be one past the address range of the function. + module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc, + resolve_tail_call_address); if (sc.function || sc.symbol) { sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range); diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index da472d17331b..6d44f71b8d95 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Value.h" #include "lldb/Core/InputReader.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Expression/ClangExpressionVariable.h" #include "lldb/Expression/ClangUserExpression.h" #include "lldb/Expression/ClangFunction.h" @@ -49,13 +50,22 @@ CommandObjectExpression::CommandOptions::~CommandOptions () { } +static OptionEnumValueElement g_description_verbosity_type[] = +{ + { eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", "Only show the description string"}, + { eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", "Show the full output, including persistent variable's name and type"}, + { 0, NULL, NULL } +}; + OptionDefinition CommandObjectExpression::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', required_argument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', required_argument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, + { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument , NULL, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, + { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, }; @@ -127,6 +137,24 @@ CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &int error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg); break; } + + case 'v': + if (!option_arg) + { + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull; + break; + } + m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg); + break; + + case 'g': + debug = true; + unwind_on_error = false; + ignore_breakpoints = false; + break; + default: error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); break; @@ -153,6 +181,8 @@ CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpret show_summary = true; try_all_threads = true; timeout = 0; + debug = false; + m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact; } const OptionDefinition* @@ -339,7 +369,10 @@ CommandObjectExpression::EvaluateExpression .SetKeepInMemory(keep_in_memory) .SetUseDynamic(m_varobj_options.use_dynamic) .SetRunOthers(m_command_options.try_all_threads) - .SetTimeoutUsec(m_command_options.timeout); + .SetDebug(m_command_options.debug); + + if (m_command_options.timeout > 0) + options.SetTimeoutUsec(m_command_options.timeout); exe_results = target->EvaluateExpression (expr, exe_ctx.GetFramePtr(), @@ -357,11 +390,10 @@ CommandObjectExpression::EvaluateExpression if (format != eFormatDefault) result_valobj_sp->SetFormat (format); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(true,format)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format)); - ValueObject::DumpValueObject (*(output_stream), - result_valobj_sp.get(), // Variable object to dump - options); + result_valobj_sp->Dump(*output_stream,options); + if (result) result->SetStatus (eReturnStatusSuccessFinishResult); } diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h index 3964f2d423eb..e0703a22a4cc 100644 --- a/source/Commands/CommandObjectExpression.h +++ b/source/Commands/CommandObjectExpression.h @@ -55,8 +55,10 @@ public: bool ignore_breakpoints; bool show_types; bool show_summary; + bool debug; uint32_t timeout; bool try_all_threads; + LanguageRuntimeDescriptionDisplayVerbosity m_verbosity; }; CommandObjectExpression (CommandInterpreter &interpreter); diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index aace3a649602..0ef973261508 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -25,6 +25,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -244,7 +245,14 @@ protected: if (command.GetArgumentCount() == 1) { const char *frame_idx_cstr = command.GetArgumentAtIndex(0); - frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0); + bool success = false; + frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0, &success); + if (!success) + { + result.AppendErrorWithFormat ("invalid frame index argument '%s'", frame_idx_cstr); + result.SetStatus (eReturnStatusFailed); + return false; + } } else if (command.GetArgumentCount() == 0) { @@ -283,7 +291,7 @@ protected: OptionDefinition CommandObjectFrameSelect::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."}, +{ LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -400,7 +408,7 @@ protected: else if (!m_option_variable.summary_string.IsCurrentValueEmpty()) summary_format_sp.reset(new StringSummaryFormat(TypeSummaryImpl::Flags(),m_option_variable.summary_string.GetCurrentValue())); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,eFormatDefault,summary_format_sp)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,eFormatDefault,summary_format_sp)); if (variable_list) { @@ -447,9 +455,7 @@ protected: if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } - ValueObject::DumpValueObject (result.GetOutputStream(), - valobj_sp.get(), - options); + valobj_sp->Dump(result.GetOutputStream(),options); } } } @@ -493,9 +499,7 @@ protected: Stream &output_stream = result.GetOutputStream(); options.SetRootValueObjectName(valobj_sp->GetParent() ? name_cstr : NULL); - ValueObject::DumpValueObject (output_stream, - valobj_sp.get(), - options); + valobj_sp->Dump(output_stream,options); } else { @@ -571,9 +575,7 @@ protected: options.SetFormat(format); options.SetRootValueObjectName(name_cstr); - ValueObject::DumpValueObject (result.GetOutputStream(), - valobj_sp.get(), - options); + valobj_sp->Dump(result.GetOutputStream(),options); } } } diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp index d2c97f91260b..bd0c3938c702 100644 --- a/source/Commands/CommandObjectHelp.cpp +++ b/source/Commands/CommandObjectHelp.cpp @@ -54,8 +54,8 @@ CommandObjectHelp::~CommandObjectHelp() OptionDefinition CommandObjectHelp::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', no_argument, NULL, 0, eArgTypeNone, "Show aliases in the command list."}, - { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', no_argument, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."}, + { LLDB_OPT_SET_ALL, false, "show-aliases", 'a', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show aliases in the command list."}, + { LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Hide user-defined commands from the list."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index 5fb79154c4ef..2d815846a607 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -215,15 +215,15 @@ protected: OptionDefinition CommandObjectLogEnable::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Set the destination file to log to."}, -{ LLDB_OPT_SET_1, false, "threadsafe", 't', no_argument, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, -{ LLDB_OPT_SET_1, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose logging." }, -{ LLDB_OPT_SET_1, false, "debug", 'g', no_argument, NULL, 0, eArgTypeNone, "Enable debug logging." }, -{ LLDB_OPT_SET_1, false, "sequence", 's', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, -{ LLDB_OPT_SET_1, false, "timestamp", 'T', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, -{ LLDB_OPT_SET_1, false, "pid-tid", 'p', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, -{ LLDB_OPT_SET_1, false, "thread-name",'n', no_argument, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, -{ LLDB_OPT_SET_1, false, "stack", 'S', no_argument, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, +{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Set the destination file to log to."}, +{ LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, +{ LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose logging." }, +{ LLDB_OPT_SET_1, false, "debug", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable debug logging." }, +{ LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, +{ LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, +{ LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, +{ LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, +{ LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index 4725a4da6578..2ee275e11f66 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -12,6 +12,8 @@ #include "CommandObjectMemory.h" // C Includes +#include <inttypes.h> + // C++ Includes // Other libraries and framework includes // Project includes @@ -21,6 +23,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectMemory.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Interpreter/Args.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -39,12 +42,12 @@ using namespace lldb_private; static OptionDefinition g_option_table[] = { - { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, - { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, - { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, + { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."}, + { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."}, + { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."}, { LLDB_OPT_SET_1| LLDB_OPT_SET_2| - LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, + LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."}, }; @@ -648,7 +651,7 @@ protected: } else if (m_format_options.GetCountValue().OptionWasSet()) { - result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count); + result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %zu), not both.\n", end_addr, item_count); result.SetStatus(eReturnStatusFailed); return false; } @@ -705,7 +708,7 @@ protected: } if (bytes_read < total_byte_size) - result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr); + result.AppendWarningWithFormat("Not all bytes (%zu/%zu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr); } else { @@ -834,11 +837,9 @@ protected: if (format != eFormatDefault) valobj_sp->SetFormat (format); - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(false,format)); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format)); - ValueObject::DumpValueObject (*output_stream, - valobj_sp.get(), - options); + valobj_sp->Dump(*output_stream,options); } else { @@ -859,16 +860,28 @@ protected: Format format = m_format_options.GetFormat(); if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) ) - && (item_byte_size != 1) - && (item_count == 1)) + && (item_byte_size != 1)) { - // this turns requests such as - // memory read -fc -s10 -c1 *charPtrPtr - // which make no sense (what is a char of size 10?) - // into a request for fetching 10 chars of size 1 from the same memory location - format = eFormatCharArray; - item_count = item_byte_size; - item_byte_size = 1; + // if a count was not passed, or it is 1 + if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1) + { + // this turns requests such as + // memory read -fc -s10 -c1 *charPtrPtr + // which make no sense (what is a char of size 10?) + // into a request for fetching 10 chars of size 1 from the same memory location + format = eFormatCharArray; + item_count = item_byte_size; + item_byte_size = 1; + } + else + { + // here we passed a count, and it was not 1 + // so we have a byte_size and a count + // we could well multiply those, but instead let's just fail + result.AppendErrorWithFormat("reading memory as characters of size %zu is not supported", item_byte_size); + result.SetStatus(eReturnStatusFailed); + return false; + } } assert (output_stream); @@ -905,8 +918,8 @@ protected: OptionDefinition g_memory_write_option_table[] = { -{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, -{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, +{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."}, +{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."}, }; @@ -1219,7 +1232,7 @@ protected: } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { - result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); + result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } @@ -1247,7 +1260,7 @@ protected: } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { - result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); + result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } @@ -1287,7 +1300,7 @@ protected: } else if (!SIntValueIsValidForSize (sval64, item_byte_size)) { - result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size); + result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %zu byte signed integer value.\n", sval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } @@ -1304,7 +1317,7 @@ protected: } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { - result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); + result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } @@ -1321,7 +1334,7 @@ protected: } else if (!UIntValueIsValidForSize (uval64, item_byte_size)) { - result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size); + result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index c2185e598ad4..ace1ef5b53fb 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -26,10 +26,158 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/Utils.h" using namespace lldb; using namespace lldb_private; +static mode_t +ParsePermissionString(const char* permissions) +{ + if (strlen(permissions) != 9) + return (mode_t)(-1); + bool user_r,user_w,user_x, + group_r,group_w,group_x, + world_r,world_w,world_x; + + user_r = (permissions[0] == 'r'); + user_w = (permissions[1] == 'w'); + user_x = (permissions[2] == 'x'); + + group_r = (permissions[3] == 'r'); + group_w = (permissions[4] == 'w'); + group_x = (permissions[5] == 'x'); + + world_r = (permissions[6] == 'r'); + world_w = (permissions[7] == 'w'); + world_x = (permissions[8] == 'x'); + + mode_t user,group,world; + user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0); + group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0); + world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0); + + return user | group | world; +} + +static OptionDefinition +g_permissions_options[] = +{ + { LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, NULL, 0, eArgTypePermissionsNumber , "Give out the numeric value for permissions (e.g. 757)" }, + { LLDB_OPT_SET_ALL, false, "permissions-string",'s', OptionParser::eRequiredArgument, NULL, 0, eArgTypePermissionsString , "Give out the string value for permissions (e.g. rwxr-xr--)." }, + { LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to read." }, + { LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to write." }, + { LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow user to execute." }, + + { LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to read." }, + { LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to write." }, + { LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow group to execute." }, + + { LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to read." }, + { LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to write." }, + { LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Allow world to execute." }, + +}; + +class OptionPermissions : public lldb_private::OptionGroup +{ +public: + OptionPermissions () + { + } + + virtual + ~OptionPermissions () + { + } + + virtual lldb_private::Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) + { + Error error; + char short_option = (char) GetDefinitions()[option_idx].short_option; + switch (short_option) + { + case 'v': + { + bool ok; + uint32_t perms = Args::StringToUInt32(option_arg, 777, 8, &ok); + if (!ok) + error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); + else + m_permissions = perms; + } + break; + case 's': + { + mode_t perms = ParsePermissionString(option_arg); + if (perms == (mode_t)-1) + error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); + else + m_permissions = perms; + } + case 'r': + m_permissions |= File::ePermissionsUserRead; + break; + case 'w': + m_permissions |= File::ePermissionsUserWrite; + break; + case 'x': + m_permissions |= File::ePermissionsUserExecute; + break; + case 'R': + m_permissions |= File::ePermissionsGroupRead; + break; + case 'W': + m_permissions |= File::ePermissionsGroupWrite; + break; + case 'X': + m_permissions |= File::ePermissionsGroupExecute; + break; + case 'd': + m_permissions |= File::ePermissionsWorldRead; + break; + case 't': + m_permissions |= File::ePermissionsWorldWrite; + break; + case 'e': + m_permissions |= File::ePermissionsWorldExecute; + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting (CommandInterpreter &interpreter) + { + m_permissions = 0; + } + + virtual uint32_t + GetNumDefinitions () + { + return llvm::array_lengthof(g_permissions_options); + } + + const lldb_private::OptionDefinition* + GetDefinitions () + { + return g_permissions_options; + } + + // Instance variables to hold the values for command options. + + uint32_t m_permissions; +private: + DISALLOW_COPY_AND_ASSIGN(OptionPermissions); +}; //---------------------------------------------------------------------- // "platform select <platform-name>" @@ -274,11 +422,26 @@ protected: } else { - result.AppendError ("no platform us currently selected\n"); + result.AppendError ("no platform is currently selected\n"); result.SetStatus (eReturnStatusFailed); } return result.Succeeded(); } + + virtual Options * + GetOptions () + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + OptionGroupOptions* m_platform_options = NULL; + if (platform_sp) + { + m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); + if (m_platform_options != NULL && !m_platform_options->m_did_finalize) + m_platform_options->Finalize(); + } + return m_platform_options; + } + }; //---------------------------------------------------------------------- @@ -359,6 +522,680 @@ protected: return result.Succeeded(); } }; + +//---------------------------------------------------------------------- +// "platform mkdir" +//---------------------------------------------------------------------- +class CommandObjectPlatformMkDir : public CommandObjectParsed +{ +public: + CommandObjectPlatformMkDir (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform mkdir", + "Make a new directory on the remote end.", + NULL, + 0), + m_options(interpreter) + { + } + + virtual + ~CommandObjectPlatformMkDir () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + std::string cmd_line; + args.GetCommandString(cmd_line); + mode_t perms; + const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r'); + if (options_permissions) + perms = options_permissions->m_permissions; + else + perms = 0000700 | 0000070 | 0000007; + uint32_t retcode = platform_sp->MakeDirectory(cmd_line,perms); + result.AppendMessageWithFormat("Status = %d\n",retcode); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } + + virtual Options * + GetOptions () + { + if (m_options.DidFinalize() == false) + { + m_options.Append(new OptionPermissions()); + m_options.Finalize(); + } + return &m_options; + } + OptionGroupOptions m_options; + +}; + +//---------------------------------------------------------------------- +// "platform fopen" +//---------------------------------------------------------------------- +class CommandObjectPlatformFOpen : public CommandObjectParsed +{ +public: + CommandObjectPlatformFOpen (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform file open", + "Open a file on the remote end.", + NULL, + 0), + m_options(interpreter) + { + } + + virtual + ~CommandObjectPlatformFOpen () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + Error error; + std::string cmd_line; + args.GetCommandString(cmd_line); + mode_t perms; + const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r'); + if (options_permissions) + perms = options_permissions->m_permissions; + else + perms = 0000700 | 0000070 | 0000007; + lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false), + File::eOpenOptionRead | File::eOpenOptionWrite | + File::eOpenOptionAppend | File::eOpenOptionCanCreate, + perms, + error); + if (error.Success()) + { + result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError(error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } + virtual Options * + GetOptions () + { + if (m_options.DidFinalize() == false) + { + m_options.Append(new OptionPermissions()); + m_options.Finalize(); + } + return &m_options; + } + OptionGroupOptions m_options; +}; + +//---------------------------------------------------------------------- +// "platform fclose" +//---------------------------------------------------------------------- +class CommandObjectPlatformFClose : public CommandObjectParsed +{ +public: + CommandObjectPlatformFClose (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform file close", + "Close a file on the remote end.", + NULL, + 0) + { + } + + virtual + ~CommandObjectPlatformFClose () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + std::string cmd_line; + args.GetCommandString(cmd_line); + const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + Error error; + bool success = platform_sp->CloseFile(fd, error); + if (success) + { + result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError(error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + +//---------------------------------------------------------------------- +// "platform fread" +//---------------------------------------------------------------------- +class CommandObjectPlatformFRead : public CommandObjectParsed +{ +public: + CommandObjectPlatformFRead (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform file read", + "Read data from a file on the remote end.", + NULL, + 0), + m_options (interpreter) + { + } + + virtual + ~CommandObjectPlatformFRead () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + std::string cmd_line; + args.GetCommandString(cmd_line); + const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + std::string buffer(m_options.m_count,0); + Error error; + uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error); + result.AppendMessageWithFormat("Return = %d\n",retcode); + result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str()); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } + virtual Options * + GetOptions () + { + return &m_options; + } + +protected: + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + bool success = false; + + switch (short_option) + { + case 'o': + m_offset = Args::StringToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + case 'c': + m_count = Args::StringToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_offset = 0; + m_count = 1; + } + + 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. + + uint32_t m_offset; + uint32_t m_count; + }; + CommandOptions m_options; +}; +OptionDefinition +CommandObjectPlatformFRead::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." }, + { LLDB_OPT_SET_1, false, "count" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount , "Number of bytes to read from the file." }, + { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL } +}; + + +//---------------------------------------------------------------------- +// "platform fwrite" +//---------------------------------------------------------------------- +class CommandObjectPlatformFWrite : public CommandObjectParsed +{ +public: + CommandObjectPlatformFWrite (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform file write", + "Write data to a file on the remote end.", + NULL, + 0), + m_options (interpreter) + { + } + + virtual + ~CommandObjectPlatformFWrite () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + std::string cmd_line; + args.GetCommandString(cmd_line); + Error error; + const lldb::user_id_t fd = Args::StringToUInt64(cmd_line.c_str(), UINT64_MAX); + uint32_t retcode = platform_sp->WriteFile (fd, + m_options.m_offset, + &m_options.m_data[0], + m_options.m_data.size(), + error); + result.AppendMessageWithFormat("Return = %d\n",retcode); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } + virtual Options * + GetOptions () + { + return &m_options; + } + +protected: + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + bool success = false; + + switch (short_option) + { + case 'o': + m_offset = Args::StringToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); + break; + case 'd': + m_data.assign(option_arg); + break; + + default: + error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_offset = 0; + m_data.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. + + uint32_t m_offset; + std::string m_data; + }; + CommandOptions m_options; +}; +OptionDefinition +CommandObjectPlatformFWrite::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." }, + { LLDB_OPT_SET_1, false, "data" , 'd', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue , "Text to write to the file." }, + { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL } +}; + +class CommandObjectPlatformFile : public CommandObjectMultiword +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommandObjectPlatformFile (CommandInterpreter &interpreter) : + CommandObjectMultiword (interpreter, + "platform file", + "A set of commands to manage file access through a platform", + "platform file [open|close|read|write] ...") + { + LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen (interpreter))); + LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose (interpreter))); + LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead (interpreter))); + LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter))); + } + + virtual + ~CommandObjectPlatformFile () + { + } + +private: + //------------------------------------------------------------------ + // For CommandObjectPlatform only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile); +}; + +//---------------------------------------------------------------------- +// "platform get-file remote-file-path host-file-path" +//---------------------------------------------------------------------- +class CommandObjectPlatformGetFile : public CommandObjectParsed +{ +public: + CommandObjectPlatformGetFile (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform get-file", + "Transfer a file from the remote end to the local host.", + "platform get-file <remote-file-spec> <local-file-spec>", + 0) + { + SetHelpLong( +"Examples: \n\ +\n\ + platform get-file /the/remote/file/path /the/local/file/path\n\ + # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n"); + + CommandArgumentEntry arg1, arg2; + CommandArgumentData file_arg_remote, file_arg_host; + + // Define the first (and only) variant of this arg. + file_arg_remote.arg_type = eArgTypeFilename; + file_arg_remote.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (file_arg_remote); + + // Define the second (and only) variant of this arg. + file_arg_host.arg_type = eArgTypeFilename; + file_arg_host.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the argument entry. + arg2.push_back (file_arg_host); + + // Push the data for the first and the second arguments into the m_arguments vector. + m_arguments.push_back (arg1); + m_arguments.push_back (arg2); + } + + virtual + ~CommandObjectPlatformGetFile () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + // If the number of arguments is incorrect, issue an error message. + if (args.GetArgumentCount() != 2) + { + result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + const char *remote_file_path = args.GetArgumentAtIndex(0); + const char *local_file_path = args.GetArgumentAtIndex(1); + Error error = platform_sp->GetFile(FileSpec(remote_file_path, false), + FileSpec(local_file_path, false)); + if (error.Success()) + { + result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n", + remote_file_path, local_file_path); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + +//---------------------------------------------------------------------- +// "platform get-size remote-file-path" +//---------------------------------------------------------------------- +class CommandObjectPlatformGetSize : public CommandObjectParsed +{ +public: + CommandObjectPlatformGetSize (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform get-size", + "Get the file size from the remote end.", + "platform get-size <remote-file-spec>", + 0) + { + SetHelpLong( +"Examples: \n\ +\n\ + platform get-size /the/remote/file/path\n\ + # Get the file size from the remote end with path /the/remote/file/path.\n"); + + CommandArgumentEntry arg1; + CommandArgumentData file_arg_remote; + + // Define the first (and only) variant of this arg. + file_arg_remote.arg_type = eArgTypeFilename; + file_arg_remote.arg_repetition = eArgRepeatPlain; + // There is only one variant this argument could be; put it into the argument entry. + arg1.push_back (file_arg_remote); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg1); + } + + virtual + ~CommandObjectPlatformGetSize () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + // If the number of arguments is incorrect, issue an error message. + if (args.GetArgumentCount() != 1) + { + result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + std::string remote_file_path(args.GetArgumentAtIndex(0)); + user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false)); + if (size != UINT64_MAX) + { + result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size); + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + +//---------------------------------------------------------------------- +// "platform put-file" +//---------------------------------------------------------------------- +class CommandObjectPlatformPutFile : public CommandObjectParsed +{ +public: + CommandObjectPlatformPutFile (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform put-file", + "Transfer a file from this system to the remote end.", + NULL, + 0) + { + } + + virtual + ~CommandObjectPlatformPutFile () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + const char* src = args.GetArgumentAtIndex(0); + const char* dst = args.GetArgumentAtIndex(1); + + FileSpec src_fs(src, true); + FileSpec dst_fs(dst, false); + + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + Error error (platform_sp->PutFile(src_fs, dst_fs)); + if (error.Success()) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError (error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("no platform currently selected\n"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } +}; + //---------------------------------------------------------------------- // "platform process launch" //---------------------------------------------------------------------- @@ -744,20 +1581,20 @@ protected: OptionDefinition CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1 , false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, -{ LLDB_OPT_SET_2 , true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, -{ LLDB_OPT_SET_3 , true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." }, -{ LLDB_OPT_SET_4 , true , "starts-with", 's', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." }, -{ LLDB_OPT_SET_5 , true , "contains" , 'c', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." }, -{ LLDB_OPT_SET_6 , true , "regex" , 'r', required_argument, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', required_argument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." }, -{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, -{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." }, -{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." }, +{ LLDB_OPT_SET_1 , false, "pid" , 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, +{ LLDB_OPT_SET_2 , true , "name" , 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, +{ LLDB_OPT_SET_3 , true , "ends-with" , 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." }, +{ LLDB_OPT_SET_4 , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." }, +{ LLDB_OPT_SET_5 , true , "contains" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." }, +{ LLDB_OPT_SET_6 , true , "regex" , 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." }, +{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, +{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." }, +{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Enable verbose output." }, { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL } }; @@ -868,8 +1705,206 @@ protected: } }; +class CommandObjectPlatformProcessAttach : public CommandObjectParsed +{ +public: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) + { + // Keep default values of all options in one place: OptionParsingStarting () + OptionParsingStarting (); + } + + ~CommandOptions () + { + } + + Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + bool success = false; + switch (short_option) + { + case 'p': + { + lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); + if (!success || pid == LLDB_INVALID_PROCESS_ID) + { + error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); + } + else + { + attach_info.SetProcessID (pid); + } + } + break; + + case 'P': + attach_info.SetProcessPluginName (option_arg); + break; + + case 'n': + attach_info.GetExecutableFile().SetFile(option_arg, false); + break; + + case 'w': + attach_info.SetWaitForLaunch(true); + break; + + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + } + return error; + } + + void + OptionParsingStarting () + { + attach_info.Clear(); + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + 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) + { + int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; + int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; + + // We are only completing the name option for now... + + const OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs[opt_defs_index].short_option == 'n') + { + // Are we in the name? + + // Look to see if there is a -P argument provided, and if so use that plugin, otherwise + // use the default plugin. + + const char *partial_name = NULL; + partial_name = input.GetArgumentAtIndex(opt_arg_pos); + + PlatformSP platform_sp (m_interpreter.GetPlatform (true)); + if (platform_sp) + { + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) + { + match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); + match_info.SetNameMatchType(eNameMatchStartsWith); + } + platform_sp->FindProcesses (match_info, process_infos); + const uint32_t num_matches = process_infos.GetSize(); + if (num_matches > 0) + { + for (uint32_t i=0; i<num_matches; ++i) + { + matches.AppendString (process_infos.GetProcessNameAtIndex(i), + process_infos.GetProcessNameLengthAtIndex(i)); + } + } + } + } + + return false; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + ProcessAttachInfo attach_info; + }; + + CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform process attach", + "Attach to a process.", + "platform process attach <cmd-options>"), + m_options (interpreter) + { + } + + ~CommandObjectPlatformProcessAttach () + { + } + + bool + DoExecute (Args& command, + CommandReturnObject &result) + { + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (platform_sp) + { + Error err; + ProcessSP remote_process_sp = + platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + else if (remote_process_sp.get() == NULL) + { + result.AppendError("could not attach: unknown reason"); + result.SetStatus (eReturnStatusFailed); + } + else + result.SetStatus (eReturnStatusSuccessFinishResult); + } + else + { + result.AppendError ("no platform is currently selected"); + result.SetStatus (eReturnStatusFailed); + } + return result.Succeeded(); + } + + Options * + GetOptions () + { + return &m_options; + } + +protected: + + CommandOptions m_options; +}; +OptionDefinition +CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, + { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, + { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, + { LLDB_OPT_SET_2, false, "waitfor",'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + class CommandObjectPlatformProcess : public CommandObjectMultiword { @@ -883,7 +1918,7 @@ public: "A set of commands to query, launch and attach to platform processes", "platform process [attach|launch|list] ...") { -// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); + LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); @@ -902,16 +1937,84 @@ private: DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); }; - +//---------------------------------------------------------------------- +// "platform shell" +//---------------------------------------------------------------------- class CommandObjectPlatformShell : public CommandObjectRaw { public: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter), + timeout(10) + { + } + + virtual + ~CommandOptions () + { + } + + virtual uint32_t + GetNumDefinitions () + { + return 1; + } + + virtual const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + virtual Error + SetOptionValue (uint32_t option_idx, + const char *option_value) + { + Error error; + + const char short_option = (char) g_option_table[option_idx].short_option; + + switch (short_option) + { + case 't': + { + bool success; + timeout = Args::StringToUInt32(option_value, 10, 10, &success); + if (!success) + error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value); + break; + } + default: + error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); + break; + } + + return error; + } + + virtual void + OptionParsingStarting () + { + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + uint32_t timeout; + }; + CommandObjectPlatformShell (CommandInterpreter &interpreter) : - CommandObjectRaw (interpreter, - "platform shell", - "Run a shell command on a the selected platform.", - "platform shell <shell-command>", - 0) + CommandObjectRaw (interpreter, + "platform shell", + "Run a shell command on a the selected platform.", + "platform shell <shell-command>", + 0), + m_options(interpreter) { } @@ -920,31 +2023,89 @@ public: { } -protected: + virtual + Options * + GetOptions () + { + return &m_options; + } + virtual bool DoExecute (const char *raw_command_line, CommandReturnObject &result) { - // TODO: Implement "Platform::RunShellCommand()" and switch over to using - // the current platform when it is in the interface. - const char *working_dir = NULL; - std::string output; - int status = -1; - int signo = -1; - Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10)); - if (!output.empty()) - result.GetOutputStream().PutCString(output.c_str()); - if (status > 0) - { - if (signo > 0) - { - const char *signo_cstr = Host::GetSignalAsCString(signo); - if (signo_cstr) - result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); + m_options.NotifyOptionParsingStarting(); + + const char* expr = NULL; + + // Print out an usage syntax on an empty command line. + if (raw_command_line[0] == '\0') + { + result.GetOutputStream().Printf("%s\n", this->GetSyntax()); + return true; + } + + if (raw_command_line[0] == '-') + { + // We have some options and these options MUST end with --. + const char *end_options = NULL; + const char *s = raw_command_line; + while (s && s[0]) + { + end_options = ::strstr (s, "--"); + if (end_options) + { + end_options += 2; // Get past the "--" + if (::isspace (end_options[0])) + { + expr = end_options; + while (::isspace (*expr)) + ++expr; + break; + } + } + s = end_options; + } + + if (end_options) + { + Args args (raw_command_line, end_options - raw_command_line); + if (!ParseOptions (args, result)) + return false; + } + } + + if (expr == NULL) + expr = raw_command_line; + + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + Error error; + if (platform_sp) + { + const char *working_dir = NULL; + std::string output; + int status = -1; + int signo = -1; + error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout)); + if (!output.empty()) + result.GetOutputStream().PutCString(output.c_str()); + if (status > 0) + { + if (signo > 0) + { + const char *signo_cstr = Host::GetSignalAsCString(signo); + if (signo_cstr) + result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); + else + result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); + } else - result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); + result.GetOutputStream().Printf("error: command returned with status %i\n", status); } - else - result.GetOutputStream().Printf("error: command returned with status %i\n", status); + } + else + { + result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n"); + error.SetErrorString("error: cannot run remote shell commands without a platform"); } if (error.Fail()) @@ -958,6 +2119,208 @@ protected: } return true; } + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectPlatformShell::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command."}, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + +struct RecurseCopyBaton +{ + const std::string& destination; + const PlatformSP& platform_sp; + Error error; +}; + + +static FileSpec::EnumerateDirectoryResult +RecurseCopy_Callback (void *baton, + FileSpec::FileType file_type, + const FileSpec &spec) +{ + RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton; + switch (file_type) + { + case FileSpec::eFileTypePipe: + case FileSpec::eFileTypeSocket: + // we have no way to copy pipes and sockets - ignore them and continue + return FileSpec::eEnumerateDirectoryResultNext; + break; + + case FileSpec::eFileTypeSymbolicLink: + // what to do for symlinks? + return FileSpec::eEnumerateDirectoryResultNext; + break; + + case FileSpec::eFileTypeDirectory: + { + // make the new directory and get in there + FileSpec new_directory(rc_baton->destination.c_str(),false); + new_directory.AppendPathComponent(spec.GetLastPathComponent()); + uint32_t errcode = rc_baton->platform_sp->MakeDirectory(new_directory, 0777); + std::string new_directory_path (new_directory.GetPath()); + if (errcode != 0) + { + rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",new_directory_path.c_str()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + + // now recurse + std::string local_path (spec.GetPath()); + RecurseCopyBaton rc_baton2 = { new_directory_path, rc_baton->platform_sp, Error() }; + FileSpec::EnumerateDirectory(local_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2); + if (rc_baton2.error.Fail()) + { + rc_baton->error.SetErrorString(rc_baton2.error.AsCString()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + return FileSpec::eEnumerateDirectoryResultNext; + } + break; + + case FileSpec::eFileTypeRegular: + { + // copy the file and keep going + std::string dest(rc_baton->destination); + dest.append(spec.GetFilename().GetCString()); + Error err = rc_baton->platform_sp->PutFile(spec, FileSpec(dest.c_str(), false)); + if (err.Fail()) + { + rc_baton->error.SetErrorString(err.AsCString()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + } + return FileSpec::eEnumerateDirectoryResultNext; + } + break; + + case FileSpec::eFileTypeInvalid: + case FileSpec::eFileTypeOther: + case FileSpec::eFileTypeUnknown: + rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s/%s", spec.GetDirectory().GetCString(), spec.GetFilename().GetCString()); + return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out + break; + } +} + +//---------------------------------------------------------------------- +// "platform install" - install a target to a remote end +//---------------------------------------------------------------------- +class CommandObjectPlatformInstall : public CommandObjectParsed +{ +public: + CommandObjectPlatformInstall (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "platform target-install", + "Install a target (bundle or executable file) to the remote end.", + "platform target-install <local-thing> <remote-sandbox>", + 0) + { + } + + virtual + ~CommandObjectPlatformInstall () + { + } + + virtual bool + DoExecute (Args& args, CommandReturnObject &result) + { + if (args.GetArgumentCount() != 2) + { + result.AppendError("platform target-install takes two arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + // TODO: move the bulk of this code over to the platform itself + std::string local_thing(args.GetArgumentAtIndex(0)); + std::string remote_sandbox(args.GetArgumentAtIndex(1)); + FileSpec source(local_thing.c_str(), true); + if (source.Exists() == false) + { + result.AppendError("source location does not exist or is not accessible"); + result.SetStatus(eReturnStatusFailed); + return false; + } + PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); + if (!platform_sp) + { + result.AppendError ("no platform currently selected"); + result.SetStatus (eReturnStatusFailed); + return false; + } + FileSpec::FileType source_type(source.GetFileType()); + if (source_type == FileSpec::eFileTypeDirectory) + { + if (platform_sp->GetSupportsRSync()) + { + FileSpec remote_folder(remote_sandbox.c_str(), false); + Error rsync_err = platform_sp->PutFile(source, remote_folder); + if (rsync_err.Success()) + { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } + } + FileSpec remote_folder(remote_sandbox.c_str(), false); + remote_folder.AppendPathComponent(source.GetLastPathComponent()); + // TODO: default permissions are bad + uint32_t errcode = platform_sp->MakeDirectory(remote_folder, 0777); + if (errcode != 0) + { + result.AppendError("unable to setup target directory on remote end"); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + // now recurse + std::string remote_folder_path (remote_folder.GetPath()); + Error err = RecurseCopy(source,remote_folder_path,platform_sp); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + else + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); + } + else if (source_type == FileSpec::eFileTypeRegular) + { + // just a plain file - push it to remote and be done + remote_sandbox.append(source.GetFilename().GetCString()); + FileSpec destination(remote_sandbox.c_str(),false); + Error err = platform_sp->PutFile(source, destination); + if (err.Success()) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + { + result.AppendError(err.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + return result.Succeeded(); + } + else + { + result.AppendError("source is not a known type of file"); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } + } +private: + + Error + RecurseCopy (const FileSpec& source, + const std::string& destination, + const PlatformSP& platform_sp) + { + std::string source_path (source.GetPath()); + RecurseCopyBaton baton = { destination, platform_sp, Error() }; + FileSpec::EnumerateDirectory(source_path.c_str(), true, true, true, RecurseCopy_Callback, &baton); + return baton.error; + } }; //---------------------------------------------------------------------- @@ -974,8 +2337,16 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); +#ifdef LLDB_CONFIGURATION_DEBUG + LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter))); + LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter))); + LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter))); + LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter))); + LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter))); +#endif LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); + LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter))); } diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index 4c406a4f2aae..8bdec6e4573a 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -302,7 +302,7 @@ protected: if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false) { result.SetStatus (eReturnStatusSuccessContinuingNoResult); - StateType state = process->WaitForProcessToStop (NULL); + StateType state = process->WaitForProcessToStop (NULL, NULL, false); if (state == eStateStopped) { @@ -359,14 +359,14 @@ protected: //OptionDefinition //CommandObjectProcessLaunch::CommandOptions::g_option_table[] = //{ -//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, -//{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, -//{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, -//{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, -//{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, -//{ SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, -//{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, -//{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, +//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, +//{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, +//{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, +//{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, +//{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, +//{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, +//{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, +//{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, //{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } //}; // @@ -701,12 +701,12 @@ protected: OptionDefinition CommandObjectProcessAttach::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "continue",'c', no_argument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."}, -{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, -{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, -{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, -{ LLDB_OPT_SET_2, false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, -{ LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, +{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."}, +{ LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, +{ LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, +{ LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, +{ LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, +{ LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -891,7 +891,7 @@ protected: OptionDefinition CommandObjectProcessContinue::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument, NULL, 0, eArgTypeUnsignedInteger, +{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1031,7 +1031,7 @@ protected: OptionDefinition CommandObjectProcessDetach::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "keep-stopped", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, +{ LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1203,7 +1203,7 @@ protected: OptionDefinition CommandObjectProcessConnect::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, + { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1908,9 +1908,9 @@ protected: OptionDefinition CommandObjectProcessHandle::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "stop", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, -{ LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, -{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, +{ LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, +{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, +{ LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index ba43f23f34ac..7cbfaa5d60fc 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -98,7 +98,7 @@ public: { strm.Indent (); - bool prefix_with_altname = m_command_options.alternate_name; + bool prefix_with_altname = (bool)m_command_options.alternate_name; bool prefix_with_name = !prefix_with_altname; reg_value.Dump(&strm, reg_info, prefix_with_name, prefix_with_altname, m_format_options.GetFormat(), 8); if ((reg_info->encoding == eEncodingUint) || (reg_info->encoding == eEncodingSint)) @@ -192,7 +192,7 @@ protected: if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx)) { if (errno) - result.AppendErrorWithFormat ("register read failed with errno: %d\n", errno); + result.AppendErrorWithFormat ("register read failed: %s\n", strerror(errno)); else result.AppendError ("unknown error while reading registers.\n"); result.SetStatus (eReturnStatusFailed); @@ -351,9 +351,9 @@ protected: const OptionDefinition CommandObjectRegisterRead::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "alternate", 'A', no_argument , NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."}, - { LLDB_OPT_SET_1 , false, "set" , 's', required_argument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."}, - { LLDB_OPT_SET_2 , false, "all" , 'a', no_argument , NULL, 0, eArgTypeNone , "Show all register sets."}, + { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Display register names using the alternate register name if there is one."}, + { LLDB_OPT_SET_1 , false, "set" , 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex , "Specify which register sets to dump by index."}, + { LLDB_OPT_SET_2 , false, "all" , 'a', OptionParser::eNoArgument , NULL, 0, eArgTypeNone , "Show all register sets."}, }; uint32_t diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp index 95cc9b68a8f7..78a5ad6ca86a 100644 --- a/source/Commands/CommandObjectSettings.cpp +++ b/source/Commands/CommandObjectSettings.cpp @@ -288,7 +288,7 @@ private: OptionDefinition CommandObjectSettingsSet::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_2, false, "global", 'g', no_argument, NULL, 0, eArgTypeNone, "Apply the new value to the global default value." }, + { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Apply the new value to the global default value." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index a08e39352b3d..1f6873611a22 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -137,8 +137,8 @@ protected: OptionDefinition CommandObjectSourceInfo::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."}, -{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."}, +{ LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."}, +{ LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -890,15 +890,15 @@ protected: OptionDefinition CommandObjectSourceList::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of source lines to display."}, +{ LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "The number of source lines to display."}, { LLDB_OPT_SET_1 | - LLDB_OPT_SET_2 , false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."}, -{ LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', no_argument, NULL, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints."}, -{ LLDB_OPT_SET_1 , false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."}, -{ LLDB_OPT_SET_1 , false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."}, -{ LLDB_OPT_SET_2 , false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."}, -{ LLDB_OPT_SET_3 , false, "address",'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."}, -{ LLDB_OPT_SET_4, false, "reverse", 'r', no_argument, NULL, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."}, + LLDB_OPT_SET_2 , false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library."}, +{ LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints."}, +{ LLDB_OPT_SET_1 , false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source."}, +{ LLDB_OPT_SET_1 , false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "The line number at which to start the display source."}, +{ LLDB_OPT_SET_2 , false, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display."}, +{ LLDB_OPT_SET_3 , false, "address",'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line."}, +{ LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index dd0e2a0011b0..ef431e25c3d4 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/State.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/Symbols.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -158,6 +159,7 @@ public: m_arch_option (), m_platform_options(true), // Do include the "--platform" option in the platform settings by passing true m_core_file (LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename, "Fullpath to a core file to use for this target."), + m_platform_path (LLDB_OPT_SET_1, false, "platform-path", 'P', 0, eArgTypePath, "Path to the remote file to use for this target."), m_symbol_file (LLDB_OPT_SET_1, false, "symfile", 's', 0, eArgTypeFilename, "Fullpath to a stand alone debug symbols file for when debug symbols are not in the executable."), m_remote_file (LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename, "Fullpath to the file on the remote host if debugging remotely."), m_add_dependents (LLDB_OPT_SET_1, false, "no-dependents", 'd', "Don't load dependent files when creating the target, just add the specified executable.", true, true) @@ -178,6 +180,7 @@ public: m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); @@ -226,7 +229,7 @@ protected: FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue()); FileSpec remote_file (m_remote_file.GetOptionValue().GetCurrentValue()); - if (argc == 1 || core_file) + if (argc == 1 || core_file || remote_file) { FileSpec symfile (m_symbol_file.GetOptionValue().GetCurrentValue()); if (symfile) @@ -243,11 +246,70 @@ protected: const char *file_path = command.GetArgumentAtIndex(0); Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path); - TargetSP target_sp; + FileSpec file_spec; + + if (file_path) + file_spec.SetFile (file_path, true); + + bool must_set_platform_path = false; + Debugger &debugger = m_interpreter.GetDebugger(); + PlatformSP platform_sp(debugger.GetPlatformList().GetSelectedPlatform ()); + + if (remote_file) + { + // I have a remote file.. two possible cases + if (file_spec && file_spec.Exists()) + { + // if the remote file does not exist, push it there + if (!platform_sp->GetFileExists (remote_file)) + { + Error err = platform_sp->PutFile(file_spec, remote_file); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + else + { + // there is no local file and we need one + // in order to make the remote ---> local transfer we need a platform + // TODO: if the user has passed in a --platform argument, use it to fetch the right platform + if (!platform_sp) + { + result.AppendError("unable to perform remote debugging without a platform"); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (file_path) + { + // copy the remote file to the local file + Error err = platform_sp->GetFile(remote_file, file_spec); + if (err.Fail()) + { + result.AppendError(err.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + // make up a local file + result.AppendError("remote --> local transfer without local path is not implemented yet"); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + + TargetSP target_sp; const char *arch_cstr = m_arch_option.GetArchitectureName(); const bool get_dependent_files = m_add_dependents.GetOptionValue().GetCurrentValue(); Error error (debugger.GetTargetList().CreateTarget (debugger, +// remote_file ? remote_file : file_spec, file_path, arch_cstr, get_dependent_files, @@ -273,6 +335,13 @@ protected: } debugger.GetTargetList().SetSelectedTarget(target_sp.get()); + if (must_set_platform_path) + { + ModuleSpec main_module_spec(file_spec); + ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec); + if (module_sp) + module_sp->SetPlatformFileSpec(remote_file); + } if (core_file) { char core_path[PATH_MAX]; @@ -341,6 +410,7 @@ private: OptionGroupArchitecture m_arch_option; OptionGroupPlatform m_platform_options; OptionGroupFile m_core_file; + OptionGroupFile m_platform_path; OptionGroupFile m_symbol_file; OptionGroupFile m_remote_file; OptionGroupBoolean m_add_dependents; @@ -650,7 +720,7 @@ public: void DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name) { - ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions()); switch (var_sp->GetScope()) { @@ -692,10 +762,7 @@ public: options.SetRootValueObjectName(root_name); - ValueObject::DumpValueObject (s, - valobj_sp.get(), - options); - + valobj_sp->Dump(s,options); } @@ -2214,7 +2281,7 @@ g_sort_option_enumeration[4] = OptionDefinition CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "sort", 's', required_argument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."}, + { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -2694,6 +2761,8 @@ protected: module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue(); if (m_symbol_file.GetOptionValue().OptionWasSet()) module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue(); + if (!module_spec.GetArchitecture().IsValid()) + module_spec.GetArchitecture() = target->GetArchitecture(); Error error; ModuleSP module_sp (target->GetSharedModule (module_spec, &error)); if (!module_sp) @@ -3401,21 +3470,21 @@ protected: OptionDefinition CommandObjectTargetModulesList::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Display the image at this address."}, - { LLDB_OPT_SET_1, false, "arch", 'A', optional_argument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."}, - { LLDB_OPT_SET_1, false, "triple", 't', optional_argument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."}, - { LLDB_OPT_SET_1, false, "header", 'h', no_argument, NULL, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise."}, - { LLDB_OPT_SET_1, false, "offset", 'o', no_argument, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."}, - { LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."}, - { LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."}, - { LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."}, - { LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."}, - { LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."}, - { LLDB_OPT_SET_1, false, "symfile-unique", 'S', optional_argument, NULL, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file."}, - { LLDB_OPT_SET_1, false, "mod-time", 'm', optional_argument, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."}, - { LLDB_OPT_SET_1, false, "ref-count", 'r', optional_argument, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."}, - { LLDB_OPT_SET_1, false, "pointer", 'p', optional_argument, NULL, 0, eArgTypeNone, "Display the module pointer."}, - { LLDB_OPT_SET_1, false, "global", 'g', no_argument, NULL, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."}, + { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Display the image at this address."}, + { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."}, + { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."}, + { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the image header address as a load address if debugging, a file address otherwise."}, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the image header address offset from the header file address (the slide amount)."}, + { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."}, + { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."}, + { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."}, + { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."}, + { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."}, + { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file."}, + { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the modification time with optional width of the module."}, + { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, NULL, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache."}, + { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, NULL, 0, eArgTypeNone, "Display the module pointer."}, + { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -3468,6 +3537,7 @@ public: case 'a': { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + m_str = option_arg; m_type = eLookupTypeAddress; m_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); if (m_addr == LLDB_INVALID_ADDRESS) @@ -3481,6 +3551,10 @@ public: m_type = eLookupTypeFunctionOrSymbol; break; } + + default: + error.SetErrorStringWithFormat ("unrecognized option %c.", short_option); + break; } return error; @@ -3591,8 +3665,21 @@ protected: } } } + else + { + result.AppendError ("address-expression or function name option must be specified."); + result.SetStatus (eReturnStatusFailed); + return false; + } size_t num_matches = sc_list.GetSize(); + if (num_matches == 0) + { + result.AppendErrorWithFormat ("no unwind data found that matches '%s'.", m_options.m_str.c_str()); + result.SetStatus (eReturnStatusFailed); + return false; + } + for (uint32_t idx = 0; idx < num_matches; idx++) { SymbolContext sc; @@ -3668,8 +3755,8 @@ protected: OptionDefinition CommandObjectTargetModulesShowUnwind::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "name", 'n', required_argument, NULL, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."}, - { LLDB_OPT_SET_2, false, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"}, + { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name."}, + { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address"}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -4112,21 +4199,21 @@ protected: OptionDefinition CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."}, - { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."}, + { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules."}, + { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."}, { LLDB_OPT_SET_2| LLDB_OPT_SET_4 | LLDB_OPT_SET_5 /* FIXME: re-enable this for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ , - false, "regex", 'r', no_argument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."}, - { LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules."}, - { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."}, - { LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."}, + false, "regex", 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."}, + { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules."}, + { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."}, + { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."}, { LLDB_OPT_SET_FROM_TO(3,5), - false, "no-inlines", 'i', no_argument, NULL, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)."}, - { LLDB_OPT_SET_4, true, "function", 'F', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."}, - { LLDB_OPT_SET_5, true, "name", 'n', required_argument, NULL, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules."}, - { LLDB_OPT_SET_6, true, "type", 't', required_argument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules."}, - { LLDB_OPT_SET_ALL, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."}, - { LLDB_OPT_SET_ALL, false, "all", 'A', no_argument, NULL, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."}, + false, "no-inlines", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)."}, + { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."}, + { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules."}, + { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules."}, + { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."}, + { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -5062,27 +5149,27 @@ private: OptionDefinition CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner, + { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, + { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run."}, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, 0, eArgTypeThreadIndex, + { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument."}, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, 0, eArgTypeThreadID, + { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument."}, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, 0, eArgTypeThreadName, + { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument."}, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, 0, eArgTypeQueueName, + { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, NULL, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument."}, - { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum, + { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run."}, - { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum, + { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run."}, - { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, 0, eArgTypeClassName, + { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." }, - { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, + { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." }, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index b8657b4361d5..f46a2219a509 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -258,8 +258,8 @@ protected: OptionDefinition CommandObjectThreadBacktrace::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, -{ LLDB_OPT_SET_1, false, "start", 's', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, +{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"}, +{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -591,10 +591,10 @@ g_duo_running_mode[] = OptionDefinition CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', required_argument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, -{ LLDB_OPT_SET_1, false, "run-mode", 'm', required_argument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, -{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', required_argument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, -{ LLDB_OPT_SET_1, false, "step-in-target", 't', required_argument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, +{ LLDB_OPT_SET_1, false, "avoid-no-debug", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether step-in will step over functions with no debug information."}, +{ LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, +{ LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, +{ LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -660,11 +660,14 @@ public: StateType state = process->GetState(); if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended)) { - Mutex::Locker locker (process->GetThreadList().GetMutex()); - const uint32_t num_threads = process->GetThreadList().GetSize(); const size_t argc = command.GetArgumentCount(); if (argc > 0) { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + Mutex::Locker locker (process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); std::vector<Thread *> resume_threads; for (uint32_t i=0; i<argc; ++i) { @@ -674,7 +677,7 @@ public: if (success) { Thread *thread = process->GetThreadList().FindThreadByIndexID(thread_idx).get(); - + if (thread) { resume_threads.push_back(thread); @@ -693,7 +696,7 @@ public: return false; } } - + if (resume_threads.empty()) { result.AppendError ("no valid thread indexes were specified"); @@ -706,12 +709,12 @@ public: result.AppendMessageWithFormat ("Resuming thread: "); else result.AppendMessageWithFormat ("Resuming threads: "); - + for (uint32_t idx=0; idx<num_threads; ++idx) { Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get(); std::vector<Thread *>::iterator this_thread_pos = find(resume_threads.begin(), resume_threads.end(), thread); - + if (this_thread_pos != resume_threads.end()) { resume_threads.erase(this_thread_pos); @@ -719,7 +722,7 @@ public: result.AppendMessageWithFormat ("%u, ", thread->GetIndexID()); else result.AppendMessageWithFormat ("%u ", thread->GetIndexID()); - + thread->SetResumeState (eStateRunning); } else @@ -732,6 +735,11 @@ public: } else { + // These two lines appear at the beginning of both blocks in + // this if..else, but that is because we need to release the + // lock before calling process->Resume below. + Mutex::Locker locker (process->GetThreadList().GetMutex()); + const uint32_t num_threads = process->GetThreadList().GetSize(); Thread *current_thread = process->GetThreadList().GetSelectedThread().get(); if (current_thread == NULL) { @@ -754,7 +762,8 @@ public: } } } - + + // We should not be holding the thread list lock when we do this. Error error (process->Resume()); if (error.Success()) { @@ -762,7 +771,7 @@ public: if (synchronous_execution) { state = process->WaitForProcessToStop (NULL); - + result.SetDidChangeProcessState (true); result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1120,9 +1129,9 @@ protected: OptionDefinition CommandObjectThreadUntil::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_1, false, "frame", 'f', required_argument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, -{ LLDB_OPT_SET_1, false, "thread", 't', required_argument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, -{ LLDB_OPT_SET_1, false, "run-mode",'m', required_argument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, +{ LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0"}, +{ LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation"}, +{ LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, g_duo_running_mode, 0, eArgTypeRunMode,"Determine how to run other threads while stepping this one"}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1458,11 +1467,213 @@ protected: OptionDefinition CommandObjectThreadReturn::CommandOptions::g_option_table[] = { -{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', no_argument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, +{ LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Return from the innermost expression evaluation."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; //------------------------------------------------------------------------- +// CommandObjectThreadJump +//------------------------------------------------------------------------- + +class CommandObjectThreadJump : public CommandObjectParsed +{ +public: + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + OptionParsingStarting (); + } + + void + OptionParsingStarting () + { + m_filenames.Clear(); + m_line_num = 0; + m_line_offset = 0; + m_load_addr = LLDB_INVALID_ADDRESS; + m_force = false; + } + + virtual + ~CommandOptions () + { + } + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + bool success; + const int short_option = m_getopt_table[option_idx].val; + Error error; + + switch (short_option) + { + case 'f': + m_filenames.AppendIfUnique (FileSpec(option_arg, false)); + if (m_filenames.GetSize() > 1) + return Error("only one source file expected."); + break; + case 'l': + m_line_num = Args::StringToUInt32 (option_arg, 0, 0, &success); + if (!success || m_line_num == 0) + return Error("invalid line number: '%s'.", option_arg); + break; + case 'b': + m_line_offset = Args::StringToSInt32 (option_arg, 0, 0, &success); + if (!success) + return Error("invalid line offset: '%s'.", option_arg); + break; + case 'a': + { + ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); + m_load_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error); + } + break; + case 'r': + m_force = true; + break; + + default: + return Error("invalid short option character '%c'", short_option); + + } + return error; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + FileSpecList m_filenames; + uint32_t m_line_num; + int32_t m_line_offset; + lldb::addr_t m_load_addr; + bool m_force; + + static OptionDefinition g_option_table[]; + }; + + virtual + Options * + GetOptions () + { + return &m_options; + } + + CommandObjectThreadJump (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "thread jump", + "Sets the program counter to a new address.", + "thread jump", + eFlagRequiresFrame | + eFlagTryTargetAPILock | + eFlagProcessMustBeLaunched | + eFlagProcessMustBePaused ), + m_options (interpreter) + { + } + + ~CommandObjectThreadJump() + { + } + +protected: + + bool DoExecute (Args& args, CommandReturnObject &result) + { + RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext(); + StackFrame *frame = m_exe_ctx.GetFramePtr(); + Thread *thread = m_exe_ctx.GetThreadPtr(); + Target *target = m_exe_ctx.GetTargetPtr(); + const SymbolContext &sym_ctx = frame->GetSymbolContext (eSymbolContextLineEntry); + + if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) + { + // Use this address directly. + Address dest = Address(m_options.m_load_addr); + + lldb::addr_t callAddr = dest.GetCallableLoadAddress (target); + if (callAddr == LLDB_INVALID_ADDRESS) + { + result.AppendErrorWithFormat ("Invalid destination address."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + if (!reg_ctx->SetPC (callAddr)) + { + result.AppendErrorWithFormat ("Error changing PC value for thread %d.", thread->GetIndexID()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else + { + // Pick either the absolute line, or work out a relative one. + int32_t line = (int32_t)m_options.m_line_num; + if (line == 0) + line = sym_ctx.line_entry.line + m_options.m_line_offset; + + // Try the current file, but override if asked. + FileSpec file = sym_ctx.line_entry.file; + if (m_options.m_filenames.GetSize() == 1) + file = m_options.m_filenames.GetFileSpecAtIndex(0); + + if (!file) + { + result.AppendErrorWithFormat ("No source file available for the current location."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + std::string warnings; + Error err = thread->JumpToLine (file, line, m_options.m_force, &warnings); + + if (err.Fail()) + { + result.SetError (err); + return false; + } + + if (!warni |