blob: f95e2ca335d02c0120d36fe5a624b95a5ffd9721 [file] [log] [blame]
Greg Clayton37f962e2011-08-22 02:49:39 +00001//===-- OperatingSystemMacOSXKernel.cpp --------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "OperatingSystemMacOSXKernel.h"
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14#include "llvm/ADT/Triple.h"
15
16#include "lldb/Core/ArchSpec.h"
17#include "lldb/Core/DataBufferHeap.h"
18#include "lldb/Core/Module.h"
19#include "lldb/Core/PluginManager.h"
20#include "lldb/Core/RegisterValue.h"
21#include "lldb/Core/ValueObjectVariable.h"
22#include "lldb/Symbol/ObjectFile.h"
23#include "lldb/Symbol/VariableList.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/StopInfo.h"
26#include "lldb/Target/Target.h"
27#include "lldb/Target/ThreadList.h"
28#include "lldb/Target/Thread.h"
29#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
30#include "Plugins/Process/Utility/RegisterContextMemory.h"
31#include "Plugins/Process/Utility/ThreadMemory.h"
32
33using namespace lldb;
34using namespace lldb_private;
35
36static ConstString &
37GetThreadGPRMemberName ()
38{
39 static ConstString g_gpr_member_name("gpr");
40 return g_gpr_member_name;
41}
42
43void
44OperatingSystemMacOSXKernel::Initialize()
45{
46 PluginManager::RegisterPlugin (GetPluginNameStatic(),
47 GetPluginDescriptionStatic(),
48 CreateInstance);
49}
50
51void
52OperatingSystemMacOSXKernel::Terminate()
53{
54 PluginManager::UnregisterPlugin (CreateInstance);
55}
56
57OperatingSystem *
58OperatingSystemMacOSXKernel::CreateInstance (Process *process, bool force)
59{
60#if 0
61 bool create = force;
62 if (!create)
63 {
64 Module* exe_module = process->GetTarget().GetExecutableModulePointer();
65 if (exe_module)
66 {
67 ObjectFile *object_file = exe_module->GetObjectFile();
68 if (object_file)
69 {
70 SectionList *section_list = object_file->GetSectionList();
71 if (section_list)
72 {
73 static ConstString g_kld_section_name ("__KLD");
74 if (section_list->FindSectionByName (g_kld_section_name))
75 {
76 create = true;
77 }
78 }
79 }
80 }
81
82 // We can limit the creation of this plug-in to "*-apple-darwin" triples
83 // if we command out the lines below...
84// if (create)
85// {
86// const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
87// create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple;
88// }
89 }
90
91 if (create)
92 return new OperatingSystemMacOSXKernel (process);
93#endif
94 return NULL;
95}
96
97
98const char *
99OperatingSystemMacOSXKernel::GetPluginNameStatic()
100{
101 return "macosx-kernel";
102}
103
104const char *
105OperatingSystemMacOSXKernel::GetPluginDescriptionStatic()
106{
107 return "Operating system plug-in that gathers OS information from darwin kernels.";
108}
109
110
111OperatingSystemMacOSXKernel::OperatingSystemMacOSXKernel (lldb_private::Process *process) :
112 OperatingSystem (process),
113 m_thread_list_valobj_sp (),
114 m_register_info_ap ()
115{
116}
117
118OperatingSystemMacOSXKernel::~OperatingSystemMacOSXKernel ()
119{
120}
121
122ValueObjectSP
123OperatingSystemMacOSXKernel::GetThreadListValueObject ()
124{
125 if (m_thread_list_valobj_sp.get() == NULL)
126 {
127 VariableList variable_list;
128 const uint32_t max_matches = 1;
129 const bool append = true;
130 static ConstString g_thread_list_name("g_thread_list");
131 Module *exe_module = m_process->GetTarget().GetExecutableModulePointer();
132 if (exe_module)
133 {
134 if (exe_module->FindGlobalVariables (g_thread_list_name,
135 append,
136 max_matches,
137 variable_list))
138 {
139 m_thread_list_valobj_sp = ValueObjectVariable::Create (m_process, variable_list.GetVariableAtIndex(0));
140 }
141 }
142 }
143 return m_thread_list_valobj_sp;
144}
145
146DynamicRegisterInfo *
147OperatingSystemMacOSXKernel::GetDynamicRegisterInfo ()
148{
149 if (m_register_info_ap.get() == NULL && m_thread_list_valobj_sp)
150 {
151 m_register_info_ap.reset (new DynamicRegisterInfo());
152 ConstString empty_name;
153 const bool can_create = true;
154 AddressType addr_type;
155 addr_t base_addr = LLDB_INVALID_ADDRESS;
156 ValueObjectSP gpr_valobj_sp (m_thread_list_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create));
157
158 if (gpr_valobj_sp->IsPointerType ())
159 base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true);
160 else
161 base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true);
162
163 ValueObjectSP child_valobj_sp;
164 if (gpr_valobj_sp)
165 {
166 ABI *abi = m_process->GetABI().get();
167 assert (abi);
168 uint32_t num_children = gpr_valobj_sp->GetNumChildren();
169
170 ConstString gpr_name (gpr_valobj_sp->GetName());
171 uint32_t reg_num = 0;
172 for (uint32_t i=0; i<num_children; ++i)
173 {
174 child_valobj_sp = gpr_valobj_sp->GetChildAtIndex(i, can_create);
175
176 ConstString reg_name(child_valobj_sp->GetName());
177 if (reg_name)
178 {
179 const char *reg_name_cstr = reg_name.GetCString();
180 while (reg_name_cstr[0] == '_')
181 ++reg_name_cstr;
182 if (reg_name_cstr != reg_name.GetCString())
183 reg_name.SetCString (reg_name_cstr);
184 }
185
186 RegisterInfo reg_info;
187 if (abi->GetRegisterInfoByName(reg_name, reg_info))
188 {
189 // Adjust the byte size and the offset to match the layout of registers in our struct
190 reg_info.byte_size = child_valobj_sp->GetByteSize();
191 reg_info.byte_offset = child_valobj_sp->GetAddressOf(addr_type, true) - base_addr;
192 reg_info.kinds[eRegisterKindLLDB] = reg_num++;
193 m_register_info_ap->AddRegister (reg_info, reg_name, empty_name, gpr_name);
194 }
195 else
196 {
197 printf ("not able to find register info for %s\n", reg_name.GetCString()); // REMOVE THIS printf before checkin!!!
198 }
199 }
200
201 m_register_info_ap->Finalize();
202 }
203 }
204 assert (m_register_info_ap.get());
205 return m_register_info_ap.get();
206}
207
208//------------------------------------------------------------------
209// PluginInterface protocol
210//------------------------------------------------------------------
211const char *
212OperatingSystemMacOSXKernel::GetPluginName()
213{
214 return "OperatingSystemMacOSXKernel";
215}
216
217const char *
218OperatingSystemMacOSXKernel::GetShortPluginName()
219{
220 return GetPluginNameStatic();
221}
222
223uint32_t
224OperatingSystemMacOSXKernel::GetPluginVersion()
225{
226 return 1;
227}
228
229uint32_t
230OperatingSystemMacOSXKernel::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
231{
232 // Make any constant strings once and cache the uniqued C string values
233 // so we don't have to rehash them each time through this function call
234 static ConstString g_tid_member_name("tid");
235 static ConstString g_next_member_name("next");
236
237 ValueObjectSP root_valobj_sp (GetThreadListValueObject ());
238 ValueObjectSP valobj_sp = root_valobj_sp;
239 const bool can_create = true;
240 while (valobj_sp)
241 {
242 if (valobj_sp->GetValueAsUnsigned(0) == 0)
243 break;
244
245 ValueObjectSP tid_valobj_sp(valobj_sp->GetChildMemberWithName(g_tid_member_name, can_create));
246 if (!tid_valobj_sp)
247 break;
248
249 tid_t tid = tid_valobj_sp->GetValueAsUnsigned (LLDB_INVALID_THREAD_ID);
250 if (tid == LLDB_INVALID_THREAD_ID)
251 break;
252
253 ThreadSP thread_sp (old_thread_list.FindThreadByID (tid, false));
254 if (!thread_sp)
255 thread_sp.reset (new ThreadMemory (*m_process, tid, valobj_sp));
256
257 new_thread_list.AddThread(thread_sp);
258
259 ValueObjectSP next_valobj_sp (valobj_sp->GetChildMemberWithName(g_next_member_name, can_create));
260
261 if (next_valobj_sp)
262 {
263 // Watch for circular linked lists
264 if (next_valobj_sp.get() == root_valobj_sp.get())
265 break;
266 }
267 next_valobj_sp.swap(valobj_sp);
268 }
269 return new_thread_list.GetSize(false);
270}
271
272void
273OperatingSystemMacOSXKernel::ThreadWasSelected (Thread *thread)
274{
275}
276
277RegisterContextSP
278OperatingSystemMacOSXKernel::CreateRegisterContextForThread (Thread *thread)
279{
280 ThreadMemory *generic_thread = (ThreadMemory *)thread;
281 RegisterContextSP reg_ctx_sp;
282
283 ValueObjectSP thread_valobj_sp (generic_thread->GetValueObject());
284 if (thread_valobj_sp)
285 {
286 const bool can_create = true;
287 AddressType addr_type;
288 addr_t base_addr = LLDB_INVALID_ADDRESS;
289 ValueObjectSP gpr_valobj_sp (thread_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create));
290 if (gpr_valobj_sp)
291 {
292 if (gpr_valobj_sp->IsPointerType ())
293 base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true);
294 else
295 base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true);
296 reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), base_addr));
297 }
298 }
299 return reg_ctx_sp;
300}
301
302StopInfoSP
303OperatingSystemMacOSXKernel::CreateThreadStopReason (lldb_private::Thread *thread)
304{
305 StopInfoSP stop_info_sp; //(StopInfo::CreateStopReasonWithSignal (*thread, SIGSTOP));
306 return stop_info_sp;
307}
308
309