307 lines
9.7 KiB
C++
307 lines
9.7 KiB
C++
//===-- OperatingSystemDarwinKernel.cpp --------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "OperatingSystemDarwinKernel.h"
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "lldb/Core/ArchSpec.h"
|
|
#include "lldb/Core/DataBufferHeap.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Core/RegisterValue.h"
|
|
#include "lldb/Core/ValueObjectVariable.h"
|
|
#include "lldb/Symbol/ClangNamespaceDecl.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
#include "lldb/Symbol/VariableList.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/StopInfo.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Target/ThreadList.h"
|
|
#include "lldb/Target/Thread.h"
|
|
#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
|
|
#include "Plugins/Process/Utility/RegisterContextMemory.h"
|
|
#include "Plugins/Process/Utility/ThreadMemory.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
static ConstString &
|
|
GetThreadGPRMemberName ()
|
|
{
|
|
static ConstString g_gpr_member_name("gpr");
|
|
return g_gpr_member_name;
|
|
}
|
|
|
|
void
|
|
OperatingSystemDarwinKernel::Initialize()
|
|
{
|
|
PluginManager::RegisterPlugin (GetPluginNameStatic(),
|
|
GetPluginDescriptionStatic(),
|
|
CreateInstance);
|
|
}
|
|
|
|
void
|
|
OperatingSystemDarwinKernel::Terminate()
|
|
{
|
|
PluginManager::UnregisterPlugin (CreateInstance);
|
|
}
|
|
|
|
OperatingSystem *
|
|
OperatingSystemDarwinKernel::CreateInstance (Process *process, bool force)
|
|
{
|
|
#if 0
|
|
bool create = force;
|
|
if (!create)
|
|
{
|
|
Module* exe_module = process->GetTarget().GetExecutableModulePointer();
|
|
if (exe_module)
|
|
{
|
|
ObjectFile *object_file = exe_module->GetObjectFile();
|
|
if (object_file)
|
|
{
|
|
if (object_file->GetStrata() != ObjectFile::eStrataKernel)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// We can limit the creation of this plug-in to "*-apple-macosx" or "*-apple-ios" triples
|
|
// if we comment out the lines below...
|
|
// if (create)
|
|
// {
|
|
// const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
|
|
// create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple;
|
|
// }
|
|
}
|
|
|
|
if (create)
|
|
return new OperatingSystemDarwinKernel (process);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
|
|
const char *
|
|
OperatingSystemDarwinKernel::GetPluginNameStatic()
|
|
{
|
|
return "macosx-kernel";
|
|
}
|
|
|
|
const char *
|
|
OperatingSystemDarwinKernel::GetPluginDescriptionStatic()
|
|
{
|
|
return "Operating system plug-in that gathers OS information from darwin kernels.";
|
|
}
|
|
|
|
|
|
OperatingSystemDarwinKernel::OperatingSystemDarwinKernel (lldb_private::Process *process) :
|
|
OperatingSystem (process),
|
|
m_thread_list_valobj_sp (),
|
|
m_register_info_ap ()
|
|
{
|
|
}
|
|
|
|
OperatingSystemDarwinKernel::~OperatingSystemDarwinKernel ()
|
|
{
|
|
}
|
|
|
|
ValueObjectSP
|
|
OperatingSystemDarwinKernel::GetThreadListValueObject ()
|
|
{
|
|
if (m_thread_list_valobj_sp.get() == NULL)
|
|
{
|
|
VariableList variable_list;
|
|
const uint32_t max_matches = 1;
|
|
const bool append = true;
|
|
static ConstString g_thread_list_name("g_thread_list");
|
|
Module *exe_module = m_process->GetTarget().GetExecutableModulePointer();
|
|
if (exe_module)
|
|
{
|
|
if (exe_module->FindGlobalVariables (g_thread_list_name,
|
|
NULL,
|
|
append,
|
|
max_matches,
|
|
variable_list))
|
|
{
|
|
m_thread_list_valobj_sp = ValueObjectVariable::Create (m_process, variable_list.GetVariableAtIndex(0));
|
|
}
|
|
}
|
|
}
|
|
return m_thread_list_valobj_sp;
|
|
}
|
|
|
|
DynamicRegisterInfo *
|
|
OperatingSystemDarwinKernel::GetDynamicRegisterInfo ()
|
|
{
|
|
if (m_register_info_ap.get() == NULL && m_thread_list_valobj_sp)
|
|
{
|
|
m_register_info_ap.reset (new DynamicRegisterInfo());
|
|
ConstString empty_name;
|
|
const bool can_create = true;
|
|
AddressType addr_type;
|
|
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
|
ValueObjectSP gpr_valobj_sp (m_thread_list_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create));
|
|
|
|
if (gpr_valobj_sp->IsPointerType ())
|
|
base_addr = gpr_valobj_sp->GetPointerValue (&addr_type);
|
|
else
|
|
base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type);
|
|
|
|
ValueObjectSP child_valobj_sp;
|
|
if (gpr_valobj_sp)
|
|
{
|
|
ABI *abi = m_process->GetABI().get();
|
|
assert (abi);
|
|
uint32_t num_children = gpr_valobj_sp->GetNumChildren();
|
|
|
|
ConstString gpr_name (gpr_valobj_sp->GetName());
|
|
uint32_t reg_num = 0;
|
|
for (uint32_t i=0; i<num_children; ++i)
|
|
{
|
|
child_valobj_sp = gpr_valobj_sp->GetChildAtIndex(i, can_create);
|
|
|
|
ConstString reg_name(child_valobj_sp->GetName());
|
|
if (reg_name)
|
|
{
|
|
const char *reg_name_cstr = reg_name.GetCString();
|
|
while (reg_name_cstr[0] == '_')
|
|
++reg_name_cstr;
|
|
if (reg_name_cstr != reg_name.GetCString())
|
|
reg_name.SetCString (reg_name_cstr);
|
|
}
|
|
|
|
RegisterInfo reg_info;
|
|
if (abi->GetRegisterInfoByName(reg_name, reg_info))
|
|
{
|
|
// Adjust the byte size and the offset to match the layout of registers in our struct
|
|
reg_info.byte_size = child_valobj_sp->GetByteSize();
|
|
reg_info.byte_offset = child_valobj_sp->GetAddressOf(true, &addr_type) - base_addr;
|
|
reg_info.kinds[eRegisterKindLLDB] = reg_num++;
|
|
m_register_info_ap->AddRegister (reg_info, reg_name, empty_name, gpr_name);
|
|
}
|
|
else
|
|
{
|
|
printf ("not able to find register info for %s\n", reg_name.GetCString()); // REMOVE THIS printf before checkin!!!
|
|
}
|
|
}
|
|
|
|
m_register_info_ap->Finalize();
|
|
}
|
|
}
|
|
assert (m_register_info_ap.get());
|
|
return m_register_info_ap.get();
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// PluginInterface protocol
|
|
//------------------------------------------------------------------
|
|
const char *
|
|
OperatingSystemDarwinKernel::GetPluginName()
|
|
{
|
|
return "OperatingSystemDarwinKernel";
|
|
}
|
|
|
|
const char *
|
|
OperatingSystemDarwinKernel::GetShortPluginName()
|
|
{
|
|
return GetPluginNameStatic();
|
|
}
|
|
|
|
uint32_t
|
|
OperatingSystemDarwinKernel::GetPluginVersion()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
bool
|
|
OperatingSystemDarwinKernel::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
|
|
{
|
|
// Make any constant strings once and cache the uniqued C string values
|
|
// so we don't have to rehash them each time through this function call
|
|
static ConstString g_tid_member_name("tid");
|
|
static ConstString g_next_member_name("next");
|
|
|
|
ValueObjectSP root_valobj_sp (GetThreadListValueObject ());
|
|
ValueObjectSP valobj_sp = root_valobj_sp;
|
|
const bool can_create = true;
|
|
while (valobj_sp)
|
|
{
|
|
if (valobj_sp->GetValueAsUnsigned(0) == 0)
|
|
break;
|
|
|
|
ValueObjectSP tid_valobj_sp(valobj_sp->GetChildMemberWithName(g_tid_member_name, can_create));
|
|
if (!tid_valobj_sp)
|
|
break;
|
|
|
|
tid_t tid = tid_valobj_sp->GetValueAsUnsigned (LLDB_INVALID_THREAD_ID);
|
|
if (tid == LLDB_INVALID_THREAD_ID)
|
|
break;
|
|
|
|
ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
|
|
if (!thread_sp)
|
|
thread_sp.reset (new ThreadMemory (m_process->shared_from_this(), tid, valobj_sp));
|
|
|
|
new_thread_list.AddThread(thread_sp);
|
|
|
|
ValueObjectSP next_valobj_sp (valobj_sp->GetChildMemberWithName(g_next_member_name, can_create));
|
|
|
|
if (next_valobj_sp)
|
|
{
|
|
// Watch for circular linked lists
|
|
if (next_valobj_sp.get() == root_valobj_sp.get())
|
|
break;
|
|
}
|
|
next_valobj_sp.swap(valobj_sp);
|
|
}
|
|
return new_thread_list.GetSize(false) > 0;
|
|
}
|
|
|
|
void
|
|
OperatingSystemDarwinKernel::ThreadWasSelected (Thread *thread)
|
|
{
|
|
}
|
|
|
|
RegisterContextSP
|
|
OperatingSystemDarwinKernel::CreateRegisterContextForThread (Thread *thread)
|
|
{
|
|
ThreadMemory *generic_thread = (ThreadMemory *)thread;
|
|
RegisterContextSP reg_ctx_sp;
|
|
|
|
ValueObjectSP thread_valobj_sp (generic_thread->GetValueObject());
|
|
if (thread_valobj_sp)
|
|
{
|
|
const bool can_create = true;
|
|
AddressType addr_type;
|
|
addr_t base_addr = LLDB_INVALID_ADDRESS;
|
|
ValueObjectSP gpr_valobj_sp (thread_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create));
|
|
if (gpr_valobj_sp)
|
|
{
|
|
if (gpr_valobj_sp->IsPointerType ())
|
|
base_addr = gpr_valobj_sp->GetPointerValue (&addr_type);
|
|
else
|
|
base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type);
|
|
reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), base_addr));
|
|
}
|
|
}
|
|
return reg_ctx_sp;
|
|
}
|
|
|
|
StopInfoSP
|
|
OperatingSystemDarwinKernel::CreateThreadStopReason (lldb_private::Thread *thread)
|
|
{
|
|
StopInfoSP stop_info_sp; //(StopInfo::CreateStopReasonWithSignal (*thread, SIGSTOP));
|
|
return stop_info_sp;
|
|
}
|
|
|
|
|