AppleObjCTrampolineHandler.cpp revision 289afcb5e26c2527a0d2e71f84e780b86bbcf90a
1b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleObjCTrampolineHandler.h" 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes 16b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleThreadPlanStepThroughObjCTrampoline.h" 17b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham 184f385f181467701d2c5225f2c954ed5771e0763fJim Ingham#include "lldb/Breakpoint/StoppointCallbackContext.h" 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ConstString.h" 204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham#include "lldb/Core/Debugger.h" 215f54ac373b119a4c6693e4875c48aa761fba0c86Greg Clayton#include "lldb/Host/FileSpec.h" 22b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Log.h" 23b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Module.h" 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Value.h" 256e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangExpression.h" 266e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangFunction.h" 276e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangUtilityFunction.h" 286e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton 29b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Symbol/ClangASTContext.h" 30b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/ObjCLanguageRuntime.h" 31b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Process.h" 32b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/RegisterContext.h" 33b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Target.h" 34b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Thread.h" 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ExecutionContext.h" 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanRunToAddress.h" 3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 38ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar#include "llvm/ADT/STLExtras.h" 39ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar 4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb; 4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private; 4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 436507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector"; 446507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = " \n\ 456507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamextern \"C\" \n\ 466507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham{ \n\ 476507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\ 486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham extern void *class_getMethodImplementation_stret(void *objc_class, void *sel); \n\ 496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham extern void * sel_getUid(char *name); \n\ 506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham extern int printf(const char *format, ...); \n\ 516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham} \n\ 526507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamextern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\ 536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *sel, \n\ 546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int is_stret, \n\ 556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int is_super, \n\ 566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int is_super2, \n\ 576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int is_fixup, \n\ 586507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int is_fixed, \n\ 596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham int debug) \n\ 606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham{ \n\ 616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_imp_return_struct \n\ 626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 636507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *class_addr; \n\ 646507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *sel_addr; \n\ 656507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *impl_addr; \n\ 666507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham }; \n\ 676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_objc_class { \n\ 696507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *isa; \n\ 706507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *super_ptr; \n\ 716507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham }; \n\ 726507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_objc_super { \n\ 736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *reciever; \n\ 746507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_objc_class *class_ptr; \n\ 756507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham }; \n\ 766507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_msg_ref { \n\ 776507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *dont_know; \n\ 786507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *sel; \n\ 796507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham }; \n\ 806507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 816507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_imp_return_struct return_struct; \n\ 826507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 836507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (debug) \n\ 846507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\ 856507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\ 866507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\ 876507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (is_super) \n\ 886507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 896507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (is_super2) \n\ 906507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 916507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\ 926507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 936507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 946507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 956507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\ 966507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 976507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 986507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 996507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void *class_ptr = (void *) [(id) object class]; \n\ 1016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (class_ptr == object) \n\ 1026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr; \n\ 1046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (debug) \n\ 1056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\", \n\ 1066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham class_ptr, class_as_class_struct->isa); \n\ 1076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.class_addr = class_as_class_struct->isa; \n\ 1086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 1106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (debug) \n\ 1126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham printf (\"[object class] returned: 0x%p.\\n\", class_ptr); \n\ 1136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.class_addr = class_ptr; \n\ 1146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 1176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (is_fixup) \n\ 1186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1196507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (is_fixed) \n\ 1206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1216507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\ 1226507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1236507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 1246507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1256507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\ 1266507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr = sel_getUid (sel_name); \n\ 1276507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (debug) \n\ 1286507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\", \n\ 1296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr, sel_name); \n\ 1306507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1316507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1326507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 1336507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1346507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr = sel; \n\ 1356507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1366507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 1376507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (is_stret) \n\ 1386507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1396507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr, \n\ 1406507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr); \n\ 1416507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else \n\ 1436507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { \n\ 1446507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\ 1456507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return_struct.sel_addr); \n\ 1466507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } \n\ 1476507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (debug) \n\ 1486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr); \n\ 1496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham \n\ 1506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return return_struct.impl_addr; \n\ 1516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham} \n\ 1526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham"; 1536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 1544f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) : 1554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_valid (true), 1564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_owner(owner), 1574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_header_addr (header_addr), 1584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_start_addr(0), 1594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_end_addr (0), 1604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_next_region (0) 1614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 1624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham SetUpRegion (); 1634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 1644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 1656e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() 1666e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton{ 1676e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton} 1686e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton 1694f385f181467701d2c5225f2c954ed5771e0763fJim Inghamvoid 1704f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() 1714f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 1724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // The header looks like: 1734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // 1744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // uint16_t headerSize 1754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // uint16_t descSize 1764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // uint32_t descCount 1774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // void * next 1784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // 1794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // First read in the header: 1804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 1814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham char memory_buffer[16]; 1824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Process *process = m_owner->GetProcess(); 1834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham DataExtractor data(memory_buffer, sizeof(memory_buffer), 1844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham process->GetByteOrder(), 1854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham process->GetAddressByteSize()); 1864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham size_t actual_size = 8 + process->GetAddressByteSize(); 1874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Error error; 1884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham size_t bytes_read = process->ReadMemory (m_header_addr, memory_buffer, actual_size, error); 1894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (bytes_read != actual_size) 1904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 1914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_valid = false; 1924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return; 1934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 1944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 1954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint32_t offset_ptr = 0; 1966916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton const uint16_t header_size = data.GetU16(&offset_ptr); 1976916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton const uint16_t descriptor_size = data.GetU16(&offset_ptr); 1986916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton const size_t num_descriptors = data.GetU32(&offset_ptr); 1994f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_next_region = data.GetPointer(&offset_ptr); 2014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // If the header size is 0, that means we've come in too early before this data is set up. 2034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Set ourselves as not valid, and continue. 2046916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton if (header_size == 0 || num_descriptors == 0) 2054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_valid = false; 2074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return; 2084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Now read in all the descriptors: 2114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // The descriptor looks like: 2124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // 2134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // uint32_t offset 2144f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // uint32_t flags 2154f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // 2164f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Where offset is either 0 - in which case it is unused, or 2174f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // it is the offset of the vtable code from the beginning of the descriptor record. 2184f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Below, we'll convert that into an absolute code address, since I don't want to have 2194f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // to compute it over and over. 2204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2214f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Ingest the whole descriptor array: 2226916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton const lldb::addr_t desc_ptr = m_header_addr + header_size; 2236916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton const size_t desc_array_size = num_descriptors * descriptor_size; 2244f385f181467701d2c5225f2c954ed5771e0763fJim Ingham DataBufferSP data_sp(new DataBufferHeap (desc_array_size, '\0')); 2254f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint8_t* dst = (uint8_t*)data_sp->GetBytes(); 2264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2274f385f181467701d2c5225f2c954ed5771e0763fJim Ingham DataExtractor desc_extractor (dst, desc_array_size, 2284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham process->GetByteOrder(), 2294f385f181467701d2c5225f2c954ed5771e0763fJim Ingham process->GetAddressByteSize()); 2304f385f181467701d2c5225f2c954ed5771e0763fJim Ingham bytes_read = process->ReadMemory(desc_ptr, dst, desc_array_size, error); 2314f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (bytes_read != desc_array_size) 2324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_valid = false; 2344f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return; 2354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // The actual code for the vtables will be laid out consecutively, so I also 2384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // compute the start and end of the whole code block. 2394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2404f385f181467701d2c5225f2c954ed5771e0763fJim Ingham offset_ptr = 0; 2414f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_start_addr = 0; 2424f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_end_addr = 0; 2434f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (int i = 0; i < num_descriptors; i++) 2454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham lldb::addr_t start_offset = offset_ptr; 2474f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint32_t offset = desc_extractor.GetU32 (&offset_ptr); 2484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint32_t flags = desc_extractor.GetU32 (&offset_ptr); 249ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar lldb::addr_t code_addr = desc_ptr + start_offset + offset; 2504f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_descriptors.push_back (VTableDescriptor(flags, code_addr)); 2514f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2524f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_code_start_addr == 0 || code_addr < m_code_start_addr) 2534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_start_addr = code_addr; 2544f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (code_addr > m_code_end_addr) 2554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_end_addr = code_addr; 2564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham offset_ptr = start_offset + descriptor_size; 2584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Finally, a little bird told me that all the vtable code blocks are the same size. 2604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Let's compute the blocks and if they are all the same add the size to the code end address: 2614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham lldb::addr_t code_size = 0; 2624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham bool all_the_same = true; 2634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (int i = 0; i < num_descriptors - 1; i++) 2644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham lldb::addr_t this_size = m_descriptors[i + 1].code_start - m_descriptors[i].code_start; 2664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (code_size == 0) 2674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham code_size = this_size; 2684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham else 2694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (this_size != code_size) 2714f385f181467701d2c5225f2c954ed5771e0763fJim Ingham all_the_same = false; 2724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (this_size > code_size) 2734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham code_size = this_size; 2744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (all_the_same) 2774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_code_end_addr += code_size; 2784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 2794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2804f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 2814f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::AddressInRegion (lldb::addr_t addr, uint32_t &flags) 2824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 2834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!IsValid()) 2844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 2854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (addr < m_code_start_addr || addr > m_code_end_addr) 2874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 2884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 2894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end(); 2904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (pos = m_descriptors.begin(); pos != end; pos++) 2914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (addr <= (*pos).code_start) 2934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 2944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham flags = (*pos).flags; 2954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return true; 2964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2974f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 2984f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 2994f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 3004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3014f385f181467701d2c5225f2c954ed5771e0763fJim Inghamvoid 3024f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s) 3034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 3044f385f181467701d2c5225f2c954ed5771e0763fJim Ingham s.Printf ("Header addr: 0x%llx Code start: 0x%llx Code End: 0x%llx Next: 0x%llx\n", 3054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region); 3064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham size_t num_elements = m_descriptors.size(); 3074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (size_t i = 0; i < num_elements; i++) 3084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham s.Indent(); 3104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham s.Printf ("Code start: 0x%llx Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags); 3114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 3134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3146e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp, 3156e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton const ModuleSP &objc_module_sp) : 3166e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton m_process_sp (process_sp), 3176e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton m_trampoline_header (LLDB_INVALID_ADDRESS), 3186e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID), 3196e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton m_objc_module_sp (objc_module_sp) 3204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 3214f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3224f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 3234f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3244f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables() 3254f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 3264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID) 3274f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id); 3284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 3294f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3304f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 3314f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols () 3324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 3334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_trampoline_header != LLDB_INVALID_ADDRESS) 3344f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return true; 3354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Target &target = m_process_sp->GetTarget(); 3364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ModuleList &modules = target.GetImages(); 3384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham size_t num_modules = modules.GetSize(); 3394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!m_objc_module_sp) 3404f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3414f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (size_t i = 0; i < num_modules; i++) 3424f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3434f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (modules.GetModuleAtIndex(i))) 3444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_objc_module_sp = modules.GetModuleAtIndex(i); 3464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham break; 3474f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3494f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3504f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3514f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_objc_module_sp) 3524f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ConstString trampoline_name ("gdb_objc_trampolines"); 354c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name, 355c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton eSymbolTypeData); 3564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (trampoline_symbol != NULL) 3574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 358bdcb6abaa287df2c5f312c51d993c1d0b0cb120cGreg Clayton if (!trampoline_symbol->GetValue().IsValid()) 3594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 3604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 361bdcb6abaa287df2c5f312c51d993c1d0b0cb120cGreg Clayton m_trampoline_header = trampoline_symbol->GetValue().GetLoadAddress(&target); 3624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_trampoline_header == LLDB_INVALID_ADDRESS) 3634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 3644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Next look up the "changed" symbol and set a breakpoint on that... 3664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ConstString changed_name ("gdb_objc_trampolines_changed"); 367c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name, 368c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton eSymbolTypeCode); 3694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (changed_symbol != NULL) 3704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 371bdcb6abaa287df2c5f312c51d993c1d0b0cb120cGreg Clayton if (!changed_symbol->GetValue().IsValid()) 3724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 3734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 374c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton lldb::addr_t changed_addr = changed_symbol->GetValue().GetOpcodeLoadAddress (&target); 3754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (changed_addr != LLDB_INVALID_ADDRESS) 3764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 377c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true); 378987c7ebe1daa425ba7abfa9643800e3237146fc0Greg Clayton if (trampolines_changed_bp_sp) 3794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 3804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID(); 3814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true); 3824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return true; 3834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 3884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 3904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 3914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 3924f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 3934f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines (void *baton, 3942f085c6ca2895663687dca704589478ff040b849Greg Clayton StoppointCallbackContext *context, 3952f085c6ca2895663687dca704589478ff040b849Greg Clayton lldb::user_id_t break_id, 3962f085c6ca2895663687dca704589478ff040b849Greg Clayton lldb::user_id_t break_loc_id) 3974f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 3984f385f181467701d2c5225f2c954ed5771e0763fJim Ingham AppleObjCVTables *vtable_handler = (AppleObjCVTables *) baton; 3994f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (vtable_handler->InitializeVTableSymbols()) 4004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 4014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // The Update function is called with the address of an added region. So we grab that address, and 4024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // feed it into ReadRegions. Of course, our friend the ABI will get the values for us. 403567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton Process *process = context->exe_ctx.GetProcessPtr(); 40475906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton const ABI *abi = process->GetABI().get(); 4054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 4074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ValueList argument_values; 4084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Value input_value; 4094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 4104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham input_value.SetValueType (Value::eValueTypeScalar); 4116916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); 4124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham argument_values.PushValue(input_value); 4134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 414567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton bool success = abi->GetArgumentValues (context->exe_ctx.GetThreadRef(), argument_values); 4154f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!success) 4164f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4174f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4184f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Now get a pointer value from the zeroth argument. 4194f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Error error; 4204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham DataExtractor data; 421801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton error = argument_values.GetValueAtIndex(0)->GetValueAsData (&(context->exe_ctx), 422801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton clang_ast_context->getASTContext(), 423801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton data, 424801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton 0, 425801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton NULL); 4264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint32_t offset_ptr = 0; 4274f385f181467701d2c5225f2c954ed5771e0763fJim Ingham lldb::addr_t region_addr = data.GetPointer(&offset_ptr); 4284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4294f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (region_addr != 0) 4304f385f181467701d2c5225f2c954ed5771e0763fJim Ingham vtable_handler->ReadRegions(region_addr); 4314f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 4324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 4344f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4354f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 4364f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions () 4374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 4384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // The no argument version reads the start region from the value of the gdb_regions_header, and 4394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // gets started from there. 4404f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4414f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_regions.clear(); 4424f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!InitializeVTableSymbols()) 4434f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham Error error; 445c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton lldb::addr_t region_addr = m_process_sp->ReadPointerFromMemory (m_trampoline_header, error); 446c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton if (error.Success()) 447c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton return ReadRegions (region_addr); 448c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton return false; 4494f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 4504f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4514f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 4524f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr) 4534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 4544f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!m_process_sp) 4554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 457e005f2ce03c489ebde9110678a29cbfe8488d5b4Greg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 4584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // We aren't starting at the trampoline symbol. 4604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham InitializeVTableSymbols (); 4614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham lldb::addr_t next_region = region_addr; 4624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Read in the sizes of the headers. 4644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham while (next_region != 0) 4654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 4664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_regions.push_back (VTableRegion(this, next_region)); 4674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!m_regions.back().IsValid()) 4684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 4694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_regions.clear(); 4704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4714f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 4724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (log) 4734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 4744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham StreamString s; 4754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_regions.back().Dump(s); 4764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham log->Printf("Read vtable region: \n%s", s.GetData()); 4774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 4784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham next_region = m_regions.back().GetNextRegionAddr(); 4804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 4814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return true; 4834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 4844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 4854f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool 4864f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables (lldb::addr_t addr, uint32_t &flags) 4874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{ 4884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham region_collection::iterator pos, end = m_regions.end(); 4894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham for (pos = m_regions.begin(); pos != end; pos++) 4904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 4914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if ((*pos).AddressInRegion (addr, flags)) 4924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return true; 4934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 4944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham return false; 4954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham} 4964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 497b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Inghamconst AppleObjCTrampolineHandler::DispatchFunction 498b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::g_dispatch_functions[] = 49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 5006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // NAME STRET SUPER SUPER2 FIXUP TYPE 5016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend", false, false, false, DispatchFunction::eFixUpNone }, 5026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fixup", false, false, false, DispatchFunction::eFixUpToFix }, 5036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fixedup", false, false, false, DispatchFunction::eFixUpFixed }, 5046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_stret", true, false, false, DispatchFunction::eFixUpNone }, 5056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_stret_fixup", true, false, false, DispatchFunction::eFixUpToFix }, 5066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_stret_fixedup", true, false, false, DispatchFunction::eFixUpFixed }, 5076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fpret", false, false, false, DispatchFunction::eFixUpNone }, 5086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fpret_fixup", false, false, false, DispatchFunction::eFixUpToFix }, 5096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fpret_fixedup", false, false, false, DispatchFunction::eFixUpFixed }, 5106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fp2ret", false, false, true, DispatchFunction::eFixUpNone }, 5116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fp2ret_fixup", false, false, true, DispatchFunction::eFixUpToFix }, 5126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSend_fp2ret_fixedup", false, false, true, DispatchFunction::eFixUpFixed }, 5136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper", false, true, false, DispatchFunction::eFixUpNone }, 5146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper_stret", true, true, false, DispatchFunction::eFixUpNone }, 5156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2", false, true, true, DispatchFunction::eFixUpNone }, 5166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2_fixup", false, true, true, DispatchFunction::eFixUpToFix }, 5176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2_fixedup", false, true, true, DispatchFunction::eFixUpFixed }, 5186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2_stret", true, true, true, DispatchFunction::eFixUpNone }, 5196507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2_stret_fixup", true, true, true, DispatchFunction::eFixUpToFix }, 5206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham {"objc_msgSendSuper2_stret_fixedup", true, true, true, DispatchFunction::eFixUpFixed }, 52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}; 52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 5236e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp, 5246e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton const ModuleSP &objc_module_sp) : 52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_process_sp (process_sp), 5264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_objc_module_sp (objc_module_sp), 52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_fn_addr (LLDB_INVALID_ADDRESS), 5286507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS), 5296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham m_msg_forward_addr (LLDB_INVALID_ADDRESS) 53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the known resolution functions: 53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_name("class_getMethodImplementation"); 53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_stret_name("class_getMethodImplementation_stret"); 5356507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham ConstString msg_forward_name("_objc_msgForward"); 5366507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham ConstString msg_forward_stret_name("_objc_msgForward_stret"); 53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 538eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton Target *target = m_process_sp ? &m_process_sp->GetTarget() : NULL; 53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode); 54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode); 5416507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode); 5426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode); 54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation) 545c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton m_impl_fn_addr = class_getMethodImplementation->GetValue().GetOpcodeLoadAddress (target); 54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation_stret) 547c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetOpcodeLoadAddress (target); 5486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (msg_forward) 549c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton m_msg_forward_addr = msg_forward->GetValue().GetOpcodeLoadAddress(target); 5506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (msg_forward_stret) 551c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton m_msg_forward_stret_addr = msg_forward_stret->GetValue().GetOpcodeLoadAddress(target); 55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: Do some kind of logging here. 55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS) 55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return; 55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 55724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol 55824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can 55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map 56024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // from there. 56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 562ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar for (int i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) 56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString name_const_str(g_dispatch_functions[i].name); 56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode); 56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (msgSend_symbol) 56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 5685d187e5495ee17f6763337a6ae28c2a7b07e4945Greg Clayton // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index. 56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret 57024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // dispatch functions. If that's as complex as it gets, we're fine. 57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 5725a26910ed231503d2a7a71365a44e379a994f4e6Greg Clayton lldb::addr_t sym_addr = msgSend_symbol->GetValue().GetOpcodeLoadAddress(target); 57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i)); 57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 5774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 5784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham // Build our vtable dispatch handler here: 5794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp)); 5804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_vtables_ap.get()) 5814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham m_vtables_ap->ReadRegions(); 58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 58324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanSP 585b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others) 58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 58724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ThreadPlanSP ret_plan_sp; 58824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); 58924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 5904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham DispatchFunction this_dispatch; 5914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham bool found_it = false; 5924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 5936507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // First step is to look and see if we are in one of the known ObjC dispatch functions. We've already compiled 5946507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // a table of same, so consult it. 5956507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 59624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MsgsendMap::iterator pos; 59724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner pos = m_msgSend_map.find (curr_pc); 59824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos != m_msgSend_map.end()) 59924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham this_dispatch = g_dispatch_functions[(*pos).second]; 6014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham found_it = true; 6024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 6034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 6046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // Next check to see if we are in a vtable region: 6056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 6064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (!found_it) 6074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 6084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham uint32_t flags; 6094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (m_vtables_ap.get()) 6104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 6114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham found_it = m_vtables_ap->IsAddressInVTables (curr_pc, flags); 6124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (found_it) 6134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 6144f385f181467701d2c5225f2c954ed5771e0763fJim Ingham this_dispatch.name = "vtable"; 6154f385f181467701d2c5225f2c954ed5771e0763fJim Ingham this_dispatch.stret_return 6164f385f181467701d2c5225f2c954ed5771e0763fJim Ingham = (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == AppleObjCVTables::eOBJC_TRAMPOLINE_STRET; 6174f385f181467701d2c5225f2c954ed5771e0763fJim Ingham this_dispatch.is_super = false; 6180984687e72f77f5e2278ed30597cc17a2e2afb62Jim Ingham this_dispatch.is_super2 = false; 6194f385f181467701d2c5225f2c954ed5771e0763fJim Ingham this_dispatch.fixedup = DispatchFunction::eFixUpFixed; 6204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 6214f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 6224f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 6234f385f181467701d2c5225f2c954ed5771e0763fJim Ingham 6244f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (found_it) 6254f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 626e005f2ce03c489ebde9110678a29cbfe8488d5b4Greg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 62724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6286507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // We are decoding a method dispatch. 6296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // First job is to pull the arguments out: 63024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 63124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); 63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 633289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton const ABI *abi = NULL; 634289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton ProcessSP process_sp (thread.CalculateProcess()); 635289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton if (process_sp) 636289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton abi = process_sp->GetABI().get(); 63724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (abi == NULL) 63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 640289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton TargetSP target_sp (thread.CalculateTarget()); 64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 642289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); 64324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ValueList argument_values; 6446507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham Value void_ptr_value; 6456507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 6466507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void_ptr_value.SetValueType (Value::eValueTypeScalar); 6476507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); 64824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 64924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int obj_index; 65024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int sel_index; 65124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 65224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // If this is a struct return dispatch, then the first argument is the 65324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // return struct pointer, and the object is the second, and the selector is the third. 65424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Otherwise the object is the first and the selector the second. 6554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (this_dispatch.stret_return) 65624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 65724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 1; 65824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 2; 6596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham argument_values.PushValue(void_ptr_value); 6606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham argument_values.PushValue(void_ptr_value); 6616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham argument_values.PushValue(void_ptr_value); 66224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 66324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 66424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 66524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 0; 66624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 1; 6676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham argument_values.PushValue(void_ptr_value); 6686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham argument_values.PushValue(void_ptr_value); 66924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 67024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 67224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool success = abi->GetArgumentValues (thread, argument_values); 67324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!success) 67424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 6756507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 676289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton ExecutionContext exe_ctx (thread.shared_from_this()); 677289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton Process *process = exe_ctx.GetProcessPtr(); 678e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // isa_addr will store the class pointer that the method is being dispatched to - so either the class 679e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // directly or the super class if this is one of the objc_msgSendSuper flavors. That's mostly used to 680e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // look up the class/selector pair in our cache. 681e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 682e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS; 6836507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong(); 684e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 685e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // Figure out the class this is being dispatched to and see if we've already cached this method call, 686e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // If so we can push a run-to-address plan directly. Otherwise we have to figure out where 687e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // the implementation lives. 6886507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 689e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (this_dispatch.is_super) 69024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 691e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (this_dispatch.is_super2) 692e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 693e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing 694e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // the object and the class to which the super message is being sent. So we need to dig the super 695e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // out of the class and use that. 696e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 697e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham Value super_value(*(argument_values.GetValueAtIndex(obj_index))); 698e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.GetScalar() += process->GetAddressByteSize(); 699e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext()); 700e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 701e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (super_value.GetScalar().IsValid()) 702e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 703e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 704e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // isa_value now holds the class pointer. The second word of the class pointer is the super-class pointer: 705e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.GetScalar() += process->GetAddressByteSize(); 706e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext()); 707e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (super_value.GetScalar().IsValid()) 708e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_addr = super_value.GetScalar().ULongLong(); 709e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 710e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 711e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 712e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf("Failed to extract the super class value from the class in objc_super."); 713e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 714e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 715e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 716e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 717e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 718e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf("Failed to extract the class value from objc_super."); 719e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 720e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 721e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 722e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 723e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing 724e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // the object and the super class to which the super message is being sent. So the class we want is 725e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // the second element of this structure. 726e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 727e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham Value super_value(*(argument_values.GetValueAtIndex(obj_index))); 728e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.GetScalar() += process->GetAddressByteSize(); 729e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham super_value.ResolveValue (&exe_ctx, clang_ast_context->getASTContext()); 730e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 731e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (super_value.GetScalar().IsValid()) 732e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 733e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_addr = super_value.GetScalar().ULongLong(); 734e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 735e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 736e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 737e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 738e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf("Failed to extract the class value from objc_super."); 739e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 740e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 74124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 742e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 743e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 744e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // In the direct dispatch case, the object->isa is the class pointer we want. 745e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 746e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // This is a little cheesy, but since object->isa is the first field, 747e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // making the object value a load address value and resolving it will get 748e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // the pointer sized data pointed to by that value... 749e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 750e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // Note, it isn't a fatal error not to be able to get the address from the object, since this might 751e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus. 752e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 753e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham Value isa_value(*(argument_values.GetValueAtIndex(obj_index))); 754e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 755e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_value.SetValueType(Value::eValueTypeLoadAddress); 756e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_value.ResolveValue(&exe_ctx, clang_ast_context->getASTContext()); 757e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (isa_value.GetScalar().IsValid()) 758e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 759e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_addr = isa_value.GetScalar().ULongLong(); 760e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 761e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 762e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 763e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 764e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf("Failed to extract the isa value from object."); 765e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 766e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 767e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 7686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 769e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache: 770e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS; 771e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 772e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (isa_addr != LLDB_INVALID_ADDRESS) 773e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 774e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 775e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 776e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf("Resolving call for class - 0x%llx and selector - 0x%llx", 777e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham isa_addr, sel_addr); 778e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 779e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime (); 780e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham assert(objc_runtime != NULL); 781e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 782e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr); 783e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 784e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 785e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (impl_addr != LLDB_INVALID_ADDRESS) 786e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 787e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham // Yup, it was in the cache, so we can run to that address directly. 788e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 789e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham if (log) 790e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham log->Printf ("Found implementation address in cache: 0x%llx", impl_addr); 791e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham 792e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others)); 793e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham } 794e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham else 795e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham { 7966507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // We haven't seen this class/selector pair yet. Look it up. 79724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner StreamString errors; 7986507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham Address impl_code_address; 7996507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham ValueList dispatch_values; 8016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // We've will inject a little function in the target that takes the object, selector and some flags, 8036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // and figures out the implementation. Looks like: 8046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // void *__lldb_objc_find_implementation_for_selector (void *object, 8056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // void *sel, 8066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int is_stret, 8076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int is_super, 8086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int is_super2, 8096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int is_fixup, 8106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int is_fixed, 8116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // int debug) 8126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // So set up the arguments for that call. 8136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (*(argument_values.GetValueAtIndex(obj_index))); 8156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (*(argument_values.GetValueAtIndex(sel_index))); 8166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham Value flag_value; 81810de7d1db3ec782ea2ccda1f39c0a40b9c301594Jim Ingham lldb::clang_type_t clang_int_type 81910de7d1db3ec782ea2ccda1f39c0a40b9c301594Jim Ingham = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingSint, 32); 8206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.SetValueType (Value::eValueTypeScalar); 8216507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.SetContext (Value::eContextTypeClangType, clang_int_type); 8226507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8236507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (this_dispatch.stret_return) 8246507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8256507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 8266507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; 8276507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8286507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (this_dispatch.is_super) 8306507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8316507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 8326507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; 8336507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8346507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8356507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (this_dispatch.is_super2) 8366507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8376507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 8386507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; 8396507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8406507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8416507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham switch (this_dispatch.fixedup) 8426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 8436507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham case DispatchFunction::eFixUpNone: 8446507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; 8456507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8466507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8476507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham break; 8486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham case DispatchFunction::eFixUpFixed: 8496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham break; 8546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham case DispatchFunction::eFixUpToFix: 8556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; 8586507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham dispatch_values.PushValue (flag_value); 8596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham break; 8606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 8616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (log) 8626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 1; 8636507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 8646507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done. 8655a26910ed231503d2a7a71365a44e379a994f4e6Greg Clayton dispatch_values.PushValue (flag_value); 8666507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // Now, if we haven't already, make and insert the function as a ClangUtilityFunction, and make and insert 8686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // it's runner ClangFunction. 86924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 87024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Scope for mutex locker: 871bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton Mutex::Locker locker(m_impl_function_mutex); 8726507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // First stage is to make the ClangUtility to hold our injected function: 8746507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8756507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. 8766507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // This is useful for debugging additions to the get_impl function 'cause you don't have 8776507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // to bother with string-ifying the code into g_lookup_implementation_function_code. 8786507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 8796507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (USE_BUILTIN_FUNCTION) 8806507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 8816507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham ConstString our_utility_function_name("__lldb_objc_find_implementation_for_selector"); 8826507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham SymbolContextList sc_list; 883567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton 884567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); 8856507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (sc_list.GetSize() == 1) 8866507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 8876507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham SymbolContext sc; 8886507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham sc_list.GetContextAtIndex(0, sc); 8896507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (sc.symbol != NULL) 8906507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham impl_code_address = sc.symbol->GetValue(); 8916507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 892567e7f3ba16eb48cb9fd6a2f26f2f7269eb6983cGreg Clayton //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); 8937577bc4d10e6bd6efb29a3a3c8190e440d9f45ebGreg Clayton //printf ("Getting address for our_utility_function: 0x%llx.\n", addr); 8946507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 8956507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 8966507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 8977577bc4d10e6bd6efb29a3a3c8190e440d9f45ebGreg Clayton //printf ("Could not find implementation function address.\n"); 8986507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return ret_plan_sp; 8996507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 9006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 9016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else if (!m_impl_code.get()) 9026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 9036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code, 9046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham g_lookup_implementation_function_name)); 9056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (!m_impl_code->Install(errors, exe_ctx)) 9066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 9076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (log) 9086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); 9096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham m_impl_code.reset(); 9106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham return ret_plan_sp; 9116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 9126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham impl_code_address.Clear(); 9136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham impl_code_address.SetOffset(m_impl_code->StartAddress()); 9146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 9156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham else 9166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham { 9176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham impl_code_address.Clear(); 9186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham impl_code_address.SetOffset(m_impl_code->StartAddress()); 9196507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 9206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 9216507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // Next make the runner function for our implementation utility function. 92224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function.get()) 92324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 92453bfd064c90a795485809a9be7dfbeaccb7ce369Jim Ingham m_impl_function.reset(new ClangFunction (thread, 925395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton clang_ast_context, 926395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton clang_void_ptr_type, 927395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton impl_code_address, 928395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton dispatch_values)); 9296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 9306507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham errors.Clear(); 93124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner unsigned num_errors = m_impl_function->CompileFunction(errors); 93224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_errors) 93324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 93424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 93524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error compiling function: \"%s\".", errors.GetData()); 93624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 93724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 93824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 93924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 9406507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (!m_impl_function->WriteFunctionWrapper(exe_ctx, errors)) 94124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 94224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 94324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); 94424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 94524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 94624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 94724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham } 94924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 95024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 95124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // Now write down the argument values for this particular call. This looks like it might be a race condition 9536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // if other threads were calling into here, but actually it isn't because we allocate a new args structure for 9546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham // this call by passing args_addr = LLDB_INVALID_ADDRESS... 9556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham 95624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; 9576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham if (!m_impl_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, dispatch_values, errors)) 95824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 95924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread, this, args_addr, 96124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 9626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham isa_addr, sel_addr, 96324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner stop_others)); 9644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham if (log) 9654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham { 9664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham StreamString s; 9674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); 9684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham log->Printf("Using ObjC step plan: %s.\n", s.GetData()); 9694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham } 97024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 97124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 97224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 97324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 97424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 97524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 97624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerClangFunction * 977b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction () 97824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 97924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_impl_function.get(); 98024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 981