Vendor import of (stripped) lldb trunk r242221:

https://llvm.org/svn/llvm-project/lldb/trunk@242221
This commit is contained in:
Dimitry Andric 2015-09-06 14:32:30 +00:00
parent 5e95aa85bb
commit 027f1c9655
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/lldb/dist/; revision=287503
svn path=/vendor/lldb/lldb-trunk-r242221/; revision=287504; tag=vendor/lldb/lldb-trunk-r242221
241 changed files with 4803 additions and 2162 deletions

View File

@ -90,6 +90,10 @@ class LLDB_API SBFrame
/// See also IsInlined().
const char *
GetFunctionName();
// Get an appropriate function name for this frame that is suitable for display to a user
const char *
GetDisplayFunctionName ();
const char *
GetFunctionName() const;

View File

@ -35,6 +35,9 @@ class LLDB_API SBFunction
const char *
GetName() const;
const char *
GetDisplayName() const;
const char *
GetMangledName () const;

View File

@ -189,6 +189,9 @@ namespace lldb {
SBError
SetFilePermissions (const char *path, uint32_t file_permissions);
SBUnixSignals
GetUnixSignals() const;
protected:
friend class SBDebugger;

View File

@ -37,6 +37,9 @@ class LLDB_API SBSymbol
const char *
GetName() const;
const char *
GetDisplayName() const;
const char *
GetMangledName () const;

View File

@ -768,6 +768,9 @@ class LLDB_API SBTarget
bool
GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level);
lldb::SBValue
EvaluateExpression (const char *expr);
lldb::SBValue
EvaluateExpression (const char *expr, const SBExpressionOptions &options);

View File

@ -65,17 +65,20 @@ class LLDB_API SBUnixSignals {
protected:
friend class SBProcess;
friend class SBPlatform;
SBUnixSignals (lldb::ProcessSP &process_sp);
SBUnixSignals(lldb::ProcessSP &process_sp);
lldb::ProcessSP
SBUnixSignals(lldb::PlatformSP &platform_sp);
lldb::UnixSignalsSP
GetSP() const;
void
SetSP (const lldb::ProcessSP &process_sp);
SetSP(const lldb::UnixSignalsSP &signals_sp);
private:
lldb::ProcessWP m_opaque_wp;
lldb::UnixSignalsWP m_opaque_wp;
};

View File

@ -187,6 +187,20 @@ class Connection
virtual bool
InterruptRead() = 0;
//------------------------------------------------------------------
/// Returns the underlying IOObject used by the Connection.
///
/// The IOObject can be used to wait for data to become available
/// on the connection. If the Connection does not use IOObjects (and
/// hence does not support waiting) this function should return a
/// null pointer.
///
/// @return
/// The underlying IOObject used for reading.
//------------------------------------------------------------------
virtual lldb::IOObjectSP
GetReadObject() { return lldb::IOObjectSP(); }
private:
//------------------------------------------------------------------
// For Connection only

View File

@ -182,8 +182,17 @@ class Mangled
/// A const reference to the demangled name string object.
//----------------------------------------------------------------------
const ConstString&
GetDemangledName () const;
GetDemangledName (lldb::LanguageType language) const;
//----------------------------------------------------------------------
/// Display demangled name get accessor.
///
/// @return
/// A const reference to the display demangled name string object.
//----------------------------------------------------------------------
ConstString
GetDisplayDemangledName (lldb::LanguageType language) const;
void
SetDemangledName (const ConstString &name)
{
@ -231,8 +240,8 @@ class Mangled
/// object has a valid name of that kind, else a const reference to the
/// other name is returned.
//----------------------------------------------------------------------
const ConstString&
GetName (NamePreference preference = ePreferDemangled) const;
ConstString
GetName (lldb::LanguageType language, NamePreference preference = ePreferDemangled) const;
//----------------------------------------------------------------------
/// Check if "name" matches either the mangled or demangled name.
@ -244,15 +253,15 @@ class Mangled
/// \b True if \a name matches either name, \b false otherwise.
//----------------------------------------------------------------------
bool
NameMatches (const ConstString &name) const
NameMatches (const ConstString &name, lldb::LanguageType language) const
{
if (m_mangled == name)
return true;
return GetDemangledName () == name;
return GetDemangledName (language) == name;
}
bool
NameMatches (const RegularExpression& regex) const;
NameMatches (const RegularExpression& regex, lldb::LanguageType language) const;
//----------------------------------------------------------------------
/// Get the memory cost of this object.

View File

@ -238,14 +238,15 @@ class StructuredData
{
}
void
bool
ForEach (std::function <bool(Object* object)> const &foreach_callback) const
{
for (const auto &object_sp : m_items)
{
if (foreach_callback(object_sp.get()) == false)
break;
return false;
}
return true;
}

View File

@ -18,6 +18,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"

View File

@ -0,0 +1,28 @@
//===-- VectorType.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_VectorType_h_
#define liblldb_VectorType_h_
#include "lldb/lldb-forward.h"
namespace lldb_private {
namespace formatters
{
bool
VectorTypeSummaryProvider (ValueObject&,
Stream&,
const TypeSummaryOptions&);
SyntheticChildrenFrontEnd*
VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
} // namespace formatters
} // namespace lldb_private
#endif // liblldb_VectorType_h_

View File

@ -30,7 +30,7 @@
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/ExecutionContext.h"
namespace lldb_private
namespace lldb_private
{
//----------------------------------------------------------------------
@ -45,7 +45,7 @@ namespace lldb_private
class ClangUserExpression : public ClangExpression
{
public:
enum { kDefaultTimeout = 500000u };
//------------------------------------------------------------------
/// Constructor
@ -59,7 +59,7 @@ class ClangUserExpression : public ClangExpression
///
/// @param[in] language
/// If not eLanguageTypeUnknown, a language to use when parsing
/// the expression. Currently restricted to those languages
/// the expression. Currently restricted to those languages
/// supported by Clang.
///
/// @param[in] desired_type
@ -70,13 +70,13 @@ class ClangUserExpression : public ClangExpression
const char *expr_prefix,
lldb::LanguageType language,
ResultType desired_type);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
virtual
virtual
~ClangUserExpression ();
//------------------------------------------------------------------
/// Parse the expression
///
@ -92,28 +92,28 @@ class ClangUserExpression : public ClangExpression
/// Determines whether interpretation is possible or mandatory.
///
/// @param[in] keep_result_in_memory
/// True if the resulting persistent variable should reside in
/// True if the resulting persistent variable should reside in
/// target memory, if applicable.
///
/// @return
/// True on success (no errors); false otherwise.
//------------------------------------------------------------------
bool
Parse (Stream &error_stream,
Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory,
bool generate_debug_info);
bool
CanInterpret ()
{
return m_can_interpret;
}
bool
MatchesContext (ExecutionContext &exe_ctx);
//------------------------------------------------------------------
/// Execute the parsed expression
///
@ -131,9 +131,9 @@ class ClangUserExpression : public ClangExpression
/// This is a shared pointer to this ClangUserExpression. This is
/// needed because Execute can push a thread plan that will hold onto
/// the ClangUserExpression for an unbounded period of time. So you
/// need to give the thread plan a reference to this object that can
/// need to give the thread plan a reference to this object that can
/// keep it alive.
///
///
/// @param[in] result
/// A pointer to direct at the persistent variable in which the
/// expression's result is stored.
@ -147,7 +147,7 @@ class ClangUserExpression : public ClangExpression
const EvaluateExpressionOptions& options,
lldb::ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
//------------------------------------------------------------------
/// Apply the side effects of the function to program state.
///
@ -157,7 +157,7 @@ class ClangUserExpression : public ClangExpression
/// @param[in] exe_ctx
/// The execution context to use when looking up entities that
/// are needed for parsing (locations of variables, etc.)
///
///
/// @param[in] result
/// A pointer to direct at the persistent variable in which the
/// expression's result is stored.
@ -177,7 +177,7 @@ class ClangUserExpression : public ClangExpression
lldb::ClangExpressionVariableSP &result,
lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
//------------------------------------------------------------------
/// Return the string that the parser should parse. Must be a full
/// translation unit.
@ -187,7 +187,7 @@ class ClangUserExpression : public ClangExpression
{
return m_transformed_text.c_str();
}
//------------------------------------------------------------------
/// Return the string that the user typed.
//------------------------------------------------------------------
@ -196,7 +196,7 @@ class ClangUserExpression : public ClangExpression
{
return m_expr_text.c_str();
}
//------------------------------------------------------------------
/// Return the function name that should be used for executing the
/// expression. Text() should contain the definition of this
@ -207,7 +207,7 @@ class ClangUserExpression : public ClangExpression
{
return "$__lldb_expr";
}
//------------------------------------------------------------------
/// Return the language that should be used when parsing. To use
/// the default, return eLanguageTypeUnknown.
@ -217,7 +217,7 @@ class ClangUserExpression : public ClangExpression
{
return m_language;
}
//------------------------------------------------------------------
/// Return the object that the parser should use when resolving external
/// values. May be NULL if everything should be self-contained.
@ -227,7 +227,7 @@ class ClangUserExpression : public ClangExpression
{
return m_expr_decl_map.get();
}
//------------------------------------------------------------------
/// Return the object that the parser should allow to access ASTs.
/// May be NULL if the ASTs do not need to be transformed.
@ -238,9 +238,9 @@ class ClangUserExpression : public ClangExpression
//------------------------------------------------------------------
clang::ASTConsumer *
ASTTransformer (clang::ASTConsumer *passthrough);
//------------------------------------------------------------------
/// Return the desired result type of the function, or
/// Return the desired result type of the function, or
/// eResultTypeAny if indifferent.
//------------------------------------------------------------------
virtual ResultType
@ -248,7 +248,7 @@ class ClangUserExpression : public ClangExpression
{
return m_desired_type;
}
//------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
@ -258,7 +258,7 @@ class ClangUserExpression : public ClangExpression
{
return true;
}
//------------------------------------------------------------------
/// Return true if external variables in the expression should be
/// resolved.
@ -302,15 +302,15 @@ class ClangUserExpression : public ClangExpression
const char *expr_prefix,
lldb::ValueObjectSP &result_valobj_sp,
Error &error);
static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
private:
//------------------------------------------------------------------
/// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
//------------------------------------------------------------------
void
ScanContext (ExecutionContext &exe_ctx,
ScanContext (ExecutionContext &exe_ctx,
lldb_private::Error &err);
bool
@ -319,21 +319,21 @@ class ClangUserExpression : public ClangExpression
lldb::addr_t &struct_address,
lldb::addr_t &object_ptr,
lldb::addr_t &cmd_ptr);
void
InstallContext (ExecutionContext &exe_ctx);
bool
LockAndCheckContext (ExecutionContext &exe_ctx,
lldb::TargetSP &target_sp,
lldb::ProcessSP &process_sp,
lldb::StackFrameSP &frame_sp);
lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression.
Address m_address; ///< The address the process is stopped in.
lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame.
lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame.
std::string m_expr_text; ///< The text of the expression, as typed by the user
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults)
@ -341,7 +341,7 @@ class ClangUserExpression : public ClangExpression
bool m_allow_objc; ///< True if the language allows Objective-C.
std::string m_transformed_text; ///< The text of the expression, as send to the parser
ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression.
std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression.
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in.
std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression.
@ -354,12 +354,12 @@ class ClangUserExpression : public ClangExpression
bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL.
bool m_const_object; ///< True if "this" is const.
Target *m_target; ///< The target for storing persistent data like types and variables.
bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise.
lldb::addr_t m_materialized_address; ///< The address at which the arguments to the expression have been materialized.
Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
};
} // namespace lldb_private
#endif // liblldb_ClangUserExpression_h_

View File

@ -44,7 +44,8 @@ class IRInterpreter
static bool
CanInterpret (llvm::Module &module,
llvm::Function &function,
lldb_private::Error &error);
lldb_private::Error &error,
const bool support_function_calls);
static bool
Interpret (llvm::Module &module,
@ -53,7 +54,8 @@ class IRInterpreter
lldb_private::IRMemoryMap &memory_map,
lldb_private::Error &error,
lldb::addr_t stack_frame_bottom,
lldb::addr_t stack_frame_top);
lldb::addr_t stack_frame_top,
lldb_private::ExecutionContext &exe_ctx);
private:
static bool

View File

@ -60,7 +60,7 @@ class IRMemoryMap
void ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error);
void ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error);
void ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error);
bool GetAllocSize(lldb::addr_t address, size_t &size);
void GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error);
lldb::ByteOrder GetByteOrder();

View File

@ -244,8 +244,8 @@ class Host
#endif // !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
#endif // defined (__APPLE__) || defined (__linux__) || defined (__FreeBSD__) || defined (__GLIBC__) || defined(__NetBSD__)
static const lldb_private::UnixSignalsSP&
GetUnixSignals ();
static const lldb::UnixSignalsSP &
GetUnixSignals();
static Error
LaunchProcess (ProcessLaunchInfo &launch_info);

View File

@ -0,0 +1,27 @@
//===-- MainLoop.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_Host_MainLoop_h_
#define lldb_Host_MainLoop_h_
#ifdef _WIN32
#include "lldb/Host/MainLoopBase.h"
namespace lldb_private
{
typedef MainLoopBase MainLoop;
}
#else
#include "lldb/Host/posix/MainLoopPosix.h"
namespace lldb_private
{
typedef MainLoopPosix MainLoop;
}
#endif
#endif // lldb_Host_MainLoop_h_

View File

@ -0,0 +1,94 @@
//===-- MainLoopBase.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_Host_posix_MainLoopBase_h_
#define lldb_Host_posix_MainLoopBase_h_
#include <functional>
#include "llvm/Support/ErrorHandling.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/IOObject.h"
namespace lldb_private {
// The purpose of this class is to enable multiplexed processing of data from different sources
// without resorting to multi-threading. Clients can register IOObjects, which will be monitored
// for readability, and when they become ready, the specified callback will be invoked.
// Monitoring for writability is not supported, but can be easily added if needed.
//
// The RegisterReadObject function return a handle, which controls the duration of the monitoring. When
// this handle is destroyed, the callback is deregistered.
//
// This class simply defines the interface common for all platforms, actual implementations are
// platform-specific.
class MainLoopBase
{
private:
class ReadHandle;
public:
MainLoopBase() { }
virtual ~MainLoopBase() { }
typedef std::unique_ptr<ReadHandle> ReadHandleUP;
typedef std::function<void(MainLoopBase &)> Callback;
virtual ReadHandleUP
RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, Error &error)
{ llvm_unreachable("Not implemented"); }
// Waits for registered events and invoke the proper callbacks. Returns when all callbacks
// deregister themselves or when someone requests termination.
virtual Error
Run()
{ llvm_unreachable("Not implemented"); }
// Requests the exit of the Run() function.
virtual void
RequestTermination()
{ llvm_unreachable("Not implemented"); }
protected:
ReadHandleUP
CreateReadHandle(const lldb::IOObjectSP &object_sp)
{ return ReadHandleUP(new ReadHandle(*this, object_sp)); }
virtual void
UnregisterReadObject(const lldb::IOObjectSP &object_sp)
{ llvm_unreachable("Not implemented"); }
private:
class ReadHandle
{
public:
~ReadHandle() { m_mainloop.UnregisterReadObject(m_object_sp); }
private:
ReadHandle(MainLoopBase &mainloop, const lldb::IOObjectSP &object_sp)
: m_mainloop(mainloop), m_object_sp(object_sp)
{ }
MainLoopBase &m_mainloop;
lldb::IOObjectSP m_object_sp;
friend class MainLoopBase;
DISALLOW_COPY_AND_ASSIGN(ReadHandle);
};
private:
DISALLOW_COPY_AND_ASSIGN(MainLoopBase);
};
} // namespace lldb_private
#endif // lldb_Host_posix_MainLoopBase_h_

View File

@ -39,6 +39,8 @@ ToSInt64 (const char *s, int64_t fail_value = 0, int base = 0, bool *success_ptr
uint64_t
ToUInt64 (const char *s, uint64_t fail_value = 0, int base = 0, bool *success_ptr = nullptr);
double
ToDouble (const char *s, double fail_value = 0.0, bool *success_ptr = nullptr);
} // namespace StringConvert
} // namespace lldb_private

View File

@ -35,8 +35,6 @@ namespace lldb_private
friend class SoftwareBreakpoint;
public:
static NativeProcessProtocol *
CreateInstance (lldb::pid_t pid);
// lldb_private::Host calls should be used to launch a process for debugging, and
// then the process should be attached to. When attaching to a process
@ -44,7 +42,6 @@ namespace lldb_private
// and then this function should be called.
NativeProcessProtocol (lldb::pid_t pid);
public:
virtual ~NativeProcessProtocol ()
{
}
@ -297,6 +294,62 @@ namespace lldb_private
virtual Error
GetFileLoadAddress(const llvm::StringRef& file_name, lldb::addr_t& load_addr) = 0;
//------------------------------------------------------------------
/// Launch a process for debugging. This method will create an concrete
/// instance of NativeProcessProtocol, based on the host platform.
/// (e.g. NativeProcessLinux on linux, etc.)
///
/// @param[in] launch_info
/// Information required to launch the process.
///
/// @param[in] native_delegate
/// The delegate that will receive messages regarding the
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
/// NativeProcessProtocol that can be used to manipulate
/// the native process.
///
/// @return
/// An error object indicating if the operation succeeded,
/// and if not, what error occurred.
//------------------------------------------------------------------
static Error
Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp);
//------------------------------------------------------------------
/// Attach to an existing process. This method will create an concrete
/// instance of NativeProcessProtocol, based on the host platform.
/// (e.g. NativeProcessLinux on linux, etc.)
///
/// @param[in] pid
/// pid of the process locatable
///
/// @param[in] native_delegate
/// The delegate that will receive messages regarding the
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
/// NativeProcessProtocol that can be used to manipulate
/// the native process.
///
/// @return
/// An error object indicating if the operation succeeded,
/// and if not, what error occurred.
//------------------------------------------------------------------
static Error
Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp);
protected:
lldb::pid_t m_pid;

View File

@ -59,12 +59,7 @@ class ConnectionFileDescriptor : public Connection
bool InterruptRead() override;
lldb::IOObjectSP
GetReadObject()
{
return m_read_sp;
}
const lldb::IOObjectSP
GetReadObject() const
GetReadObject() override
{
return m_read_sp;
}

View File

@ -0,0 +1,100 @@
//===-- MainLoopPosix.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_Host_posix_MainLoopPosix_h_
#define lldb_Host_posix_MainLoopPosix_h_
#include "lldb/Host/MainLoopBase.h"
#include "llvm/ADT/DenseMap.h"
namespace lldb_private {
// Posix implementation of the MainLoopBase class. It can monitor file descriptors for
// readability using pselect. In addition to the common base, this class provides the ability to
// invoke a given handler when a signal is received.
//
// Since this class is primarily intended to be used for single-threaded processing, it does not
// attempt to perform any internal synchronisation and any concurrent accesses must be protected
// externally. However, it is perfectly legitimate to have more than one instance of this class
// running on separate threads, or even a single thread (with some limitations on signal
// monitoring).
// TODO: Add locking if this class is to be used in a multi-threaded context.
class MainLoopPosix: public MainLoopBase
{
private:
class SignalHandle;
public:
typedef std::unique_ptr<SignalHandle> SignalHandleUP;
~MainLoopPosix() override;
ReadHandleUP
RegisterReadObject(const lldb::IOObjectSP &object_sp, const Callback &callback, Error &error) override;
// Listening for signals from multiple MainLoopPosix instances is perfectly safe as long as they
// don't try to listen for the same signal. The callback function is invoked when the control
// returns to the Run() function, not when the hander is executed. This means that you can
// treat the callback as a normal function and perform things which would not be safe in a
// signal handler. However, since the callback is not invoked synchronously, you cannot use
// this mechanism to handle SIGSEGV and the like.
SignalHandleUP
RegisterSignal(int signo, const Callback &callback, Error &error);
Error
Run() override;
// This should only be performed from a callback. Do not attempt to terminate the processing
// from another thread.
// TODO: Add synchronization if we want to be terminated from another thread.
void
RequestTermination() override
{ m_terminate_request = true; }
protected:
void
UnregisterReadObject(const lldb::IOObjectSP &object_sp) override;
void
UnregisterSignal(int signo);
private:
class SignalHandle
{
public:
~SignalHandle() { m_mainloop.UnregisterSignal(m_signo); }
private:
SignalHandle(MainLoopPosix &mainloop, int signo) : m_mainloop(mainloop), m_signo(signo) { }
MainLoopPosix &m_mainloop;
int m_signo;
friend class MainLoopPosix;
DISALLOW_COPY_AND_ASSIGN(SignalHandle);
};
struct SignalInfo
{
Callback callback;
struct sigaction old_action;
bool was_blocked : 1;
};
llvm::DenseMap<IOObject::WaitableHandle, Callback> m_read_fds;
llvm::DenseMap<int, SignalInfo> m_signals;
bool m_terminate_request : 1;
};
} // namespace lldb_private
#endif // lldb_Host_posix_MainLoopPosix_h_

View File

@ -160,6 +160,9 @@ class CommandObject
{
}
void
FormatLongHelpText (Stream &output_strm, const char *long_help);
void
GenerateHelpText (CommandReturnObject &result);

View File

@ -123,7 +123,7 @@ class FunctionInfo
/// @return
/// A const reference to the method name object.
//------------------------------------------------------------------
const ConstString&
ConstString
GetName () const;
//------------------------------------------------------------------
@ -240,11 +240,14 @@ class InlineFunctionInfo : public FunctionInfo
Dump(Stream *s, bool show_fullpaths) const;
void
DumpStopContext (Stream *s) const;
DumpStopContext (Stream *s, lldb::LanguageType language) const;
const ConstString &
GetName () const;
ConstString
GetName (lldb::LanguageType language) const;
ConstString
GetDisplayName (lldb::LanguageType language) const;
//------------------------------------------------------------------
/// Get accessor for the call site declaration information.
///
@ -437,6 +440,8 @@ class Function :
return m_range;
}
lldb::LanguageType
GetLanguage() const;
//------------------------------------------------------------------
/// Find the file and line number of the source location of the start
/// of the function. This will use the declaration if present and fall
@ -524,11 +529,14 @@ class Function :
return m_frame_base;
}
const ConstString &
GetName() const
{
return m_mangled.GetName();
}
ConstString
GetName() const;
ConstString
GetNameNoArguments () const;
ConstString
GetDisplayName () const;
const Mangled &
GetMangled() const

View File

@ -152,18 +152,28 @@ class Symbol :
lldb::addr_t
ResolveCallableAddress(Target &target) const;
const ConstString &
GetName () const
{
return m_mangled.GetName();
}
ConstString
GetName () const;
ConstString
GetNameNoArguments () const;
ConstString
GetDisplayName () const;
uint32_t
GetID() const
{
return m_uid;
}
lldb::LanguageType
GetLanguage() const
{
// TODO: See if there is a way to determine the language for a symbol somehow, for now just return our best guess
return m_mangled.GuessLanguage();
}
void
SetID(uint32_t uid)
{

View File

@ -55,7 +55,7 @@ class Variable : public UserID
return m_declaration;
}
const ConstString&
ConstString
GetName() const;
SymbolContextScope *
@ -70,12 +70,7 @@ class Variable : public UserID
// function that can be called by commands and expression parsers to make
// sure we match anything we come across.
bool
NameMatches (const ConstString &name) const
{
if (m_name == name)
return true;
return m_mangled.NameMatches (name);
}
NameMatches (const ConstString &name) const;
bool
NameMatches (const RegularExpression& regex) const;
@ -83,6 +78,9 @@ class Variable : public UserID
Type *
GetType();
lldb::LanguageType
GetLanguage () const;
lldb::ValueType
GetScope() const
{

View File

@ -39,10 +39,9 @@ class ABI :
};
eType type; /* value of eType */
size_t size; /* size in bytes of this argument */
union {
lldb::addr_t value; /* literal value */
uint8_t *data; /* host data pointer */
};
lldb::addr_t value; /* literal value */
std::unique_ptr<uint8_t[]> data_ap; /* host data pointer */
};
virtual
@ -58,7 +57,7 @@ class ABI :
lldb::addr_t returnAddress,
llvm::ArrayRef<lldb::addr_t> args) const = 0;
// Prepare trivial call used from ThreadPlanFunctionCallGDB
// Prepare trivial call used from ThreadPlanFunctionCallUsingABI
// AD:
// . Because i don't want to change other ABI's this is not declared pure virtual.
// The dummy implementation will simply fail. Only HexagonABI will currently

View File

@ -863,6 +863,12 @@ class ModuleCache;
return 1;
}
virtual const lldb::UnixSignalsSP &
GetRemoteUnixSignals();
const lldb::UnixSignalsSP &
GetUnixSignals();
//------------------------------------------------------------------
/// Locate a queue name given a thread's qaddr
///
@ -939,65 +945,6 @@ class ModuleCache;
virtual const std::vector<ConstString> &
GetTrapHandlerSymbolNames ();
//------------------------------------------------------------------
/// Launch a process for debugging.
///
/// This differs from Launch in that it returns a NativeProcessProtocol.
/// Currently used by lldb-gdbserver.
///
/// @param[in] launch_info
/// Information required to launch the process.
///
/// @param[in] native_delegate
/// The delegate that will receive messages regarding the
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
/// NativeProcessProtocol that can be used to manipulate
/// the native process.
///
/// @return
/// An error object indicating if the operation succeeded,
/// and if not, what error occurred.
//------------------------------------------------------------------
virtual Error
LaunchNativeProcess (
ProcessLaunchInfo &launch_info,
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp);
//------------------------------------------------------------------
/// Attach to an existing process on the given platform.
///
/// This method differs from Attach() in that it returns a
/// NativeProcessProtocol. Currently this is used by lldb-gdbserver.
///
/// @param[in] pid
/// pid of the process locatable by the platform.
///
/// @param[in] native_delegate
/// The delegate that will receive messages regarding the
/// inferior. Must outlive the NativeProcessProtocol
/// instance.
///
/// @param[out] process_sp
/// On successful return from the method, this parameter
/// contains the shared pointer to the
/// NativeProcessProtocol that can be used to manipulate
/// the native process.
///
/// @return
/// An error object indicating if the operation succeeded,
/// and if not, what error occurred.
//------------------------------------------------------------------
virtual Error
AttachNativeProcess (lldb::pid_t pid,
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp);
protected:
bool m_is_host;
// Set to true when we are able to actually set the OS version while

View File

@ -30,6 +30,7 @@
#include "lldb/Core/Event.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Breakpoint/BreakpointSiteList.h"
#include "lldb/Host/HostThread.h"
@ -949,7 +950,7 @@ class Process :
/// Construct with a shared pointer to a target, the Process listener,
/// and the appropriate UnixSignalsSP for the process.
//------------------------------------------------------------------
Process(Target &target, Listener &listener, const UnixSignalsSP &unix_signals_sp);
Process(Target &target, Listener &listener, const lldb::UnixSignalsSP &unix_signals_sp);
//------------------------------------------------------------------
/// Destructor.
@ -1401,10 +1402,10 @@ class Process :
Signal (int signal);
void
SetUnixSignals (const UnixSignalsSP &signals_sp);
SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
UnixSignals &
GetUnixSignals ();
const lldb::UnixSignalsSP &
GetUnixSignals();
//==================================================================
// Plug-in Process Control Overrides
@ -1887,6 +1888,37 @@ class Process :
virtual void
ModulesDidLoad (ModuleList &module_list);
//------------------------------------------------------------------
/// Retrieve the list of shared libraries that are loaded for this process
///
/// For certain platforms, the time it takes for the DynamicLoader plugin to
/// read all of the shared libraries out of memory over a slow communication
/// channel may be too long. In that instance, the gdb-remote stub may be
/// able to retrieve the necessary information about the solibs out of memory
/// and return a concise summary sufficient for the DynamicLoader plugin.
///
/// @param [in] image_list_address
/// The address where the table of shared libraries is stored in memory,
/// if that is appropriate for this platform. Else this may be
/// passed as LLDB_INVALID_ADDRESS.
///
/// @param [in] image_count
/// The number of shared libraries that are present in this process, if
/// that is appropriate for this platofrm Else this may be passed as
/// LLDB_INVALID_ADDRESS.
///
/// @return
/// A StructureDataSP object which, if non-empty, will contain the
/// information the DynamicLoader needs to get the initial scan of
/// solibs resolved.
//------------------------------------------------------------------
virtual lldb_private::StructuredData::ObjectSP
GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
{
return StructuredData::ObjectSP();
}
protected:
void
@ -2439,7 +2471,40 @@ class Process :
/// True if execution of JIT code is possible; false otherwise.
//------------------------------------------------------------------
void SetCanJIT (bool can_jit);
//------------------------------------------------------------------
/// Determines whether executing function calls using the interpreter
/// is possible for this process.
///
/// @return
/// True if possible; false otherwise.
//------------------------------------------------------------------
bool CanInterpretFunctionCalls ()
{
return m_can_interpret_function_calls;
}
//------------------------------------------------------------------
/// Sets whether executing function calls using the interpreter
/// is possible for this process.
///
/// @param[in] can_interpret_function_calls
/// True if possible; false otherwise.
//------------------------------------------------------------------
void SetCanInterpretFunctionCalls (bool can_interpret_function_calls)
{
m_can_interpret_function_calls = can_interpret_function_calls;
}
//------------------------------------------------------------------
/// Sets whether executing code in this process is possible.
/// This could be either through JIT or interpreting.
///
/// @param[in] can_run_code
/// True if execution of code is possible; false otherwise.
//------------------------------------------------------------------
void SetCanRunCode (bool can_run_code);
//------------------------------------------------------------------
/// Actually deallocate memory in the process.
///
@ -3205,7 +3270,7 @@ class Process :
lldb::DynamicCheckerFunctionsUP m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use.
lldb::OperatingSystemUP m_os_ap;
lldb::SystemRuntimeUP m_system_runtime_ap;
UnixSignalsSP m_unix_signals_sp; /// This is the current signal set for this process.
lldb::UnixSignalsSP m_unix_signals_sp; /// This is the current signal set for this process.
lldb::ABISP m_abi_sp;
lldb::IOHandlerSP m_process_input_reader;
Communication m_stdio_communication;
@ -3236,6 +3301,7 @@ class Process :
lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent.
std::map<lldb::addr_t,lldb::addr_t> m_resolved_indirect_addresses;
bool m_destroy_in_process;
bool m_can_interpret_function_calls; // Some targets, e.g the OSX kernel, don't support the ability to modify the stack.
enum {
eCanJITDontKnow= 0,

View File

@ -34,6 +34,10 @@ class ThreadPlanCallFunction : public ThreadPlan
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options);
ThreadPlanCallFunction(Thread &thread,
const Address &function,
const EvaluateExpressionOptions &options);
virtual
~ThreadPlanCallFunction ();
@ -134,7 +138,8 @@ class ThreadPlanCallFunction : public ThreadPlan
virtual bool
DoPlanExplainsStop (Event *event_ptr);
private:
virtual void
SetReturnValue();
bool
ConstructorSetup (Thread &thread,
@ -153,7 +158,7 @@ class ThreadPlanCallFunction : public ThreadPlan
bool
BreakpointsExplainStop ();
bool m_valid;
bool m_stop_other_threads;
bool m_unwind_on_error;
@ -172,13 +177,14 @@ class ThreadPlanCallFunction : public ThreadPlan
// it's nice to know the real stop reason.
// This gets set in DoTakedown.
StreamString m_constructor_errors;
ClangASTType m_return_type;
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
bool m_should_clear_objc_exception_bp;
bool m_should_clear_cxx_exception_bp;
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
private:
ClangASTType m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};

View File

@ -0,0 +1,58 @@
//===-- ThreadPlanCallFunctionUsingABI.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_ThreadPlanCallFunctionUsingABI_h_
#define liblldb_ThreadPlanCallFunctionUsingABI_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Type.h"
namespace lldb_private {
class ThreadPlanCallFunctionUsingABI : public ThreadPlanCallFunction
{
// Create a thread plan to call a function at the address passed in the "function"
// argument, this function is executed using register manipulation instead of JIT.
// Class derives from ThreadPlanCallFunction and differs by calling a alternative
// ABI interface ABI::PrepareTrivialCall() which provides more detailed information.
public:
ThreadPlanCallFunctionUsingABI (Thread &thread,
const Address &function_address,
llvm::Type &function_prototype,
llvm::Type &return_type,
llvm::ArrayRef<ABI::CallArgument> args,
const EvaluateExpressionOptions &options);
~ThreadPlanCallFunctionUsingABI ();
void
GetDescription (Stream *s, lldb::DescriptionLevel level) override;
protected:
void
SetReturnValue () override;
private:
llvm::Type &m_return_type;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunctionUsingABI);
};
} // namespace lldb_private
#endif // liblldb_ThreadPlanCallFunctionUsingABI_h_

View File

@ -26,6 +26,9 @@ namespace lldb_private
class UnixSignals
{
public:
static lldb::UnixSignalsSP
Create(const ArchSpec &arch);
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
@ -89,6 +92,12 @@ class UnixSignals
int32_t
GetNextSignalNumber (int32_t current_signal) const;
int32_t
GetNumSignals() const;
int32_t
GetSignalAtIndex(int32_t index) const;
// We assume that the elements of this object are constant once it is constructed,
// since a process should never need to add or remove symbols as it runs. So don't
// call these functions anywhere but the constructor of your subclass of UnixSignals or in
@ -130,14 +139,18 @@ class UnixSignals
~Signal () {}
};
void
virtual void
Reset ();
typedef std::map <int32_t, Signal> collection;
collection m_signals;
DISALLOW_COPY_AND_ASSIGN (UnixSignals);
// GDBRemote signals need to be copyable.
UnixSignals(const UnixSignals &rhs);
const UnixSignals &
operator=(const UnixSignals &rhs) = delete;
};
} // Namespace lldb

View File

@ -11,6 +11,7 @@
#define utility_JSON_h_
#include "lldb/Core/Stream.h"
#include "lldb/Utility/StringExtractor.h"
#include <inttypes.h>
#include <map>
@ -22,6 +23,7 @@
#include "llvm/Support/Casting.h"
namespace lldb_private {
class JSONValue
{
public:
@ -97,8 +99,9 @@ namespace lldb_private {
{
public:
JSONNumber ();
JSONNumber (int64_t i);
explicit JSONNumber (uint64_t i);
explicit JSONNumber (double d);
JSONNumber (const JSONNumber& s) = delete;
JSONNumber&
operator = (const JSONNumber& s) = delete;
@ -107,10 +110,19 @@ namespace lldb_private {
Write (Stream& s);
typedef std::shared_ptr<JSONNumber> SP;
int64_t
uint64_t
GetData () { return m_data; }
double
GetAsDouble()
{
if (m_is_integer)
return (double)m_data;
else
return m_double;
}
static bool classof(const JSONValue *V)
{
return V->GetKind() == JSONValue::Kind::Number;
@ -120,7 +132,9 @@ namespace lldb_private {
~JSONNumber () = default;
private:
int64_t m_data;
bool m_is_integer;
uint64_t m_data;
double m_double;
};
class JSONTrue : public JSONValue
@ -271,6 +285,48 @@ namespace lldb_private {
Vector m_elements;
};
class JSONParser : public StringExtractor
{
public:
enum Token
{
Invalid,
Error,
ObjectStart,
ObjectEnd,
ArrayStart,
ArrayEnd,
Comma,
Colon,
String,
Integer,
Float,
True,
False,
Null,
EndOfFile
};
JSONParser (const char *cstr);
int
GetEscapedChar (bool &was_escaped);
Token
GetToken (std::string &value);
JSONValue::SP
ParseJSONValue ();
protected:
JSONValue::SP
ParseJSONObject ();
JSONValue::SP
ParseJSONArray ();
};
}
#endif // utility_ProcessStructReader_h_

View File

@ -67,6 +67,9 @@ class StringExtractor
m_index = 0;
}
void
SkipSpaces ();
std::string &
GetStringRef ()
{
@ -96,6 +99,15 @@ class StringExtractor
char
GetChar (char fail_value = '\0');
char
PeekChar (char fail_value = '\0')
{
const char *cstr = Peek();
if (cstr)
return cstr[0];
return fail_value;
}
int
DecodeHexU8();

View File

@ -423,6 +423,8 @@ namespace lldb {
#ifndef LLDB_DISABLE_PYTHON
typedef std::shared_ptr<lldb_private::ScriptedSyntheticChildren> ScriptedSyntheticChildrenSP;
#endif
typedef std::shared_ptr<lldb_private::UnixSignals> UnixSignalsSP;
typedef std::weak_ptr<lldb_private::UnixSignals> UnixSignalsWP;
typedef std::shared_ptr<lldb_private::UnwindAssembly> UnwindAssemblySP;
typedef std::shared_ptr<lldb_private::UnwindPlan> UnwindPlanSP;
typedef lldb_private::SharingPtr<lldb_private::ValueObject> ValueObjectSP;

View File

@ -34,7 +34,6 @@ namespace lldb_private
typedef std::weak_ptr<lldb_private::NativeProcessProtocol> NativeProcessProtocolWP;
typedef std::shared_ptr<lldb_private::NativeRegisterContext> NativeRegisterContextSP;
typedef std::shared_ptr<lldb_private::NativeThreadProtocol> NativeThreadProtocolSP;
typedef std::shared_ptr<lldb_private::UnixSignals> UnixSignalsSP;
}
#endif // #if defined(__cplusplus)

View File

@ -75,7 +75,15 @@ SBBlock::GetInlinedName () const
{
const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
if (inlined_info)
return inlined_info->GetName().AsCString (NULL);
{
Function *function = m_opaque_ptr->CalculateSymbolContextFunction();
LanguageType language;
if (function)
language = function->GetLanguage();
else
language = lldb::eLanguageTypeUnknown;
return inlined_info->GetName(language).AsCString (NULL);
}
}
return NULL;
}

View File

@ -1571,7 +1571,7 @@ SBFrame::GetFunctionName() const
if (inlined_block)
{
const InlineFunctionInfo* inlined_info = inlined_block->GetInlinedFunctionInfo();
name = inlined_info->GetName().AsCString();
name = inlined_info->GetName(sc.function->GetLanguage()).AsCString();
}
}
@ -1602,3 +1602,59 @@ SBFrame::GetFunctionName() const
}
return name;
}
const char *
SBFrame::GetDisplayFunctionName()
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
const char *name = NULL;
ExecutionContext exe_ctx(m_opaque_sp.get());
StackFrame *frame = NULL;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
if (target && process)
{
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&process->GetRunLock()))
{
frame = exe_ctx.GetFramePtr();
if (frame)
{
SymbolContext sc (frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol));
if (sc.block)
{
Block *inlined_block = sc.block->GetContainingInlinedBlock ();
if (inlined_block)
{
const InlineFunctionInfo* inlined_info = inlined_block->GetInlinedFunctionInfo();
name = inlined_info->GetDisplayName(sc.function->GetLanguage()).AsCString();
}
}
if (name == NULL)
{
if (sc.function)
name = sc.function->GetDisplayName().GetCString();
}
if (name == NULL)
{
if (sc.symbol)
name = sc.symbol->GetDisplayName().GetCString();
}
}
else
{
if (log)
log->Printf ("SBFrame::GetDisplayFunctionName () => error: could not reconstruct frame object for this SBFrame.");
}
}
else
{
if (log)
log->Printf ("SBFrame::GetDisplayFunctionName() => error: process is running");
}
}
return name;
}

View File

@ -60,7 +60,7 @@ SBFunction::GetName() const
{
const char *cstr = NULL;
if (m_opaque_ptr)
cstr = m_opaque_ptr->GetMangled().GetName().AsCString();
cstr = m_opaque_ptr->GetName().AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
@ -75,6 +75,26 @@ SBFunction::GetName() const
return cstr;
}
const char *
SBFunction::GetDisplayName() const
{
const char *cstr = NULL;
if (m_opaque_ptr)
cstr = m_opaque_ptr->GetMangled().GetDisplayDemangledName(m_opaque_ptr->GetLanguage()).AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
if (cstr)
log->Printf ("SBFunction(%p)::GetDisplayName () => \"%s\"",
static_cast<void*>(m_opaque_ptr), cstr);
else
log->Printf ("SBFunction(%p)::GetDisplayName () => NULL",
static_cast<void*>(m_opaque_ptr));
}
return cstr;
}
const char *
SBFunction::GetMangledName () const
{

View File

@ -11,6 +11,7 @@
#include "lldb/API/SBError.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBUnixSignals.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/File.h"
@ -638,3 +639,11 @@ SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
}
SBUnixSignals
SBPlatform::GetUnixSignals() const
{
if (auto platform_sp = GetSP())
return SBUnixSignals{platform_sp};
return {};
}

View File

@ -912,14 +912,10 @@ SBProcess::Signal (int signo)
SBUnixSignals
SBProcess::GetUnixSignals()
{
SBUnixSignals sb_unix_signals;
ProcessSP process_sp(GetSP());
if (process_sp)
{
sb_unix_signals.SetSP(process_sp);
}
if (auto process_sp = GetSP())
return SBUnixSignals{process_sp};
return sb_unix_signals;
return {};
}
void

View File

@ -63,7 +63,7 @@ SBSymbol::GetName() const
{
const char *name = NULL;
if (m_opaque_ptr)
name = m_opaque_ptr->GetMangled().GetName().AsCString();
name = m_opaque_ptr->GetName().AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
@ -72,6 +72,20 @@ SBSymbol::GetName() const
return name;
}
const char *
SBSymbol::GetDisplayName() const
{
const char *name = NULL;
if (m_opaque_ptr)
name = m_opaque_ptr->GetMangled().GetDisplayDemangledName(m_opaque_ptr->GetLanguage()).AsCString();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
log->Printf ("SBSymbol(%p)::GetDisplayName () => \"%s\"",
static_cast<void*>(m_opaque_ptr), name ? name : "");
return name;
}
const char *
SBSymbol::GetMangledName () const
{

View File

@ -2293,6 +2293,19 @@ SBTarget::FindSymbols (const char *name, lldb::SymbolType symbol_type)
}
lldb::SBValue
SBTarget::EvaluateExpression (const char *expr)
{
TargetSP target_sp(GetSP());
if (!target_sp)
return SBValue();
SBExpressionOptions options;
lldb::DynamicValueType fetch_dynamic_value = target_sp->GetPreferDynamicValue();
options.SetFetchDynamicValue (fetch_dynamic_value);
options.SetUnwindOnError (true);
return EvaluateExpression(expr, options);
}
lldb::SBValue
SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &options)

View File

@ -392,7 +392,7 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
case eStopReasonSignal:
{
stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals ().GetSignalAsCString (stop_info_sp->GetValue());
stop_desc = exe_ctx.GetProcessPtr()->GetUnixSignals()->GetSignalAsCString(stop_info_sp->GetValue());
if (stop_desc == NULL || stop_desc[0] == '\0')
{
static char signal_desc[] = "signal";

View File

@ -9,6 +9,7 @@
#include "lldb/lldb-defines.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Core/Log.h"
@ -25,8 +26,13 @@ SBUnixSignals::SBUnixSignals (const SBUnixSignals &rhs) :
{
}
SBUnixSignals::SBUnixSignals (ProcessSP &process_sp) :
m_opaque_wp(process_sp)
SBUnixSignals::SBUnixSignals(ProcessSP &process_sp) :
m_opaque_wp(process_sp ? process_sp->GetUnixSignals() : nullptr)
{
}
SBUnixSignals::SBUnixSignals(PlatformSP &platform_sp) :
m_opaque_wp(platform_sp ? platform_sp->GetUnixSignals() : nullptr)
{
}
@ -42,16 +48,16 @@ SBUnixSignals::~SBUnixSignals()
{
}
ProcessSP
UnixSignalsSP
SBUnixSignals::GetSP() const
{
return m_opaque_wp.lock();
}
void
SBUnixSignals::SetSP (const ProcessSP &process_sp)
SBUnixSignals::SetSP(const UnixSignalsSP &signals_sp)
{
m_opaque_wp = process_sp;
m_opaque_wp = signals_sp;
}
void
@ -63,30 +69,33 @@ SBUnixSignals::Clear ()
bool
SBUnixSignals::IsValid() const
{
return (bool) GetSP();
return static_cast<bool>(GetSP());
}
const char *
SBUnixSignals::GetSignalAsCString (int32_t signo) const
{
ProcessSP process_sp(GetSP());
if (process_sp) return process_sp->GetUnixSignals().GetSignalAsCString(signo);
return NULL;
if (auto signals_sp = GetSP())
return signals_sp->GetSignalAsCString(signo);
return nullptr;
}
int32_t
SBUnixSignals::GetSignalNumberFromName (const char *name) const
{
ProcessSP process_sp(GetSP());
if (process_sp) return process_sp->GetUnixSignals().GetSignalNumberFromName(name);
return -1;
if (auto signals_sp = GetSP())
return signals_sp->GetSignalNumberFromName(name);
return LLDB_INVALID_SIGNAL_NUMBER;
}
bool
SBUnixSignals::GetShouldSuppress (int32_t signo) const
{
ProcessSP process_sp(GetSP());
if (process_sp) return process_sp->GetUnixSignals().GetShouldSuppress(signo);
if (auto signals_sp = GetSP())
return signals_sp->GetShouldSuppress(signo);
return false;
}
@ -94,25 +103,28 @@ bool
SBUnixSignals::SetShouldSuppress (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ProcessSP process_sp(GetSP());
auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldSuppress (signo=%d, value=%d)",
static_cast<void*>(process_sp.get()),
static_cast<void*>(signals_sp.get()),
signo,
value);
}
if (process_sp) return process_sp->GetUnixSignals().SetShouldSuppress(signo, value);
if (signals_sp)
return signals_sp->SetShouldSuppress(signo, value);
return false;
}
bool
SBUnixSignals::GetShouldStop (int32_t signo) const
{
ProcessSP process_sp(GetSP());
if (process_sp) return process_sp->GetUnixSignals().GetShouldStop(signo);
if (auto signals_sp = GetSP())
return signals_sp->GetShouldStop(signo);
return false;
}
@ -120,25 +132,28 @@ bool
SBUnixSignals::SetShouldStop (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ProcessSP process_sp(GetSP());
auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldStop (signo=%d, value=%d)",
static_cast<void*>(process_sp.get()),
static_cast<void*>(signals_sp.get()),
signo,
value);
}
if (process_sp) return process_sp->GetUnixSignals().SetShouldStop(signo, value);
if (signals_sp)
return signals_sp->SetShouldStop(signo, value);
return false;
}
bool
SBUnixSignals::GetShouldNotify (int32_t signo) const
{
ProcessSP process_sp(GetSP());
if (process_sp) return process_sp->GetUnixSignals().GetShouldNotify(signo);
if (auto signals_sp = GetSP())
return signals_sp->GetShouldNotify(signo);
return false;
}
@ -146,54 +161,36 @@ bool
SBUnixSignals::SetShouldNotify (int32_t signo, bool value)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
ProcessSP process_sp(GetSP());
auto signals_sp = GetSP();
if (log)
{
log->Printf ("SBUnixSignals(%p)::SetShouldNotify (signo=%d, value=%d)",
static_cast<void*>(process_sp.get()),
static_cast<void*>(signals_sp.get()),
signo,
value);
}
if (process_sp) return process_sp->GetUnixSignals().SetShouldNotify(signo, value);
if (signals_sp)
return signals_sp->SetShouldNotify(signo, value);
return false;
}
int32_t
SBUnixSignals::GetNumSignals () const
{
if (auto process_sp = GetSP())
{
// only valid while we hold process_sp
UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
int32_t num_signals = 0;
for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
signo != LLDB_INVALID_SIGNAL_NUMBER;
signo = unix_signals_ptr->GetNextSignalNumber(signo))
{
num_signals++;
}
return num_signals;
}
return LLDB_INVALID_SIGNAL_NUMBER;
if (auto signals_sp = GetSP())
return signals_sp->GetNumSignals();
return -1;
}
int32_t
SBUnixSignals::GetSignalAtIndex (int32_t index) const
{
if (auto process_sp = GetSP())
{
// only valid while we hold process_sp
UnixSignals *unix_signals_ptr = &process_sp->GetUnixSignals();
int32_t idx = 0;
for (int32_t signo = unix_signals_ptr->GetFirstSignalNumber();
signo != LLDB_INVALID_SIGNAL_NUMBER;
signo = unix_signals_ptr->GetNextSignalNumber(signo))
{
if (index == idx) return signo;
idx++;
}
}
if (auto signals_sp = GetSP())
return signals_sp->GetSignalAtIndex(index);
return LLDB_INVALID_SIGNAL_NUMBER;
}

View File

@ -58,7 +58,6 @@
#if defined(_MSC_VER)
#include "lldb/Host/windows/windows.h"
#include "Plugins/Process/Windows/DynamicLoaderWindows.h"
#include "Plugins/Process/Windows/ProcessWindows.h"
#endif
@ -264,7 +263,6 @@ SystemInitializerFull::Initialize()
RenderScriptRuntime::Initialize();
#if defined(_MSC_VER)
DynamicLoaderWindows::Initialize();
ProcessWindows::Initialize();
#endif
#if defined(__FreeBSD__)
@ -369,9 +367,6 @@ SystemInitializerFull::Terminate()
ProcessKDP::Terminate();
SymbolVendorMacOSX::Terminate();
#endif
#if defined(_MSC_VER)
DynamicLoaderWindows::Terminate();
#endif
#if defined(__FreeBSD__)
ProcessFreeBSD::Terminate();

View File

@ -611,7 +611,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
s->EOL();
s->Indent("function = ");
s->PutCString (sc.function->GetMangled().GetName().AsCString("<unknown>"));
s->PutCString (sc.function->GetName().AsCString("<unknown>"));
}
if (sc.line_entry.line > 0)
@ -632,7 +632,7 @@ BreakpointLocation::GetDescription (Stream *s, lldb::DescriptionLevel level)
s->Indent ("re-exported target = ");
else
s->Indent("symbol = ");
s->PutCString(sc.symbol->GetMangled().GetName().AsCString("<unknown>"));
s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
}
}
}

View File

@ -1249,27 +1249,27 @@ class CommandObjectBreakpointDisable : public CommandObjectParsed
CommandObjectBreakpointDisable (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"breakpoint disable",
"Disable the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disable them all.",
"Disable the specified breakpoint(s) without removing them. If none are specified, disable all breakpoints.",
NULL)
{
SetHelpLong(
"Disable the specified breakpoint(s) without removing it/them. \n\
If no breakpoints are specified, disable them all.\n\
\n\
Note: disabling a breakpoint will cause none of its locations to be hit\n\
regardless of whether they are enabled or disabled. So the sequence: \n\
\n\
(lldb) break disable 1\n\
(lldb) break enable 1.1\n\
\n\
will NOT cause location 1.1 to get hit. To achieve that, do:\n\
\n\
(lldb) break disable 1.*\n\
(lldb) break enable 1.1\n\
\n\
The first command disables all the locations of breakpoint 1, \n\
"Disable the specified breakpoint(s) without removing them. \
If none are specified, disable all breakpoints." R"(
)" "Note: disabling a breakpoint will cause none of its locations to be hit \
regardless of whether they are enabled or disabled. After the sequence:" R"(
(lldb) break disable 1
(lldb) break enable 1.1
execution will NOT stop at location 1.1. To achieve that, type:
(lldb) break disable 1.*
(lldb) break enable 1.1
)" "The first command disables all the locations of breakpoint 1, \
the second re-enables the first location."
);
);
CommandArgumentEntry arg;
CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange);

View File

@ -49,143 +49,120 @@ class CommandObjectBreakpointCommandAdd :
m_options (interpreter)
{
SetHelpLong (
"\nGeneral information about entering breakpoint commands\n\
------------------------------------------------------\n\
\n\
This command will cause you to be prompted to enter the command or set of\n\
commands you wish to be executed when the specified breakpoint is hit. You\n\
will be told to enter your command(s), and will see a '> 'prompt. Because\n\
you can enter one or many commands to be executed when a breakpoint is hit,\n\
you will continue to be prompted after each new-line that you enter, until you\n\
enter the word 'DONE', which will cause the commands you have entered to be\n\
stored with the breakpoint and executed when the breakpoint is hit.\n\
\n\
Syntax checking is not necessarily done when breakpoint commands are entered.\n\
An improperly written breakpoint command will attempt to get executed when the\n\
breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
not appear to be getting executed, go back and check your syntax.\n\
\n\
Special information about PYTHON breakpoint commands\n\
----------------------------------------------------\n\
\n\
You may enter either one line of Python, multiple lines of Python (including\n\
function definitions), or specify a Python function in a module that has already,\n\
or will be imported. If you enter a single line of Python, that will be passed\n\
to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
function definitions, they will be passed to the Python interpreter as soon as\n\
you finish entering the breakpoint command, and they can be called later (don't\n\
forget to add calls to them, if you want them called when the breakpoint is\n\
hit). If you enter multiple lines of Python that are not function definitions,\n\
they will be collected into a new, automatically generated Python function, and\n\
a call to the newly generated function will be attached to the breakpoint.\n\
\n\
\n\
This auto-generated function is passed in three arguments:\n\
\n\
frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
location that was hit.\n\
dict: the python session dictionary hit.\n\
\n\
When specifying a python function with the --python-function option, you need\n\
to supply the function name prepended by the module name. So if you import a\n\
module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
specify the option as:\n\
\n\
--python-function myutils.breakpoint_callback\n\
\n\
The function itself must have the following prototype:\n\
\n\
def breakpoint_callback(frame, bp_loc, dict):\n\
# Your code goes here\n\
\n\
The arguments are the same as the 3 auto generation function arguments listed\n\
above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
can get you to the thread (frame.GetThread()), the thread can get you to the\n\
process (thread.GetProcess()), and the process can get you back to the target\n\
(process.GetTarget()).\n\
\n\
Important Note: Because loose Python code gets collected into functions, if you\n\
want to access global variables in the 'loose' code, you need to specify that\n\
they are global, using the 'global' keyword. Be sure to use correct Python\n\
syntax, including indentation, when entering Python breakpoint commands.\n\
\n\
As a third option, you can pass the name of an already existing Python function\n\
and that function will be attached to the breakpoint. It will get passed the\n\
frame and bp_loc arguments mentioned above.\n\
\n\
Example Python one-line breakpoint command:\n\
\n\
(lldb) breakpoint command add -s python 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> print \"Hit this breakpoint!\"\n\
> DONE\n\
\n\
As a convenience, this also works for a short Python one-liner:\n\
(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
(lldb) run\n\
Launching '.../a.out' (x86_64)\n\
(lldb) Fri Sep 10 12:17:45 2010\n\
Process 21778 Stopped\n\
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
36 \n\
37 int c(int val)\n\
38 {\n\
39 -> return val + 3;\n\
40 }\n\
41 \n\
42 int main (int argc, char const *argv[])\n\
(lldb)\n\
\n\
Example multiple line Python breakpoint command, using function definition:\n\
\n\
(lldb) breakpoint command add -s python 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> def breakpoint_output (bp_no):\n\
> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
> print out_string\n\
> return True\n\
> breakpoint_output (1)\n\
> DONE\n\
\n\
\n\
Example multiple line Python breakpoint command, using 'loose' Python:\n\
\n\
(lldb) breakpoint command add -s p 1\n\
Enter your Python command(s). Type 'DONE' to end.\n\
> global bp_count\n\
> bp_count = bp_count + 1\n\
> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
> DONE\n\
\n\
In this case, since there is a reference to a global variable,\n\
'bp_count', you will also need to make sure 'bp_count' exists and is\n\
initialized:\n\
\n\
(lldb) script\n\
>>> bp_count = 0\n\
>>> quit()\n\
\n\
(lldb)\n\
\n\
\n\
Your Python code, however organized, can optionally return a value.\n\
If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
to which the code is associated. Returning anything other than False, or even\n\
returning None, or even omitting a return statement entirely, will cause\n\
LLDB to stop.\n\
\n\
Final Note: If you get a warning that no breakpoint command was generated, but\n\
you did not get any syntax errors, you probably forgot to add a call to your\n\
functions.\n\
\n\
Special information about debugger command breakpoint commands\n\
--------------------------------------------------------------\n\
\n\
You may enter any debugger command, exactly as you would at the debugger prompt.\n\
You may enter as many debugger commands as you like, but do NOT enter more than\n\
one command per line.\n" );
R"(
General information about entering breakpoint commands
------------------------------------------------------
)" "This command will prompt for commands to be executed when the specified \
breakpoint is hit. Each command is typed on its own line following the '> ' \
prompt until 'DONE' is entered." R"(
)" "Syntactic errors may not be detected when initially entered, and many \
malformed commands can silently fail when executed. If your breakpoint commands \
do not appear to be executing, double-check the command syntax." R"(
)" "Note: You may enter any debugger command exactly as you would at the debugger \
prompt. There is no limit to the number of commands supplied, but do NOT enter \
more than one command per line." R"(
Special information about PYTHON breakpoint commands
----------------------------------------------------
)" "You may enter either one or more lines of Python, including function \
definitions or calls to functions that will have been imported by the time \
the code executes. Single line breakpoint commands will be interpreted 'as is' \
when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
generated function, and a call to the function will be attached to the breakpoint." R"(
This auto-generated function is passed in three arguments:
frame: an lldb.SBFrame object for the frame which hit breakpoint.
bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
dict: the python session dictionary hit.
)" "When specifying a python function with the --python-function option, you need \
to supply the function name prepended by the module name:" R"(
--python-function myutils.breakpoint_callback
The function itself must have the following prototype:
def breakpoint_callback(frame, bp_loc, dict):
# Your code goes here
)" "The arguments are the same as the arguments passed to generated functions as \
described above. Note that the global variable 'lldb.frame' will NOT be updated when \
this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
can get you to the thread via frame.GetThread(), the thread can get you to the \
process via thread.GetProcess(), and the process can get you back to the target \
via process.GetTarget()." R"(
)" "Important Note: As Python code gets collected into functions, access to global \
variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
Python syntax, including indentation, when entering Python breakpoint commands." R"(
Example Python one-line breakpoint command:
(lldb) breakpoint command add -s python 1
Enter your Python command(s). Type 'DONE' to end.
> print "Hit this breakpoint!"
> DONE
As a convenience, this also works for a short Python one-liner:
(lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
(lldb) run
Launching '.../a.out' (x86_64)
(lldb) Fri Sep 10 12:17:45 2010
Process 21778 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
Example multiple line Python breakpoint command:
(lldb) breakpoint command add -s p 1
Enter your Python command(s). Type 'DONE' to end.
> global bp_count
> bp_count = bp_count + 1
> print "Hit this breakpoint " + repr(bp_count) + " times!"
> DONE
Example multiple line Python breakpoint command, using function definition:
(lldb) breakpoint command add -s python 1
Enter your Python command(s). Type 'DONE' to end.
> def breakpoint_output (bp_no):
> out_string = "Hit breakpoint number " + repr (bp_no)
> print out_string
> return True
> breakpoint_output (1)
> DONE
)" "In this case, since there is a reference to a global variable, \
'bp_count', you will also need to make sure 'bp_count' exists and is \
initialized:" R"(
(lldb) script
>>> bp_count = 0
>>> quit()
)" "Your Python code, however organized, can optionally return a value. \
If the returned value is False, that tells LLDB not to stop at the breakpoint \
to which the code is associated. Returning anything other than False, or even \
returning None, or even omitting a return statement entirely, will cause \
LLDB to stop." R"(
)" "Final Note: A warning that no breakpoint command was generated when there \
are no syntax errors may indicate that a function was declared but never called."
);
CommandArgumentEntry arg;
CommandArgumentData bp_id_arg;

View File

@ -450,60 +450,74 @@ class CommandObjectCommandsAlias : public CommandObjectRaw
NULL)
{
SetHelpLong(
"'alias' allows the user to create a short-cut or abbreviation for long \n\
commands, multi-word commands, and commands that take particular options. \n\
Below are some simple examples of how one might use the 'alias' command: \n\
\n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
// command. \n\
'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
// command. Since breakpoint commands are two-word \n\
// commands, the user will still need to enter the \n\
// second word after 'bp', e.g. 'bp enable' or \n\
// 'bp delete'. \n\
'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
// two-word command 'breakpoint list'. \n\
\nAn alias can include some options for the command, with the values either \n\
filled in at the time the alias is created, or specified as positional \n\
arguments, to be filled in when the alias is invoked. The following example \n\
shows how to create aliases with options: \n\
\n\
'command alias bfl breakpoint set -f %1 -l %2' \n\
\nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
options already part of the alias. So if the user wants to set a breakpoint \n\
by file and line without explicitly having to use the -f and -l options, the \n\
user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
for the actual arguments that will be passed when the alias command is used. \n\
The number in the placeholder refers to the position/order the actual value \n\
occupies when the alias is used. All the occurrences of '%1' in the alias \n\
will be replaced with the first argument, all the occurrences of '%2' in the \n\
alias will be replaced with the second argument, and so on. This also allows \n\
actual arguments to be used multiple times within an alias (see 'process \n\
launch' example below). \n\
Note: the positional arguments must substitute as whole words in the resultant\n\
command, so you can't at present do something like:\n\
\n\
command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
\n\
to get the file extension \".cpp\" automatically appended. For more complex\n\
aliasing, use the \"command regex\" command instead.\n\
\nSo in the 'bfl' case, the actual file value will be \n\
filled in with the first argument following 'bfl' and the actual line number \n\
value will be filled in with the second argument. The user would use this \n\
alias as follows: \n\
\n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
<... some time later ...> \n\
(lldb) bfl my-file.c 137 \n\
\nThis would be the same as if the user had entered \n\
'breakpoint set -f my-file.c -l 137'. \n\
\nAnother example: \n\
\n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\
(lldb) pltty /dev/tty0 \n\
// becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
\nIf the user always wanted to pass the same value to a particular option, the \n\
alias could be defined with that value directly in the alias as a constant, \n\
rather than using a positional placeholder: \n\
\n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
// 3 of whatever file is indicated. \n");
"'alias' allows the user to create a short-cut or abbreviation for long \
commands, multi-word commands, and commands that take particular options. \
Below are some simple examples of how one might use the 'alias' command:" R"(
(lldb) command alias sc script
Creates the abbreviation 'sc' for the 'script' command.
(lldb) command alias bp breakpoint
)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
breakpoint commands are two-word commands, the user would still need to \
enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
(lldb) command alias bpl breakpoint list
Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
)" "An alias can include some options for the command, with the values either \
filled in at the time the alias is created, or specified as positional \
arguments, to be filled in when the alias is invoked. The following example \
shows how to create aliases with options:" R"(
(lldb) command alias bfl breakpoint set -f %1 -l %2
)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
options already part of the alias. So if the user wants to set a breakpoint \
by file and line without explicitly having to use the -f and -l options, the \
user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
for the actual arguments that will be passed when the alias command is used. \
The number in the placeholder refers to the position/order the actual value \
occupies when the alias is used. All the occurrences of '%1' in the alias \
will be replaced with the first argument, all the occurrences of '%2' in the \
alias will be replaced with the second argument, and so on. This also allows \
actual arguments to be used multiple times within an alias (see 'process \
launch' example below)." R"(
)" "Note: the positional arguments must substitute as whole words in the resultant \
command, so you can't at present do something like this to append the file extension \
\".cpp\":" R"(
(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
)" "For more complex aliasing, use the \"command regex\" command instead. In the \
'bfl' case above, the actual file value will be filled in with the first argument \
following 'bfl' and the actual line number value will be filled in with the second \
argument. The user would use this alias as follows:" R"(
(lldb) command alias bfl breakpoint set -f %1 -l %2
(lldb) bfl my-file.c 137
This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
Another example:
(lldb) command alias pltty process launch -s -o %1 -e %1
(lldb) pltty /dev/tty0
Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
)" "If the user always wanted to pass the same value to a particular option, the \
alias could be defined with that value directly in the alias as a constant, \
rather than using a positional placeholder:" R"(
(lldb) command alias bl3 breakpoint set -f %1 -l 3
Always sets a breakpoint on line 3 of whatever file is indicated.)"
);
CommandArgumentEntry arg1;
CommandArgumentEntry arg2;
@ -960,31 +974,30 @@ class CommandObjectCommandsAddRegex :
IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
SetHelpLong(
"This command allows the user to create powerful regular expression commands\n"
"with substitutions. The regular expressions and substitutions are specified\n"
"using the regular expression substitution format of:\n"
"\n"
" s/<regex>/<subst>/\n"
"\n"
"<regex> is a regular expression that can use parenthesis to capture regular\n"
"expression input and substitute the captured matches in the output using %1\n"
"for the first match, %2 for the second, and so on.\n"
"\n"
"The regular expressions can all be specified on the command line if more than\n"
"one argument is provided. If just the command name is provided on the command\n"
"line, then the regular expressions and substitutions can be entered on separate\n"
" lines, followed by an empty line to terminate the command definition.\n"
"\n"
"EXAMPLES\n"
"\n"
"The following example will define a regular expression command named 'f' that\n"
"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
"a number follows 'f':\n"
"\n"
" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
"\n"
);
SetHelpLong(R"(
)" "This command allows the user to create powerful regular expression commands \
with substitutions. The regular expressions and substitutions are specified \
using the regular expression substitution format of:" R"(
s/<regex>/<subst>/
)" "<regex> is a regular expression that can use parenthesis to capture regular \
expression input and substitute the captured matches in the output using %1 \
for the first match, %2 for the second, and so on." R"(
)" "The regular expressions can all be specified on the command line if more than \
one argument is provided. If just the command name is provided on the command \
line, then the regular expressions and substitutions can be entered on separate \
lines, followed by an empty line to terminate the command definition." R"(
EXAMPLES
)" "The following example will define a regular expression command named 'f' that \
will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
a number follows 'f':" R"(
(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
);
}
~CommandObjectCommandsAddRegex()

View File

@ -202,35 +202,39 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
m_expr_line_count (0),
m_expr_lines ()
{
SetHelpLong(
"Timeouts:\n\
If the expression can be evaluated statically (without running code) then it will be.\n\
Otherwise, by default the expression will run on the current thread with a short timeout:\n\
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted\n\
and resumed with all threads running. You can use the -a option to disable retrying on all\n\
threads. You can use the -t option to set a shorter timeout.\n\
\n\
User defined variables:\n\
You can define your own variables for convenience or to be used in subsequent expressions.\n\
You define them the same way you would define variables in C. If the first character of \n\
your user defined variable is a $, then the variable's value will be available in future\n\
expressions, otherwise it will just be available in the current expression.\n\
\n\
\n\
Continuing evaluation after a breakpoint:\n\
If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once\n\
you are done with your investigation, you can either remove the expression execution frames\n\
from the stack with \"thread return -x\" or if you are still interested in the expression result\n\
you can issue the \"continue\" command and the expression evaluation will complete and the\n\
expression result will be available using the \"thread.completed-expression\" key in the thread\n\
format.\n\
\n\
Examples: \n\
\n\
expr my_struct->a = my_array[3] \n\
expr -f bin -- (index * 8) + 5 \n\
expr unsigned int $foo = 5\n\
expr char c[] = \"foo\"; c[0]\n");
SetHelpLong(
R"(
Timeouts:
)" " If the expression can be evaluated statically (without running code) then it will be. \
Otherwise, by default the expression will run on the current thread with a short timeout: \
currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
and resumed with all threads running. You can use the -a option to disable retrying on all \
threads. You can use the -t option to set a shorter timeout." R"(
User defined variables:
)" " You can define your own variables for convenience or to be used in subsequent expressions. \
You define them the same way you would define variables in C. If the first character of \
your user defined variable is a $, then the variable's value will be available in future \
expressions, otherwise it will just be available in the current expression." R"(
Continuing evaluation after a breakpoint:
)" " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
you are done with your investigation, you can either remove the expression execution frames \
from the stack with \"thread return -x\" or if you are still interested in the expression result \
you can issue the \"continue\" command and the expression evaluation will complete and the \
expression result will be available using the \"thread.completed-expression\" key in the thread \
format." R"(
Examples:
expr my_struct->a = my_array[3]
expr -f bin -- (index * 8) + 5
expr unsigned int $foo = 5
expr char c[] = \"foo\"; c[0])"
);
CommandArgumentEntry arg;
CommandArgumentData expression_arg;

View File

@ -1067,10 +1067,12 @@ class CommandObjectPlatformGetFile : public CommandObjectParsed
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");
R"(Examples:
(lldb) platform get-file /the/remote/file/path /the/local/file/path
Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"
);
CommandArgumentEntry arg1, arg2;
CommandArgumentData file_arg_remote, file_arg_host;
@ -1150,10 +1152,12 @@ class CommandObjectPlatformGetSize : public CommandObjectParsed
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");
R"(Examples:
(lldb) platform get-size /the/remote/file/path
Get the file size from the remote end with path /the/remote/file/path.)"
);
CommandArgumentEntry arg1;
CommandArgumentData file_arg_remote;

View File

@ -1337,7 +1337,7 @@ class CommandObjectProcessSignal : public CommandObjectParsed
if (::isxdigit (signal_name[0]))
signo = StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
else
signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
if (signo == LLDB_INVALID_SIGNAL_NUMBER)
{
@ -1681,7 +1681,8 @@ class CommandObjectProcessHandle : public CommandObjectParsed
NULL),
m_options (interpreter)
{
SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n");
SetHelpLong ("\nIf no signals are specified, update them all. If no update "
"option is specified, list the current values.");
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@ -1734,14 +1735,14 @@ class CommandObjectProcessHandle : public CommandObjectParsed
}
void
PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
PrintSignal(Stream &str, int32_t signo, const char *sig_name, const UnixSignalsSP &signals_sp)
{
bool stop;
bool suppress;
bool notify;
str.Printf ("%-11s ", sig_name);
if (signals.GetSignalInfo (signo, suppress, stop, notify))
if (signals_sp->GetSignalInfo(signo, suppress, stop, notify))
{
bool pass = !suppress;
str.Printf ("%s %s %s",
@ -1753,7 +1754,7 @@ class CommandObjectProcessHandle : public CommandObjectParsed
}
void
PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
PrintSignalInformation(Stream &str, Args &signal_args, int num_valid_signals, const UnixSignalsSP &signals_sp)
{
PrintSignalHeader (str);
@ -1762,18 +1763,18 @@ class CommandObjectProcessHandle : public CommandObjectParsed
size_t num_args = signal_args.GetArgumentCount();
for (size_t i = 0; i < num_args; ++i)
{
int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i));
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals_sp);
}
}
else // Print info for ALL signals
{
int32_t signo = signals.GetFirstSignalNumber();
int32_t signo = signals_sp->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
signo = signals.GetNextSignalNumber (signo);
PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo), signals_sp);
signo = signals_sp->GetNextSignalNumber(signo);
}
}
}
@ -1830,27 +1831,27 @@ class CommandObjectProcessHandle : public CommandObjectParsed
}
size_t num_args = signal_args.GetArgumentCount();
UnixSignals &signals = process_sp->GetUnixSignals();
UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
int num_signals_set = 0;
if (num_args > 0)
{
for (size_t i = 0; i < num_args; ++i)
{
int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
int32_t signo = signals_sp->GetSignalNumberFromName(signal_args.GetArgumentAtIndex(i));
if (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
// Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
// the value is either 0 or 1.
if (stop_action != -1)
signals.SetShouldStop (signo, (bool) stop_action);
signals_sp->SetShouldStop(signo, stop_action);
if (pass_action != -1)
{
bool suppress = ! ((bool) pass_action);
signals.SetShouldSuppress (signo, suppress);
bool suppress = !pass_action;
signals_sp->SetShouldSuppress(signo, suppress);
}
if (notify_action != -1)
signals.SetShouldNotify (signo, (bool) notify_action);
signals_sp->SetShouldNotify(signo, notify_action);
++num_signals_set;
}
else
@ -1866,25 +1867,25 @@ class CommandObjectProcessHandle : public CommandObjectParsed
{
if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
{
int32_t signo = signals.GetFirstSignalNumber();
int32_t signo = signals_sp->GetFirstSignalNumber();
while (signo != LLDB_INVALID_SIGNAL_NUMBER)
{
if (notify_action != -1)
signals.SetShouldNotify (signo, (bool) notify_action);
signals_sp->SetShouldNotify(signo, notify_action);
if (stop_action != -1)
signals.SetShouldStop (signo, (bool) stop_action);
signals_sp->SetShouldStop(signo, stop_action);
if (pass_action != -1)
{
bool suppress = ! ((bool) pass_action);
signals.SetShouldSuppress (signo, suppress);
bool suppress = !pass_action;
signals_sp->SetShouldSuppress(signo, suppress);
}
signo = signals.GetNextSignalNumber (signo);
signo = signals_sp->GetNextSignalNumber(signo);
}
}
}
}
PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals_sp);
if (num_signals_set > 0)
result.SetStatus (eReturnStatusSuccessFinishNoResult);

View File

@ -60,24 +60,25 @@ class CommandObjectSettingsSet : public CommandObjectRaw
m_arguments.push_back (arg2);
SetHelpLong (
"When setting a dictionary or array variable, you can set multiple entries \n\
at once by giving the values to the set command. For example: \n\
\n\
(lldb) settings set target.run-args value1 value2 value3 \n\
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345 \n\
\n\
(lldb) settings show target.run-args \n\
[0]: 'value1' \n\
[1]: 'value2' \n\
[3]: 'value3' \n\
(lldb) settings show target.env-vars \n\
'MYPATH=~/.:/usr/bin'\n\
'SOME_ENV_VAR=12345' \n\
\n\
Warning: The 'set' command re-sets the entire array or dictionary. If you \n\
just want to add, remove or update individual values (or add something to \n\
the end), use one of the other settings sub-commands: append, replace, \n\
insert-before or insert-after.\n");
"\nWhen setting a dictionary or array variable, you can set multiple entries \
at once by giving the values to the set command. For example:" R"(
(lldb) settings set target.run-args value1 value2 value3
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
(lldb) settings show target.run-args
[0]: 'value1'
[1]: 'value2'
[3]: 'value3'
(lldb) settings show target.env-vars
'MYPATH=~/.:/usr/bin'
'SOME_ENV_VAR=12345'
)" "Warning: The 'set' command re-sets the entire array or dictionary. If you \
just want to add, remove or update individual values (or add something to \
the end), use one of the other settings sub-commands: append, replace, \
insert-before or insert-after."
);
}

View File

@ -764,31 +764,39 @@ class CommandObjectTypeFormatAdd : public CommandObjectParsed
m_arguments.push_back (type_arg);
SetHelpLong(
"Some examples of using this command.\n"
"We use as reference the following snippet of code:\n"
"\n"
"typedef int Aint;\n"
"typedef float Afloat;\n"
"typedef Aint Bint;\n"
"typedef Afloat Bfloat;\n"
"\n"
"Aint ix = 5;\n"
"Bint iy = 5;\n"
"\n"
"Afloat fx = 3.14;\n"
"BFloat fy = 3.14;\n"
"\n"
"Typing:\n"
"type format add -f hex AInt\n"
"frame variable iy\n"
"will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n"
"To prevent this type\n"
"type format add -f hex -C no AInt\n"
"\n"
"A similar reasoning applies to\n"
"type format add -f hex -C no float -p\n"
"which now prints all floats and float&s as hexadecimal, but does not format float*s\n"
"and does not change the default display for Afloat and Bfloat objects.\n"
R"(
The following examples of 'type format add' refer to this code snippet for context:
typedef int Aint;
typedef float Afloat;
typedef Aint Bint;
typedef Afloat Bfloat;
Aint ix = 5;
Bint iy = 5;
Afloat fx = 3.14;
BFloat fy = 3.14;
Adding default formatting:
(lldb) type format add -f hex AInt
(lldb) frame variable iy
)" " Produces hexidecimal display of iy, because no formatter is available for Bint and \
the one for Aint is used instead." R"(
To prevent this use the cascade option '-C no' to prevent evaluation of typedef chains:
(lldb) type format add -f hex -C no AInt
Similar reasoning applies to this:
(lldb) type format add -f hex -C no float -p
)" " All float values and float references are now formatted as hexadecimal, but not \
pointers to floats. Nor will it change the default display for Afloat and Bfloat objects."
);
// Add the "--format" to all options groups
@ -1736,69 +1744,86 @@ CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &in
m_arguments.push_back (type_arg);
SetHelpLong(
"Some examples of using this command.\n"
"We use as reference the following snippet of code:\n"
"struct JustADemo\n"
"{\n"
"int* ptr;\n"
"float value;\n"
"JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n"
"};\n"
"JustADemo object(42,3.14);\n"
"struct AnotherDemo : public JustADemo\n"
"{\n"
"uint8_t byte;\n"
"AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n"
"};\n"
"AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n"
"\n"
"type summary add --summary-string \"the answer is ${*var.ptr}\" JustADemo\n"
"when typing frame variable object you will get \"the answer is 42\"\n"
"type summary add --summary-string \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n"
"when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n"
"\n"
"Alternatively, you could also say\n"
"type summary add --summary-string \"${var%V} -> ${*var}\" \"int *\"\n"
"and replace the above summary string with\n"
"type summary add --summary-string \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n"
"to obtain a similar result\n"
"\n"
"To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n"
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n"
"\n"
"This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n"
"If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n"
"type summary add --summary-string \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n"
"A similar option -r exists for references.\n"
"\n"
"If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n"
"you can use the -c option, without giving any summary string:\n"
"type summary add -c JustADemo\n"
"frame variable object\n"
"the output being similar to (ptr=0xsomeaddress, value=3.14)\n"
"\n"
"If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n"
"type summary add -e --summary-string \"*ptr = ${*var.ptr}\" JustADemo\n"
"Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n"
"to get an output like:\n"
"\n"
"*ptr = 42 {\n"
" ptr = 0xsomeaddress\n"
" value = 3.14\n"
"}\n"
"\n"
"You can also add Python summaries, in which case you will use lldb public API to gather information from your variables"
"and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your"
"script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n"
"type summary add JustADemo -o \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n"
"If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with "
"the word DONE on a line by itself to mark you're finished editing your code:\n"
"(lldb)type summary add JustADemo -P\n"
" value = valobj.GetChildMemberWithName('value');\n"
" return 'My value is ' + value.GetValue();\n"
"DONE\n"
"(lldb) <-- type further LLDB commands here\n"
);
R"(
The following examples of 'type summary add' refer to this code snippet for context:
struct JustADemo
{
int* ptr;
float value;
JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}
};
JustADemo demo_instance(42, 3.14);
typedef JustADemo NewDemo;
NewDemo new_demo_instance(42, 3.14);
(lldb) type summary add --summary-string "the answer is ${*var.ptr}" JustADemo
Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42"
(lldb) type summary add --summary-string "the answer is ${*var.ptr}, and the question is ${var.value}" JustADemo
Subsequently displaying demo_instance with 'frame variable' or 'expression' will display "the answer is 42 and the question is 3.14"
)" "Alternatively, you could define formatting for all pointers to integers and \
rely on that when formatting JustADemo to obtain the same result:" R"(
(lldb) type summary add --summary-string "${var%V} -> ${*var}" "int *"
(lldb) type summary add --summary-string "the answer is ${var.ptr}, and the question is ${var.value}" JustADemo
)" "Type summaries are automatically applied to derived typedefs, so the examples \
above apply to both JustADemo and NewDemo. The cascade option can be used to \
suppress this behavior:" R"(
(lldb) type summary add --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo -C no
The summary will now be used for values of JustADemo but not NewDemo.
)" "By default summaries are shown for pointers and references to values of the \
specified type. To suppress formatting for pointers use the -p option, or apply \
the corresponding -r option to suppress formatting for references:" R"(
(lldb) type summary add -p -r --summary-string "${var.ptr}, ${var.value},{${var.byte}}" JustADemo
)" "One-line summaries including all fields in a type can be inferred without supplying an \
explicit summary string by passing the -c option:" R"(
(lldb) type summary add -c JustADemo
(lldb) frame variable demo_instance
(ptr=<address>, value=3.14)
)" "Type summaries normally suppress the nested display of individual fields. To \
supply a summary to supplement the default structure add the -e option:" R"(
(lldb) type summary add -e --summary-string "*ptr = ${*var.ptr}" JustADemo
)" "Now when displaying JustADemo values the int* is displayed, followed by the \
standard LLDB sequence of children, one per line:" R"(
*ptr = 42 {
ptr = <address>
value = 3.14
}
)" "You can also add summaries written in Python. These scripts use lldb public API to \
gather information from your variables and produce a meaningful summary. To start a \
multi-line script use the -P option. The function declaration will be displayed along with \
a comment describing the two arguments. End your script with the word 'DONE' on a line by \
itself:" R"(
(lldb) type summary add JustADemo -P
def function (valobj,internal_dict):
"""valobj: an SBValue which you want to provide a summary for
internal_dict: an LLDB support object not to be used"""
value = valobj.GetChildMemberWithName('value');
return 'My value is ' + value.GetValue();
DONE
Alternatively, the -o option can be used when providing a simple one-line Python script:
(lldb) type summary add JustADemo -o "value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();")"
);
}
bool
@ -4117,31 +4142,37 @@ class CommandObjectTypeFilterAdd : public CommandObjectParsed
m_arguments.push_back (type_arg);
SetHelpLong(
"Some examples of using this command.\n"
"We use as reference the following snippet of code:\n"
"\n"
"class Foo {;\n"
" int a;\n"
" int b;\n"
" int c;\n"
" int d;\n"
" int e;\n"
" int f;\n"
" int g;\n"
" int h;\n"
" int i;\n"
"} \n"
"Typing:\n"
"type filter add --child a --child g Foo\n"
"frame variable a_foo\n"
"will produce an output where only a and g are displayed\n"
"Other children of a_foo (b,c,d,e,f,h and i) are available by asking for them, as in:\n"
"frame variable a_foo.b a_foo.c ... a_foo.i\n"
"\n"
"Use option --raw to frame variable prevails on the filter\n"
"frame variable a_foo --raw\n"
"shows all the children of a_foo (a thru i) as if no filter was defined\n"
);
R"(
The following examples of 'type filter add' refer to this code snippet for context:
class Foo {
int a;
int b;
int c;
int d;
int e;
int f;
int g;
int h;
int i;
}
Foo my_foo;
Adding a simple filter:
(lldb) type filter add --child a --child g Foo
(lldb) frame variable my_foo
)" "Produces output where only a and g are displayed. Other children of my_foo \
(b, c, d, e, f, h and i) are available by asking for them explicitly:" R"(
(lldb) frame variable my_foo.b my_foo.c my_foo.i
)" "The formatting option --raw on frame variable bypasses the filter, showing \
all children of my_foo as if no filter was defined:" R"(
(lldb) frame variable my_foo --raw)"
);
}
~CommandObjectTypeFilterAdd ()

View File

@ -931,10 +931,14 @@ class CommandObjectWatchpointSetVariable : public CommandObjectParsed
m_option_watchpoint ()
{
SetHelpLong(
"Examples: \n\
\n\
watchpoint set variable -w read_write my_global_var \n\
# Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
R"(
Examples:
(lldb) watchpoint set variable -w read_write my_global_var
)" " Watches my_global_var for read/write access, with the region to watch \
corresponding to the byte size of the data type."
);
CommandArgumentEntry arg;
CommandArgumentData var_name_arg;
@ -1138,10 +1142,13 @@ class CommandObjectWatchpointSetExpression : public CommandObjectRaw
m_option_watchpoint ()
{
SetHelpLong(
"Examples: \n\
\n\
watchpoint set expression -w write -x 1 -- foo + 32\n\
# Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
R"(
Examples:
(lldb) watchpoint set expression -w write -x 1 -- foo + 32
Watches write access for the 1-byte region pointed to by the address 'foo + 32')"
);
CommandArgumentEntry arg;
CommandArgumentData expression_arg;

View File

@ -48,121 +48,112 @@ class CommandObjectWatchpointCommandAdd :
m_options (interpreter)
{
SetHelpLong (
"\nGeneral information about entering watchpoint commands \n\
------------------------------------------------------ \n\
\n\
This command will cause you to be prompted to enter the command or set \n\
of commands you wish to be executed when the specified watchpoint is \n\
hit. You will be told to enter your command(s), and will see a '> ' \n\
prompt. Because you can enter one or many commands to be executed when \n\
a watchpoint is hit, you will continue to be prompted after each \n\
new-line that you enter, until you enter the word 'DONE', which will \n\
cause the commands you have entered to be stored with the watchpoint \n\
and executed when the watchpoint is hit. \n\
\n\
Syntax checking is not necessarily done when watchpoint commands are \n\
entered. An improperly written watchpoint command will attempt to get \n\
executed when the watchpoint gets hit, and usually silently fail. If \n\
your watchpoint command does not appear to be getting executed, go \n\
back and check your syntax. \n\
\n\
\n\
Special information about PYTHON watchpoint commands \n\
---------------------------------------------------- \n\
\n\
You may enter either one line of Python or multiple lines of Python \n\
(including defining whole functions, if desired). If you enter a \n\
single line of Python, that will be passed to the Python interpreter \n\
'as is' when the watchpoint gets hit. If you enter function \n\
definitions, they will be passed to the Python interpreter as soon as \n\
you finish entering the watchpoint command, and they can be called \n\
later (don't forget to add calls to them, if you want them called when \n\
the watchpoint is hit). If you enter multiple lines of Python that \n\
are not function definitions, they will be collected into a new, \n\
automatically generated Python function, and a call to the newly \n\
generated function will be attached to the watchpoint. \n\
\n\
This auto-generated function is passed in two arguments: \n\
\n\
frame: an SBFrame object representing the frame which hit the watchpoint. \n\
From the frame you can get back to the thread and process. \n\
wp: the watchpoint that was hit. \n\
\n\
Important Note: Because loose Python code gets collected into functions, \n\
if you want to access global variables in the 'loose' code, you need to \n\
specify that they are global, using the 'global' keyword. Be sure to \n\
use correct Python syntax, including indentation, when entering Python \n\
watchpoint commands. \n\
\n\
As a third option, you can pass the name of an already existing Python function \n\
and that function will be attached to the watchpoint. It will get passed the \n\
frame and wp_loc arguments mentioned above. \n\
\n\
Example Python one-line watchpoint command: \n\
\n\
(lldb) watchpoint command add -s python 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> print \"Hit this watchpoint!\" \n\
> DONE \n\
\n\
As a convenience, this also works for a short Python one-liner: \n\
(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
(lldb) run \n\
Launching '.../a.out' (x86_64) \n\
(lldb) Fri Sep 10 12:17:45 2010 \n\
Process 21778 Stopped \n\
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
36 \n\
37 int c(int val)\n\
38 {\n\
39 -> return val + 3;\n\
40 }\n\
41 \n\
42 int main (int argc, char const *argv[])\n\
(lldb) \n\
\n\
Example multiple line Python watchpoint command, using function definition: \n\
\n\
(lldb) watchpoint command add -s python 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> def watchpoint_output (wp_no): \n\
> out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
> print out_string \n\
> return True \n\
> watchpoint_output (1) \n\
> DONE \n\
\n\
\n\
Example multiple line Python watchpoint command, using 'loose' Python: \n\
\n\
(lldb) watchpoint command add -s p 1 \n\
Enter your Python command(s). Type 'DONE' to end. \n\
> global wp_count \n\
> wp_count = wp_count + 1 \n\
> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
> DONE \n\
\n\
In this case, since there is a reference to a global variable, \n\
'wp_count', you will also need to make sure 'wp_count' exists and is \n\
initialized: \n\
\n\
(lldb) script \n\
>>> wp_count = 0 \n\
>>> quit() \n\
\n\
(lldb) \n\
\n\
\n\
Final Note: If you get a warning that no watchpoint command was generated, \n\
but you did not get any syntax errors, you probably forgot to add a call \n\
to your functions. \n\
\n\
Special information about debugger command watchpoint commands \n\
-------------------------------------------------------------- \n\
\n\
You may enter any debugger command, exactly as you would at the \n\
debugger prompt. You may enter as many debugger commands as you like, \n\
but do NOT enter more than one command per line. \n" );
R"(
General information about entering watchpoint commands
------------------------------------------------------
)" "This command will prompt for commands to be executed when the specified \
watchpoint is hit. Each command is typed on its own line following the '> ' \
prompt until 'DONE' is entered." R"(
)" "Syntactic errors may not be detected when initially entered, and many \
malformed commands can silently fail when executed. If your watchpoint commands \
do not appear to be executing, double-check the command syntax." R"(
)" "Note: You may enter any debugger command exactly as you would at the debugger \
prompt. There is no limit to the number of commands supplied, but do NOT enter \
more than one command per line." R"(
Special information about PYTHON watchpoint commands
----------------------------------------------------
)" "You may enter either one or more lines of Python, including function \
definitions or calls to functions that will have been imported by the time \
the code executes. Single line watchpoint commands will be interpreted 'as is' \
when the watchpoint is hit. Multiple lines of Python will be wrapped in a \
generated function, and a call to the function will be attached to the watchpoint." R"(
This auto-generated function is passed in three arguments:
frame: an lldb.SBFrame object for the frame which hit the watchpoint.
wp: the watchpoint that was hit.
)" "When specifying a python function with the --python-function option, you need \
to supply the function name prepended by the module name:" R"(
--python-function myutils.watchpoint_callback
The function itself must have the following prototype:
def watchpoint_callback(frame, wp):
# Your code goes here
)" "The arguments are the same as the arguments passed to generated functions as \
described above. Note that the global variable 'lldb.frame' will NOT be updated when \
this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
can get you to the thread via frame.GetThread(), the thread can get you to the \
process via thread.GetProcess(), and the process can get you back to the target \
via process.GetTarget()." R"(
)" "Important Note: As Python code gets collected into functions, access to global \
variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
Python syntax, including indentation, when entering Python watchpoint commands." R"(
Example Python one-line watchpoint command:
(lldb) watchpoint command add -s python 1
Enter your Python command(s). Type 'DONE' to end.
> print "Hit this watchpoint!"
> DONE
As a convenience, this also works for a short Python one-liner:
(lldb) watchpoint command add -s python 1 -o 'import time; print time.asctime()'
(lldb) run
Launching '.../a.out' (x86_64)
(lldb) Fri Sep 10 12:17:45 2010
Process 21778 Stopped
* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread
36
37 int c(int val)
38 {
39 -> return val + 3;
40 }
41
42 int main (int argc, char const *argv[])
Example multiple line Python watchpoint command, using function definition:
(lldb) watchpoint command add -s python 1
Enter your Python command(s). Type 'DONE' to end.
> def watchpoint_output (wp_no):
> out_string = "Hit watchpoint number " + repr (wp_no)
> print out_string
> return True
> watchpoint_output (1)
> DONE
Example multiple line Python watchpoint command, using 'loose' Python:
(lldb) watchpoint command add -s p 1
Enter your Python command(s). Type 'DONE' to end.
> global wp_count
> wp_count = wp_count + 1
> print "Hit this watchpoint " + repr(wp_count) + " times!"
> DONE
)" "In this case, since there is a reference to a global variable, \
'wp_count', you will also need to make sure 'wp_count' exists and is \
initialized:" R"(
(lldb) script
>>> wp_count = 0
>>> quit()
)" "Final Note: A warning that no watchpoint command was generated when there \
are no syntax errors may indicate that a function was declared but never called."
);
CommandArgumentEntry arg;
CommandArgumentData wp_id_arg;

View File

@ -887,20 +887,15 @@ ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t su
}
else if (arch_type == eArchTypeELF)
{
llvm::Triple::OSType ostype;
switch (os)
{
case llvm::ELF::ELFOSABI_AIX: ostype = llvm::Triple::OSType::AIX; break;
case llvm::ELF::ELFOSABI_FREEBSD: ostype = llvm::Triple::OSType::FreeBSD; break;
case llvm::ELF::ELFOSABI_GNU: ostype = llvm::Triple::OSType::Linux; break;
case llvm::ELF::ELFOSABI_NETBSD: ostype = llvm::Triple::OSType::NetBSD; break;
case llvm::ELF::ELFOSABI_OPENBSD: ostype = llvm::Triple::OSType::OpenBSD; break;
case llvm::ELF::ELFOSABI_SOLARIS: ostype = llvm::Triple::OSType::Solaris; break;
default:
ostype = llvm::Triple::OSType::UnknownOS;
case llvm::ELF::ELFOSABI_AIX: m_triple.setOS (llvm::Triple::OSType::AIX); break;
case llvm::ELF::ELFOSABI_FREEBSD: m_triple.setOS (llvm::Triple::OSType::FreeBSD); break;
case llvm::ELF::ELFOSABI_GNU: m_triple.setOS (llvm::Triple::OSType::Linux); break;
case llvm::ELF::ELFOSABI_NETBSD: m_triple.setOS (llvm::Triple::OSType::NetBSD); break;
case llvm::ELF::ELFOSABI_OPENBSD: m_triple.setOS (llvm::Triple::OSType::OpenBSD); break;
case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS (llvm::Triple::OSType::Solaris); break;
}
m_triple.setOS (ostype);
m_triple.setVendor (llvm::Triple::UnknownVendor);
}
// Fall back onto setting the machine type if the arch by name failed...
if (m_triple.getArch () == llvm::Triple::UnknownArch)
@ -1186,11 +1181,46 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
case ArchSpec::eCore_mips32:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last)
return true;
try_inverse = false;
}
break;
case ArchSpec::eCore_mips32el:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last)
return true;
try_inverse = false;
}
case ArchSpec::eCore_mips64:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last)
return true;
if (core2 >= ArchSpec::kCore_mips64_first && core2 <= ArchSpec::kCore_mips64_last)
return true;
try_inverse = false;
}
case ArchSpec::eCore_mips64el:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last)
return true;
if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= ArchSpec::kCore_mips64el_last)
return true;
try_inverse = false;
}
case ArchSpec::eCore_mips64r2:
case ArchSpec::eCore_mips64r3:
case ArchSpec::eCore_mips64r5:
case ArchSpec::eCore_mips64r6:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32_first && core2 <= (core1 - 10))
@ -1201,11 +1231,9 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
case ArchSpec::eCore_mips64el:
case ArchSpec::eCore_mips64r2el:
case ArchSpec::eCore_mips64r3el:
case ArchSpec::eCore_mips64r5el:
case ArchSpec::eCore_mips64r6el:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= (core1 - 10))
@ -1216,6 +1244,63 @@ cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_in
}
break;
case ArchSpec::eCore_mips32r2:
case ArchSpec::eCore_mips32r3:
case ArchSpec::eCore_mips32r5:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32_first && core2 <= core1)
return true;
}
break;
case ArchSpec::eCore_mips32r2el:
case ArchSpec::eCore_mips32r3el:
case ArchSpec::eCore_mips32r5el:
if (!enforce_exact_match)
{
if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= core1)
return true;
}
break;
case ArchSpec::eCore_mips32r6:
if (!enforce_exact_match)
{
if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6)
return true;
}
break;
case ArchSpec::eCore_mips32r6el:
if (!enforce_exact_match)
{
if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el)
return true;
return true;
}
break;
case ArchSpec::eCore_mips64r6:
if (!enforce_exact_match)
{
if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6)
return true;
if (core2 == ArchSpec::eCore_mips64 || core2 == ArchSpec::eCore_mips64r6)
return true;
}
break;
case ArchSpec::eCore_mips64r6el:
if (!enforce_exact_match)
{
if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el)
return true;
if (core2 == ArchSpec::eCore_mips64el || core2 == ArchSpec::eCore_mips64r6el)
return true;
}
break;
default:
break;
}

View File

@ -1830,26 +1830,14 @@ DataExtractor::Dump (Stream *s,
}
else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy))
{
const auto &semantics = ast->getFloatTypeSemantics(ast->LongDoubleTy);
const auto byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
llvm::APInt apint;
switch (target_sp->GetArchitecture().GetMachine())
if (GetAPInt(*this, &offset, byte_size, apint))
{
case llvm::Triple::x86:
case llvm::Triple::x86_64:
// clang will assert when constructing the apfloat if we use a 16 byte integer value
if (GetAPInt (*this, &offset, 10, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
break;
default:
if (GetAPInt (*this, &offset, item_byte_size, apint))
{
llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->LongDoubleTy), apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
break;
llvm::APFloat apfloat(semantics, apint);
apfloat.toString(sv, format_precision, format_max_padding);
}
}
else if (item_bit_size == ast->getTypeSize(ast->HalfTy))

View File

@ -1666,7 +1666,7 @@ FormatEntity::Format (const Entry &entry,
if (inline_info)
{
s.PutCString(" [inlined] ");
inline_info->GetName().Dump(&s);
inline_info->GetName(sc->function->GetLanguage()).Dump(&s);
}
}
}
@ -1679,9 +1679,9 @@ FormatEntity::Format (const Entry &entry,
{
ConstString name;
if (sc->function)
name = sc->function->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
name = sc->function->GetNameNoArguments();
else if (sc->symbol)
name = sc->symbol->GetMangled().GetName (Mangled::ePreferDemangledWithoutArguments);
name = sc->symbol->GetNameNoArguments();
if (name)
{
s.PutCString(name.GetCString());
@ -1724,7 +1724,7 @@ FormatEntity::Format (const Entry &entry,
{
s.PutCString (cstr);
s.PutCString (" [inlined] ");
cstr = inline_info->GetName().GetCString();
cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString();
}
VariableList args;

View File

@ -66,7 +66,7 @@ cstring_is_mangled(const char *s)
}
static const ConstString &
get_demangled_name_without_arguments (const Mangled *obj)
get_demangled_name_without_arguments (ConstString mangled, ConstString demangled)
{
// This pair is <mangled name, demangled name without function arguments>
static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args;
@ -77,9 +77,6 @@ get_demangled_name_without_arguments (const Mangled *obj)
static ConstString g_last_mangled;
static ConstString g_last_demangled;
ConstString mangled = obj->GetMangledName ();
ConstString demangled = obj->GetDemangledName ();
if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled)
{
return g_most_recent_mangled_to_name_sans_args.second;
@ -197,7 +194,7 @@ Mangled::Clear ()
int
Mangled::Compare (const Mangled& a, const Mangled& b)
{
return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
return ConstString::Compare(a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
}
@ -261,7 +258,7 @@ Mangled::SetValue (const ConstString &name)
// object's lifetime.
//----------------------------------------------------------------------
const ConstString&
Mangled::GetDemangledName () const
Mangled::GetDemangledName (lldb::LanguageType language) const
{
// Check to make sure we have a valid mangled name and that we
// haven't already decoded our mangled name.
@ -339,13 +336,20 @@ Mangled::GetDemangledName () const
}
ConstString
Mangled::GetDisplayDemangledName (lldb::LanguageType language) const
{
return GetDemangledName(language);
}
bool
Mangled::NameMatches (const RegularExpression& regex) const
Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType language) const
{
if (m_mangled && regex.Execute (m_mangled.AsCString()))
return true;
if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
ConstString demangled = GetDemangledName(language);
if (demangled && regex.Execute (demangled.AsCString()))
return true;
return false;
}
@ -353,30 +357,28 @@ Mangled::NameMatches (const RegularExpression& regex) const
//----------------------------------------------------------------------
// Get the demangled name if there is one, else return the mangled name.
//----------------------------------------------------------------------
const ConstString&
Mangled::GetName (Mangled::NamePreference preference) const
ConstString
Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const
{
ConstString demangled = GetDemangledName(language);
if (preference == ePreferDemangledWithoutArguments)
{
// Call the accessor to make sure we get a demangled name in case
// it hasn't been demangled yet...
GetDemangledName();
return get_demangled_name_without_arguments (this);
return get_demangled_name_without_arguments (m_mangled, demangled);
}
if (preference == ePreferDemangled)
{
// Call the accessor to make sure we get a demangled name in case
// it hasn't been demangled yet...
if (GetDemangledName())
return m_demangled;
if (demangled)
return demangled;
return m_mangled;
}
else
{
if (m_mangled)
return m_mangled;
return GetDemangledName();
return demangled;
}
}
@ -429,7 +431,7 @@ Mangled::GuessLanguage () const
ConstString mangled = GetMangledName();
if (mangled)
{
if (GetDemangledName())
if (GetDemangledName(lldb::eLanguageTypeUnknown))
{
if (cstring_is_mangled(mangled.GetCString()))
return lldb::eLanguageTypeC_plus_plus;
@ -447,7 +449,7 @@ operator << (Stream& s, const Mangled& obj)
if (obj.GetMangledName())
s << "mangled = '" << obj.GetMangledName() << "'";
const ConstString& demangled = obj.GetDemangledName();
const ConstString& demangled = obj.GetDemangledName(lldb::eLanguageTypeUnknown);
if (demangled)
s << ", demangled = '" << demangled << '\'';
else

View File

@ -14,301 +14,148 @@
#include <inttypes.h>
#include "lldb/Core/StreamString.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/JSON.h"
using namespace lldb_private;
static StructuredData::ObjectSP read_json_object (const char **ch);
static StructuredData::ObjectSP read_json_array (const char **ch);
//----------------------------------------------------------------------
// Functions that use a JSONParser to parse JSON into StructuredData
//----------------------------------------------------------------------
static StructuredData::ObjectSP ParseJSONValue (JSONParser &json_parser);
static StructuredData::ObjectSP ParseJSONObject (JSONParser &json_parser);
static StructuredData::ObjectSP ParseJSONArray (JSONParser &json_parser);
static StructuredData::ObjectSP
read_json_number (const char **ch)
ParseJSONObject (JSONParser &json_parser)
{
StructuredData::ObjectSP object_sp;
while (isspace (**ch))
(*ch)++;
const char *start_of_number = *ch;
bool is_integer = true;
bool is_float = false;
while (isdigit(**ch) || **ch == '-' || **ch == '.' || **ch == '+' || **ch == 'e' || **ch == 'E')
{
if (isdigit(**ch) == false && **ch != '-')
{
is_integer = false;
is_float = true;
}
(*ch)++;
}
while (isspace (**ch))
(*ch)++;
if (**ch == ',' || **ch == ']' || **ch == '}')
{
if (is_integer)
{
errno = 0;
uint64_t val = strtoul (start_of_number, NULL, 10);
if (errno == 0)
{
object_sp.reset(new StructuredData::Integer());
object_sp->GetAsInteger()->SetValue (val);
}
}
if (is_float)
{
char *end_of_number = NULL;
errno = 0;
double val = strtod (start_of_number, &end_of_number);
if (errno == 0 && end_of_number != start_of_number && end_of_number != NULL)
{
object_sp.reset(new StructuredData::Float());
object_sp->GetAsFloat()->SetValue (val);
}
}
}
return object_sp;
}
// The "JSONParser::Token::ObjectStart" token should have already been consumed
// by the time this function is called
std::unique_ptr<StructuredData::Dictionary> dict_up(new StructuredData::Dictionary());
static std::string
read_json_string (const char **ch)
{
std::string string;
if (**ch == '"')
std::string value;
std::string key;
while (1)
{
(*ch)++;
while (**ch != '\0')
{
if (**ch == '"')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
break;
}
else if (**ch == '\\')
{
switch (**ch)
{
case '"':
string.push_back('"');
*ch += 2;
break;
case '\\':
string.push_back('\\');
*ch += 2;
break;
case '/':
string.push_back('/');
*ch += 2;
break;
case 'b':
string.push_back('\b');
*ch += 2;
break;
case 'f':
string.push_back('\f');
*ch += 2;
break;
case 'n':
string.push_back('\n');
*ch += 2;
break;
case 'r':
string.push_back('\r');
*ch += 2;
break;
case 't':
string.push_back('\t');
*ch += 2;
break;
case 'u':
// FIXME handle four-hex-digits
*ch += 10;
break;
default:
*ch += 1;
}
}
else
{
string.push_back (**ch);
}
(*ch)++;
}
}
return string;
}
JSONParser::Token token = json_parser.GetToken(value);
static StructuredData::ObjectSP
read_json_value (const char **ch)
{
StructuredData::ObjectSP object_sp;
while (isspace (**ch))
(*ch)++;
if (**ch == '{')
{
object_sp = read_json_object (ch);
}
else if (**ch == '[')
{
object_sp = read_json_array (ch);
}
else if (**ch == '"')
{
std::string string = read_json_string (ch);
object_sp.reset(new StructuredData::String());
object_sp->GetAsString()->SetValue(string);
}
else
{
if (strncmp (*ch, "true", 4) == 0)
if (token == JSONParser::Token::String)
{
object_sp.reset(new StructuredData::Boolean());
object_sp->GetAsBoolean()->SetValue(true);
*ch += 4;
key.swap(value);
token = json_parser.GetToken(value);
if (token == JSONParser::Token::Colon)
{
StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
if (value_sp)
dict_up->AddItem(key, value_sp);
else
break;
}
}
else if (strncmp (*ch, "false", 5) == 0)
else if (token == JSONParser::Token::ObjectEnd)
{
object_sp.reset(new StructuredData::Boolean());
object_sp->GetAsBoolean()->SetValue(false);
*ch += 5;
return StructuredData::ObjectSP(dict_up.release());
}
else if (strncmp (*ch, "null", 4) == 0)
else if (token == JSONParser::Token::Comma)
{
object_sp.reset(new StructuredData::Null());
*ch += 4;
continue;
}
else
{
object_sp = read_json_number (ch);
break;
}
}
return object_sp;
return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
read_json_array (const char **ch)
ParseJSONArray (JSONParser &json_parser)
{
StructuredData::ObjectSP object_sp;
if (**ch == '[')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
// The "JSONParser::Token::ObjectStart" token should have already been consumed
// by the time this function is called
std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array());
bool first_value = true;
while (**ch != '\0' && (first_value || **ch == ','))
std::string value;
std::string key;
while (1)
{
StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
if (value_sp)
array_up->AddItem(value_sp);
else
break;
JSONParser::Token token = json_parser.GetToken(value);
if (token == JSONParser::Token::Comma)
{
if (**ch == ',')
(*ch)++;
first_value = false;
while (isspace (**ch))
(*ch)++;
lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
if (value_sp)
{
if (object_sp.get() == NULL)
{
object_sp.reset(new StructuredData::Array());
}
object_sp->GetAsArray()->Push (value_sp);
}
while (isspace (**ch))
(*ch)++;
continue;
}
if (**ch == ']')
else if (token == JSONParser::Token::ArrayEnd)
{
// FIXME should throw an error if we don't see a } to close out the JSON object
(*ch)++;
while (isspace (**ch))
(*ch)++;
return StructuredData::ObjectSP(array_up.release());
}
else
{
break;
}
}
return object_sp;
return StructuredData::ObjectSP();
}
static StructuredData::ObjectSP
read_json_object (const char **ch)
ParseJSONValue (JSONParser &json_parser)
{
StructuredData::ObjectSP object_sp;
if (**ch == '{')
std::string value;
const JSONParser::Token token = json_parser.GetToken(value);
switch (token)
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
bool first_pair = true;
while (**ch != '\0' && (first_pair || **ch == ','))
{
first_pair = false;
if (**ch == ',')
(*ch)++;
while (isspace (**ch))
(*ch)++;
if (**ch != '"')
break;
std::string key_string = read_json_string (ch);
while (isspace (**ch))
(*ch)++;
if (key_string.size() > 0 && **ch == ':')
{
(*ch)++;
while (isspace (**ch))
(*ch)++;
lldb_private::StructuredData::ObjectSP value_sp = read_json_value (ch);
if (value_sp.get())
{
if (object_sp.get() == NULL)
{
object_sp.reset(new StructuredData::Dictionary());
}
object_sp->GetAsDictionary()->AddItem (key_string.c_str(), value_sp);
}
}
while (isspace (**ch))
(*ch)++;
}
if (**ch == '}')
{
// FIXME should throw an error if we don't see a } to close out the JSON object
(*ch)++;
while (isspace (**ch))
(*ch)++;
}
}
return object_sp;
}
case JSONParser::Token::ObjectStart:
return ParseJSONObject(json_parser);
case JSONParser::Token::ArrayStart:
return ParseJSONArray(json_parser);
case JSONParser::Token::Integer:
{
bool success = false;
uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
if (success)
return StructuredData::ObjectSP(new StructuredData::Integer(uval));
}
break;
case JSONParser::Token::Float:
{
bool success = false;
double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
if (success)
return StructuredData::ObjectSP(new StructuredData::Float(val));
}
break;
case JSONParser::Token::String:
return StructuredData::ObjectSP(new StructuredData::String(value));
case JSONParser::Token::True:
case JSONParser::Token::False:
return StructuredData::ObjectSP(new StructuredData::Boolean(token == JSONParser::Token::True));
case JSONParser::Token::Null:
return StructuredData::ObjectSP(new StructuredData::Null());
default:
break;
}
return StructuredData::ObjectSP();
}
StructuredData::ObjectSP
StructuredData::ParseJSON (std::string json_text)
{
StructuredData::ObjectSP object_sp;
const size_t json_text_size = json_text.size();
if (json_text_size > 0)
{
const char *start_of_json_text = json_text.c_str();
const char *c = json_text.c_str();
while (*c != '\0' &&
static_cast<size_t>(c - start_of_json_text) <= json_text_size)
{
while (isspace (*c) &&
static_cast<size_t>(c - start_of_json_text) < json_text_size)
c++;
if (*c == '{')
{
object_sp = read_json_object (&c);
}
else if (*c == '[')
{
object_sp = read_json_array (&c);
}
else
{
// We have bad characters here, this is likely an illegal JSON string.
return object_sp;
}
}
}
JSONParser json_parser(json_text.c_str());
StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
return object_sp;
}
@ -395,7 +242,7 @@ StructuredData::Integer::Dump (Stream &s) const
void
StructuredData::Float::Dump (Stream &s) const
{
s.Printf ("%lf", m_value);
s.Printf ("%lg", m_value);
}
void

View File

@ -1608,6 +1608,26 @@ FormatManager::LoadHardcodedFormatters()
}
return nullptr;
});
m_hardcoded_summaries.push_back(
[](lldb_private::ValueObject& valobj,
lldb::DynamicValueType,
FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
.SetCascades(true)
.SetDontShowChildren(true)
.SetHideItemNames(true)
.SetShowMembersOneLiner(true)
.SetSkipPointers(true)
.SetSkipReferences(false),
lldb_private::formatters::VectorTypeSummaryProvider,
"vector_type pointer summary provider"));
if (valobj.GetClangType().IsVectorType(nullptr, nullptr))
{
if (fmt_mgr.GetCategory(fmt_mgr.m_vectortypes_category_name)->IsEnabled())
return formatter_sp;
}
return nullptr;
});
}
{
// insert code to load synthetics here

View File

@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/CXXFormatterFunctions.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTType.h"
@ -267,6 +268,51 @@ namespace lldb_private {
}
}
bool
lldb_private::formatters::VectorTypeSummaryProvider (ValueObject& valobj,
Stream& s,
const TypeSummaryOptions&)
{
auto synthetic_children = VectorTypeSyntheticFrontEndCreator(nullptr, valobj.GetSP());
if (!synthetic_children)
return false;
synthetic_children->Update();
s.PutChar('(');
bool first = true;
size_t idx = 0, len = synthetic_children->CalculateNumChildren();
for (;
idx < len;
idx++)
{
auto child_sp = synthetic_children->GetChildAtIndex(idx);
if (!child_sp)
continue;
child_sp = child_sp->GetQualifiedRepresentationIfAvailable(lldb::eDynamicDontRunTarget, true);
const char* child_value = child_sp->GetValueAsCString();
if (child_value && *child_value)
{
if (first)
{
s.Printf("%s", child_value);
first = false;
}
else
{
s.Printf(", %s", child_value);
}
}
}
s.PutChar(')');
return true;
}
lldb_private::SyntheticChildrenFrontEnd*
lldb_private::formatters::VectorTypeSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{

View File

@ -1527,6 +1527,31 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
context.m_found.function_with_type_info = true;
context.m_found.function = true;
}
else if (llvm::isa<clang::VarDecl>(decl_from_modules))
{
if (log)
{
log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules",
current_id,
name.GetCString());
}
clang::Decl *copied_decl = m_ast_importer->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr;
if (!copied_var_decl)
{
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules",
current_id);
break;
}
context.AddNamedDecl(copied_var_decl);
context.m_found.variable = true;
}
}
} while (0);
}

View File

@ -541,11 +541,12 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
Error interpret_error;
can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error);
Process *process = exe_ctx.GetProcessPtr();
bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);
if (!ir_can_run)
{
err.SetErrorString("The expression could not be prepared to run in the target");

View File

@ -18,6 +18,7 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
@ -444,18 +445,18 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
}
ssize_t found_priority = -1;
clang::MacroInfo *info = nullptr;
clang::MacroInfo *macro_info = nullptr;
for (clang::ModuleMacro *macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
{
clang::Module *module = macro->getOwningModule();
clang::Module *module = module_macro->getOwningModule();
{
ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module));
if (pi != module_priorities.end() && pi->second > found_priority)
{
info = macro->getMacroInfo();
macro_info = module_macro->getMacroInfo();
found_priority = pi->second;
}
}
@ -465,26 +466,20 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
if (top_level_module != module)
{
ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module));
if ((pi != module_priorities.end()) && pi->second > found_priority)
{
info = macro->getMacroInfo();
macro_info = module_macro->getMacroInfo();
found_priority = pi->second;
}
}
}
if (!info)
if (macro_info)
{
continue;
}
if (mi->second.getLatest()->getKind() == clang::MacroDirective::MD_Define)
{
std::string macro_expansion = "#define ";
macro_expansion.append(mi->first->getName().str().c_str());
if (clang::MacroInfo *macro_info = mi->second.getLatest()->getMacroInfo())
{
if (macro_info->isFunctionLike())
{
@ -560,9 +555,7 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
if (invalid)
{
#ifdef LLDB_CONFIGURATION_DEBUG
assert(!"Unhandled token kind");
#endif
lldbassert(!"Unhandled token kind");
macro_expansion.append("<unknown literal value>");
}
else
@ -594,17 +587,11 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec
}
}
}
}
else
{
#ifdef LLDB_CONFIGURATION_DEBUG
assert(!"#define with no macro info");
#endif
}
if (handler(macro_expansion))
{
return;
if (handler(macro_expansion))
{
return;
}
}
}
}

View File

@ -891,7 +891,8 @@ ClangUserExpression::Execute (Stream &error_stream,
*m_execution_unit_sp.get(),
interpreter_error,
function_stack_bottom,
function_stack_top);
function_stack_top,
exe_ctx);
if (!interpreter_error.Success())
{

View File

@ -373,7 +373,7 @@ IRExecutionUnit::GetRunnableInfo(Error &error,
ss.PutCString("\n");
emitNewLine = true;
ss.PutCString(" ");
ss.PutCString(Mangled(failed_lookup).GetDemangledName().AsCString());
ss.PutCString(Mangled(failed_lookup).GetDemangledName(lldb::eLanguageTypeObjC_plus_plus).AsCString());
}
m_failed_lookups.clear();

View File

@ -267,11 +267,11 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
if (mangled_name.GetMangledName())
m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n",
mangled_name.GetName().GetCString(),
mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(),
mangled_name.GetMangledName().GetCString());
else
m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
mangled_name.GetName().GetCString());
mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString());
}
return LookupResult::Fail;
}

View File

@ -10,17 +10,28 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Host/Endian.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h"
@ -455,7 +466,8 @@ static const char *infinite_loop_error = "Interpreter ran for too m
bool
IRInterpreter::CanInterpret (llvm::Module &module,
llvm::Function &function,
lldb_private::Error &error)
lldb_private::Error &error,
const bool support_function_calls)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -507,7 +519,7 @@ IRInterpreter::CanInterpret (llvm::Module &module,
return false;
}
if (!CanIgnoreCall(call_inst))
if (!CanIgnoreCall(call_inst) && !support_function_calls)
{
if (log)
log->Printf("Unsupported instruction: %s", PrintValue(ii).c_str());
@ -611,7 +623,8 @@ IRInterpreter::Interpret (llvm::Module &module,
lldb_private::IRMemoryMap &memory_map,
lldb_private::Error &error,
lldb::addr_t stack_frame_bottom,
lldb::addr_t stack_frame_top)
lldb::addr_t stack_frame_top,
lldb_private::ExecutionContext &exe_ctx)
{
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@ -668,29 +681,7 @@ IRInterpreter::Interpret (llvm::Module &module,
{
default:
break;
case Instruction::Call:
{
const CallInst *call_inst = dyn_cast<CallInst>(inst);
if (!call_inst)
{
if (log)
log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
error.SetErrorToGenericError();
error.SetErrorString(interpreter_internal_error);
return false;
}
if (!CanIgnoreCall(call_inst))
{
if (log)
log->Printf("The interpreter shouldn't have accepted %s", PrintValue(call_inst).c_str());
error.SetErrorToGenericError();
error.SetErrorString(interpreter_internal_error);
return false;
}
}
break;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
@ -1476,6 +1467,242 @@ IRInterpreter::Interpret (llvm::Module &module,
}
}
break;
case Instruction::Call:
{
const CallInst *call_inst = dyn_cast<CallInst>(inst);
if (!call_inst)
{
if (log)
log->Printf("getOpcode() returns %s, but instruction is not a CallInst", inst->getOpcodeName());
error.SetErrorToGenericError();
error.SetErrorString(interpreter_internal_error);
return false;
}
if (CanIgnoreCall(call_inst))
break;
// Get the return type
llvm::Type *returnType = call_inst->getType();
if (returnType == nullptr)
{
error.SetErrorToGenericError();
error.SetErrorString("unable to access return type");
return false;
}
// Work with void, integer and pointer return types
if (!returnType->isVoidTy() &&
!returnType->isIntegerTy() &&
!returnType->isPointerTy())
{
error.SetErrorToGenericError();
error.SetErrorString("return type is not supported");
return false;
}
// Check we can actually get a thread
if (exe_ctx.GetThreadPtr() == nullptr)
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("unable to acquire thread");
return false;
}
// Make sure we have a valid process
if (!exe_ctx.GetProcessPtr())
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("unable to get the process");
return false;
}
// Find the address of the callee function
lldb_private::Scalar I;
const llvm::Value *val = call_inst->getCalledValue();
if (!frame.EvaluateValue(I, val, module))
{
error.SetErrorToGenericError();
error.SetErrorString("unable to get address of function");
return false;
}
lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS));
lldb_private::StreamString error_stream;
lldb_private::EvaluateExpressionOptions options;
// We generally receive a function pointer which we must dereference
llvm::Type* prototype = val->getType();
if (!prototype->isPointerTy())
{
error.SetErrorToGenericError();
error.SetErrorString("call need function pointer");
return false;
}
// Dereference the function pointer
prototype = prototype->getPointerElementType();
if (!(prototype->isFunctionTy() || prototype->isFunctionVarArg()))
{
error.SetErrorToGenericError();
error.SetErrorString("call need function pointer");
return false;
}
// Find number of arguments
const int numArgs = call_inst->getNumArgOperands();
// We work with a fixed array of 16 arguments which is our upper limit
static lldb_private::ABI::CallArgument rawArgs[16];
if (numArgs >= 16)
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("function takes too many arguments");
return false;
}
// Push all function arguments to the argument list that will
// be passed to the call function thread plan
for (int i = 0; i < numArgs; i++)
{
// Get details of this argument
llvm::Value *arg_op = call_inst->getArgOperand(i);
llvm::Type *arg_ty = arg_op->getType();
// Ensure that this argument is an supported type
if (!arg_ty->isIntegerTy() && !arg_ty->isPointerTy())
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("argument %d must be integer type", i);
return false;
}
// Extract the arguments value
lldb_private::Scalar tmp_op = 0;
if (!frame.EvaluateValue(tmp_op, arg_op, module))
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("unable to evaluate argument %d", i);
return false;
}
// Check if this is a string literal or constant string pointer
if (arg_ty->isPointerTy())
{
// Pointer to just one type
assert(arg_ty->getNumContainedTypes() == 1);
lldb::addr_t addr = tmp_op.ULongLong();
size_t dataSize = 0;
if (memory_map.GetAllocSize(addr, dataSize))
{
// Create the required buffer
rawArgs[i].size = dataSize;
rawArgs[i].data_ap.reset(new uint8_t[dataSize + 1]);
// Read string from host memory
memory_map.ReadMemory(rawArgs[i].data_ap.get(), addr, dataSize, error);
if (error.Fail())
{
assert(!"we have failed to read the string from memory");
return false;
}
// Add null terminator
rawArgs[i].data_ap[dataSize] = '\0';
rawArgs[i].type = lldb_private::ABI::CallArgument::HostPointer;
}
else
{
assert(!"unable to locate host data for transfer to device");
return false;
}
}
else /* if ( arg_ty->isPointerTy() ) */
{
rawArgs[i].type = lldb_private::ABI::CallArgument::TargetValue;
// Get argument size in bytes
rawArgs[i].size = arg_ty->getIntegerBitWidth() / 8;
// Push value into argument list for thread plan
rawArgs[i].value = tmp_op.ULongLong();
}
}
// Pack the arguments into an llvm::array
llvm::ArrayRef<lldb_private::ABI::CallArgument> args(rawArgs, numArgs);
// Setup a thread plan to call the target function
lldb::ThreadPlanSP call_plan_sp
(
new lldb_private::ThreadPlanCallFunctionUsingABI
(
exe_ctx.GetThreadRef(),
funcAddr,
*prototype,
*returnType,
args,
options
)
);
// Check if the plan is valid
if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream))
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong());
return false;
}
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
// Execute the actual function call thread plan
lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream);
// Check that the thread plan completed successfully
if (res != lldb::ExpressionResults::eExpressionCompleted)
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("ThreadPlanCallFunctionUsingABI failed");
return false;
}
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
// Void return type
if (returnType->isVoidTy())
{
// Cant assign to void types, so we leave the frame untouched
}
else
// Integer or pointer return type
if (returnType->isIntegerTy() || returnType->isPointerTy())
{
// Get the encapsulated return value
lldb::ValueObjectSP retVal = call_plan_sp.get()->GetReturnValueObject();
lldb_private::Scalar returnVal = -1;
lldb_private::ValueObject *vobj = retVal.get();
// Check if the return value is valid
if (vobj == nullptr || retVal.empty())
{
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("unable to get the return value");
return false;
}
// Extract the return value as a integer
lldb_private::Value & value = vobj->GetValue();
returnVal = value.GetScalar();
// Push the return value as the result
frame.AssignValue(inst, returnVal, module);
}
}
break;
}
++frame.m_ii;

View File

@ -418,6 +418,32 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
m_allocations.erase(iter);
}
bool
IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
{
AllocationMap::iterator iter = FindAllocation(address, size);
if (iter == m_allocations.end())
return false;
Allocation &al = iter->second;
if (address > (al.m_process_start + al.m_size))
{
size = 0;
return false;
}
if (address > al.m_process_start)
{
int dif = address - al.m_process_start;
size = al.m_size - dif;
return true;
}
size = al.m_size;
return true;
}
void
IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
{

View File

@ -1070,13 +1070,9 @@ Host::SetCrashDescription (const char *description)
#endif
#if !defined (__linux__) && !defined (__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined (__NetBSD__)
const lldb_private::UnixSignalsSP&
Host::GetUnixSignals ()
const UnixSignalsSP &
Host::GetUnixSignals()
{
static UnixSignalsSP s_unix_signals_sp (new UnixSignals ());
static const auto s_unix_signals_sp = UnixSignals::Create(HostInfo::GetArchitecture());
return s_unix_signals_sp;
}
#endif

View File

@ -441,3 +441,25 @@ NativeProcessProtocol::Terminate ()
{
// Default implementation does nothing.
}
#ifndef __linux__
// These need to be implemented to support lldb-gdb-server on a given platform. Stubs are
// provided to make the rest of the code link on non-supported platforms.
Error
NativeProcessProtocol::Launch (ProcessLaunchInfo &launch_info,
NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
}
Error
NativeProcessProtocol::Attach (lldb::pid_t pid,
NativeDelegate &native_delegate,
NativeProcessProtocolSP &process_sp)
{
llvm_unreachable("Platform has no NativeProcessProtocol support");
}
#endif

View File

@ -15,79 +15,103 @@
// Project includes
#include "lldb/Host/StringConvert.h"
namespace lldb_private {
namespace StringConvert {
int32_t
ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
namespace lldb_private
{
if (s && s[0])
namespace StringConvert
{
char *end = nullptr;
const long sval = ::strtol (s, &end, base);
if (*end == '\0')
int32_t
ToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
const long sval = ::strtol (s, &end, base);
if (*end == '\0')
{
if (success_ptr)
*success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
return (int32_t)sval; // All characters were used, return the result
}
}
if (success_ptr)
*success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
return (int32_t)sval; // All characters were used, return the result
*success_ptr = false;
return fail_value;
}
}
if (success_ptr) *success_ptr = false;
return fail_value;
}
uint32_t
ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
const unsigned long uval = ::strtoul (s, &end, base);
if (*end == '\0')
uint32_t
ToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
const unsigned long uval = ::strtoul (s, &end, base);
if (*end == '\0')
{
if (success_ptr)
*success_ptr = (uval <= UINT32_MAX);
return (uint32_t)uval; // All characters were used, return the result
}
}
if (success_ptr)
*success_ptr = (uval <= UINT32_MAX);
return (uint32_t)uval; // All characters were used, return the result
*success_ptr = false;
return fail_value;
}
}
if (success_ptr) *success_ptr = false;
return fail_value;
}
int64_t
ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
int64_t uval = ::strtoll (s, &end, base);
if (*end == '\0')
int64_t
ToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
{
if (success_ptr) *success_ptr = true;
return uval; // All characters were used, return the result
if (s && s[0])
{
char *end = nullptr;
int64_t uval = ::strtoll (s, &end, base);
if (*end == '\0')
{
if (success_ptr)
*success_ptr = true;
return uval; // All characters were used, return the result
}
}
if (success_ptr)
*success_ptr = false;
return fail_value;
}
}
if (success_ptr) *success_ptr = false;
return fail_value;
}
uint64_t
ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
uint64_t uval = ::strtoull (s, &end, base);
if (*end == '\0')
uint64_t
ToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
{
if (success_ptr) *success_ptr = true;
return uval; // All characters were used, return the result
if (s && s[0])
{
char *end = nullptr;
uint64_t uval = ::strtoull (s, &end, base);
if (*end == '\0')
{
if (success_ptr)
*success_ptr = true;
return uval; // All characters were used, return the result
}
}
if (success_ptr) *success_ptr = false;
return fail_value;
}
double
ToDouble (const char *s, double fail_value, bool *success_ptr)
{
if (s && s[0])
{
char *end = nullptr;
double val = strtod (s, &end);
if (*end == '\0')
{
if (success_ptr)
*success_ptr = true;
return val; // All characters were used, return the result
}
}
if (success_ptr)
*success_ptr = false;
return fail_value;
}
}
if (success_ptr) *success_ptr = false;
return fail_value;
}
}
}

View File

@ -40,8 +40,6 @@
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/NameMatches.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "llvm/Support/Host.h"
extern "C" {
@ -277,13 +275,6 @@ Host::GetAuxvData(lldb_private::Process *process)
return buf_sp;
}
const UnixSignalsSP&
Host::GetUnixSignals ()
{
static const lldb_private::UnixSignalsSP s_unix_signals_sp (new FreeBSDSignals ());
return s_unix_signals_sp;
}
Error
Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
{

View File

@ -0,0 +1,193 @@
//===-- MainLoopPosix.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/posix/MainLoopPosix.h"
#include <vector>
#include "lldb/Core/Error.h"
using namespace lldb;
using namespace lldb_private;
static sig_atomic_t g_signal_flags[NSIG];
static void
SignalHandler(int signo, siginfo_t *info, void *)
{
assert(signo < NSIG);
g_signal_flags[signo] = 1;
}
MainLoopPosix::~MainLoopPosix()
{
assert(m_read_fds.size() == 0);
assert(m_signals.size() == 0);
}
MainLoopPosix::ReadHandleUP
MainLoopPosix::RegisterReadObject(const IOObjectSP &object_sp, const Callback &callback, Error &error)
{
if (!object_sp || !object_sp->IsValid())
{
error.SetErrorString("IO object is not valid.");
return nullptr;
}
const bool inserted = m_read_fds.insert({object_sp->GetWaitableHandle(), callback}).second;
if (! inserted)
{
error.SetErrorStringWithFormat("File descriptor %d already monitored.",
object_sp->GetWaitableHandle());
return nullptr;
}
return CreateReadHandle(object_sp);
}
// We shall block the signal, then install the signal handler. The signal will be unblocked in
// the Run() function to check for signal delivery.
MainLoopPosix::SignalHandleUP
MainLoopPosix::RegisterSignal(int signo, const Callback &callback, Error &error)
{
if (m_signals.find(signo) != m_signals.end())
{
error.SetErrorStringWithFormat("Signal %d already monitored.", signo);
return nullptr;
}
SignalInfo info;
info.callback = callback;
struct sigaction new_action;
new_action.sa_sigaction = &SignalHandler;
new_action.sa_flags = SA_SIGINFO;
sigemptyset(&new_action.sa_mask);
sigaddset(&new_action.sa_mask, signo);
sigset_t old_set;
if (int ret = pthread_sigmask(SIG_BLOCK, &new_action.sa_mask, &old_set))
{
error.SetErrorStringWithFormat("pthread_sigmask failed with error %d\n", ret);
return nullptr;
}
info.was_blocked = sigismember(&old_set, signo);
if (sigaction(signo, &new_action, &info.old_action) == -1)
{
error.SetErrorToErrno();
if (!info.was_blocked)
pthread_sigmask(SIG_UNBLOCK, &new_action.sa_mask, nullptr);
return nullptr;
}
m_signals.insert({signo, info});
g_signal_flags[signo] = 0;
return SignalHandleUP(new SignalHandle(*this, signo));
}
void
MainLoopPosix::UnregisterReadObject(const lldb::IOObjectSP &object_sp)
{
bool erased = m_read_fds.erase(object_sp->GetWaitableHandle());
(void) erased;
assert(erased);
}
void
MainLoopPosix::UnregisterSignal(int signo)
{
// We undo the actions of RegisterSignal on a best-effort basis.
auto it = m_signals.find(signo);
assert(it != m_signals.end());
sigaction(signo, &it->second.old_action, nullptr);
sigset_t set;
sigemptyset(&set);
sigaddset(&set, signo);
pthread_sigmask(it->second.was_blocked ? SIG_BLOCK : SIG_UNBLOCK, &set, nullptr);
m_signals.erase(it);
}
Error
MainLoopPosix::Run()
{
std::vector<int> signals;
sigset_t sigmask;
std::vector<int> read_fds;
fd_set read_fd_set;
m_terminate_request = false;
// run until termination or until we run out of things to listen to
while (! m_terminate_request && (!m_read_fds.empty() || !m_signals.empty()))
{
// To avoid problems with callbacks changing the things we're supposed to listen to, we
// will store the *real* list of events separately.
signals.clear();
read_fds.clear();
FD_ZERO(&read_fd_set);
int nfds = 0;
if (int ret = pthread_sigmask(SIG_SETMASK, nullptr, &sigmask))
return Error("pthread_sigmask failed with error %d\n", ret);
for (const auto &fd: m_read_fds)
{
read_fds.push_back(fd.first);
FD_SET(fd.first, &read_fd_set);
nfds = std::max(nfds, fd.first+1);
}
for (const auto &sig: m_signals)
{
signals.push_back(sig.first);
sigdelset(&sigmask, sig.first);
}
if (pselect(nfds, &read_fd_set, nullptr, nullptr, nullptr, &sigmask) == -1 && errno != EINTR)
return Error(errno, eErrorTypePOSIX);
for (int sig: signals)
{
if (g_signal_flags[sig] == 0)
continue; // No signal
g_signal_flags[sig] = 0;
auto it = m_signals.find(sig);
if (it == m_signals.end())
continue; // Signal must have gotten unregistered in the meantime
it->second.callback(*this); // Do the work
if (m_terminate_request)
return Error();
}
for (int fd: read_fds)
{
if (!FD_ISSET(fd, &read_fd_set))
continue; // Not ready
auto it = m_read_fds.find(fd);
if (it == m_read_fds.end())
continue; // File descriptor must have gotten unregistered in the meantime
it->second(*this); // Do the work
if (m_terminate_request)
return Error();
}
}
return Error();
}

View File

@ -17,6 +17,7 @@
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
#include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h"
#include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h"
@ -106,6 +107,7 @@ SystemInitializerCommon::Initialize()
ObjectFileELF::Initialize();
ObjectFilePECOFF::Initialize();
DynamicLoaderPOSIXDYLD::Initialize();
DynamicLoaderWindowsDYLD::Initialize();
platform_freebsd::PlatformFreeBSD::Initialize();
platform_linux::PlatformLinux::Initialize();
PlatformWindows::Initialize();
@ -152,6 +154,7 @@ SystemInitializerCommon::Terminate()
ObjectFileELF::Terminate();
ObjectFilePECOFF::Terminate();
DynamicLoaderPOSIXDYLD::Terminate();
DynamicLoaderWindowsDYLD::Terminate();
platform_freebsd::PlatformFreeBSD::Terminate();
platform_linux::PlatformLinux::Terminate();
PlatformWindows::Terminate();

View File

@ -10,6 +10,7 @@
#include "lldb/Interpreter/CommandObject.h"
#include <string>
#include <sstream>
#include <map>
#include <stdlib.h>
@ -920,6 +921,27 @@ ExprPathHelpTextCallback()
" meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
}
void
CommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
{
CommandInterpreter& interpreter = GetCommandInterpreter();
std::stringstream lineStream (long_help);
std::string line;
while (std::getline (lineStream, line)) {
if (line.empty()) {
output_strm << "\n";
continue;
}
size_t result = line.find_first_not_of (" \t");
if (result == std::string::npos) {
result = 0;
}
std::string whitespace_prefix = line.substr (0, result);
std::string remainder = line.substr (result);
interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
}
}
void
CommandObject::GenerateHelpText (CommandReturnObject &result)
{
@ -947,7 +969,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong();
if ((long_help != nullptr)
&& (strlen (long_help) > 0))
output_strm.Printf ("\n%s", long_help);
FormatLongHelpText (output_strm, long_help);
if (WantsRawCommandString() && !WantsCompletion())
{
// Emit the message about using ' -- ' between the end of the command options and the raw input
@ -984,7 +1006,7 @@ CommandObject::GenerateHelpText (Stream &output_strm)
const char *long_help = GetHelpLong();
if ((long_help != nullptr)
&& (strlen (long_help) > 0))
output_strm.Printf ("%s", long_help);
FormatLongHelpText (output_strm, long_help);
else if (WantsRawCommandString())
{
std::string help_text (GetHelp());

View File

@ -236,7 +236,8 @@ ABISP
ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86)
if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
(arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS()))
{
if (!g_abi_sp)
g_abi_sp.reset (new ABIMacOSX_i386);

View File

@ -257,7 +257,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
sp -= argSize;
// write this argument onto the stack of the host process
proc.get( )->WriteMemory( sp, arg.data, arg.size, error );
proc.get( )->WriteMemory( sp, arg.data_ap.get(), arg.size, error );
if ( error.Fail( ) )
return false;

View File

@ -168,6 +168,9 @@ DynamicLoaderHexagonDYLD::DidAttach()
// Disable JIT for hexagon targets because its not supported
m_process->SetCanJIT(false);
// Enable Interpreting of function call expressions
m_process->SetCanInterpretFunctionCalls(true);
// Add the current executable to the module list
ModuleList module_list;
module_list.Append(executable);
@ -500,7 +503,7 @@ DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop
if (sym == NULL || !sym->IsTrampoline())
return thread_plan_sp;
const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
const ConstString sym_name = sym->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled);
if (!sym_name)
return thread_plan_sp;

View File

@ -458,7 +458,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
if (sym == NULL || !sym->IsTrampoline())
return thread_plan_sp;
const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
ConstString sym_name = sym->GetName();
if (!sym_name)
return thread_plan_sp;
@ -667,7 +667,9 @@ DynamicLoaderPOSIXDYLD::ResolveExecutableModule (lldb::ModuleSP &module_sp)
if (module_sp && module_sp->MatchesModuleSpec (module_spec))
return;
auto error = platform_sp->ResolveExecutable (module_spec, module_sp, nullptr);
const auto executable_search_paths (Target::GetDefaultExecutableSearchPaths());
auto error = platform_sp->ResolveExecutable (
module_spec, module_sp, !executable_search_paths.IsEmpty() ? &executable_search_paths : nullptr);
if (error.Fail ())
{
StreamString stream;

View File

@ -0,0 +1,102 @@
//===-- DynamicLoaderWindowsDYLD.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DynamicLoaderWindowsDYLD.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "llvm/ADT/Triple.h"
using namespace lldb;
using namespace lldb_private;
DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
: DynamicLoader(process)
{
}
DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD()
{
}
void DynamicLoaderWindowsDYLD::Initialize()
{
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
}
void DynamicLoaderWindowsDYLD::Terminate()
{
}
ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic()
{
static ConstString g_plugin_name("windows-dyld");
return g_plugin_name;
}
const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
{
return "Dynamic loader plug-in that watches for shared library "
"loads/unloads in Windows processes.";
}
DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
{
bool should_create = force;
if (!should_create)
{
const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
if (triple_ref.getOS() == llvm::Triple::Win32)
should_create = true;
}
if (should_create)
return new DynamicLoaderWindowsDYLD (process);
return nullptr;
}
void DynamicLoaderWindowsDYLD::DidAttach()
{
}
void DynamicLoaderWindowsDYLD::DidLaunch()
{
}
Error DynamicLoaderWindowsDYLD::CanLoadImage()
{
return Error();
}
ConstString DynamicLoaderWindowsDYLD::GetPluginName()
{
return GetPluginNameStatic();
}
uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion()
{
return 1;
}
ThreadPlanSP
DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
{
return ThreadPlanSP();
}

View File

@ -0,0 +1,43 @@
//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
#include "lldb/lldb-forward.h"
#include "lldb/Target/DynamicLoader.h"
namespace lldb_private
{
class DynamicLoaderWindowsDYLD : public DynamicLoader
{
public:
DynamicLoaderWindowsDYLD(Process *process);
virtual ~DynamicLoaderWindowsDYLD();
static void Initialize();
static void Terminate();
static ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
static DynamicLoader *CreateInstance(Process *process, bool force);
void DidAttach () override;
void DidLaunch () override;
Error CanLoadImage () override;
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override;
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
};
}
#endif

View File

@ -106,7 +106,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
Symbol *symbol = sc.symbol;
if (symbol != NULL)
{
const char *name = symbol->GetMangled().GetDemangledName().AsCString();
const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString();
if (name && strstr(name, vtable_demangled_prefix) == name)
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));

View File

@ -1558,7 +1558,7 @@ ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
std::string
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
{
size_t pos = symbol_name.find("@");
size_t pos = symbol_name.find('@');
return symbol_name.substr(0, pos).str();
}
@ -1795,7 +1795,16 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
static ConstString bss_section_name(".bss");
static ConstString opd_section_name(".opd"); // For ppc64
//StreamFile strm(stdout, false);
// On Android the oatdata and the oatexec symbols in system@framework@boot.oat covers the full
// .text section what causes issues with displaying unusable symbol name to the user and very
// slow unwinding speed because the instruction emulation based unwind plans try to emulate all
// instructions in these symbols. Don't add these symbols to the symbol list as they have no
// use for the debugger and they are causing a lot of trouble.
// Filtering can't be restricted to Android because this special object file don't contain the
// note section specifying the environment to Android but the custom extension and file name
// makes it highly unlikely that this will collide with anything else.
bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat");
unsigned i;
for (i = 0; i < num_symbols; ++i)
{
@ -1809,7 +1818,10 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
(symbol_name == NULL || symbol_name[0] == '\0'))
continue;
//symbol.Dump (&strm, i, &strtab_data, section_list);
// Skipping oatdata and oatexec sections if it is requested. See details above the
// definition of skip_oatdata_oatexec for the reasons.
if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 || ::strcmp(symbol_name, "oatexec") == 0))
continue;
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
@ -2031,8 +2043,9 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
if (! mangled_name.empty())
mangled.SetMangledName( ConstString((mangled_name + suffix).str()) );
llvm::StringRef demangled_name = mangled.GetDemangledName().GetStringRef();
if (! demangled_name.empty())
ConstString demangled = mangled.GetDemangledName(lldb::eLanguageTypeUnknown);
llvm::StringRef demangled_name = demangled.GetStringRef();
if (!demangled_name.empty())
mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) );
}

View File

@ -535,6 +535,14 @@ PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
return false;
}
const lldb::UnixSignalsSP &
PlatformPOSIX::GetRemoteUnixSignals() {
if (IsRemote() && m_remote_platform_sp)
return m_remote_platform_sp->GetRemoteUnixSignals();
return Platform::GetRemoteUnixSignals();
}
FileSpec
PlatformPOSIX::GetRemoteWorkingDirectory()
{
@ -785,9 +793,6 @@ PlatformPOSIX::Attach (ProcessAttachInfo &attach_info,
if (process_sp)
{
// Set UnixSignals appropriately.
process_sp->SetUnixSignals (Host::GetUnixSignals ());
auto listener_sp = attach_info.GetHijackListener();
if (listener_sp == nullptr)
{

View File

@ -109,6 +109,9 @@ class PlatformPOSIX : public lldb_private::Platform
lldb_private::ArchSpec
GetRemoteSystemArchitecture () override;
const lldb::UnixSignalsSP &
GetRemoteUnixSignals() override;
size_t
GetEnvironment (lldb_private::StringList &environment) override;

View File

@ -32,6 +32,8 @@
#include "Utility/UriParser.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_gdb_server;
@ -139,13 +141,14 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
// Resolve any executable within an apk on Android?
//Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
if (resolved_module_spec.GetFileSpec().Exists())
if (resolved_module_spec.GetFileSpec().Exists() ||
module_spec.GetUUID().IsValid())
{
if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
{
error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
NULL,
module_search_paths_ptr,
NULL,
NULL);
@ -161,7 +164,7 @@ PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec,
{
error = ModuleList::GetSharedModule (resolved_module_spec,
exe_module_sp,
NULL,
module_search_paths_ptr,
NULL,
NULL);
// Did we find an executable using one of the
@ -413,6 +416,7 @@ PlatformRemoteGDBServer::DisconnectRemote ()
{
Error error;
m_gdb_client.Disconnect(&error);
m_remote_signals_sp.reset();
return error;
}
@ -871,6 +875,97 @@ PlatformRemoteGDBServer::RunShellCommand(const char *command, // Shoul
void
PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames ()
{
{
m_trap_handlers.push_back (ConstString ("_sigtramp"));
}
const UnixSignalsSP &
PlatformRemoteGDBServer::GetRemoteUnixSignals()
{
if (!IsConnected())
return Platform::GetRemoteUnixSignals();
if (m_remote_signals_sp)
return m_remote_signals_sp;
// If packet not implemented or JSON failed to parse,
// we'll guess the signal set based on the remote architecture.
m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
const char packet[] = "jSignalsInfo";
StringExtractorGDBRemote response;
auto result = m_gdb_client.SendPacketAndWaitForResponse(
packet, strlen(packet), response, false);
if (result != decltype(result)::Success ||
response.GetResponseType() != response.eResponse)
return m_remote_signals_sp;
auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
if (!object_sp || !object_sp->IsValid())
return m_remote_signals_sp;
auto array_sp = object_sp->GetAsArray();
if (!array_sp || !array_sp->IsValid())
return m_remote_signals_sp;
auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();
bool done = array_sp->ForEach(
[&remote_signals_sp](StructuredData::Object *object) -> bool
{
if (!object || !object->IsValid())
return false;
auto dict = object->GetAsDictionary();
if (!dict || !dict->IsValid())
return false;
// Signal number and signal name are required.
int signo;
if (!dict->GetValueForKeyAsInteger("signo", signo))
return false;
std::string name;
if (!dict->GetValueForKeyAsString("name", name))
return false;
// We can live without short_name, description, etc.
std::string short_name{""};
auto object_sp = dict->GetValueForKey("short_name");
if (object_sp && object_sp->IsValid())
short_name = object_sp->GetStringValue();
bool suppress{false};
object_sp = dict->GetValueForKey("suppress");
if (object_sp && object_sp->IsValid())
suppress = object_sp->GetBooleanValue();
bool stop{false};
object_sp = dict->GetValueForKey("stop");
if (object_sp && object_sp->IsValid())
stop = object_sp->GetBooleanValue();
bool notify{false};
object_sp = dict->GetValueForKey("notify");
if (object_sp && object_sp->IsValid())
notify = object_sp->GetBooleanValue();
std::string description{""};
object_sp = dict->GetValueForKey("description");
if (object_sp && object_sp->IsValid())
description = object_sp->GetStringValue();
remote_signals_sp->AddSignal(signo,
name.c_str(),
short_name.c_str(),
suppress, stop, notify,
description.c_str());
return true;
});
if (done)
m_remote_signals_sp = std::move(remote_signals_sp);
return m_remote_signals_sp;
}

View File

@ -18,6 +18,7 @@
// Project includes
#include "lldb/Target/Platform.h"
#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
namespace lldb_private {
namespace platform_gdb_server {
@ -213,12 +214,17 @@ class PlatformRemoteGDBServer : public Platform
void
CalculateTrapHandlerSymbolNames () override;
const lldb::UnixSignalsSP &
GetRemoteUnixSignals() override;
protected:
process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
std::string m_platform_scheme;
std::string m_platform_hostname;
lldb::UnixSignalsSP m_remote_signals_sp;
// Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
// failure. Subclasses should override this method if they want to do extra actions before or
// after launching the lldb-gdbserver.

View File

@ -46,7 +46,7 @@ FreeBSDThread::WillResume(lldb::StateType resume_state)
ProcessSP process_sp(GetProcess());
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
int signo = GetResumeSignal();
bool signo_valid = process->GetUnixSignals().SignalIsValid(signo);
bool signo_valid = process->GetUnixSignals()->SignalIsValid(signo);
switch (resume_state)
{

View File

@ -1297,7 +1297,7 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
if (log)
log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d",
__FUNCTION__,
monitor->m_process->GetUnixSignals().GetSignalAsCString (signo),
monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo),
"SI_USER",
info->si_pid);
if (info->si_pid == getpid())
@ -1307,7 +1307,7 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
}
if (log)
log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals()->GetSignalAsCString (signo));
switch (signo)
{
@ -1483,7 +1483,7 @@ ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo)
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log) {
const char *signame = m_process->GetUnixSignals().GetSignalAsCString (signo);
const char *signame = m_process->GetUnixSignals()->GetSignalAsCString (signo);
if (signame == nullptr)
signame = "<none>";
log->Printf("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s",

View File

@ -33,7 +33,7 @@ class ProcessPOSIX :
//------------------------------------------------------------------
ProcessPOSIX(lldb_private::Target& target,
lldb_private::Listener &listener,
lldb_private::UnixSignalsSP &unix_signals_sp);
lldb::UnixSignalsSP &unix_signals_sp);
virtual
~ProcessPOSIX();

View File

@ -13,6 +13,8 @@
// Project includes
#include "FreeBSDSignals.h"
using namespace lldb_private;
FreeBSDSignals::FreeBSDSignals()
: UnixSignals()
{

View File

@ -13,16 +13,19 @@
// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
/// FreeBSD specific set of Unix signals.
class FreeBSDSignals
: public lldb_private::UnixSignals
class FreeBSDSignals : public UnixSignals
{
public:
FreeBSDSignals();
private:
void
Reset();
Reset() override;
};
} // namespace lldb_private
#endif // liblldb_FreeBSDSignals_H_

View File

@ -0,0 +1,32 @@
//===-- GDBRemoteSignals.cpp ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "GDBRemoteSignals.h"
using namespace lldb_private;
GDBRemoteSignals::GDBRemoteSignals()
: UnixSignals()
{
Reset();
}
GDBRemoteSignals::GDBRemoteSignals(const lldb::UnixSignalsSP &rhs)
: UnixSignals(*rhs)
{
}
void
GDBRemoteSignals::Reset()
{
m_signals.clear();
}

View File

@ -0,0 +1,36 @@
//===-- GDBRemoteSignals.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_GDBRemoteSignals_H_
#define liblldb_GDBRemoteSignals_H_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
/// Empty set of Unix signals to be filled by PlatformRemoteGDBServer
class GDBRemoteSignals : public UnixSignals
{
public:
GDBRemoteSignals();
GDBRemoteSignals(const lldb::UnixSignalsSP &rhs);
private:
void
Reset() override;
};
} // namespace lldb_private
#endif // liblldb_GDBRemoteSignals_H_

View File

@ -12,7 +12,7 @@
// Project includes
#include "LinuxSignals.h"
using namespace lldb_private::process_linux;
using namespace lldb_private;
LinuxSignals::LinuxSignals()
: UnixSignals()

View File

@ -17,21 +17,18 @@
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
namespace process_linux {
/// Linux specific set of Unix signals.
class LinuxSignals
: public lldb_private::UnixSignals
{
public:
LinuxSignals();
/// Linux specific set of Unix signals.
class LinuxSignals : public UnixSignals
{
public:
LinuxSignals();
private:
void
Reset();
};
private:
void
Reset() override;
};
} // namespace lldb_private
} // namespace process_linux
#endif
#endif // liblldb_LinuxSignals_H_

View File

@ -12,7 +12,7 @@
// Project includes
#include "MipsLinuxSignals.h"
using namespace lldb_private::process_linux;
using namespace lldb_private;
MipsLinuxSignals::MipsLinuxSignals()
: UnixSignals()

Some files were not shown because too many files have changed in this diff Show More