AppleObjCRuntimeV1.cpp revision ae2ae94bd72daf435204e99a0e03ccc64470a843
1//===-- AppleObjCRuntimeV1.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 "AppleObjCRuntimeV1.h" 11#include "AppleObjCTrampolineHandler.h" 12 13#include "llvm/Support/MachO.h" 14#include "clang/AST/Type.h" 15 16#include "lldb/Breakpoint/BreakpointLocation.h" 17#include "lldb/Core/ConstString.h" 18#include "lldb/Core/Error.h" 19#include "lldb/Core/Log.h" 20#include "lldb/Core/Module.h" 21#include "lldb/Core/PluginManager.h" 22#include "lldb/Core/Scalar.h" 23#include "lldb/Core/StreamString.h" 24#include "lldb/Expression/ClangFunction.h" 25#include "lldb/Expression/ClangUtilityFunction.h" 26#include "lldb/Symbol/ClangASTContext.h" 27#include "lldb/Target/ExecutionContext.h" 28#include "lldb/Target/Process.h" 29#include "lldb/Target/RegisterContext.h" 30#include "lldb/Target/Target.h" 31#include "lldb/Target/Thread.h" 32 33#include <vector> 34 35using namespace lldb; 36using namespace lldb_private; 37 38static const char *pluginName = "AppleObjCRuntimeV1"; 39static const char *pluginDesc = "Apple Objective C Language Runtime - Version 1"; 40static const char *pluginShort = "language.apple.objc.v1"; 41 42bool 43AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value, 44 lldb::DynamicValueType use_dynamic, 45 TypeAndOrName &class_type_or_name, 46 Address &address) 47{ 48 return false; 49} 50 51//------------------------------------------------------------------ 52// Static Functions 53//------------------------------------------------------------------ 54lldb_private::LanguageRuntime * 55AppleObjCRuntimeV1::CreateInstance (Process *process, lldb::LanguageType language) 56{ 57 // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make 58 // sure we aren't using the V1 runtime. 59 if (language == eLanguageTypeObjC) 60 { 61 ModuleSP objc_module_sp; 62 63 if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == eAppleObjC_V1) 64 return new AppleObjCRuntimeV1 (process); 65 else 66 return NULL; 67 } 68 else 69 return NULL; 70} 71 72void 73AppleObjCRuntimeV1::Initialize() 74{ 75 PluginManager::RegisterPlugin (pluginName, 76 pluginDesc, 77 CreateInstance); 78} 79 80void 81AppleObjCRuntimeV1::Terminate() 82{ 83 PluginManager::UnregisterPlugin (CreateInstance); 84} 85 86//------------------------------------------------------------------ 87// PluginInterface protocol 88//------------------------------------------------------------------ 89const char * 90AppleObjCRuntimeV1::GetPluginName() 91{ 92 return pluginName; 93} 94 95const char * 96AppleObjCRuntimeV1::GetShortPluginName() 97{ 98 return pluginShort; 99} 100 101uint32_t 102AppleObjCRuntimeV1::GetPluginVersion() 103{ 104 return 1; 105} 106 107BreakpointResolverSP 108AppleObjCRuntimeV1::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) 109{ 110 BreakpointResolverSP resolver_sp; 111 112 if (throw_bp) 113 resolver_sp.reset (new BreakpointResolverName (bkpt, 114 "objc_exception_throw", 115 eFunctionNameTypeBase, 116 Breakpoint::Exact, 117 eLazyBoolNo)); 118 // FIXME: don't do catch yet. 119 return resolver_sp; 120} 121 122struct BufStruct { 123 char contents[2048]; 124}; 125 126ClangUtilityFunction * 127AppleObjCRuntimeV1::CreateObjectChecker(const char *name) 128{ 129 std::auto_ptr<BufStruct> buf(new BufStruct); 130 131 assert(snprintf(&buf->contents[0], sizeof(buf->contents), 132 "struct __objc_class \n" 133 "{ \n" 134 " struct __objc_class *isa; \n" 135 " struct __objc_class *super_class; \n" 136 " const char *name; \n" 137 " // rest of struct elided because unused \n" 138 "}; \n" 139 " \n" 140 "struct __objc_object \n" 141 "{ \n" 142 " struct __objc_class *isa; \n" 143 "}; \n" 144 " \n" 145 "extern \"C\" void \n" 146 "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n" 147 "{ \n" 148 " struct __objc_object *obj = (struct __objc_object*)$__lldb_arg_obj; \n" 149 " (int)strlen(obj->isa->name); \n" 150 "} \n", 151 name) < sizeof(buf->contents)); 152 153 return new ClangUtilityFunction(buf->contents, name); 154} 155 156// this code relies on the assumption that an Objective-C object always starts 157// with an ISA at offset 0. 158ObjCLanguageRuntime::ObjCISA 159AppleObjCRuntimeV1::GetISA(ValueObject& valobj) 160{ 161 if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC) 162 return 0; 163 164 // if we get an invalid VO (which might still happen when playing around 165 // with pointers returned by the expression parser, don't consider this 166 // a valid ObjC object) 167 if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid) 168 return 0; 169 170 addr_t isa_pointer = valobj.GetPointerValue(); 171 172 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 173 174 Process *process = exe_ctx.GetProcessPtr(); 175 if (process) 176 { 177 uint8_t pointer_size = process->GetAddressByteSize(); 178 179 Error error; 180 return process->ReadUnsignedIntegerFromMemory (isa_pointer, 181 pointer_size, 182 0, 183 error); 184 } 185 return 0; 186} 187 188AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer) 189{ 190 ObjCISA ptr_value = isa_pointer.GetValueAsUnsigned(0); 191 192 lldb::ProcessSP process_sp = isa_pointer.GetProcessSP(); 193 194 Initialize (ptr_value,process_sp); 195} 196 197AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp) 198{ 199 Initialize (isa, process_sp); 200} 201 202void 203AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp) 204{ 205 if (!isa || !process_sp) 206 { 207 m_valid = false; 208 return; 209 } 210 211 m_valid = true; 212 213 Error error; 214 215 m_isa = process_sp->ReadPointerFromMemory(isa, error); 216 217 if (error.Fail()) 218 { 219 m_valid = false; 220 return; 221 } 222 223 uint32_t ptr_size = process_sp->GetAddressByteSize(); 224 225 if (!IsPointerValid(m_isa,ptr_size)) 226 { 227 m_valid = false; 228 return; 229 } 230 231 m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error); 232 233 if (error.Fail()) 234 { 235 m_valid = false; 236 return; 237 } 238 239 if (!IsPointerValid(m_parent_isa,ptr_size,true)) 240 { 241 m_valid = false; 242 return; 243 } 244 245 lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error); 246 247 if (error.Fail()) 248 { 249 m_valid = false; 250 return; 251 } 252 253 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 254 255 size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error); 256 257 if (error.Fail()) 258 { 259 m_valid = false; 260 return; 261 } 262 263 if (count) 264 m_name = ConstString((char*)buffer_sp->GetBytes()); 265 else 266 m_name = ConstString(); 267 268 m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error); 269 270 if (error.Fail()) 271 { 272 m_valid = false; 273 return; 274 } 275 276 m_process_wp = lldb::ProcessWP(process_sp); 277} 278 279AppleObjCRuntime::ClassDescriptorSP 280AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass () 281{ 282 if (!m_valid) 283 return NULL; 284 ProcessSP process_sp = m_process_wp.lock(); 285 if (!process_sp) 286 return NULL; 287 return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp)); 288} 289 290ObjCLanguageRuntime::ClassDescriptorSP 291AppleObjCRuntimeV1::GetClassDescriptor (ValueObject& in_value) 292{ 293 ObjCISA isa = GetISA(in_value); 294 295 ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa); 296 ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end(); 297 298 if (found != end && found->second) 299 return found->second; 300 301 ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(in_value)); 302 if (descriptor && descriptor->IsValid()) 303 m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor; 304 return descriptor; 305} 306 307ObjCLanguageRuntime::ClassDescriptorSP 308AppleObjCRuntimeV1::GetClassDescriptor (ObjCISA isa) 309{ 310 ObjCLanguageRuntime::ISAToDescriptorIterator found = m_isa_to_descriptor_cache.find(isa); 311 ObjCLanguageRuntime::ISAToDescriptorIterator end = m_isa_to_descriptor_cache.end(); 312 313 if (found != end && found->second) 314 return found->second; 315 316 ClassDescriptorSP descriptor = ClassDescriptorSP(new ClassDescriptorV1(isa,m_process->CalculateProcess())); 317 if (descriptor && descriptor->IsValid()) 318 m_isa_to_descriptor_cache[descriptor->GetISA()] = descriptor; 319 return descriptor; 320} 321