forked from OSchip/llvm-project
Modified the host process monitor callback function Host::StartMonitoringChildProcess
to spawn a thread for each process that is being monitored. Previously LLDB would spawn a single thread that would wait for any child process which isn't ok to do as a shared library (LLDB.framework on Mac OSX, or lldb.so on linux). The old single thread used to call wait4() with a pid of -1 which could cause it to reap child processes that it shouldn't have. Re-wrote the way Function blocks are handles. Previously I attempted to keep all blocks in a single memory allocation (in a std::vector). This made the code somewhat efficient, but hard to work with. I got rid of the old BlockList class, and went to a straight parent with children relationship. This new approach will allow for partial parsing of the blocks within a function. llvm-svn: 111706
This commit is contained in:
parent
a94e3d1124
commit
0b76a2c21f
|
@ -66,33 +66,17 @@ public:
|
|||
/// get called if the child process exits.
|
||||
///
|
||||
/// @return
|
||||
/// A unique handle to the process monitoring information that
|
||||
/// can be used to stop monitoring a child process.
|
||||
/// A thread handle that can be used to cancel the thread that
|
||||
/// was spawned to monitor \a pid.
|
||||
///
|
||||
/// @see static void Host::StopMonitoringChildProcess (uint32_t)
|
||||
//------------------------------------------------------------------
|
||||
static uint32_t
|
||||
static lldb::thread_t
|
||||
StartMonitoringChildProcess (MonitorChildProcessCallback callback,
|
||||
void *callback_baton,
|
||||
lldb::pid_t pid,
|
||||
bool monitor_signals);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Stop monitoring a child process.
|
||||
///
|
||||
/// @param[in] handle
|
||||
/// A unique handle returned from a previous call to
|
||||
/// Host::StartMonitoringChildProcess(...).
|
||||
///
|
||||
/// @return
|
||||
/// \b true if the the handle was found and disabled, \b false
|
||||
/// if the monitor map with handle of \a handle was not found.
|
||||
///
|
||||
/// @see static int Host::StartMonitoringChildProcess (MonitorChildProcessCallback *, void *, lldb::pid_t, bool)
|
||||
//------------------------------------------------------------------
|
||||
static bool
|
||||
StopMonitoringChildProcess (uint32_t handle);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the host page size.
|
||||
///
|
||||
|
|
|
@ -43,17 +43,6 @@ class Block :
|
|||
public SymbolContextScope
|
||||
{
|
||||
public:
|
||||
friend class Function;
|
||||
friend class BlockList;
|
||||
//------------------------------------------------------------------
|
||||
/// Enumeration values for special and invalid Block User ID
|
||||
/// values.
|
||||
//------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
RootID = LLDB_INVALID_UID - 1, ///< The Block UID for the root block
|
||||
InvalidID = LLDB_INVALID_UID ///< Invalid Block UID.
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Construct with a User ID \a uid, \a depth.
|
||||
|
@ -79,55 +68,22 @@ public:
|
|||
///
|
||||
/// @see BlockList
|
||||
//------------------------------------------------------------------
|
||||
Block (lldb::user_id_t uid, uint32_t depth, BlockList* block_list);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Copy constructor.
|
||||
///
|
||||
/// Makes a copy of the another Block object \a rhs.
|
||||
///
|
||||
/// @param[in] rhs
|
||||
/// A const Block object reference to copy.
|
||||
//------------------------------------------------------------------
|
||||
Block (const Block& rhs);
|
||||
Block (lldb::user_id_t uid);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor.
|
||||
//------------------------------------------------------------------
|
||||
~Block ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Assignment operator.
|
||||
///
|
||||
/// Copies the block value from another Block object \a rhs
|
||||
/// into \a this object.
|
||||
///
|
||||
/// @param[in] rhs
|
||||
/// A const Block object reference to copy.
|
||||
///
|
||||
/// @return
|
||||
/// A const Block object reference to \a this.
|
||||
//------------------------------------------------------------------
|
||||
const Block&
|
||||
operator= (const Block& rhs);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Add a child to this object.
|
||||
///
|
||||
/// @param[in] uid
|
||||
/// The UID for a given block. This value is given by the
|
||||
/// SymbolFile plug-in and can be any value that helps the
|
||||
/// SymbolFile plug-in to match this block back to the debug
|
||||
/// information data that it parses for further or more in
|
||||
/// depth parsing. Common values would be the index into a
|
||||
/// table, or an offset into the debug information.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \a uid if the child was successfully added to this
|
||||
/// block, or Block::InvalidID on failure.
|
||||
/// @param[in] child_block_sp
|
||||
/// A shared pointer to a child block that will get added to
|
||||
/// this block.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
AddChild (lldb::user_id_t uid);
|
||||
void
|
||||
AddChild (const lldb::BlockSP &child_block_sp);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Add a new offset range to this block.
|
||||
|
@ -177,9 +133,6 @@ public:
|
|||
bool
|
||||
Contains (const VMRange& range) const;
|
||||
|
||||
bool
|
||||
ContainsBlockWithID (lldb::user_id_t block_id) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Dump the block contents.
|
||||
///
|
||||
|
@ -215,40 +168,10 @@ public:
|
|||
|
||||
void
|
||||
GetDescription (Stream *s,
|
||||
Function *function,
|
||||
lldb::DescriptionLevel level,
|
||||
Process *process) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the parent block's UID.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the parent block, or Block::InvalidID
|
||||
/// if this block has no parent.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetParentUID () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the sibling block's UID.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the sibling block, or Block::InvalidID
|
||||
/// if this block has no sibling.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetSiblingUID () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the first child block's UID.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the first child block, or Block::InvalidID
|
||||
/// if this block has no first child.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetFirstChildUID () const;
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the parent block.
|
||||
///
|
||||
|
@ -260,14 +183,17 @@ public:
|
|||
GetParent () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the sibling block.
|
||||
/// Get the sibling block for this block.
|
||||
///
|
||||
/// @return
|
||||
/// The sibling block pointer, or NULL if this block has no
|
||||
/// sibling.
|
||||
//------------------------------------------------------------------
|
||||
Block *
|
||||
GetSibling () const;
|
||||
GetSibling () const
|
||||
{
|
||||
return m_sibling;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the first child block.
|
||||
|
@ -387,6 +313,19 @@ public:
|
|||
const Declaration *decl_ptr,
|
||||
const Declaration *call_decl_ptr);
|
||||
|
||||
|
||||
void
|
||||
SetParentScope (SymbolContextScope *parent_scope)
|
||||
{
|
||||
m_parent_scope = parent_scope;
|
||||
}
|
||||
|
||||
void
|
||||
SetSibling (Block *block)
|
||||
{
|
||||
m_sibling = block;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set accessor for the variable list.
|
||||
///
|
||||
|
@ -400,358 +339,39 @@ public:
|
|||
void
|
||||
SetVariableList (lldb::VariableListSP& variable_list_sp);
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
/// Get accessor for the integer block depth value.
|
||||
///
|
||||
/// @return
|
||||
/// The integer depth of this block in the block hiearchy.
|
||||
//------------------------------------------------------------------
|
||||
uint32_t Depth () const;
|
||||
|
||||
bool
|
||||
BlockInfoHasBeenParsed() const
|
||||
{
|
||||
return m_parsed_block_info;
|
||||
}
|
||||
|
||||
void
|
||||
SetBlockInfoHasBeenParsed (bool b, bool set_children);
|
||||
|
||||
Block *
|
||||
FindBlockByID (lldb::user_id_t block_id);
|
||||
|
||||
protected:
|
||||
typedef std::vector<lldb::BlockSP> collection;
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
//------------------------------------------------------------------
|
||||
BlockList *m_block_list; ///< The block list, one of which is this one
|
||||
uint32_t m_depth; ///< The depth of this block where zero is the root block
|
||||
SymbolContextScope *m_parent_scope;
|
||||
Block *m_sibling;
|
||||
collection m_children;
|
||||
VMRange::collection m_ranges; ///< A list of address offset ranges relative to the function's section/offset address.
|
||||
lldb::InlineFunctionInfoSP m_inlineInfoSP; ///< Inlined function information.
|
||||
lldb::VariableListSP m_variables; ///< The variable list for all local, static and paramter variables scoped to this block.
|
||||
// TOOD: add a Type* list
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class BlockList Block.h "lldb/Symbol/Block.h"
|
||||
/// @brief A class that contains a heirachical collection of lexical
|
||||
/// block objects where one block is the root.
|
||||
///
|
||||
/// A collection of Block objects is managed by this class. All access
|
||||
/// to the block data is made through the block_uid of each block. This
|
||||
/// facilitates partial parsing and can enable block specific data to
|
||||
/// only be parsed when the data is asked for (variables, params, types,
|
||||
/// etc).
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
class BlockList
|
||||
{
|
||||
public:
|
||||
friend class Block;
|
||||
typedef std::vector<Block> collection;///< Our block collection type.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Construct with \a function and section offset based address
|
||||
/// range.
|
||||
///
|
||||
/// @param[in] function
|
||||
/// A const Function object that owns this block list.
|
||||
///
|
||||
/// @param[in] range
|
||||
/// A section offset based address range object.
|
||||
//------------------------------------------------------------------
|
||||
BlockList (Function *function, const AddressRange& range);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor.
|
||||
//------------------------------------------------------------------
|
||||
~BlockList ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Add a child block to a parent block.
|
||||
///
|
||||
/// Adds a new child to a parent block. The UID values for
|
||||
/// blocks are created by the SymbolFile plug-ins and should have
|
||||
/// values that facilitate correlating an existing Block object
|
||||
/// with information in the debug information file. Typically
|
||||
/// a table index, or a debug information offset is used.
|
||||
///
|
||||
/// @param[in] parent_uid
|
||||
/// The UID for a the existing parent block that will have
|
||||
/// a new child, whose UID is \a child_uid, added to its
|
||||
/// child list.
|
||||
///
|
||||
/// @param[in] child_uid
|
||||
/// The UID for the new child block.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \a child_uid if the child was successfully added
|
||||
/// to the parent \a parent_uid, or Block::InvalidID on
|
||||
/// failure (if the parent doesn't exist).
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
AddChild (lldb::user_id_t parent_uid, lldb::user_id_t child_uid);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Add a child block to a parent block.
|
||||
///
|
||||
/// Adds a new child to a parent block. The UID values for
|
||||
/// blocks are created by the SymbolFile plug-ins and should have
|
||||
/// values that facilitate correlating an existing Block object
|
||||
/// with information in the debug information file. Typically
|
||||
/// a table index, or a debug information offset is used.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID for a the existing block that will get the
|
||||
/// new range.
|
||||
///
|
||||
/// @param[in] start_offset
|
||||
/// An offset into this object's address range that
|
||||
/// describes the start address of a range for \a block_uid.
|
||||
///
|
||||
/// @param[in] end_offset
|
||||
/// An offset into this object's address range that
|
||||
/// describes the end address of a range for for \a block_uid.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \b true if the range was successfully added to
|
||||
/// the block whose UID is \a block_uid, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
AddRange (lldb::user_id_t block_uid, lldb::addr_t start_offset, lldb::addr_t end_offset);
|
||||
|
||||
// const Block *
|
||||
// FindDeepestBlockForAddress (const Address &addr);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get accessor for the section offset based address range.
|
||||
///
|
||||
/// All Block objects contained in a BlockList are relative to
|
||||
/// the base address in this object.
|
||||
///
|
||||
/// @return
|
||||
/// Returns a reference to the section offset based address
|
||||
/// range object.
|
||||
//------------------------------------------------------------------
|
||||
AddressRange &
|
||||
GetAddressRange ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get const accessor for the section offset based address range.
|
||||
///
|
||||
/// All Block objects contained in a BlockList are relative to
|
||||
/// the base address in this object.
|
||||
///
|
||||
/// @return
|
||||
/// Returns a const reference to the section offset based
|
||||
/// address range object.
|
||||
//------------------------------------------------------------------
|
||||
const AddressRange &
|
||||
GetAddressRange () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Dump the block list contents.
|
||||
///
|
||||
/// @param[in] s
|
||||
/// The stream to which to dump the object descripton.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block in the block list to dump. If this
|
||||
/// value is Block::RootID, then the entire block list will
|
||||
/// dumped as long as \a depth is set to a large enough value.
|
||||
///
|
||||
/// @param[in] depth
|
||||
/// Limit the number of levels deep that this function should
|
||||
/// print as the block whose UID is \a block_uid can contain
|
||||
/// child blocks. Specify INT_MAX to dump all child blocks.
|
||||
///
|
||||
/// @param[in] show_context
|
||||
/// If \b true, variables will dump their context information.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
Dump (Stream *s, lldb::user_id_t block_uid, uint32_t depth, bool show_context) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get a block object pointer by block UID.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block to retrieve.
|
||||
///
|
||||
/// @return
|
||||
/// A pointer to the block object, or NULL if \a block_uid
|
||||
/// doesn't exist in the block list.
|
||||
//------------------------------------------------------------------
|
||||
Block *
|
||||
GetBlockByID (lldb::user_id_t block_uid);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get a const block object pointer by block UID.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block to retrieve.
|
||||
///
|
||||
/// @return
|
||||
/// A const pointer to the block object, or NULL if \a block_uid
|
||||
/// doesn't exist in the block list.
|
||||
//------------------------------------------------------------------
|
||||
const Block *
|
||||
GetBlockByID (lldb::user_id_t block_uid) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get a function object pointer for the block list.
|
||||
///
|
||||
/// @return
|
||||
/// A pointer to the function object.
|
||||
//------------------------------------------------------------------
|
||||
Function *
|
||||
GetFunction ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get a const function object pointer for the block list.
|
||||
///
|
||||
/// @return
|
||||
/// A const pointer to the function object.
|
||||
//------------------------------------------------------------------
|
||||
const Function *
|
||||
GetFunction () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the first child block UID for the block whose UID is \a
|
||||
/// block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to access information for.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the first child block, or Block::InvalidID
|
||||
/// if this block has no children, or if \a block_uid is not
|
||||
/// a valid block ID for this block list.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetFirstChild (lldb::user_id_t block_uid) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the parent block UID for the block whose UID is \a
|
||||
/// block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to access information for.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the parent block, or Block::InvalidID
|
||||
/// if this block has no parent, or if \a block_uid is not
|
||||
/// a valid block ID for this block list.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetParent (lldb::user_id_t block_uid) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the sibling block UID for the block whose UID is \a
|
||||
/// block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to access information for.
|
||||
///
|
||||
/// @return
|
||||
/// The UID of the sibling block, or Block::InvalidID
|
||||
/// if this block has no sibling, or if \a block_uid is not
|
||||
/// a valid block ID for this block list.
|
||||
//------------------------------------------------------------------
|
||||
lldb::user_id_t
|
||||
GetSibling (lldb::user_id_t block_uid) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the variable list for the block whose UID is \a block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to access information for.
|
||||
///
|
||||
/// @param[in] can_create
|
||||
/// If \b true, the variable list can be parsed on demand. If
|
||||
/// \b false, the variable list contained in this object will
|
||||
/// be returned.
|
||||
///
|
||||
/// @return
|
||||
/// The variable list shared pointer which may contain a NULL
|
||||
/// variable list object.
|
||||
//------------------------------------------------------------------
|
||||
lldb::VariableListSP
|
||||
GetVariableList (lldb::user_id_t block_uid, bool get_child_variables, bool can_create);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check if the block list is empty.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \b true if the block list is empty, \b false
|
||||
/// otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
IsEmpty () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the memory cost of this object.
|
||||
///
|
||||
/// Returns the cost of this object plus any owned objects (address
|
||||
/// range, and contains Block objects).
|
||||
///
|
||||
/// @return
|
||||
/// The number of bytes that this object occupies in memory.
|
||||
//------------------------------------------------------------------
|
||||
size_t
|
||||
MemorySize () const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the variable list for the block whose UID is \a block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to set information for.
|
||||
///
|
||||
/// @param[in] variable_list_sp
|
||||
/// A shared pointer to list of variables.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \b true if the variable list was successfully added
|
||||
/// to the block, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
SetVariableList (lldb::user_id_t block_uid, lldb::VariableListSP& variable_list_sp);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the inlined function info for the block whose UID is \a
|
||||
/// block_uid.
|
||||
///
|
||||
/// @param[in] block_uid
|
||||
/// The UID of the block we wish to set information for.
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The method name for the inlined function. This value should
|
||||
/// not be NULL.
|
||||
///
|
||||
/// @param[in] mangled
|
||||
/// The mangled method name for the inlined function. This can
|
||||
/// be NULL if there is no mangled name for an inlined function
|
||||
/// or if the name is the same as \a name.
|
||||
///
|
||||
/// @param[in] decl_ptr
|
||||
/// A optional pointer to declaration information for the
|
||||
/// inlined function information. This value can be NULL to
|
||||
/// indicate that no declaration information is available.
|
||||
///
|
||||
/// @param[in] call_decl_ptr
|
||||
/// Optional calling location declaration information that
|
||||
/// describes from where this inlined function was called.
|
||||
///
|
||||
/// @return
|
||||
/// Returns \b true if the inline function info was successfully
|
||||
/// associated with the block, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
SetInlinedFunctionInfo (lldb::user_id_t block_uid, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr);
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
//------------------------------------------------------------------
|
||||
Function *m_function; ///< A pointer to the function that owns this block list.
|
||||
AddressRange m_range; ///< The section offset based address range.
|
||||
collection m_blocks; ///< A contiguous array of block objects.
|
||||
|
||||
bool
|
||||
BlockContainsBlockWithID (const lldb::user_id_t block_id, const lldb::user_id_t find_block_id) const;
|
||||
bool m_parsed_block_info:1, ///< Set to true if this block and it's children have all been parsed
|
||||
m_parsed_block_variables:1,
|
||||
m_parsed_child_blocks:1;
|
||||
|
||||
private:
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN (BlockList);
|
||||
DISALLOW_COPY_AND_ASSIGN (Block);
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_Block_h_
|
||||
|
|
|
@ -419,8 +419,11 @@ public:
|
|||
CalculateSymbolContext(SymbolContext* sc);
|
||||
|
||||
const AddressRange &
|
||||
GetAddressRange();
|
||||
|
||||
GetAddressRange()
|
||||
{
|
||||
return m_range;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Find the file and line number of the source location of the start
|
||||
/// of the function. This will use the declaration if present and fall
|
||||
|
@ -450,15 +453,6 @@ public:
|
|||
void
|
||||
GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return whether this Function represents an inlined version of the
|
||||
/// original function.
|
||||
///
|
||||
/// @return
|
||||
/// \b true if inlined, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool IsInlined();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get accessor for the block list.
|
||||
///
|
||||
|
@ -468,8 +462,8 @@ public:
|
|||
///
|
||||
/// @see BlockList
|
||||
//------------------------------------------------------------------
|
||||
BlockList&
|
||||
GetBlocks (bool can_create);
|
||||
Block&
|
||||
GetBlock (bool can_create);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get accessor for the compile unit that owns this function.
|
||||
|
@ -611,14 +605,15 @@ protected:
|
|||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
//------------------------------------------------------------------
|
||||
CompileUnit *m_comp_unit; ///< The compile unit that owns this function.
|
||||
CompileUnit *m_comp_unit; ///< The compile unit that owns this function.
|
||||
lldb::user_id_t m_type_uid; ///< The user ID of for the prototype Type for this function.
|
||||
Type * m_type; ///< The function prototype type for this function that include the function info (FunctionInfo), return type and parameters.
|
||||
Mangled m_mangled; ///< The mangled function name if any, if empty, there is no mangled information.
|
||||
BlockList m_blocks; ///< All lexical blocks contained in this function.
|
||||
Type * m_type; ///< The function prototype type for this function that include the function info (FunctionInfo), return type and parameters.
|
||||
Mangled m_mangled; ///< The mangled function name if any, if empty, there is no mangled information.
|
||||
Block m_block; ///< All lexical blocks contained in this function.
|
||||
AddressRange m_range; ///< The function address range that covers the widest range needed to contain all blocks
|
||||
DWARFExpression m_frame_base; ///< The frame base expression for variables that are relative to the frame pointer.
|
||||
Flags m_flags;
|
||||
uint32_t m_prologue_byte_size; ///< Compute the prologue size once and cache it
|
||||
uint32_t m_prologue_byte_size; ///< Compute the prologue size once and cache it
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Function);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@ class ArchSpec;
|
|||
class Args;
|
||||
class Baton;
|
||||
class Block;
|
||||
class BlockList;
|
||||
class Breakpoint;
|
||||
class BreakpointID;
|
||||
class BreakpointIDList;
|
||||
|
|
|
@ -2791,6 +2791,7 @@
|
|||
);
|
||||
LLVM_BUILD_DIR = "$(SRCROOT)/llvm";
|
||||
LLVM_CONFIGURATION = Release;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
OTHER_CFLAGS = (
|
||||
"-DFOR_DYLD=0",
|
||||
"-DSUPPORT_REMOTE_UNWINDING",
|
||||
|
|
|
@ -626,28 +626,21 @@ ClangExpressionDeclMap::FindVariableInScope(const SymbolContext &sym_ctx,
|
|||
{
|
||||
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
||||
|
||||
Function *function(m_sym_ctx->function);
|
||||
Block *block(m_sym_ctx->block);
|
||||
|
||||
if (!function || !block)
|
||||
if (m_sym_ctx->function == NULL || m_sym_ctx->block == NULL)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("function = %p, block = %p", function, block);
|
||||
log->Printf("function = %p, block = %p", m_sym_ctx->function, m_sym_ctx->block);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BlockList& blocks(function->GetBlocks(true));
|
||||
|
||||
ConstString name_cs(name);
|
||||
|
||||
lldb::user_id_t current_block_id;
|
||||
Block *current_block;
|
||||
|
||||
for (current_block_id = block->GetID();
|
||||
current_block_id != Block::InvalidID;
|
||||
current_block_id = blocks.GetParent(current_block_id))
|
||||
{
|
||||
Block *current_block(blocks.GetBlockByID(current_block_id));
|
||||
|
||||
for (current_block = m_sym_ctx->block;
|
||||
current_block != NULL;
|
||||
current_block = current_block->GetParent())
|
||||
{
|
||||
lldb::VariableListSP var_list = current_block->GetVariableList(false, true);
|
||||
|
||||
if (!var_list)
|
||||
|
|
|
@ -508,102 +508,48 @@ Host::ResolveExecutableInBundle (FileSpec *file)
|
|||
|
||||
struct MonitorInfo
|
||||
{
|
||||
uint32_t handle;
|
||||
pthread_t thread;
|
||||
Host::MonitorChildProcessCallback callback;
|
||||
void *callback_baton;
|
||||
bool monitor_signals;
|
||||
lldb::pid_t pid; // The process ID to monitor
|
||||
Host::MonitorChildProcessCallback callback; // The callback function to call when "pid" exits or signals
|
||||
void *callback_baton; // The callback baton for the callback function
|
||||
bool monitor_signals; // If true, call the callback when "pid" gets signaled.
|
||||
};
|
||||
|
||||
typedef std::multimap<lldb::pid_t, MonitorInfo> MonitorInfoMap;
|
||||
static pthread_mutex_t g_monitor_map_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
typedef lldb::SharedPtr<MonitorInfoMap>::Type MonitorInfoMapSP;
|
||||
|
||||
static MonitorInfoMapSP&
|
||||
GetMonitorMap (bool can_create)
|
||||
{
|
||||
static MonitorInfoMapSP g_monitor_map_sp;
|
||||
if (can_create && g_monitor_map_sp.get() == NULL)
|
||||
{
|
||||
g_monitor_map_sp.reset (new MonitorInfoMap);
|
||||
}
|
||||
return g_monitor_map_sp;
|
||||
}
|
||||
|
||||
static Predicate<bool>&
|
||||
GetChildProcessPredicate ()
|
||||
{
|
||||
static Predicate<bool> g_has_child_processes;
|
||||
return g_has_child_processes;
|
||||
}
|
||||
|
||||
static void *
|
||||
MonitorChildProcessThreadFunction (void *arg);
|
||||
|
||||
static pthread_t g_monitor_thread;
|
||||
|
||||
uint32_t
|
||||
lldb::thread_t
|
||||
Host::StartMonitoringChildProcess
|
||||
(
|
||||
MonitorChildProcessCallback callback,
|
||||
Host::MonitorChildProcessCallback callback,
|
||||
void *callback_baton,
|
||||
lldb::pid_t pid,
|
||||
bool monitor_signals
|
||||
)
|
||||
{
|
||||
static uint32_t g_handle = 0;
|
||||
|
||||
lldb::thread_t thread = LLDB_INVALID_HOST_THREAD;
|
||||
if (callback)
|
||||
{
|
||||
Mutex::Locker locker(&g_monitor_map_mutex);
|
||||
if (!g_monitor_thread)
|
||||
{
|
||||
lldb::pid_t wait_pid = -1;
|
||||
g_monitor_thread = ThreadCreate ("<lldb.host.wait4>",
|
||||
MonitorChildProcessThreadFunction,
|
||||
&wait_pid,
|
||||
NULL);
|
||||
if (g_monitor_thread)
|
||||
{
|
||||
//Host::ThreadDetach (g_monitor_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_monitor_thread)
|
||||
{
|
||||
MonitorInfo info = { ++g_handle, 0, callback, callback_baton, monitor_signals };
|
||||
MonitorInfoMapSP monitor_map_sp (GetMonitorMap (true));
|
||||
if (monitor_map_sp)
|
||||
{
|
||||
monitor_map_sp->insert(std::make_pair(pid, info));
|
||||
GetChildProcessPredicate ().SetValue (true, eBroadcastOnChange);
|
||||
return info.handle;
|
||||
}
|
||||
}
|
||||
std::auto_ptr<MonitorInfo> info_ap(new MonitorInfo);
|
||||
|
||||
info_ap->pid = pid;
|
||||
info_ap->callback = callback;
|
||||
info_ap->callback_baton = callback_baton;
|
||||
info_ap->monitor_signals = monitor_signals;
|
||||
|
||||
char thread_name[256];
|
||||
::snprintf (thread_name, sizeof(thread_name), "<lldb.host.wait4(pid=%i)>", pid);
|
||||
thread = ThreadCreate (thread_name,
|
||||
MonitorChildProcessThreadFunction,
|
||||
info_ap.get(),
|
||||
NULL);
|
||||
|
||||
if (thread != LLDB_INVALID_HOST_THREAD)
|
||||
info_ap.release();
|
||||
}
|
||||
return 0;
|
||||
return thread;
|
||||
}
|
||||
|
||||
bool
|
||||
Host::StopMonitoringChildProcess (uint32_t handle)
|
||||
{
|
||||
Mutex::Locker locker(&g_monitor_map_mutex);
|
||||
MonitorInfoMapSP monitor_map_sp (GetMonitorMap (false));
|
||||
if (monitor_map_sp)
|
||||
{
|
||||
MonitorInfoMap::iterator pos, end = monitor_map_sp->end();
|
||||
for (pos = monitor_map_sp->end(); pos != end; ++pos)
|
||||
{
|
||||
if (pos->second.handle == handle)
|
||||
{
|
||||
monitor_map_sp->erase(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Scoped class that will disable thread canceling when it is
|
||||
// constructed, and exception safely restore the previous value it
|
||||
|
@ -643,64 +589,37 @@ MonitorChildProcessThreadFunction (void *arg)
|
|||
if (log)
|
||||
log->Printf ("%s (arg = %p) thread starting...", function, arg);
|
||||
|
||||
const lldb::pid_t wait_pid = -1;//*((pid_t*)arg);
|
||||
MonitorInfo *info = (MonitorInfo *)arg;
|
||||
|
||||
const Host::MonitorChildProcessCallback callback = info->callback;
|
||||
void * const callback_baton = info->callback_baton;
|
||||
const lldb::pid_t pid = info->pid;
|
||||
const bool monitor_signals = info->monitor_signals;
|
||||
|
||||
delete info;
|
||||
|
||||
int status = -1;
|
||||
const int options = 0;
|
||||
struct rusage *rusage = NULL;
|
||||
while (1)
|
||||
{
|
||||
if (log)
|
||||
log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, wait_pid, options, rusage);
|
||||
log->Printf("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p)...", function, pid, options, rusage);
|
||||
|
||||
// Wait for all child processes
|
||||
::pthread_testcancel ();
|
||||
lldb::pid_t pid = ::wait4 (wait_pid, &status, options, rusage);
|
||||
const lldb::pid_t wait_pid = ::wait4 (pid, &status, options, rusage);
|
||||
::pthread_testcancel ();
|
||||
|
||||
if (pid < 0)
|
||||
if (wait_pid == -1)
|
||||
{
|
||||
// No child processes to watch wait for the mutex to be cleared
|
||||
|
||||
// Scope for "locker"
|
||||
{
|
||||
ScopedPThreadCancelDisabler pthread_cancel_disabler;
|
||||
|
||||
// First clear out all monitor entries since we have no processes
|
||||
// to watch.
|
||||
Mutex::Locker locker(&g_monitor_map_mutex);
|
||||
// Since we don't have any child processes, we can safely clear
|
||||
// anyone with a valid pid.
|
||||
MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
|
||||
if (monitor_map_sp)
|
||||
{
|
||||
MonitorInfoMap::iterator pos = monitor_map_sp->begin();
|
||||
while (pos != monitor_map_sp->end())
|
||||
{
|
||||
// pid value of 0 and -1 are special (see man page on wait4...)
|
||||
if (pos->first > 0)
|
||||
{
|
||||
MonitorInfoMap::iterator next_pos = pos; ++next_pos;
|
||||
monitor_map_sp->erase (pos, next_pos);
|
||||
pos = next_pos;
|
||||
}
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf("%s no child processes, wait for some...", function);
|
||||
GetChildProcessPredicate ().SetValue (false, eBroadcastNever);
|
||||
::pthread_testcancel();
|
||||
GetChildProcessPredicate ().WaitForValueEqualTo (true);
|
||||
if (log)
|
||||
log->Printf("%s resuming monitoring of child processes.", function);
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
else if (wait_pid == pid)
|
||||
{
|
||||
ScopedPThreadCancelDisabler pthread_cancel_disabler;
|
||||
bool exited = false;
|
||||
int signal = 0;
|
||||
int exit_status = 0;
|
||||
|
@ -728,80 +647,47 @@ MonitorChildProcessThreadFunction (void *arg)
|
|||
status_cstr = "(???)";
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
|
||||
function,
|
||||
wait_pid,
|
||||
options,
|
||||
rusage,
|
||||
pid,
|
||||
status,
|
||||
status_cstr,
|
||||
signal,
|
||||
exit_status);
|
||||
|
||||
// Scope for mutex locker
|
||||
// Scope for pthread_cancel_disabler
|
||||
{
|
||||
// Notify anyone listening to this process
|
||||
Mutex::Locker locker(&g_monitor_map_mutex);
|
||||
MonitorInfoMapSP monitor_map_sp(GetMonitorMap (false));
|
||||
if (monitor_map_sp)
|
||||
ScopedPThreadCancelDisabler pthread_cancel_disabler;
|
||||
|
||||
if (log)
|
||||
log->Printf ("%s ::wait4 (pid = %i, &status, options = %i, rusage = %p) => pid = %i, status = 0x%8.8x (%s), signal = %i, exit_state = %i",
|
||||
function,
|
||||
wait_pid,
|
||||
options,
|
||||
rusage,
|
||||
pid,
|
||||
status,
|
||||
status_cstr,
|
||||
signal,
|
||||
exit_status);
|
||||
|
||||
if (exited || (signal != 0 && monitor_signals))
|
||||
{
|
||||
std::pair<MonitorInfoMap::iterator, MonitorInfoMap::iterator> range;
|
||||
range = monitor_map_sp->equal_range(pid);
|
||||
MonitorInfoMap::iterator pos;
|
||||
for (pos = range.first; pos != range.second; ++pos)
|
||||
{
|
||||
if (exited || (signal != 0 && pos->second.monitor_signals))
|
||||
{
|
||||
bool callback_return = pos->second.callback (pos->second.callback_baton, pid, signal, exit_status);
|
||||
|
||||
if (exited || callback_return)
|
||||
{
|
||||
// Make this entry as needing to be removed by
|
||||
// setting its handle to zero
|
||||
pos->second.handle = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any entries that requested to be removed or any
|
||||
// entries for child processes that did exit. We know this
|
||||
// because we changed the handles to an invalid value.
|
||||
pos = monitor_map_sp->begin();
|
||||
while (pos != monitor_map_sp->end())
|
||||
{
|
||||
if (pos->second.handle == 0)
|
||||
{
|
||||
MonitorInfoMap::iterator next_pos = pos; ++next_pos;
|
||||
monitor_map_sp->erase (pos, next_pos);
|
||||
pos = next_pos;
|
||||
}
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
bool callback_return = callback (callback_baton, pid, signal, exit_status);
|
||||
|
||||
// If our process exited, then this thread should exit
|
||||
if (exited)
|
||||
break;
|
||||
// If the callback returns true, it means this process should
|
||||
// exit
|
||||
if (callback_return)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("ProcessMacOSX::%s (arg = %p) thread exiting...", __FUNCTION__, arg);
|
||||
log->Printf ("%s (arg = %p) thread exiting...", __FUNCTION__, arg);
|
||||
|
||||
g_monitor_thread = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Host::WillTerminate ()
|
||||
{
|
||||
if (g_monitor_thread != NULL)
|
||||
{
|
||||
ThreadCancel (g_monitor_thread, NULL);
|
||||
GetChildProcessPredicate ().SetValue (true, eBroadcastAlways);
|
||||
ThreadJoin(g_monitor_thread, NULL, NULL);
|
||||
g_monitor_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -226,6 +226,7 @@ ProcessMacOSX::ProcessMacOSX(Target& target, Listener &listener) :
|
|||
m_task (this),
|
||||
m_flags (eFlagsNone),
|
||||
m_stdio_thread (LLDB_INVALID_HOST_THREAD),
|
||||
m_monitor_thread (LLDB_INVALID_HOST_THREAD),
|
||||
m_stdio_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_stdout_data (),
|
||||
m_exception_messages (),
|
||||
|
@ -244,6 +245,7 @@ ProcessMacOSX::~ProcessMacOSX()
|
|||
{
|
||||
// m_mach_process.UnregisterNotificationCallbacks (this);
|
||||
Clear();
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -450,7 +452,7 @@ ProcessMacOSX::DidLaunchOrAttach ()
|
|||
// Install a signal handler so we can catch when our child process
|
||||
// dies and set the exit status correctly.
|
||||
|
||||
Host::StartMonitoringChildProcess (Process::SetProcessExitStatus, NULL, GetID(), false);
|
||||
m_monitor_thread = Host::StartMonitoringChildProcess (Process::SetProcessExitStatus, NULL, GetID(), false);
|
||||
|
||||
if (m_arch_spec == ArchSpec("arm"))
|
||||
{
|
||||
|
@ -1156,6 +1158,14 @@ ProcessMacOSX::Clear()
|
|||
m_exception_messages.clear();
|
||||
}
|
||||
|
||||
if (m_monitor_thread != LLDB_INVALID_HOST_THREAD)
|
||||
{
|
||||
Host::ThreadCancel (m_monitor_thread, NULL);
|
||||
thread_result_t thread_result;
|
||||
Host::ThreadJoin (m_monitor_thread, &thread_result, NULL);
|
||||
m_monitor_thread = LLDB_INVALID_HOST_THREAD;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -239,6 +239,7 @@ protected:
|
|||
MachTask m_task; // The mach task for this process
|
||||
lldb_private::Flags m_flags; // Process specific flags (see eFlags enums)
|
||||
lldb::thread_t m_stdio_thread; // Thread ID for the thread that watches for child process stdio
|
||||
lldb::thread_t m_monitor_thread; // Thread ID for the thread that watches for child process stdio
|
||||
lldb_private::Mutex m_stdio_mutex; // Multithreaded protection for stdio
|
||||
std::string m_stdout_data;
|
||||
MachException::Message::collection m_exception_messages; // A collection of exception messages caught when listening to the exception port
|
||||
|
|
|
@ -110,7 +110,7 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
|
|||
m_byte_order (eByteOrderHost),
|
||||
m_gdb_comm(),
|
||||
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
|
||||
m_debugserver_monitor (0),
|
||||
m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
|
||||
m_last_stop_packet (),
|
||||
m_register_info (),
|
||||
m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
|
||||
|
@ -134,6 +134,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
|
|||
//----------------------------------------------------------------------
|
||||
ProcessGDBRemote::~ProcessGDBRemote()
|
||||
{
|
||||
if (m_debugserver_thread != LLDB_INVALID_HOST_THREAD)
|
||||
{
|
||||
Host::ThreadCancel (m_debugserver_thread, NULL);
|
||||
thread_result_t thread_result;
|
||||
Host::ThreadJoin (m_debugserver_thread, &thread_result, NULL);
|
||||
m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
|
||||
}
|
||||
// m_mach_process.UnregisterNotificationCallbacks (this);
|
||||
Clear();
|
||||
}
|
||||
|
@ -535,11 +542,11 @@ ProcessGDBRemote::ConnectToDebugserver (const char *host_port)
|
|||
m_gdb_comm.SendAck('+');
|
||||
|
||||
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
|
||||
m_debugserver_monitor = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
|
||||
(void*)(intptr_t)GetID(), // Pass the inferior pid in the thread argument (which is a void *)
|
||||
m_debugserver_pid,
|
||||
false);
|
||||
|
||||
m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess,
|
||||
this,
|
||||
m_debugserver_pid,
|
||||
false);
|
||||
|
||||
StringExtractorGDBRemote response;
|
||||
if (m_gdb_comm.SendPacketAndWaitForResponse("QStartNoAckMode", response, 1, false))
|
||||
{
|
||||
|
@ -1907,47 +1914,42 @@ ProcessGDBRemote::MonitorDebugserverProcess
|
|||
// "debugserver_pid" argument passed in is the process ID for
|
||||
// debugserver that we are tracking...
|
||||
|
||||
lldb::pid_t gdb_remote_pid = (lldb::pid_t)(intptr_t)callback_baton;
|
||||
TargetSP target_sp(Debugger::FindTargetWithProcessID (gdb_remote_pid));
|
||||
if (target_sp)
|
||||
ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton;
|
||||
|
||||
if (process)
|
||||
{
|
||||
ProcessSP process_sp (target_sp->GetProcessSP());
|
||||
if (process_sp)
|
||||
// Sleep for a half a second to make sure our inferior process has
|
||||
// time to set its exit status before we set it incorrectly when
|
||||
// both the debugserver and the inferior process shut down.
|
||||
usleep (500000);
|
||||
// If our process hasn't yet exited, debugserver might have died.
|
||||
// If the process did exit, the we are reaping it.
|
||||
if (process->GetState() != eStateExited)
|
||||
{
|
||||
// Sleep for a half a second to make sure our inferior process has
|
||||
// time to set its exit status before we set it incorrectly when
|
||||
// both the debugserver and the inferior process shut down.
|
||||
usleep (500000);
|
||||
// If our process hasn't yet exited, debugserver might have died.
|
||||
// If the process did exit, the we are reaping it.
|
||||
if (process_sp->GetState() != eStateExited)
|
||||
char error_str[1024];
|
||||
if (signo)
|
||||
{
|
||||
char error_str[1024];
|
||||
if (signo)
|
||||
{
|
||||
const char *signal_cstr = process_sp->GetUnixSignals().GetSignalAsCString (signo);
|
||||
if (signal_cstr)
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
|
||||
else
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
|
||||
}
|
||||
const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
|
||||
if (signal_cstr)
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
|
||||
else
|
||||
{
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
|
||||
}
|
||||
|
||||
process_sp->SetExitStatus (-1, error_str);
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)process_sp.get();
|
||||
// Debugserver has exited we need to let our ProcessGDBRemote
|
||||
// know that it no longer has a debugserver instance
|
||||
gdb_process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
// We are returning true to this function below, so we can
|
||||
// forget about the monitor handle.
|
||||
gdb_process->m_debugserver_monitor = 0;
|
||||
::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
|
||||
}
|
||||
|
||||
process->SetExitStatus (-1, error_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Debugserver has exited we need to let our ProcessGDBRemote
|
||||
// know that it no longer has a debugserver instance
|
||||
process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
|
||||
// We are returning true to this function below, so we can
|
||||
// forget about the monitor handle.
|
||||
process->m_debugserver_thread = LLDB_INVALID_HOST_THREAD;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -324,7 +324,7 @@ protected:
|
|||
lldb::ByteOrder m_byte_order;
|
||||
GDBRemoteCommunication m_gdb_comm;
|
||||
lldb::pid_t m_debugserver_pid;
|
||||
uint32_t m_debugserver_monitor;
|
||||
lldb::thread_t m_debugserver_thread;
|
||||
StringExtractor m_last_stop_packet;
|
||||
GDBRemoteDynamicRegisterInfo m_register_info;
|
||||
lldb_private::Broadcaster m_async_broadcaster;
|
||||
|
|
|
@ -785,8 +785,7 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
|
|||
static void
|
||||
AddRangesToBlock
|
||||
(
|
||||
BlockList& blocks,
|
||||
lldb::user_id_t blockID,
|
||||
Block& block,
|
||||
DWARFDebugRanges::RangeList& ranges,
|
||||
addr_t block_base_addr
|
||||
)
|
||||
|
@ -796,7 +795,7 @@ AddRangesToBlock
|
|||
const DWARFDebugRanges::Range *debug_range;
|
||||
for (range_idx = 0; (debug_range = ranges.RangeAtIndex(range_idx)) != NULL; range_idx++)
|
||||
{
|
||||
blocks.AddRange(blockID, debug_range->begin_offset, debug_range->end_offset);
|
||||
block.AddRange(debug_range->begin_offset, debug_range->end_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1129,7 +1128,7 @@ size_t
|
|||
SymbolFileDWARF::ParseFunctionBlocks
|
||||
(
|
||||
const SymbolContext& sc,
|
||||
lldb::user_id_t parentBlockID,
|
||||
Block *parent_block,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
addr_t subprogram_low_pc,
|
||||
|
@ -1151,18 +1150,31 @@ SymbolFileDWARF::ParseFunctionBlocks
|
|||
DWARFDebugRanges::RangeList ranges;
|
||||
const char *name = NULL;
|
||||
const char *mangled_name = NULL;
|
||||
BlockList& blocks = sc.function->GetBlocks(false);
|
||||
Block *block = NULL;
|
||||
if (tag != DW_TAG_subprogram)
|
||||
{
|
||||
BlockSP block_sp(new Block (die->GetOffset()));
|
||||
parent_block->AddChild(block_sp);
|
||||
block = block_sp.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
block = parent_block;
|
||||
}
|
||||
|
||||
lldb::user_id_t blockID = blocks.AddChild(parentBlockID, die->GetOffset());
|
||||
int decl_file = 0;
|
||||
int decl_line = 0;
|
||||
int decl_column = 0;
|
||||
int call_file = 0;
|
||||
int call_line = 0;
|
||||
int call_column = 0;
|
||||
if (die->GetDIENamesAndRanges(this, dwarf_cu, name, mangled_name, ranges,
|
||||
decl_file, decl_line, decl_column,
|
||||
call_file, call_line, call_column))
|
||||
if (die->GetDIENamesAndRanges (this,
|
||||
dwarf_cu,
|
||||
name,
|
||||
mangled_name,
|
||||
ranges,
|
||||
decl_file, decl_line, decl_column,
|
||||
call_file, call_line, call_column))
|
||||
{
|
||||
if (tag == DW_TAG_subprogram)
|
||||
{
|
||||
|
@ -1185,7 +1197,7 @@ SymbolFileDWARF::ParseFunctionBlocks
|
|||
}
|
||||
}
|
||||
|
||||
AddRangesToBlock (blocks, blockID, ranges, subprogram_low_pc);
|
||||
AddRangesToBlock (*block, ranges, subprogram_low_pc);
|
||||
|
||||
if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL))
|
||||
{
|
||||
|
@ -1199,15 +1211,20 @@ SymbolFileDWARF::ParseFunctionBlocks
|
|||
call_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file),
|
||||
call_line, call_column));
|
||||
|
||||
blocks.SetInlinedFunctionInfo(blockID, name, mangled_name, decl_ap.get(), call_ap.get());
|
||||
block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get());
|
||||
}
|
||||
|
||||
++blocks_added;
|
||||
|
||||
if (parse_children && die->HasChildren())
|
||||
{
|
||||
blocks_added += ParseFunctionBlocks(sc, blockID, dwarf_cu, die->GetFirstChild(),
|
||||
subprogram_low_pc, true, true);
|
||||
blocks_added += ParseFunctionBlocks (sc,
|
||||
block,
|
||||
dwarf_cu,
|
||||
die->GetFirstChild(),
|
||||
subprogram_low_pc,
|
||||
true,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1582,12 +1599,12 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
|
|||
|
||||
if (resolve_scope & eSymbolContextBlock)
|
||||
{
|
||||
BlockList& blocks = sc.function->GetBlocks(true);
|
||||
Block& block = sc.function->GetBlock (true);
|
||||
|
||||
if (block_die != NULL)
|
||||
sc.block = blocks.GetBlockByID(block_die->GetOffset());
|
||||
sc.block = block.FindBlockByID (block_die->GetOffset());
|
||||
else
|
||||
sc.block = blocks.GetBlockByID(function_die->GetOffset());
|
||||
sc.block = block.FindBlockByID (function_die->GetOffset());
|
||||
if (sc.block)
|
||||
resolved |= eSymbolContextBlock;
|
||||
}
|
||||
|
@ -1674,12 +1691,12 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
|
|||
|
||||
if (sc.function != NULL)
|
||||
{
|
||||
BlockList& blocks = sc.function->GetBlocks(true);
|
||||
Block& block = sc.function->GetBlock (true);
|
||||
|
||||
if (block_die != NULL)
|
||||
sc.block = blocks.GetBlockByID(block_die->GetOffset());
|
||||
sc.block = block.FindBlockByID (block_die->GetOffset());
|
||||
else
|
||||
sc.block = blocks.GetBlockByID(function_die->GetOffset());
|
||||
sc.block = block.FindBlockByID (function_die->GetOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3126,7 +3143,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar
|
|||
}
|
||||
else if (sc.function != NULL)
|
||||
{
|
||||
symbol_context_scope = sc.function->GetBlocks(true).GetBlockByID(sc_parent_die->GetOffset());
|
||||
symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
|
||||
if (symbol_context_scope == NULL)
|
||||
symbol_context_scope = sc.function;
|
||||
}
|
||||
|
@ -3235,7 +3252,7 @@ SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
|
|||
const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
|
||||
if (function_die)
|
||||
{
|
||||
ParseFunctionBlocks(sc, Block::RootID, dwarf_cu, function_die, LLDB_INVALID_ADDRESS, false, true);
|
||||
ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3430,7 +3447,7 @@ SymbolFileDWARF::ParseVariableDIE
|
|||
}
|
||||
else if (sc.function != NULL)
|
||||
{
|
||||
symbol_context_scope = sc.function->GetBlocks(true).GetBlockByID(sc_parent_die->GetOffset());
|
||||
symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
|
||||
if (symbol_context_scope == NULL)
|
||||
symbol_context_scope = sc.function;
|
||||
}
|
||||
|
@ -3495,11 +3512,14 @@ SymbolFileDWARF::ParseVariables
|
|||
if (sc.function != NULL)
|
||||
{
|
||||
// Check to see if we already have parsed the variables for the given scope
|
||||
variables = sc.function->GetBlocks(true).GetVariableList(sc_parent_die->GetOffset(), false, false);
|
||||
|
||||
Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die->GetOffset());
|
||||
assert (block != NULL);
|
||||
variables = block->GetVariableList(false, true);
|
||||
if (variables.get() == NULL)
|
||||
{
|
||||
variables.reset(new VariableList());
|
||||
sc.function->GetBlocks(true).SetVariableList(sc_parent_die->GetOffset(), variables);
|
||||
block->SetVariableList(variables);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -222,7 +222,7 @@ protected:
|
|||
bool GetFunction (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
|
||||
lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, const DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
|
||||
size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
|
||||
lldb::user_id_t parentBlockID,
|
||||
lldb_private::Block *parent_block,
|
||||
const DWARFCompileUnit* dwarf_cu,
|
||||
const DWARFDebugInfoEntry *die,
|
||||
lldb::addr_t subprogram_low_pc,
|
||||
|
|
|
@ -17,47 +17,26 @@
|
|||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
Block::Block(user_id_t uid, uint32_t depth, BlockList* blocks) :
|
||||
Block::Block(lldb::user_id_t uid) :
|
||||
UserID(uid),
|
||||
m_block_list(blocks),
|
||||
m_depth(depth),
|
||||
m_ranges(),
|
||||
m_inlineInfoSP(),
|
||||
m_variables()
|
||||
m_parent_scope (NULL),
|
||||
m_sibling (NULL),
|
||||
m_children (),
|
||||
m_ranges (),
|
||||
m_inlineInfoSP (),
|
||||
m_variables (),
|
||||
m_parsed_block_info (false),
|
||||
m_parsed_block_variables (false),
|
||||
m_parsed_child_blocks (false)
|
||||
{
|
||||
}
|
||||
|
||||
Block::Block(const Block& rhs) :
|
||||
UserID(rhs),
|
||||
m_block_list(rhs.m_block_list),
|
||||
m_depth(rhs.m_depth),
|
||||
m_ranges(rhs.m_ranges),
|
||||
m_inlineInfoSP(rhs.m_inlineInfoSP),
|
||||
m_variables(rhs.m_variables)
|
||||
{
|
||||
}
|
||||
|
||||
const Block&
|
||||
Block::operator= (const Block& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
UserID::operator= (rhs);
|
||||
m_block_list = rhs.m_block_list;
|
||||
m_depth = rhs.m_depth;
|
||||
m_ranges = rhs.m_ranges;
|
||||
m_inlineInfoSP = rhs.m_inlineInfoSP;
|
||||
m_variables = rhs.m_variables;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Block::~Block ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Block::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process) const
|
||||
Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Process *process) const
|
||||
{
|
||||
size_t num_ranges = m_ranges.size();
|
||||
if (num_ranges)
|
||||
|
@ -65,9 +44,9 @@ Block::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *process)
|
|||
|
||||
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
||||
if (process)
|
||||
base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
|
||||
base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(process);
|
||||
if (base_addr == LLDB_INVALID_ADDRESS)
|
||||
base_addr = m_block_list->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||
base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress();
|
||||
|
||||
s->Printf("range%s = ", num_ranges > 1 ? "s" : "");
|
||||
std::vector<VMRange>::const_iterator pos, end = m_ranges.end();
|
||||
|
@ -85,9 +64,13 @@ Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
|
|||
{
|
||||
if (depth < 0)
|
||||
{
|
||||
// We have a depth that is less than zero, print our parent blocks
|
||||
// first
|
||||
m_block_list->Dump(s, GetParentUID(), depth + 1, show_context);
|
||||
Block *parent = GetParent();
|
||||
if (parent)
|
||||
{
|
||||
// We have a depth that is less than zero, print our parent blocks
|
||||
// first
|
||||
parent->Dump(s, base_addr, depth + 1, show_context);
|
||||
}
|
||||
}
|
||||
|
||||
s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
|
||||
|
@ -126,12 +109,9 @@ Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
|
|||
m_variables->Dump(s, show_context);
|
||||
}
|
||||
|
||||
uint32_t blockID = m_block_list->GetFirstChild(GetID());
|
||||
while (blockID != Block::InvalidID)
|
||||
for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
|
||||
{
|
||||
m_block_list->Dump(s, blockID, depth - 1, show_context);
|
||||
|
||||
blockID = m_block_list->GetSibling(blockID);
|
||||
child_block->Dump(s, base_addr, depth - 1, show_context);
|
||||
}
|
||||
|
||||
s->IndentLess();
|
||||
|
@ -140,11 +120,28 @@ Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const
|
|||
}
|
||||
|
||||
|
||||
Block *
|
||||
Block::FindBlockByID (user_id_t block_id)
|
||||
{
|
||||
if (block_id == GetID())
|
||||
return this;
|
||||
|
||||
Block *matching_block = NULL;
|
||||
for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
|
||||
{
|
||||
matching_block = child_block->FindBlockByID (block_id);
|
||||
if (matching_block)
|
||||
break;
|
||||
}
|
||||
return matching_block;
|
||||
}
|
||||
|
||||
void
|
||||
Block::CalculateSymbolContext(SymbolContext* sc)
|
||||
{
|
||||
if (m_parent_scope)
|
||||
m_parent_scope->CalculateSymbolContext(sc);
|
||||
sc->block = this;
|
||||
m_block_list->GetFunction()->CalculateSymbolContext(sc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -196,7 +193,10 @@ Block::DumpStopContext (Stream *s, const SymbolContext *sc)
|
|||
void
|
||||
Block::DumpSymbolContext(Stream *s)
|
||||
{
|
||||
m_block_list->GetFunction()->DumpSymbolContext(s);
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
if (sc.function)
|
||||
sc.function->DumpSymbolContext(s);
|
||||
s->Printf(", Block{0x%8.8x}", GetID());
|
||||
}
|
||||
|
||||
|
@ -212,37 +212,19 @@ Block::Contains (const VMRange& range) const
|
|||
return VMRange::ContainsRange(m_ranges, range);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BlockList::BlockContainsBlockWithID (const user_id_t block_id, const user_id_t find_block_id) const
|
||||
Block *
|
||||
Block::GetParent () const
|
||||
{
|
||||
if (block_id == Block::InvalidID)
|
||||
return false;
|
||||
|
||||
if (block_id == find_block_id)
|
||||
return true;
|
||||
else
|
||||
if (m_parent_scope)
|
||||
{
|
||||
user_id_t child_block_id = GetFirstChild(block_id);
|
||||
while (child_block_id != Block::InvalidID)
|
||||
{
|
||||
if (BlockContainsBlockWithID (child_block_id, find_block_id))
|
||||
return true;
|
||||
child_block_id = GetSibling(child_block_id);
|
||||
}
|
||||
SymbolContext sc;
|
||||
m_parent_scope->CalculateSymbolContext(&sc);
|
||||
if (sc.block)
|
||||
return sc.block;
|
||||
}
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
Block::ContainsBlockWithID (user_id_t block_id) const
|
||||
{
|
||||
return m_block_list->BlockContainsBlockWithID (GetID(), block_id);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Block::AddRange(addr_t start_offset, addr_t end_offset)
|
||||
{
|
||||
|
@ -275,46 +257,30 @@ Block::MemorySize() const
|
|||
|
||||
}
|
||||
|
||||
Block *
|
||||
Block::GetParent () const
|
||||
{
|
||||
return m_block_list->GetBlockByID (m_block_list->GetParent(GetID()));
|
||||
}
|
||||
|
||||
Block *
|
||||
Block::GetSibling () const
|
||||
{
|
||||
return m_block_list->GetBlockByID (m_block_list->GetSibling(GetID()));
|
||||
}
|
||||
|
||||
Block *
|
||||
Block::GetFirstChild () const
|
||||
{
|
||||
return m_block_list->GetBlockByID (m_block_list->GetFirstChild(GetID()));
|
||||
if (m_children.empty())
|
||||
return NULL;
|
||||
return m_children.front().get();
|
||||
}
|
||||
|
||||
user_id_t
|
||||
Block::GetParentUID() const
|
||||
void
|
||||
Block::AddChild(const BlockSP &child_block_sp)
|
||||
{
|
||||
return m_block_list->GetParent(GetID());
|
||||
}
|
||||
if (child_block_sp)
|
||||
{
|
||||
Block *block_needs_sibling = NULL;
|
||||
|
||||
user_id_t
|
||||
Block::GetSiblingUID() const
|
||||
{
|
||||
return m_block_list->GetSibling(GetID());
|
||||
}
|
||||
if (!m_children.empty())
|
||||
block_needs_sibling = m_children.back().get();
|
||||
|
||||
user_id_t
|
||||
Block::GetFirstChildUID() const
|
||||
{
|
||||
return m_block_list->GetFirstChild(GetID());
|
||||
}
|
||||
child_block_sp->SetParentScope (this);
|
||||
m_children.push_back (child_block_sp);
|
||||
|
||||
user_id_t
|
||||
Block::AddChild(user_id_t userID)
|
||||
{
|
||||
return m_block_list->AddChild(GetID(), userID);
|
||||
if (block_needs_sibling)
|
||||
block_needs_sibling->SetSibling (child_block_sp.get());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -329,12 +295,16 @@ VariableListSP
|
|||
Block::GetVariableList (bool get_child_variables, bool can_create)
|
||||
{
|
||||
VariableListSP variable_list_sp;
|
||||
if (m_variables.get() == NULL && can_create)
|
||||
if (m_parsed_block_variables == false)
|
||||
{
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
assert(sc.module_sp);
|
||||
sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
|
||||
if (m_variables.get() == NULL && can_create)
|
||||
{
|
||||
m_parsed_block_variables = true;
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
assert(sc.module_sp);
|
||||
sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_variables.get())
|
||||
|
@ -387,285 +357,14 @@ Block::SetVariableList(VariableListSP& variables)
|
|||
m_variables = variables;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Block::Depth () const
|
||||
{
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
BlockList::BlockList(Function *function, const AddressRange& range) :
|
||||
m_function(function),
|
||||
m_range(range),
|
||||
m_blocks()
|
||||
{
|
||||
}
|
||||
|
||||
BlockList::~BlockList()
|
||||
{
|
||||
}
|
||||
|
||||
AddressRange &
|
||||
BlockList::GetAddressRange()
|
||||
{
|
||||
return m_range;
|
||||
}
|
||||
|
||||
const AddressRange &
|
||||
BlockList::GetAddressRange() const
|
||||
{
|
||||
return m_range;
|
||||
}
|
||||
|
||||
void
|
||||
BlockList::Dump(Stream *s, user_id_t blockID, uint32_t depth, bool show_context) const
|
||||
Block::SetBlockInfoHasBeenParsed (bool b, bool set_children)
|
||||
{
|
||||
const Block* block = GetBlockByID(blockID);
|
||||
if (block)
|
||||
block->Dump(s, m_range.GetBaseAddress().GetFileAddress(), depth, show_context);
|
||||
}
|
||||
|
||||
Function *
|
||||
BlockList::GetFunction()
|
||||
{
|
||||
return m_function;
|
||||
}
|
||||
|
||||
|
||||
const Function *
|
||||
BlockList::GetFunction() const
|
||||
{
|
||||
return m_function;
|
||||
}
|
||||
|
||||
user_id_t
|
||||
BlockList::GetParent(user_id_t blockID) const
|
||||
{
|
||||
collection::const_iterator end = m_blocks.end();
|
||||
collection::const_iterator begin = m_blocks.begin();
|
||||
collection::const_iterator pos = std::find_if(begin, end, UserID::IDMatches(blockID));
|
||||
|
||||
if (pos != end && pos != begin && pos->Depth() > 0)
|
||||
m_parsed_block_info = b;
|
||||
if (set_children)
|
||||
{
|
||||
const uint32_t parent_depth = pos->Depth() - 1;
|
||||
|
||||
while (--pos >= begin)
|
||||
{
|
||||
if (pos->Depth() == parent_depth)
|
||||
return pos->GetID();
|
||||
}
|
||||
m_parsed_child_blocks = true;
|
||||
for (Block *child_block = GetFirstChild(); child_block != NULL; child_block = child_block->GetSibling())
|
||||
child_block->SetBlockInfoHasBeenParsed (b, true);
|
||||
}
|
||||
return Block::InvalidID;
|
||||
}
|
||||
|
||||
user_id_t
|
||||
BlockList::GetSibling(user_id_t blockID) const
|
||||
{
|
||||
collection::const_iterator end = m_blocks.end();
|
||||
collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
|
||||
|
||||
if (pos != end)
|
||||
{
|
||||
const uint32_t sibling_depth = pos->Depth();
|
||||
while (++pos != end)
|
||||
{
|
||||
uint32_t depth = pos->Depth();
|
||||
if (depth == sibling_depth)
|
||||
return pos->GetID();
|
||||
if (depth < sibling_depth)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Block::InvalidID;
|
||||
}
|
||||
|
||||
user_id_t
|
||||
BlockList::GetFirstChild(user_id_t blockID) const
|
||||
{
|
||||
if (!m_blocks.empty())
|
||||
{
|
||||
if (blockID == Block::RootID)
|
||||
{
|
||||
return m_blocks.front().GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
collection::const_iterator end = m_blocks.end();
|
||||
collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
|
||||
|
||||
if (pos != end)
|
||||
{
|
||||
collection::const_iterator child_pos = pos + 1;
|
||||
if (child_pos != end)
|
||||
{
|
||||
if (child_pos->Depth() == pos->Depth() + 1)
|
||||
return child_pos->GetID();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Block::InvalidID;
|
||||
}
|
||||
|
||||
|
||||
// Return the current number of bytes that this object occupies in memory
|
||||
size_t
|
||||
BlockList::MemorySize() const
|
||||
{
|
||||
size_t mem_size = sizeof(BlockList);
|
||||
|
||||
collection::const_iterator pos, end = m_blocks.end();
|
||||
for (pos = m_blocks.begin(); pos != end; ++pos)
|
||||
mem_size += pos->MemorySize(); // Each block can vary in size
|
||||
|
||||
return mem_size;
|
||||
|
||||
}
|
||||
|
||||
user_id_t
|
||||
BlockList::AddChild (user_id_t parentID, user_id_t childID)
|
||||
{
|
||||
bool added = false;
|
||||
if (parentID == Block::RootID)
|
||||
{
|
||||
assert(m_blocks.empty());
|
||||
Block block(childID, 0, this);
|
||||
m_blocks.push_back(block);
|
||||
added = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
collection::iterator end = m_blocks.end();
|
||||
collection::iterator parent_pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(parentID));
|
||||
assert(parent_pos != end);
|
||||
if (parent_pos != end)
|
||||
{
|
||||
const uint32_t parent_sibling_depth = parent_pos->Depth();
|
||||
|
||||
collection::iterator insert_pos = parent_pos;
|
||||
collection::iterator prev_sibling = end;
|
||||
while (++insert_pos != end)
|
||||
{
|
||||
if (insert_pos->Depth() <= parent_sibling_depth)
|
||||
break;
|
||||
}
|
||||
|
||||
Block child_block(childID, parent_pos->Depth() + 1, this);
|
||||
collection::iterator child_pos = m_blocks.insert(insert_pos, child_block);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
if (added)
|
||||
return childID;
|
||||
return Block::InvalidID;
|
||||
}
|
||||
|
||||
const Block *
|
||||
BlockList::GetBlockByID(user_id_t blockID) const
|
||||
{
|
||||
if (m_blocks.empty() || blockID == Block::InvalidID)
|
||||
return NULL;
|
||||
|
||||
if (blockID == Block::RootID)
|
||||
blockID = m_blocks.front().GetID();
|
||||
|
||||
collection::const_iterator end = m_blocks.end();
|
||||
collection::const_iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
|
||||
if (pos != end)
|
||||
return &(*pos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Block *
|
||||
BlockList::GetBlockByID(user_id_t blockID)
|
||||
{
|
||||
if (m_blocks.empty() || blockID == Block::InvalidID)
|
||||
return NULL;
|
||||
|
||||
if (blockID == Block::RootID)
|
||||
blockID = m_blocks.front().GetID();
|
||||
|
||||
collection::iterator end = m_blocks.end();
|
||||
collection::iterator pos = std::find_if(m_blocks.begin(), end, UserID::IDMatches(blockID));
|
||||
if (pos != end)
|
||||
return &(*pos);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
BlockList::AddRange(user_id_t blockID, addr_t start_offset, addr_t end_offset)
|
||||
{
|
||||
Block *block = GetBlockByID(blockID);
|
||||
|
||||
if (block)
|
||||
{
|
||||
block->AddRange(start_offset, end_offset);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//
|
||||
//const Block *
|
||||
//BlockList::FindDeepestBlockForAddress (const Address &addr)
|
||||
//{
|
||||
// if (m_range.Contains(addr))
|
||||
// {
|
||||
// addr_t block_offset = addr.GetFileAddress() - m_range.GetBaseAddress().GetFileAddress();
|
||||
// collection::const_iterator pos, end = m_blocks.end();
|
||||
// collection::const_iterator deepest_match_pos = end;
|
||||
// for (pos = m_blocks.begin(); pos != end; ++pos)
|
||||
// {
|
||||
// if (pos->Contains (block_offset))
|
||||
// {
|
||||
// if (deepest_match_pos == end || deepest_match_pos->Depth() < pos->Depth())
|
||||
// deepest_match_pos = pos;
|
||||
// }
|
||||
// }
|
||||
// if (deepest_match_pos != end)
|
||||
// return &(*deepest_match_pos);
|
||||
// }
|
||||
// return NULL;
|
||||
//}
|
||||
//
|
||||
bool
|
||||
BlockList::SetInlinedFunctionInfo(user_id_t blockID, const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr)
|
||||
{
|
||||
Block *block = GetBlockByID(blockID);
|
||||
|
||||
if (block)
|
||||
{
|
||||
block->SetInlinedFunctionInfo(name, mangled, decl_ptr, call_decl_ptr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
VariableListSP
|
||||
BlockList::GetVariableList(user_id_t blockID, bool get_child_variables, bool can_create)
|
||||
{
|
||||
VariableListSP variable_list_sp;
|
||||
Block *block = GetBlockByID(blockID);
|
||||
if (block)
|
||||
variable_list_sp = block->GetVariableList(get_child_variables, can_create);
|
||||
return variable_list_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
BlockList::IsEmpty() const
|
||||
{
|
||||
return m_blocks.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
BlockList::SetVariableList(user_id_t blockID, VariableListSP& variables)
|
||||
{
|
||||
Block *block = GetBlockByID(blockID);
|
||||
if (block)
|
||||
{
|
||||
block->SetVariableList(variables);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
|
|
@ -191,16 +191,18 @@ Function::Function
|
|||
Type * type,
|
||||
const AddressRange& range
|
||||
) :
|
||||
UserID(func_uid),
|
||||
m_comp_unit(comp_unit),
|
||||
m_type_uid(type_uid),
|
||||
m_type(type),
|
||||
m_mangled(mangled),
|
||||
m_blocks(this, range),
|
||||
m_frame_base(),
|
||||
m_flags(),
|
||||
m_prologue_byte_size(0)
|
||||
UserID (func_uid),
|
||||
m_comp_unit (comp_unit),
|
||||
m_type_uid (type_uid),
|
||||
m_type (type),
|
||||
m_mangled (mangled),
|
||||
m_block (func_uid),
|
||||
m_range (range),
|
||||
m_frame_base (),
|
||||
m_flags (),
|
||||
m_prologue_byte_size (0)
|
||||
{
|
||||
m_block.SetParentScope(this);
|
||||
assert(comp_unit != NULL);
|
||||
}
|
||||
|
||||
|
@ -213,16 +215,18 @@ Function::Function
|
|||
Type *type,
|
||||
const AddressRange &range
|
||||
) :
|
||||
UserID(func_uid),
|
||||
m_comp_unit(comp_unit),
|
||||
m_type_uid(type_uid),
|
||||
m_type(type),
|
||||
m_mangled(mangled, true),
|
||||
m_blocks(this, range),
|
||||
m_frame_base(),
|
||||
m_flags(),
|
||||
m_prologue_byte_size(0)
|
||||
UserID (func_uid),
|
||||
m_comp_unit (comp_unit),
|
||||
m_type_uid (type_uid),
|
||||
m_type (type),
|
||||
m_mangled (mangled, true),
|
||||
m_block (func_uid),
|
||||
m_range (range),
|
||||
m_frame_base (),
|
||||
m_flags (),
|
||||
m_prologue_byte_size (0)
|
||||
{
|
||||
m_block.SetParentScope(this);
|
||||
assert(comp_unit != NULL);
|
||||
}
|
||||
|
||||
|
@ -231,24 +235,6 @@ Function::~Function()
|
|||
{
|
||||
}
|
||||
|
||||
const AddressRange &
|
||||
Function::GetAddressRange()
|
||||
{
|
||||
return GetBlocks(true).GetAddressRange();
|
||||
}
|
||||
|
||||
bool
|
||||
Function::IsInlined()
|
||||
{
|
||||
Block *root_block = GetBlocks(true).GetBlockByID(Block::RootID);
|
||||
if (root_block)
|
||||
{
|
||||
if (root_block->InlinedFunctionInfo() != NULL)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
void
|
||||
Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
|
||||
{
|
||||
|
@ -301,17 +287,18 @@ Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no)
|
|||
}
|
||||
}
|
||||
|
||||
BlockList &
|
||||
Function::GetBlocks(bool can_create)
|
||||
Block &
|
||||
Function::GetBlock (bool can_create)
|
||||
{
|
||||
if (m_blocks.IsEmpty() && can_create)
|
||||
if (!m_block.BlockInfoHasBeenParsed() && can_create)
|
||||
{
|
||||
SymbolContext sc;
|
||||
CalculateSymbolContext(&sc);
|
||||
assert(sc.module_sp);
|
||||
sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
|
||||
m_block.SetBlockInfoHasBeenParsed (true, true);
|
||||
}
|
||||
return m_blocks;
|
||||
return m_block;
|
||||
}
|
||||
|
||||
CompileUnit*
|
||||
|
@ -358,8 +345,8 @@ Function::Dump(Stream *s, bool show_context) const
|
|||
|
||||
s->EOL();
|
||||
// Dump the root object
|
||||
if (!m_blocks.IsEmpty())
|
||||
m_blocks.Dump(s, Block::RootID, INT_MAX, show_context);
|
||||
if (m_block.BlockInfoHasBeenParsed ())
|
||||
m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context);
|
||||
}
|
||||
|
||||
|
||||
|
@ -380,7 +367,7 @@ Function::DumpSymbolContext(Stream *s)
|
|||
size_t
|
||||
Function::MemorySize () const
|
||||
{
|
||||
size_t mem_size = sizeof(Function) + m_blocks.MemorySize();
|
||||
size_t mem_size = sizeof(Function) + m_block.MemorySize();
|
||||
return mem_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Process *
|
|||
s->Indent(" Blocks: ");
|
||||
else
|
||||
s->Indent(" ");
|
||||
(*pos)->GetDescription(s, level, process);
|
||||
(*pos)->GetDescription(s, function, level, process);
|
||||
s->EOL();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ Variable::IsInScope (StackFrame *frame)
|
|||
SymbolContext variable_sc;
|
||||
CalculateSymbolContext (&variable_sc);
|
||||
if (variable_sc.function && variable_sc.block)
|
||||
return variable_sc.block->ContainsBlockWithID (frame_block->GetID());
|
||||
return variable_sc.block->FindBlockByID(frame_block->GetID()) != NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -280,7 +280,7 @@ StackFrame::GetVariableList ()
|
|||
{
|
||||
bool get_child_variables = true;
|
||||
bool can_create = true;
|
||||
m_variable_list_sp = m_sc.function->GetBlocks(can_create).GetVariableList (Block::RootID, get_child_variables, can_create);
|
||||
m_variable_list_sp = m_sc.function->GetBlock (can_create).GetVariableList (get_child_variables, can_create);
|
||||
}
|
||||
}
|
||||
return m_variable_list_sp.get();
|
||||
|
|
Loading…
Reference in New Issue