for eh_frame and stabs register numberings. This is not complete but it's a step in the right direction. It's almost entirely mechanical. lldb informally uses "gcc register numbering" to mean eh_frame. Why? Probably because there's a notorious bug with gcc on i386 darwin where the register numbers in eh_frame were incorrect. In all other cases, eh_frame register numbering is identical to dwarf. lldb informally uses "gdb register numbering" to mean stabs. There are no official definitions of stabs register numbers for different architectures, so the implementations of gdb and gcc are the de facto reference source. There were some incorrect uses of these register number types in lldb already. I fixed the ones that I saw as I made this change. This commit changes all references to "gcc" and "gdb" register numbers in lldb to "eh_frame" and "stabs" to make it clear what is actually being represented. lldb cannot parse the stabs debug format, and given that no one is using stabs any more, it is unlikely that it ever will. A more comprehensive cleanup would remove the stabs register numbers altogether - it's unnecessary cruft / complication to all of our register structures. In ProcessGDBRemote, when we get register definitions from the gdb-remote stub, we expect to see "gcc:" (qRegisterInfo) or "gcc_regnum" (qXfer:features:read: packet to get xml payload). This patch changes ProcessGDBRemote to also accept "ehframe:" and "ehframe_regnum" from these remotes. I did not change GDBRemoteCommunicationServerLLGS or debugserver to send these new packets. I don't know what kind of interoperability constraints we might be working under. At some point in the future we should transition to using the more descriptive names. Throughout lldb we're still using enum names like "gcc_r0" and "gdb_r0", for eh_frame and stabs register numberings. These should be cleaned up eventually too. The sources link cleanly on macosx native with xcode build. I don't think we'll see problems on other platforms but please let me know if I broke anyone. llvm-svn: 245141
209 lines
6.3 KiB
C++
209 lines
6.3 KiB
C++
//===-- ABI.cpp -------------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Target/ABI.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Core/Value.h"
|
|
#include "lldb/Core/ValueObjectConstResult.h"
|
|
#include "lldb/Expression/ClangPersistentVariables.h"
|
|
#include "lldb/Symbol/CompilerType.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Target/Thread.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
ABISP
|
|
ABI::FindPlugin (const ArchSpec &arch)
|
|
{
|
|
ABISP abi_sp;
|
|
ABICreateInstance create_callback;
|
|
|
|
for (uint32_t idx = 0;
|
|
(create_callback = PluginManager::GetABICreateCallbackAtIndex(idx)) != NULL;
|
|
++idx)
|
|
{
|
|
abi_sp = create_callback(arch);
|
|
|
|
if (abi_sp)
|
|
return abi_sp;
|
|
}
|
|
abi_sp.reset();
|
|
return abi_sp;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Constructor
|
|
//----------------------------------------------------------------------
|
|
ABI::ABI()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//----------------------------------------------------------------------
|
|
ABI::~ABI()
|
|
{
|
|
}
|
|
|
|
bool
|
|
ABI::GetRegisterInfoByName (const ConstString &name, RegisterInfo &info)
|
|
{
|
|
uint32_t count = 0;
|
|
const RegisterInfo *register_info_array = GetRegisterInfoArray (count);
|
|
if (register_info_array)
|
|
{
|
|
const char *unique_name_cstr = name.GetCString();
|
|
uint32_t i;
|
|
for (i=0; i<count; ++i)
|
|
{
|
|
if (register_info_array[i].name == unique_name_cstr)
|
|
{
|
|
info = register_info_array[i];
|
|
return true;
|
|
}
|
|
}
|
|
for (i=0; i<count; ++i)
|
|
{
|
|
if (register_info_array[i].alt_name == unique_name_cstr)
|
|
{
|
|
info = register_info_array[i];
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
ABI::GetRegisterInfoByKind (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &info)
|
|
{
|
|
if (reg_kind < eRegisterKindEHFrame || reg_kind >= kNumRegisterKinds)
|
|
return false;
|
|
|
|
uint32_t count = 0;
|
|
const RegisterInfo *register_info_array = GetRegisterInfoArray (count);
|
|
if (register_info_array)
|
|
{
|
|
for (uint32_t i=0; i<count; ++i)
|
|
{
|
|
if (register_info_array[i].kinds[reg_kind] == reg_num)
|
|
{
|
|
info = register_info_array[i];
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
ValueObjectSP
|
|
ABI::GetReturnValueObject (Thread &thread,
|
|
CompilerType &ast_type,
|
|
bool persistent) const
|
|
{
|
|
if (!ast_type.IsValid())
|
|
return ValueObjectSP();
|
|
|
|
ValueObjectSP return_valobj_sp;
|
|
|
|
return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type);
|
|
if (!return_valobj_sp)
|
|
return return_valobj_sp;
|
|
|
|
// Now turn this into a persistent variable.
|
|
// FIXME: This code is duplicated from Target::EvaluateExpression, and it is used in similar form in a couple
|
|
// of other places. Figure out the correct Create function to do all this work.
|
|
|
|
if (persistent)
|
|
{
|
|
ClangPersistentVariables& persistent_variables = thread.CalculateTarget()->GetPersistentVariables();
|
|
ConstString persistent_variable_name (persistent_variables.GetNextPersistentVariableName());
|
|
|
|
lldb::ValueObjectSP const_valobj_sp;
|
|
|
|
// Check in case our value is already a constant value
|
|
if (return_valobj_sp->GetIsConstant())
|
|
{
|
|
const_valobj_sp = return_valobj_sp;
|
|
const_valobj_sp->SetName (persistent_variable_name);
|
|
}
|
|
else
|
|
const_valobj_sp = return_valobj_sp->CreateConstantValue (persistent_variable_name);
|
|
|
|
lldb::ValueObjectSP live_valobj_sp = return_valobj_sp;
|
|
|
|
return_valobj_sp = const_valobj_sp;
|
|
|
|
ClangExpressionVariableSP clang_expr_variable_sp(persistent_variables.CreatePersistentVariable(return_valobj_sp));
|
|
|
|
assert (clang_expr_variable_sp.get());
|
|
|
|
// Set flags and live data as appropriate
|
|
|
|
const Value &result_value = live_valobj_sp->GetValue();
|
|
|
|
switch (result_value.GetValueType())
|
|
{
|
|
case Value::eValueTypeHostAddress:
|
|
case Value::eValueTypeFileAddress:
|
|
// we don't do anything with these for now
|
|
break;
|
|
case Value::eValueTypeScalar:
|
|
case Value::eValueTypeVector:
|
|
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
|
|
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
|
|
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
|
|
break;
|
|
case Value::eValueTypeLoadAddress:
|
|
clang_expr_variable_sp->m_live_sp = live_valobj_sp;
|
|
clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
|
|
break;
|
|
}
|
|
|
|
return_valobj_sp = clang_expr_variable_sp->GetValueObject();
|
|
}
|
|
return return_valobj_sp;
|
|
}
|
|
|
|
ValueObjectSP
|
|
ABI::GetReturnValueObject(Thread &thread, llvm::Type &ast_type, bool persistent) const
|
|
{
|
|
ValueObjectSP return_valobj_sp;
|
|
return_valobj_sp = GetReturnValueObjectImpl( thread, ast_type );
|
|
return return_valobj_sp;
|
|
}
|
|
|
|
// specialized to work with llvm IR types
|
|
//
|
|
// for now we will specify a default implementation so that we don't need to
|
|
// modify other ABIs
|
|
lldb::ValueObjectSP
|
|
ABI::GetReturnValueObjectImpl( Thread &thread, llvm::Type &ir_type ) const
|
|
{
|
|
ValueObjectSP return_valobj_sp;
|
|
|
|
/* this is a dummy and will only be called if an ABI does not override this */
|
|
|
|
return return_valobj_sp;
|
|
}
|
|
|
|
bool
|
|
ABI::PrepareTrivialCall (Thread &thread,
|
|
lldb::addr_t sp,
|
|
lldb::addr_t functionAddress,
|
|
lldb::addr_t returnAddress,
|
|
llvm::Type &returntype,
|
|
llvm::ArrayRef<ABI::CallArgument> args) const
|
|
{
|
|
// dummy prepare trivial call
|
|
assert( !"Should never get here!" );
|
|
return false;
|
|
}
|