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