forked from OSchip/llvm-project
Added a ClangUtilityFunction class that allows the
debugger to insert self-contained functions for use by expressions (mainly for error-checking). In order to support detecting whether a crash occurred in one of these helpers -- currently our preferred way of reporting that an error-check failed -- added a bit of support for getting the extent of a JITted function in addition to just its base. llvm-svn: 112324
This commit is contained in:
parent
38f6b7fe3b
commit
e71d553cd4
|
@ -41,6 +41,13 @@ class RecordingMemoryManager;
|
|||
class ClangExpression
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor
|
||||
//------------------------------------------------------------------
|
||||
virtual ~ClangExpression ()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the string that the parser should parse. Must be a full
|
||||
/// translation unit.
|
||||
|
|
|
@ -93,7 +93,12 @@ public:
|
|||
/// @param[out] func_addr
|
||||
/// The address to which the function has been written.
|
||||
///
|
||||
/// @para[in] exe_ctx
|
||||
/// @param[out] func_end
|
||||
/// The end of the function's allocated memory region. (func_addr
|
||||
/// and func_end do not delimit an allocated region; the allocated
|
||||
/// region may begin before func_addr.)
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to write the function into.
|
||||
///
|
||||
/// @return
|
||||
|
@ -101,7 +106,8 @@ public:
|
|||
/// Test with Success().
|
||||
//------------------------------------------------------------------
|
||||
Error
|
||||
MakeJIT (lldb::addr_t &func_addr,
|
||||
MakeJIT (lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
ExecutionContext &exe_ctx);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,11 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
ClangUserExpression (const char *expr);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Destructor
|
||||
//------------------------------------------------------------------
|
||||
virtual ~ClangUserExpression ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Parse the expression
|
||||
///
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_ClangUtilityFunction_h_
|
||||
#define liblldb_ClangUtilityFunction_h_
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
|
||||
#include "lldb/lldb-forward.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/ClangForward.h"
|
||||
#include "lldb/Expression/ClangExpression.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h"
|
||||
/// @brief Encapsulates a single expression for use with Clang
|
||||
///
|
||||
/// LLDB uses expressions for various purposes, notably to call functions
|
||||
/// and as a backend for the expr command. ClangUtilityFunction encapsulates
|
||||
/// a self-contained function meant to be used from other code. Utility
|
||||
/// functions can perform error-checking for ClangUserExpressions,
|
||||
//----------------------------------------------------------------------
|
||||
class ClangUtilityFunction : public ClangExpression
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
///
|
||||
/// @param[in] text
|
||||
/// The text of the function. Must be a full translation unit.
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The name of the function, as used in the text.
|
||||
//------------------------------------------------------------------
|
||||
ClangUtilityFunction (const char *text,
|
||||
const char *name);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Install the utility function into a process
|
||||
///
|
||||
/// @param[in] error_stream
|
||||
/// A stream to print parse errors and warnings to.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to install the utility function to.
|
||||
///
|
||||
/// @return
|
||||
/// True on success (no errors); false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
Install (Stream &error_stream, ExecutionContext &exe_ctx);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check whether the given PC is inside the function
|
||||
///
|
||||
/// Especially useful if the function dereferences NULL to indicate a failed
|
||||
/// assert.
|
||||
///
|
||||
/// @param[in] pc
|
||||
/// The program counter to check.
|
||||
///
|
||||
/// @return
|
||||
/// True if the program counter falls within the function's bounds;
|
||||
/// false if not (or the function is not JIT compiled)
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
ContainsAddress (lldb::addr_t address)
|
||||
{
|
||||
// nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS,
|
||||
// so this always returns false if the function is not JIT compiled yet
|
||||
return (address >= m_jit_begin && address < m_jit_end);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the address of the function's JIT-compiled code, or
|
||||
/// LLDB_INVALID_ADDRESS if the function is not JIT compiled
|
||||
//------------------------------------------------------------------
|
||||
lldb::addr_t
|
||||
StartAddress ()
|
||||
{
|
||||
return m_jit_begin;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the string that the parser should parse. Must be a full
|
||||
/// translation unit.
|
||||
//------------------------------------------------------------------
|
||||
const char *
|
||||
Text ()
|
||||
{
|
||||
return m_function_text.c_str();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the function name that should be used for executing the
|
||||
/// expression. Text() should contain the definition of this
|
||||
/// function.
|
||||
//------------------------------------------------------------------
|
||||
const char *
|
||||
FunctionName ()
|
||||
{
|
||||
return m_function_name.c_str();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the object that the parser should use when resolving external
|
||||
/// values. May be NULL if everything should be self-contained.
|
||||
//------------------------------------------------------------------
|
||||
ClangExpressionDeclMap *
|
||||
DeclMap ()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the object that the parser should use when registering
|
||||
/// local variables. May be NULL if the Expression doesn't care.
|
||||
//------------------------------------------------------------------
|
||||
ClangExpressionVariableStore *
|
||||
LocalVariables ()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the object that the parser should allow to access ASTs.
|
||||
/// May be NULL if the ASTs do not need to be transformed.
|
||||
///
|
||||
/// @param[in] passthrough
|
||||
/// The ASTConsumer that the returned transformer should send
|
||||
/// the ASTs to after transformation.
|
||||
//------------------------------------------------------------------
|
||||
clang::ASTConsumer *
|
||||
ASTTransformer (clang::ASTConsumer *passthrough)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the stream that the parser should use to write DWARF
|
||||
/// opcodes.
|
||||
//------------------------------------------------------------------
|
||||
StreamString &
|
||||
DwarfOpcodeStream ()
|
||||
{
|
||||
return *((StreamString*)NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
|
||||
std::string m_function_name; ///< The name of the function.
|
||||
|
||||
lldb::addr_t m_jit_begin; ///< The address of the JITted code. LLDB_INVALID_ADDRESS if invalid.
|
||||
lldb::addr_t m_jit_end; ///< The end of the JITted code. LLDB_INVALID_ADDRESS if invalid.
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_ClangUtilityFunction_h_
|
|
@ -52,7 +52,9 @@ namespace lldb_private {
|
|||
//----------------------------------------------------------------------
|
||||
class RecordingMemoryManager : public llvm::JITMemoryManager
|
||||
{
|
||||
friend Error ClangExpressionParser::MakeJIT (uint64_t &, ExecutionContext &);
|
||||
friend Error ClangExpressionParser::MakeJIT (uint64_t &,
|
||||
uint64_t&,
|
||||
ExecutionContext &);
|
||||
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -336,6 +336,8 @@
|
|||
49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; };
|
||||
49445C2A12245E5500C11A81 /* ClangExpressionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 49445C2912245E5500C11A81 /* ClangExpressionParser.h */; };
|
||||
49445E351225AB6A00C11A81 /* ClangUserExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 49445E341225AB6A00C11A81 /* ClangUserExpression.h */; };
|
||||
497C86BE122823D800B54702 /* ClangUtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */; };
|
||||
497C86C2122823F300B54702 /* ClangUtilityFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 497C86C1122823F300B54702 /* ClangUtilityFunction.h */; };
|
||||
49A8A3A011D568A300AD3B68 /* ASTResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ASTResultSynthesizer.cpp */; };
|
||||
49A8A3A411D568BF00AD3B68 /* ASTResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */; };
|
||||
49BB309611F79450001A4197 /* TaggedASTType.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BB309511F79450001A4197 /* TaggedASTType.h */; };
|
||||
|
@ -919,6 +921,8 @@
|
|||
495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = "<group>"; };
|
||||
497650CE11A21BEE008DDB57 /* ABIMacOSX_i386.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABIMacOSX_i386.cpp; path = "ABI/MacOSX-i386/ABIMacOSX_i386.cpp"; sourceTree = "<group>"; };
|
||||
497650CF11A21BEE008DDB57 /* ABIMacOSX_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABIMacOSX_i386.h; path = "ABI/MacOSX-i386/ABIMacOSX_i386.h"; sourceTree = "<group>"; };
|
||||
497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangUtilityFunction.cpp; path = source/Expression/ClangUtilityFunction.cpp; sourceTree = "<group>"; };
|
||||
497C86C1122823F300B54702 /* ClangUtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangUtilityFunction.h; path = include/lldb/Expression/ClangUtilityFunction.h; sourceTree = "<group>"; };
|
||||
497E7B331188ED300065CCA1 /* ABI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ABI.h; path = include/lldb/Target/ABI.h; sourceTree = "<group>"; };
|
||||
497E7B9D1188F6690065CCA1 /* ABI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ABI.cpp; path = source/Target/ABI.cpp; sourceTree = "<group>"; };
|
||||
499F381E11A5B3F300F5CE02 /* CommandObjectArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectArgs.h; path = source/Commands/CommandObjectArgs.h; sourceTree = "<group>"; };
|
||||
|
@ -1854,8 +1858,6 @@
|
|||
49D7072611B5AD03001AD875 /* ClangASTSource.h */,
|
||||
49D7072811B5AD11001AD875 /* ClangASTSource.cpp */,
|
||||
26BC7DC010F1B79500F91463 /* ClangExpression.h */,
|
||||
49445E341225AB6A00C11A81 /* ClangUserExpression.h */,
|
||||
26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */,
|
||||
4C98D3E0118FB98F00E575D0 /* ClangFunction.h */,
|
||||
4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */,
|
||||
49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */,
|
||||
|
@ -1866,6 +1868,10 @@
|
|||
26BC7ED610F1B86700F91463 /* ClangExpressionVariable.cpp */,
|
||||
49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */,
|
||||
49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */,
|
||||
49445E341225AB6A00C11A81 /* ClangUserExpression.h */,
|
||||
26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */,
|
||||
497C86C1122823F300B54702 /* ClangUtilityFunction.h */,
|
||||
497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */,
|
||||
26BC7DC310F1B79500F91463 /* DWARFExpression.h */,
|
||||
26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */,
|
||||
49A8A3A311D568BF00AD3B68 /* ASTResultSynthesizer.h */,
|
||||
|
@ -2243,6 +2249,7 @@
|
|||
49445C2A12245E5500C11A81 /* ClangExpressionParser.h in Headers */,
|
||||
49445E351225AB6A00C11A81 /* ClangUserExpression.h in Headers */,
|
||||
4911934C1226383D00578B7F /* ASTStructExtractor.h in Headers */,
|
||||
497C86C2122823F300B54702 /* ClangUtilityFunction.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2700,6 +2707,7 @@
|
|||
49FB515E121481B000DF8983 /* DWARFExpression.cpp in Sources */,
|
||||
49445C2612245E3600C11A81 /* ClangExpressionParser.cpp in Sources */,
|
||||
491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */,
|
||||
497C86BE122823D800B54702 /* ClangUtilityFunction.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -369,7 +369,9 @@ ClangExpressionParser::MakeDWARF ()
|
|||
}
|
||||
|
||||
Error
|
||||
ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, ExecutionContext &exe_ctx)
|
||||
ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
ExecutionContext &exe_ctx)
|
||||
{
|
||||
Error err;
|
||||
|
||||
|
@ -507,7 +509,10 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, ExecutionContext &exe_c
|
|||
(*pos).m_remote_addr = m_jit_mm->GetRemoteAddressForLocal ((*pos).m_local_addr);
|
||||
|
||||
if (!(*pos).m_name.compare(m_expr.FunctionName()))
|
||||
{
|
||||
func_end = m_jit_mm->GetRemoteRangeForLocal ((*pos).m_local_addr).second;
|
||||
func_addr = (*pos).m_remote_addr;
|
||||
}
|
||||
}
|
||||
|
||||
err.Clear();
|
||||
|
|
|
@ -227,7 +227,9 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
|
|||
if (m_JITted)
|
||||
return true;
|
||||
|
||||
Error jit_error = m_parser->MakeJIT(m_wrapper_function_addr, exe_ctx);
|
||||
lldb::addr_t wrapper_function_end;
|
||||
|
||||
Error jit_error = m_parser->MakeJIT(m_wrapper_function_addr, wrapper_function_end, exe_ctx);
|
||||
|
||||
if (!jit_error.Success())
|
||||
return false;
|
||||
|
|
|
@ -45,6 +45,10 @@ ClangUserExpression::ClangUserExpression (const char *expr) :
|
|||
m_transformed_text = m_transformed_stream.GetData();
|
||||
}
|
||||
|
||||
ClangUserExpression::~ClangUserExpression ()
|
||||
{
|
||||
}
|
||||
|
||||
clang::ASTConsumer *
|
||||
ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
|
||||
{
|
||||
|
@ -123,7 +127,9 @@ ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
|
|||
|
||||
m_dwarf_opcodes.reset();
|
||||
|
||||
Error jit_error = parser.MakeJIT (m_jit_addr, exe_ctx);
|
||||
lldb::addr_t jit_end;
|
||||
|
||||
Error jit_error = parser.MakeJIT (m_jit_addr, jit_end, exe_ctx);
|
||||
|
||||
if (jit_error.Success())
|
||||
{
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
//===-- ClangUserExpression.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
|
||||
#include <stdio.h>
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
// C++ Includes
|
||||
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Expression/ClangExpressionParser.h"
|
||||
#include "lldb/Expression/ClangUtilityFunction.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Constructor
|
||||
///
|
||||
/// @param[in] text
|
||||
/// The text of the function. Must be a full translation unit.
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The name of the function, as used in the text.
|
||||
//------------------------------------------------------------------
|
||||
ClangUtilityFunction::ClangUtilityFunction (const char *text,
|
||||
const char *name) :
|
||||
m_function_text(text),
|
||||
m_function_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Install the utility function into a process
|
||||
///
|
||||
/// @param[in] error_stream
|
||||
/// A stream to print parse errors and warnings to.
|
||||
///
|
||||
/// @param[in] exe_ctx
|
||||
/// The execution context to install the utility function to.
|
||||
///
|
||||
/// @return
|
||||
/// True on success (no errors); false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
ClangUtilityFunction::Install (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx)
|
||||
{
|
||||
////////////////////////////////////
|
||||
// Set up the target and compiler
|
||||
//
|
||||
|
||||
Target *target = exe_ctx.target;
|
||||
|
||||
if (!target)
|
||||
{
|
||||
error_stream.PutCString ("error: invalid target\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstString target_triple;
|
||||
|
||||
target->GetTargetTriple (target_triple);
|
||||
|
||||
if (!target_triple)
|
||||
target_triple = Host::GetTargetTriple ();
|
||||
|
||||
if (!target_triple)
|
||||
{
|
||||
error_stream.PutCString ("error: invalid target triple\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Parse the expression
|
||||
//
|
||||
|
||||
ClangExpressionParser parser(target_triple.GetCString(), *this);
|
||||
|
||||
unsigned num_errors = parser.Parse (error_stream);
|
||||
|
||||
if (num_errors)
|
||||
{
|
||||
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// JIT the output of the parser
|
||||
//
|
||||
|
||||
Error jit_error = parser.MakeJIT (m_jit_begin, m_jit_end, exe_ctx);
|
||||
|
||||
if (jit_error.Success())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue