2010-06-09 00:52:24 +08:00
|
|
|
//===-- ABISysV_x86_64.cpp --------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "ABISysV_x86_64.h"
|
|
|
|
|
|
|
|
#include "lldb/Core/ConstString.h"
|
|
|
|
#include "lldb/Core/DataExtractor.h"
|
|
|
|
#include "lldb/Core/Error.h"
|
2010-10-08 09:58:41 +08:00
|
|
|
#include "lldb/Core/Log.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Core/Module.h"
|
|
|
|
#include "lldb/Core/PluginManager.h"
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
#include "lldb/Core/RegisterValue.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Core/Value.h"
|
|
|
|
#include "lldb/Symbol/ClangASTContext.h"
|
2011-05-12 02:39:18 +08:00
|
|
|
#include "lldb/Symbol/UnwindPlan.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
#include "lldb/Target/Process.h"
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
#include "lldb/Target/StackFrame.h"
|
|
|
|
#include "lldb/Target/Thread.h"
|
|
|
|
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
static const char *pluginName = "ABISysV_x86_64";
|
|
|
|
static const char *pluginDesc = "System V ABI for x86_64 targets";
|
|
|
|
static const char *pluginShort = "abi.sysv-x86_64";
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
size_t
|
|
|
|
ABISysV_x86_64::GetRedZoneSize () const
|
|
|
|
{
|
|
|
|
return 128;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
// Static Functions
|
|
|
|
//------------------------------------------------------------------
|
2011-05-12 02:39:18 +08:00
|
|
|
ABISP
|
2011-02-16 05:59:32 +08:00
|
|
|
ABISysV_x86_64::CreateInstance (const ArchSpec &arch)
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2011-05-12 02:39:18 +08:00
|
|
|
static ABISP g_abi_sp;
|
2011-02-16 05:59:32 +08:00
|
|
|
if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
|
2011-05-12 02:39:18 +08:00
|
|
|
{
|
|
|
|
if (!g_abi_sp)
|
|
|
|
g_abi_sp.reset (new ABISysV_x86_64);
|
|
|
|
return g_abi_sp;
|
|
|
|
}
|
|
|
|
return ABISP();
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
|
|
|
|
lldb::addr_t sp,
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
lldb::addr_t func_addr,
|
|
|
|
lldb::addr_t return_addr,
|
|
|
|
lldb::addr_t *arg1_ptr,
|
|
|
|
lldb::addr_t *arg2_ptr,
|
|
|
|
lldb::addr_t *arg3_ptr) const
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-11-06 09:53:30 +08:00
|
|
|
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2010-10-08 09:58:41 +08:00
|
|
|
|
|
|
|
if (log)
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
log->Printf("ABISysV_x86_64::PrepareTrivialCall\n(\n thread = %p\n sp = 0x%llx\n func_addr = 0x%llx\n return_addr = 0x%llx\n arg1_ptr = %p (0x%llx)\n arg2_ptr = %p (0x%llx)\n arg3_ptr = %p (0x%llx)\n)",
|
2010-10-08 09:58:41 +08:00
|
|
|
(void*)&thread,
|
|
|
|
(uint64_t)sp,
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
(uint64_t)func_addr,
|
|
|
|
(uint64_t)return_addr,
|
|
|
|
arg1_ptr, arg1_ptr ? (uint64_t)*arg1_ptr : (uint64_t) 0,
|
|
|
|
arg2_ptr, arg2_ptr ? (uint64_t)*arg2_ptr : (uint64_t) 0,
|
|
|
|
arg3_ptr, arg3_ptr ? (uint64_t)*arg3_ptr : (uint64_t) 0);
|
2010-10-08 09:58:41 +08:00
|
|
|
|
2011-01-07 06:15:06 +08:00
|
|
|
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
|
2010-06-09 00:52:24 +08:00
|
|
|
if (!reg_ctx)
|
|
|
|
return false;
|
2010-09-08 05:23:34 +08:00
|
|
|
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
RegisterValue reg_value;
|
|
|
|
if (arg1_ptr)
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
{
|
2010-10-08 09:58:41 +08:00
|
|
|
if (log)
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
log->Printf("About to write arg1 (0x%llx) into RDI", (uint64_t)*arg1_ptr);
|
|
|
|
|
|
|
|
reg_value.SetUInt64(*arg1_ptr);
|
|
|
|
if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName("rdi", 0), reg_value))
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
return false;
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
|
|
|
|
if (arg2_ptr)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("About to write arg2 (0x%llx) into RSI", (uint64_t)*arg2_ptr);
|
|
|
|
|
|
|
|
reg_value.SetUInt64(*arg2_ptr);
|
|
|
|
if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName("rsi", 0), reg_value))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (arg3_ptr)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("About to write arg3 (0x%llx) into RDX", (uint64_t)*arg3_ptr);
|
|
|
|
reg_value.SetUInt64(*arg3_ptr);
|
|
|
|
if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName("rdx", 0), reg_value))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
Removed the hacky "#define this ___clang_this" handler
for C++ classes. Replaced it with a less hacky approach:
- If an expression is defined in the context of a
method of class A, then that expression is wrapped as
___clang_class::___clang_expr(void*) { ... }
instead of ___clang_expr(void*) { ... }.
- ___clang_class is resolved as the type of the target
of the "this" pointer in the method the expression
is defined in.
- When reporting the type of ___clang_class, a method
with the signature ___clang_expr(void*) is added to
that class, so that Clang doesn't complain about a
method being defined without a corresponding
declaration.
- Whenever the expression gets called, "this" gets
looked up, type-checked, and then passed in as the
first argument.
This required the following changes:
- The ABIs were changed to support passing of the "this"
pointer as part of trivial calls.
- ThreadPlanCallFunction and ClangFunction were changed
to support passing of an optional "this" pointer.
- ClangUserExpression was extended to perform the
wrapping described above.
- ClangASTSource was changed to revert the changes
required by the hack.
- ClangExpressionParser, IRForTarget, and
ClangExpressionDeclMap were changed to handle
different manglings of ___clang_expr flexibly. This
meant no longer searching for a function called
___clang_expr, but rather looking for a function whose
name *contains* ___clang_expr.
- ClangExpressionParser and ClangExpressionDeclMap now
remember whether "this" is required, and know how to
look it up as necessary.
A few inheritance bugs remain, and I'm trying to resolve
these. But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.
llvm-svn: 114384
2010-09-21 08:44:12 +08:00
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
// First, align the SP
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
|
2010-10-08 09:58:41 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("16-byte aligning SP: 0x%llx to 0x%llx", (uint64_t)sp, (uint64_t)(sp & ~0xfull));
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
sp &= ~(0xfull); // 16-byte alignment
|
|
|
|
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
// The return address is pushed onto the stack (yes after the alignment...)
|
2010-06-09 00:52:24 +08:00
|
|
|
sp -= 8;
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
|
|
|
|
reg_value.SetUInt64 (return_addr);
|
|
|
|
|
2010-10-08 09:58:41 +08:00
|
|
|
if (log)
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
log->Printf("Pushing the return address onto the stack: new SP 0x%llx, return address 0x%llx", (uint64_t)sp, (uint64_t)return_addr);
|
|
|
|
|
|
|
|
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfoByName("rip");
|
|
|
|
Error error (reg_ctx->WriteRegisterValueToMemory(pc_reg_info, sp, pc_reg_info->byte_size, reg_value));
|
|
|
|
if (error.Fail())
|
2010-06-09 00:52:24 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// %rsp is set to the actual stack value.
|
|
|
|
|
2010-10-08 09:58:41 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf("Writing SP (0x%llx) down", (uint64_t)sp);
|
|
|
|
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
reg_value.SetUInt64(sp);
|
|
|
|
if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("rsp"), reg_value))
|
2010-06-09 00:52:24 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// %rip is set to the address of the called function.
|
2010-10-08 09:58:41 +08:00
|
|
|
|
|
|
|
if (log)
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
log->Printf("Writing new IP (0x%llx) down", (uint64_t)func_addr);
|
|
|
|
|
|
|
|
reg_value.SetUInt64(func_addr);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
Cleaned up the ABI::PrepareTrivialCall() function to take three argument
pointers:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t *arg1_ptr,
lldb::addr_t *arg2_ptr,
lldb::addr_t *arg3_ptr) const = 0;
Prior to this it was:
virtual bool
PrepareTrivialCall (Thread &thread,
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
This was because the function that called this slowly added more features to
be able to call a C++ member function that might have a "this" pointer, and
then later added "self + cmd" support for objective C. Cleaning this code up
and the code that calls it makes it easier to implement the functions for
new targets.
The MacOSX_arm::PrepareTrivialCall() is now filled in and ready for testing.
llvm-svn: 131221
2011-05-12 10:14:56 +08:00
|
|
|
if (!reg_ctx->WriteRegister(pc_reg_info, func_addr))
|
2010-06-09 00:52:24 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ReadIntegerArgument(Scalar &scalar,
|
|
|
|
unsigned int bit_width,
|
|
|
|
bool is_signed,
|
|
|
|
Thread &thread,
|
|
|
|
uint32_t *argument_register_ids,
|
|
|
|
unsigned int ¤t_argument_register,
|
|
|
|
addr_t ¤t_stack_argument)
|
|
|
|
{
|
|
|
|
if (bit_width > 64)
|
|
|
|
return false; // Scalar can't hold large integer arguments
|
|
|
|
|
|
|
|
uint64_t arg_contents;
|
|
|
|
|
|
|
|
if (current_argument_register < 6)
|
|
|
|
{
|
|
|
|
arg_contents = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
|
|
|
|
current_argument_register++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
uint8_t arg_data[sizeof(arg_contents)];
|
|
|
|
Error error;
|
|
|
|
thread.GetProcess().ReadMemory(current_stack_argument, arg_data, sizeof(arg_contents), error);
|
2011-02-16 05:59:32 +08:00
|
|
|
DataExtractor arg_data_extractor (arg_data, sizeof(arg_contents),
|
|
|
|
thread.GetProcess().GetTarget().GetArchitecture().GetByteOrder(),
|
|
|
|
thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize());
|
2010-06-09 00:52:24 +08:00
|
|
|
uint32_t offset = 0;
|
|
|
|
arg_contents = arg_data_extractor.GetMaxU64(&offset, bit_width / 8);
|
|
|
|
if (!offset)
|
|
|
|
return false;
|
|
|
|
current_stack_argument += (bit_width / 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_signed)
|
|
|
|
{
|
|
|
|
switch (bit_width)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case 8:
|
|
|
|
scalar = (int8_t)(arg_contents & 0xff);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
scalar = (int16_t)(arg_contents & 0xffff);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
scalar = (int32_t)(arg_contents & 0xffffffff);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
scalar = (int64_t)arg_contents;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (bit_width)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
case 8:
|
|
|
|
scalar = (uint8_t)(arg_contents & 0xff);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
scalar = (uint16_t)(arg_contents & 0xffff);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
scalar = (uint32_t)(arg_contents & 0xffffffff);
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
scalar = (uint64_t)arg_contents;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::GetArgumentValues (Thread &thread,
|
|
|
|
ValueList &values) const
|
|
|
|
{
|
|
|
|
unsigned int num_values = values.GetSize();
|
|
|
|
unsigned int value_index;
|
|
|
|
|
|
|
|
// For now, assume that the types in the AST values come from the Target's
|
|
|
|
// scratch AST.
|
|
|
|
|
|
|
|
clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
|
|
|
|
|
|
|
|
// Extract the register context so we can read arguments from registers
|
|
|
|
|
2011-01-07 06:15:06 +08:00
|
|
|
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
if (!reg_ctx)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Get the pointer to the first stack argument so we have a place to start
|
|
|
|
// when reading data
|
|
|
|
|
|
|
|
addr_t sp = reg_ctx->GetSP(0);
|
|
|
|
|
|
|
|
if (!sp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
addr_t current_stack_argument = sp + 8; // jump over return address
|
|
|
|
|
|
|
|
uint32_t argument_register_ids[6];
|
|
|
|
|
2010-09-10 15:49:16 +08:00
|
|
|
argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
|
|
|
|
argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
|
|
|
|
argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
|
|
|
|
argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->kinds[eRegisterKindLLDB];
|
|
|
|
argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->kinds[eRegisterKindLLDB];
|
|
|
|
argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->kinds[eRegisterKindLLDB];
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
unsigned int current_argument_register = 0;
|
|
|
|
|
|
|
|
for (value_index = 0;
|
|
|
|
value_index < num_values;
|
|
|
|
++value_index)
|
|
|
|
{
|
|
|
|
Value *value = values.GetValueAtIndex(value_index);
|
|
|
|
|
|
|
|
if (!value)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We currently only support extracting values with Clang QualTypes.
|
|
|
|
// Do we care about others?
|
|
|
|
switch (value->GetContextType())
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
return false;
|
2010-11-13 11:52:47 +08:00
|
|
|
case Value::eContextTypeClangType:
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-09-29 09:12:09 +08:00
|
|
|
void *value_type = value->GetClangType();
|
2010-06-09 00:52:24 +08:00
|
|
|
bool is_signed;
|
|
|
|
|
|
|
|
if (ClangASTContext::IsIntegerType (value_type, is_signed))
|
|
|
|
{
|
2010-08-03 08:35:52 +08:00
|
|
|
size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
ReadIntegerArgument(value->GetScalar(),
|
|
|
|
bit_width,
|
|
|
|
is_signed,
|
|
|
|
thread,
|
|
|
|
argument_register_ids,
|
|
|
|
current_argument_register,
|
|
|
|
current_stack_argument);
|
|
|
|
}
|
|
|
|
else if (ClangASTContext::IsPointerType (value_type))
|
|
|
|
{
|
|
|
|
ReadIntegerArgument(value->GetScalar(),
|
|
|
|
64,
|
|
|
|
false,
|
|
|
|
thread,
|
|
|
|
argument_register_ids,
|
|
|
|
current_argument_register,
|
|
|
|
current_stack_argument);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::GetReturnValue (Thread &thread,
|
|
|
|
Value &value) const
|
|
|
|
{
|
|
|
|
switch (value.GetContextType())
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
return false;
|
2010-11-13 11:52:47 +08:00
|
|
|
case Value::eContextTypeClangType:
|
2010-06-09 00:52:24 +08:00
|
|
|
{
|
2010-09-29 09:12:09 +08:00
|
|
|
void *value_type = value.GetClangType();
|
2010-06-09 00:52:24 +08:00
|
|
|
bool is_signed;
|
|
|
|
|
2011-01-07 06:15:06 +08:00
|
|
|
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
if (!reg_ctx)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (ClangASTContext::IsIntegerType (value_type, is_signed))
|
|
|
|
{
|
|
|
|
// For now, assume that the types in the AST values come from the Target's
|
|
|
|
// scratch AST.
|
|
|
|
|
|
|
|
clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
|
|
|
|
|
|
|
|
// Extract the register context so we can read arguments from registers
|
|
|
|
|
2010-08-03 08:35:52 +08:00
|
|
|
size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
|
2010-09-10 15:49:16 +08:00
|
|
|
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
switch (bit_width)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case 128:
|
|
|
|
// Scalar can't hold 128-bit literals, so we don't handle this
|
|
|
|
return false;
|
|
|
|
case 64:
|
|
|
|
if (is_signed)
|
|
|
|
value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
|
|
|
|
else
|
|
|
|
value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
if (is_signed)
|
|
|
|
value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
|
|
|
|
else
|
|
|
|
value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
if (is_signed)
|
|
|
|
value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
|
|
|
|
else
|
|
|
|
value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
if (is_signed)
|
|
|
|
value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
|
|
|
|
else
|
|
|
|
value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ClangASTContext::IsPointerType (value_type))
|
|
|
|
{
|
2010-09-10 15:49:16 +08:00
|
|
|
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
|
2010-06-09 00:52:24 +08:00
|
|
|
value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// not handled yet
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-05-12 02:39:18 +08:00
|
|
|
bool
|
|
|
|
ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
|
|
|
|
{
|
|
|
|
uint32_t reg_kind = unwind_plan.GetRegisterKind();
|
|
|
|
uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
|
|
|
|
uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
|
|
|
|
|
|
|
|
switch (reg_kind)
|
|
|
|
{
|
|
|
|
case eRegisterKindDWARF:
|
|
|
|
case eRegisterKindGCC:
|
|
|
|
sp_reg_num = gcc_dwarf_rsp;
|
|
|
|
pc_reg_num = gcc_dwarf_rip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eRegisterKindGDB:
|
|
|
|
sp_reg_num = gdb_rsp;
|
|
|
|
pc_reg_num = gdb_rip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eRegisterKindGeneric:
|
|
|
|
sp_reg_num = LLDB_REGNUM_GENERIC_SP;
|
|
|
|
pc_reg_num = LLDB_REGNUM_GENERIC_PC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp_reg_num == LLDB_INVALID_REGNUM ||
|
|
|
|
pc_reg_num == LLDB_INVALID_REGNUM)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
UnwindPlan::Row row;
|
|
|
|
row.SetCFARegister (sp_reg_num);
|
|
|
|
row.SetCFAOffset (8);
|
|
|
|
row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
|
|
|
|
unwind_plan.AppendRow (row);
|
|
|
|
unwind_plan.SetSourceName (pluginName);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
|
|
|
|
{
|
|
|
|
uint32_t reg_kind = unwind_plan.GetRegisterKind();
|
|
|
|
uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
|
|
|
|
uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
|
|
|
|
uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
|
|
|
|
|
|
|
|
switch (reg_kind)
|
|
|
|
{
|
|
|
|
case eRegisterKindDWARF:
|
|
|
|
case eRegisterKindGCC:
|
|
|
|
fp_reg_num = gcc_dwarf_rbp;
|
|
|
|
sp_reg_num = gcc_dwarf_rsp;
|
|
|
|
pc_reg_num = gcc_dwarf_rip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eRegisterKindGDB:
|
|
|
|
fp_reg_num = gdb_rbp;
|
|
|
|
sp_reg_num = gdb_rsp;
|
|
|
|
pc_reg_num = gdb_rip;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eRegisterKindGeneric:
|
|
|
|
fp_reg_num = LLDB_REGNUM_GENERIC_FP;
|
|
|
|
sp_reg_num = LLDB_REGNUM_GENERIC_SP;
|
|
|
|
pc_reg_num = LLDB_REGNUM_GENERIC_PC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fp_reg_num == LLDB_INVALID_REGNUM ||
|
|
|
|
sp_reg_num == LLDB_INVALID_REGNUM ||
|
|
|
|
pc_reg_num == LLDB_INVALID_REGNUM)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
UnwindPlan::Row row;
|
|
|
|
|
|
|
|
const int32_t ptr_size = 8;
|
|
|
|
row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
|
|
|
|
row.SetCFAOffset (2 * ptr_size);
|
|
|
|
row.SetOffset (0);
|
|
|
|
|
|
|
|
row.SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
|
|
|
|
row.SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
|
|
|
|
row.SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * 0, true);
|
|
|
|
|
|
|
|
unwind_plan.AppendRow (row);
|
|
|
|
unwind_plan.SetSourceName ("x86_64 default unwind plan");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info)
|
|
|
|
{
|
|
|
|
return !RegisterIsCalleeSaved (reg_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
|
|
|
|
{
|
|
|
|
if (reg_info)
|
|
|
|
{
|
|
|
|
// Volatile registers include: rbx, rbp, rsp, r12, r13, r14, r15, rip
|
|
|
|
const char *name = reg_info->name;
|
|
|
|
if (name[0] == 'r')
|
|
|
|
{
|
|
|
|
switch (name[1])
|
|
|
|
{
|
|
|
|
case '1': // r12, r13, r14, r15
|
|
|
|
if (name[2] >= '2' && name[2] <= '5')
|
|
|
|
return name[3] == '\0';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b': // rbp, rbx
|
|
|
|
if (name[2] == 'p' || name[2] == 'x')
|
|
|
|
return name[3] == '\0';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i': // rip
|
|
|
|
if (name[2] == 'p')
|
|
|
|
return name[3] == '\0';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's': // rsp
|
|
|
|
if (name[2] == 'p')
|
|
|
|
return name[3] == '\0';
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-06-09 00:52:24 +08:00
|
|
|
void
|
|
|
|
ABISysV_x86_64::Initialize()
|
|
|
|
{
|
|
|
|
PluginManager::RegisterPlugin (pluginName,
|
|
|
|
pluginDesc,
|
|
|
|
CreateInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ABISysV_x86_64::Terminate()
|
|
|
|
{
|
|
|
|
PluginManager::UnregisterPlugin (CreateInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
// PluginInterface protocol
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
const char *
|
|
|
|
ABISysV_x86_64::GetPluginName()
|
|
|
|
{
|
|
|
|
return pluginName;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
ABISysV_x86_64::GetShortPluginName()
|
|
|
|
{
|
|
|
|
return pluginShort;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
ABISysV_x86_64::GetPluginVersion()
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|