16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//===-- AppleObjCRuntimeV2.cpp --------------------------------------*- C++ -*-===//
26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//                     The LLVM Compiler Infrastructure
46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This file is distributed under the University of Illinois Open Source
66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// License. See LICENSE.TXT for details.
76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//
86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//===----------------------------------------------------------------------===//
96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/lldb-python.h"
116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <string>
136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <vector>
146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <stdint.h>
156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/lldb-enumerations.h"
176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/ClangForward.h"
186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/ClangASTType.h"
196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/ClangForward.h"
216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/ConstString.h"
226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Error.h"
236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Log.h"
246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Module.h"
256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/PluginManager.h"
266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Scalar.h"
276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Section.h"
286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/StreamString.h"
296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/Timer.h"
306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Core/ValueObjectVariable.h"
316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Expression/ClangFunction.h"
326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Expression/ClangUtilityFunction.h"
336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/ClangASTContext.h"
346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/ObjectFile.h"
356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/Symbol.h"
366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/TypeList.h"
376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Symbol/VariableList.h"
386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Target/ExecutionContext.h"
396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Target/Process.h"
406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Target/RegisterContext.h"
416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Target/Target.h"
426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "lldb/Target/Thread.h"
436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "AppleObjCRuntimeV2.h"
456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "AppleObjCTypeVendor.h"
466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "AppleObjCTrampolineHandler.h"
476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <vector>
496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing namespace lldb;
516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing namespace lldb_private;
526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 2 second timeout when running utility functions
546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Testing using the new C++11 raw string literals. If this breaks GCC then we will
586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// need to revert to the code above...
596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char *g_get_dynamic_class_info_body = R"(
606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennextern "C"
626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t strlen(const char *);
646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *strncpy (char * s1, const char * s2, size_t n);
656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int printf(const char * format, ...);
666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef ENABLE_DEBUG_PRINTF
696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define DEBUG_PRINTF(fmt, ...)
726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct _NXMapTable {
756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void *prototype;
766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned num_classes;
776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    unsigned num_buckets_minus_one;
786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void *buckets;
796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} NXMapTable;
806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define NX_MAPNOTAKEY   ((void *)(-1))
826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct BucketInfo
846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char *name_ptr;
866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Class isa;
876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} BucketInfo;
886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct ClassInfo
906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Class isa;
926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t hash;
936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} __attribute__((__packed__));
946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennuint32_t
966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                             void *class_infos_ptr,
986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                             uint32_t class_infos_byte_size)
996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (grc)
1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const unsigned num_classes = grc->num_classes;
1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (class_infos_ptr)
1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            BucketInfo *buckets = (BucketInfo *)grc->buckets;
1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            uint32_t idx = 0;
1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (buckets[i].name_ptr != NX_MAPNOTAKEY)
1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    if (idx < max_class_infos)
1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    {
1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        const char *s = buckets[i].name_ptr;
1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        uint32_t h = 5381;
1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        for (unsigned char c = *s; c; c = *++s)
1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            h = ((h << 5) + h) + c;
1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        class_infos[idx].hash = h;
1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        class_infos[idx].isa = buckets[i].isa;
1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    }
1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    ++idx;
1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (idx < max_class_infos)
1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                class_infos[idx].isa = NULL;
1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                class_infos[idx].hash = 0;
1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return num_classes;
1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 0;
1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn)";
1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Testing using the new C++11 raw string literals. If this breaks GCC then we will
1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// need to revert to the code above...
1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic const char *g_get_shared_cache_class_info_body = R"(
1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennextern "C"
1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char *class_getName(void *objc_class);
1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    size_t strlen(const char *);
1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char *strncpy (char * s1, const char * s2, size_t n);
1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int printf(const char * format, ...);
1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef ENABLE_DEBUG_PRINTF
1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else
1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#define DEBUG_PRINTF(fmt, ...)
1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif
1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct objc_classheader_t {
1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int32_t clsOffset;
1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int32_t hiOffset;
1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct objc_clsopt_t {
1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t capacity;
1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t occupied;
1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t shift;
1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t mask;
1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t zero;
1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t unused;
1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint64_t salt;
1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t scramble[256];
1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint8_t tab[0]; // tab[mask+1]
1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //  uint8_t checkbytes[capacity];
1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //  int32_t offset[capacity];
1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //  objc_classheader_t clsOffsets[capacity];
1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //  uint32_t duplicateCount;
1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    //  objc_classheader_t duplicateOffsets[duplicateCount];
1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct objc_opt_t {
1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t version;
1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int32_t selopt_offset;
1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int32_t headeropt_offset;
1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int32_t clsopt_offset;
1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn};
1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstruct ClassInfo
1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Class isa;
1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t hash;
1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}  __attribute__((__packed__));
1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennuint32_t
2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  void *class_infos_ptr,
2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                  uint32_t class_infos_byte_size)
2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t idx = 0;
2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    DEBUG_PRINTF ("class_infos_byte_size = %u (%zu class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (objc_opt_ro_ptr)
2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (objc_opt->version == 12)
2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const objc_clsopt_t* clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            int32_t zeroOffset = 16;
2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for (uint32_t i=0; i<clsopt->capacity; ++i)
2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int32_t clsOffset = classOffsets[i].clsOffset;
2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (clsOffset & 1)
2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    continue; // duplicate
2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if (clsOffset == zeroOffset)
2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    continue; // zero offset
2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (class_infos && idx < max_class_infos)
2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const char *name = class_getName (class_infos[idx].isa);
2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Hash the class name so we don't have to read it
2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const char *s = name;
2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    uint32_t h = 5381;
2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for (unsigned char c = *s; c; c = *++s)
2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        h = ((h << 5) + h) + c;
2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    class_infos[idx].hash = h;
2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ++idx;
2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const uint32_t duplicate_count = *duplicate_count_ptr;
2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            for (uint32_t i=0; i<duplicate_count; ++i)
2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (clsOffset & 1)
2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    continue; // duplicate
2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                else if (clsOffset == zeroOffset)
2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    continue; // zero offset
2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (class_infos && idx < max_class_infos)
2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const char *name = class_getName (class_infos[idx].isa);
2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    // Hash the class name so we don't have to read it
2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    const char *s = name;
2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    uint32_t h = 5381;
2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    for (unsigned char c = *s; c; c = *++s)
2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                        h = ((h << 5) + h) + c;
2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    class_infos[idx].hash = h;
2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                ++idx;
2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("%u class_infos\n", idx);
2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        DEBUG_PRINTF ("done\n");
2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return idx;
2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn)";
2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic uint64_t
2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennExtractRuntimeGlobalSymbol (Process* process,
2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            ConstString name,
2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            const ModuleSP &module_sp,
2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            Error& error,
2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            bool read_value = true,
2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            uint8_t byte_size = 0,
2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            uint64_t default_value = LLDB_INVALID_ADDRESS,
2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                            SymbolType sym_type = lldb::eSymbolTypeData)
2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!process)
2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        error.SetErrorString("no process");
3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return default_value;
3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!module_sp)
3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        error.SetErrorString("no module");
3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return default_value;
3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!byte_size)
3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        byte_size = process->GetAddressByteSize();
3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (symbol)
3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        lldb::addr_t symbol_load_addr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (symbol_load_addr != LLDB_INVALID_ADDRESS)
3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (read_value)
3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return symbol_load_addr;
3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            error.SetErrorString("symbol address invalid");
3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return default_value;
3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        error.SetErrorString("no symbol");
3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return default_value;
3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                        const ModuleSP &objc_module_sp) :
3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    AppleObjCRuntime (process),
3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_class_info_function(),
3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_class_info_code(),
3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_class_info_args (LLDB_INVALID_ADDRESS),
3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_shared_cache_class_info_function(),
3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_shared_cache_class_info_code(),
3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_type_vendor_ap (),
3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS),
3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_hash_signature (),
3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_has_object_getClass (false),
3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_loaded_objc_opt (false),
3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)),
3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_tagged_pointer_vendor_ap(TaggedPointerVendor::CreateInstance(*this,objc_module_sp))
3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    static const ConstString g_gdb_object_getClass("gdb_object_getClass");
3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::~AppleObjCRuntimeV2()
3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool
3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              DynamicValueType use_dynamic,
3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              TypeAndOrName &class_type_or_name,
3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                              Address &address)
3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert (in_value.GetProcessSP().get() == m_process);
3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert (m_process != NULL);
3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class_type_or_name.Clear();
3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Make sure we can have a dynamic value before starting...
3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (CouldHaveDynamicValue (in_value))
3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // First job, pull out the address at 0 offset from the object  That will be the ISA pointer.
3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (objc_class_sp)
3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            const addr_t object_ptr = in_value.GetPointerValue();
3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            address.SetRawAddress(object_ptr);
3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            ConstString class_name (objc_class_sp->GetClassName());
3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            class_type_or_name.SetName(class_name);
3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            TypeSP type_sp (objc_class_sp->GetType());
3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (type_sp)
3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                class_type_or_name.SetTypeSP (type_sp);
3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            else
3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                type_sp = LookupInCompleteClassCache (class_name);
3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                if (type_sp)
3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                {
3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    objc_class_sp->SetType (type_sp);
3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                    class_type_or_name.SetTypeSP (type_sp);
3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                }
3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return class_type_or_name.IsEmpty() == false;
4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------------------------------------------------------------------
4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Static Functions
4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------------------------------------------------------------------
4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennLanguageRuntime *
4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // sure we aren't using the V1 runtime.
4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (language == eLanguageTypeObjC)
4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        ModuleSP objc_module_sp;
4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == eAppleObjC_V2)
4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return new AppleObjCRuntimeV2 (process, objc_module_sp);
4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return NULL;
4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return NULL;
4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid
4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::Initialize()
4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PluginManager::RegisterPlugin (GetPluginNameStatic(),
4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   "Apple Objective C Language Runtime - Version 2",
4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                   CreateInstance);
4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid
4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::Terminate()
4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    PluginManager::UnregisterPlugin (CreateInstance);
4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennlldb_private::ConstString
4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::GetPluginNameStatic()
4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    static ConstString g_name("apple-objc-v2");
4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return g_name;
4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------------------------------------------------------------------
4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// PluginInterface protocol
4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//------------------------------------------------------------------
4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennlldb_private::ConstString
4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::GetPluginName()
4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return GetPluginNameStatic();
4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennuint32_t
4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::GetPluginVersion()
4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return 1;
4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennBreakpointResolverSP
4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    BreakpointResolverSP resolver_sp;
4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (throw_bp)
4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        resolver_sp.reset (new BreakpointResolverName (bkpt,
4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       "objc_exception_throw",
4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       eFunctionNameTypeBase,
4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       Breakpoint::Exact,
4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                       eLazyBoolNo));
4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // FIXME: We don't do catch breakpoints for ObjC yet.
4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // Should there be some way for the runtime to specify what it can do in this regard?
4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return resolver_sp;
4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennClangUtilityFunction *
4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::CreateObjectChecker(const char *name)
4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    char check_function_code[2048];
4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    int len = 0;
4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (m_has_object_getClass)
4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = ::snprintf (check_function_code,
4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          sizeof(check_function_code),
4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\" void *gdb_object_getClass(void *);                                          \n"
4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\"  int printf(const char *format, ...);                                       \n"
4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\" void                                                                        \n"
4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "{                                                                                        \n"
4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       return; // nil is ok                                                              \n"
4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   if (!gdb_object_getClass($__lldb_arg_obj))                                            \n"
4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       *((volatile int *)0) = 'ocgc';                                                    \n"
4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   {                                                                                     \n"
4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "                                                respondsToSelector:                      \n"
4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "                                       (struct objc_selector *) $__lldb_arg_selector];   \n"
5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       if (responds == (signed char) 0)                                                  \n"
5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "           *((volatile int *)0) = 'ocgc';                                                \n"
5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   }                                                                                     \n"
5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "}                                                                                        \n",
5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          name);
5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    else
5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        len = ::snprintf (check_function_code,
5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          sizeof(check_function_code),
5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\" void *gdb_class_getClass(void *);                                           \n"
5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\"  int printf(const char *format, ...);                                       \n"
5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "extern \"C\"  void                                                                       \n"
5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector)                                    \n"
5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "{                                                                                        \n"
5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   if ($__lldb_arg_obj == (void *)0)                                                     \n"
5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       return; // nil is ok                                                              \n"
5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "    void **$isa_ptr = (void **)$__lldb_arg_obj;                                          \n"
5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "    if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr))                        \n"
5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       *((volatile int *)0) = 'ocgc';                                                    \n"
5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   else if ($__lldb_arg_selector != (void *)0)                                           \n"
5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   {                                                                                     \n"
5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "        signed char responds = (signed char) [(id) $__lldb_arg_obj                       \n"
5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "                                                respondsToSelector:                      \n"
5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "                                        (struct objc_selector *) $__lldb_arg_selector];  \n"
5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "       if (responds == (signed char) 0)                                                  \n"
5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "           *((volatile int *)0) = 'ocgc';                                                \n"
5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "   }                                                                                     \n"
5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          "}                                                                                        \n",
5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                          name);
5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    assert (len < (int)sizeof(check_function_code));
5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return new ClangUtilityFunction(check_function_code, name);
5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennsize_t
5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::GetByteOffsetForIvar (ClangASTType &parent_ast_type, const char *ivar_name)
5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!class_name || *class_name == '\0' || !ivar_name || *ivar_name == '\0')
5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return LLDB_INVALID_IVAR_OFFSET;
5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    std::string buffer("OBJC_IVAR_$_");
5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buffer.append (class_name);
5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buffer.push_back ('.');
5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    buffer.append (ivar_name);
5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ConstString ivar_const_str (buffer.c_str());
5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    SymbolContextList sc_list;
5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Target &target = m_process->GetTarget();
5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    SymbolContext ivar_offset_symbol;
5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (sc_list.GetSize() != 1
5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        || !sc_list.GetContextAtIndex(0, ivar_offset_symbol)
5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        || ivar_offset_symbol.symbol == NULL)
5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return LLDB_INVALID_IVAR_OFFSET;
5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    addr_t ivar_offset_address = ivar_offset_symbol.symbol->GetAddress().GetLoadAddress (&target);
5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Error error;
5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    uint32_t ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                     4,
5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                     LLDB_INVALID_IVAR_OFFSET,
5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                                                                     error);
5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return ivar_offset;
5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// tagged pointers are special not-a-real-pointer values that contain both type and value information
5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this routine attempts to check with as little computational effort as possible whether something
5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool
5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennAppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    if (!m_tagged_pointer_vendor_ap)
5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return false;
5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn}
5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennclass RemoteNXMapTable
5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{
5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennpublic:
5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    RemoteNXMapTable () :
5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_count (0),
5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_num_buckets_minus_one (0),
5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_buckets_ptr (LLDB_INVALID_ADDRESS),
5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_process (NULL),
5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_end_iterator (*this, -1),
5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_load_addr (LLDB_INVALID_ADDRESS),
5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_map_pair_size (0),
5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_invalid_key (0)
5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    void
6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    Dump ()
6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        printf ("RemoteNXMapTable.m_count = %u\n", m_count);
6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    bool
6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    ParseHeader (Process* process, lldb::addr_t load_addr)
6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_process = process;
6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_load_addr = load_addr;
6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_map_pair_size = m_process->GetAddressByteSize() * 2;
6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        Error err;
6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // This currently holds true for all platforms we support, but we might
6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // need to change this to use get the actualy byte size of "unsigned"
6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // from the target AST...
6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const uint32_t unsigned_byte_size = sizeof(uint32_t);
6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bool success = true;
6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (load_addr == LLDB_INVALID_ADDRESS)
6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            success = false;
6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        else
6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // unsigned count;
6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (m_count)
6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cursor += unsigned_byte_size;
6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // unsigned nbBucketsMinusOne;
6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                cursor += unsigned_byte_size;
6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // void *buckets;
6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        if (!success)
6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_count = 0;
6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_num_buckets_minus_one = 0;
6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_buckets_ptr = LLDB_INVALID_ADDRESS;
6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        return success;
6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    }
6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    friend class const_iterator;
6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    class const_iterator
6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    {
6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn    public:
6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            AdvanceToValidIndex();
6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // AdvanceToValidIndex() has been called by rhs already.
6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const_iterator &operator=(const const_iterator &rhs)
6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            // AdvanceToValidIndex() has been called by rhs already.
6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            assert (&m_parent == &rhs.m_parent);
6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            m_index = rhs.m_index;
6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return *this;
6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bool operator==(const const_iterator &rhs) const
6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (&m_parent != &rhs.m_parent)
6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return false;
6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (m_index != rhs.m_index)
6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return false;
6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return true;
6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        bool operator!=(const const_iterator &rhs) const
6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return !(operator==(rhs));
6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const_iterator &operator++()
6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            AdvanceToValidIndex();
7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            return *this;
7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        }
7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        const element operator*() const
7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn        {
7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (m_index == -1)
7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            {
7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                // TODO find a way to make this an error, but not an assert
7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return element();
7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            }
7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            size_t map_pair_size = m_parent.m_map_pair_size;
7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            Error err;
7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (!err.Success())
7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return element();
7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn            if (!err.Success())
7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn                return element();
7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn
725            std::string key_string;
726
727            m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
728            if (!err.Success())
729                return element();
730
731            return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
732        }
733    private:
734        void AdvanceToValidIndex ()
735        {
736            if (m_index == -1)
737                return;
738
739            const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
740            const size_t map_pair_size = m_parent.m_map_pair_size;
741            const lldb::addr_t invalid_key = m_parent.m_invalid_key;
742            Error err;
743
744            while (m_index--)
745            {
746                lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
747                lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
748
749                if (!err.Success())
750                {
751                    m_index = -1;
752                    return;
753                }
754
755                if (key != invalid_key)
756                    return;
757            }
758        }
759        RemoteNXMapTable   &m_parent;
760        int                 m_index;
761    };
762
763    const_iterator begin ()
764    {
765        return const_iterator(*this, m_num_buckets_minus_one + 1);
766    }
767
768    const_iterator end ()
769    {
770        return m_end_iterator;
771    }
772
773    uint32_t
774    GetCount () const
775    {
776        return m_count;
777    }
778
779    uint32_t
780    GetBucketCount () const
781    {
782        return m_num_buckets_minus_one;
783    }
784
785    lldb::addr_t
786    GetBucketDataPointer () const
787    {
788        return m_buckets_ptr;
789    }
790
791    lldb::addr_t
792    GetTableLoadAddress() const
793    {
794        return m_load_addr;
795    }
796
797private:
798    // contents of _NXMapTable struct
799    uint32_t m_count;
800    uint32_t m_num_buckets_minus_one;
801    lldb::addr_t m_buckets_ptr;
802    lldb_private::Process *m_process;
803    const_iterator m_end_iterator;
804    lldb::addr_t m_load_addr;
805    size_t m_map_pair_size;
806    lldb::addr_t m_invalid_key;
807};
808
809
810
811AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
812    m_count (0),
813    m_num_buckets (0),
814    m_buckets_ptr (0)
815{
816}
817
818void
819AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
820{
821    m_count = hash_table.GetCount();
822    m_num_buckets = hash_table.GetBucketCount();
823    m_buckets_ptr = hash_table.GetBucketDataPointer();
824}
825
826bool
827AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
828{
829    if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
830    {
831        return false; // Failed to parse the header, no need to update anything
832    }
833
834    // Check with out current signature and return true if the count,
835    // number of buckets or the hash table address changes.
836    if (m_count == hash_table.GetCount() &&
837        m_num_buckets == hash_table.GetBucketCount() &&
838        m_buckets_ptr == hash_table.GetBucketDataPointer())
839    {
840        // Hash table hasn't changed
841        return false;
842    }
843    // Hash table data has changed, we need to update
844    return true;
845}
846
847class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
848{
849public:
850    friend class lldb_private::AppleObjCRuntimeV2;
851
852private:
853    // The constructor should only be invoked by the runtime as it builds its caches
854    // or populates them.  A ClassDescriptorV2 should only ever exist in a cache.
855    ClassDescriptorV2 (AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
856        m_runtime (runtime),
857        m_objc_class_ptr (isa),
858        m_name (name)
859    {
860    }
861
862public:
863    virtual ConstString
864    GetClassName ()
865    {
866        if (!m_name)
867        {
868            lldb_private::Process *process = m_runtime.GetProcess();
869
870            if (process)
871            {
872                std::unique_ptr<objc_class_t> objc_class;
873                std::unique_ptr<class_ro_t> class_ro;
874                std::unique_ptr<class_rw_t> class_rw;
875
876                if (!Read_objc_class(process, objc_class))
877                    return m_name;
878                if (!Read_class_row(process, *objc_class, class_ro, class_rw))
879                    return m_name;
880
881                m_name = ConstString(class_ro->m_name.c_str());
882            }
883        }
884        return m_name;
885    }
886
887    virtual ObjCLanguageRuntime::ClassDescriptorSP
888    GetSuperclass ()
889    {
890        lldb_private::Process *process = m_runtime.GetProcess();
891
892        if (!process)
893            return ObjCLanguageRuntime::ClassDescriptorSP();
894
895        std::unique_ptr<objc_class_t> objc_class;
896
897        if (!Read_objc_class(process, objc_class))
898            return ObjCLanguageRuntime::ClassDescriptorSP();
899
900        return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
901    }
902
903    virtual bool
904    IsValid ()
905    {
906        return true;    // any Objective-C v2 runtime class descriptor we vend is valid
907    }
908
909    // a custom descriptor is used for tagged pointers
910    virtual bool
911    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
912                          uint64_t* value_bits = NULL,
913                          uint64_t* payload = NULL)
914    {
915        return false;
916    }
917
918    virtual uint64_t
919    GetInstanceSize ()
920    {
921        lldb_private::Process *process = m_runtime.GetProcess();
922
923        if (process)
924        {
925            std::unique_ptr<objc_class_t> objc_class;
926            std::unique_ptr<class_ro_t> class_ro;
927            std::unique_ptr<class_rw_t> class_rw;
928
929            if (!Read_objc_class(process, objc_class))
930                return 0;
931            if (!Read_class_row(process, *objc_class, class_ro, class_rw))
932                return 0;
933
934            return class_ro->m_instanceSize;
935        }
936
937        return 0;
938    }
939
940    virtual ObjCLanguageRuntime::ObjCISA
941    GetISA ()
942    {
943        return m_objc_class_ptr;
944    }
945
946    virtual bool
947    Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
948              std::function <bool (const char *, const char *)> const &instance_method_func,
949              std::function <bool (const char *, const char *)> const &class_method_func,
950              std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func)
951    {
952        lldb_private::Process *process = m_runtime.GetProcess();
953
954        std::unique_ptr<objc_class_t> objc_class;
955        std::unique_ptr<class_ro_t> class_ro;
956        std::unique_ptr<class_rw_t> class_rw;
957
958        if (!Read_objc_class(process, objc_class))
959            return 0;
960        if (!Read_class_row(process, *objc_class, class_ro, class_rw))
961            return 0;
962
963        static ConstString NSObject_name("NSObject");
964
965        if (m_name != NSObject_name && superclass_func)
966            superclass_func(objc_class->m_superclass);
967
968        if (instance_method_func)
969        {
970            std::unique_ptr<method_list_t> base_method_list;
971
972            base_method_list.reset(new method_list_t);
973            if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
974                return false;
975
976            if (base_method_list->m_entsize != method_t::GetSize(process))
977                return false;
978
979            std::unique_ptr<method_t> method;
980            method.reset(new method_t);
981
982            for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
983            {
984                method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
985
986                if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
987                    break;
988            }
989        }
990
991        if (class_method_func)
992        {
993            ClassDescriptorV2 metaclass(m_runtime, objc_class->m_isa, NULL); // The metaclass is not in the cache
994
995            // We don't care about the metaclass's superclass, or its class methods.  Its instance methods are
996            // our class methods.
997
998            metaclass.Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
999                               class_method_func,
1000                               std::function <bool (const char *, const char *)> (nullptr),
1001                               std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
1002        }
1003
1004        if (ivar_func)
1005        {
1006            ivar_list_t ivar_list;
1007            if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
1008                return false;
1009
1010            if (ivar_list.m_entsize != ivar_t::GetSize(process))
1011                return false;
1012
1013            ivar_t ivar;
1014
1015            for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
1016            {
1017                ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
1018
1019                if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
1020                    break;
1021            }
1022        }
1023
1024        return true;
1025    }
1026
1027    virtual
1028    ~ClassDescriptorV2 ()
1029    {
1030    }
1031
1032private:
1033    static const uint32_t RW_REALIZED = (1 << 31);
1034
1035    struct objc_class_t {
1036        ObjCLanguageRuntime::ObjCISA    m_isa;              // The class's metaclass.
1037        ObjCLanguageRuntime::ObjCISA    m_superclass;
1038        lldb::addr_t                    m_cache_ptr;
1039        lldb::addr_t                    m_vtable_ptr;
1040        lldb::addr_t                    m_data_ptr;
1041        uint8_t                         m_flags;
1042
1043        objc_class_t () :
1044            m_isa (0),
1045            m_superclass (0),
1046            m_cache_ptr (0),
1047            m_vtable_ptr (0),
1048            m_data_ptr (0),
1049            m_flags (0)
1050        {
1051        }
1052
1053        void
1054        Clear()
1055        {
1056            m_isa = 0;
1057            m_superclass = 0;
1058            m_cache_ptr = 0;
1059            m_vtable_ptr = 0;
1060            m_data_ptr = 0;
1061            m_flags = 0;
1062        }
1063
1064        bool Read(Process *process, lldb::addr_t addr)
1065        {
1066            size_t ptr_size = process->GetAddressByteSize();
1067
1068            size_t objc_class_size = ptr_size   // uintptr_t isa;
1069            + ptr_size   // Class superclass;
1070            + ptr_size   // void *cache;
1071            + ptr_size   // IMP *vtable;
1072            + ptr_size;  // uintptr_t data_NEVER_USE;
1073
1074            DataBufferHeap objc_class_buf (objc_class_size, '\0');
1075            Error error;
1076
1077            process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
1078            if (error.Fail())
1079            {
1080                return false;
1081            }
1082
1083            DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
1084
1085            lldb::offset_t cursor = 0;
1086
1087            m_isa           = extractor.GetAddress_unchecked(&cursor);   // uintptr_t isa;
1088            m_superclass    = extractor.GetAddress_unchecked(&cursor);   // Class superclass;
1089            m_cache_ptr     = extractor.GetAddress_unchecked(&cursor);   // void *cache;
1090            m_vtable_ptr    = extractor.GetAddress_unchecked(&cursor);   // IMP *vtable;
1091            lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor);   // uintptr_t data_NEVER_USE;
1092
1093            m_flags         = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
1094            m_data_ptr      = data_NEVER_USE & ~(lldb::addr_t)3;
1095
1096            return true;
1097        }
1098    };
1099
1100    struct class_ro_t {
1101        uint32_t                        m_flags;
1102        uint32_t                        m_instanceStart;
1103        uint32_t                        m_instanceSize;
1104        uint32_t                        m_reserved;
1105
1106        lldb::addr_t                    m_ivarLayout_ptr;
1107        lldb::addr_t                    m_name_ptr;
1108        lldb::addr_t                    m_baseMethods_ptr;
1109        lldb::addr_t                    m_baseProtocols_ptr;
1110        lldb::addr_t                    m_ivars_ptr;
1111
1112        lldb::addr_t                    m_weakIvarLayout_ptr;
1113        lldb::addr_t                    m_baseProperties_ptr;
1114
1115        std::string                     m_name;
1116
1117        bool Read(Process *process, lldb::addr_t addr)
1118        {
1119            size_t ptr_size = process->GetAddressByteSize();
1120
1121            size_t size = sizeof(uint32_t)             // uint32_t flags;
1122            + sizeof(uint32_t)                         // uint32_t instanceStart;
1123            + sizeof(uint32_t)                         // uint32_t instanceSize;
1124            + (ptr_size == 8 ? sizeof(uint32_t) : 0)   // uint32_t reserved; // __LP64__ only
1125            + ptr_size                                 // const uint8_t *ivarLayout;
1126            + ptr_size                                 // const char *name;
1127            + ptr_size                                 // const method_list_t *baseMethods;
1128            + ptr_size                                 // const protocol_list_t *baseProtocols;
1129            + ptr_size                                 // const ivar_list_t *ivars;
1130            + ptr_size                                 // const uint8_t *weakIvarLayout;
1131            + ptr_size;                                // const property_list_t *baseProperties;
1132
1133            DataBufferHeap buffer (size, '\0');
1134            Error error;
1135
1136            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1137            if (error.Fail())
1138            {
1139                return false;
1140            }
1141
1142            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1143
1144            lldb::offset_t cursor = 0;
1145
1146            m_flags             = extractor.GetU32_unchecked(&cursor);
1147            m_instanceStart     = extractor.GetU32_unchecked(&cursor);
1148            m_instanceSize      = extractor.GetU32_unchecked(&cursor);
1149            if (ptr_size == 8)
1150                m_reserved      = extractor.GetU32_unchecked(&cursor);
1151            else
1152                m_reserved      = 0;
1153            m_ivarLayout_ptr     = extractor.GetAddress_unchecked(&cursor);
1154            m_name_ptr           = extractor.GetAddress_unchecked(&cursor);
1155            m_baseMethods_ptr    = extractor.GetAddress_unchecked(&cursor);
1156            m_baseProtocols_ptr  = extractor.GetAddress_unchecked(&cursor);
1157            m_ivars_ptr          = extractor.GetAddress_unchecked(&cursor);
1158            m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
1159            m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
1160
1161            DataBufferHeap name_buf(1024, '\0');
1162
1163            process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
1164
1165            if (error.Fail())
1166            {
1167                return false;
1168            }
1169
1170            m_name.assign((char*)name_buf.GetBytes());
1171
1172            return true;
1173        }
1174    };
1175
1176    struct class_rw_t {
1177        uint32_t                        m_flags;
1178        uint32_t                        m_version;
1179
1180        lldb::addr_t                    m_ro_ptr;
1181        union {
1182            lldb::addr_t                m_method_list_ptr;
1183            lldb::addr_t                m_method_lists_ptr;
1184        };
1185        lldb::addr_t                    m_properties_ptr;
1186        lldb::addr_t                    m_protocols_ptr;
1187
1188        ObjCLanguageRuntime::ObjCISA    m_firstSubclass;
1189        ObjCLanguageRuntime::ObjCISA    m_nextSiblingClass;
1190
1191        bool Read(Process *process, lldb::addr_t addr)
1192        {
1193            size_t ptr_size = process->GetAddressByteSize();
1194
1195            size_t size = sizeof(uint32_t)  // uint32_t flags;
1196            + sizeof(uint32_t)  // uint32_t version;
1197            + ptr_size          // const class_ro_t *ro;
1198            + ptr_size          // union { method_list_t **method_lists; method_list_t *method_list; };
1199            + ptr_size          // struct chained_property_list *properties;
1200            + ptr_size          // const protocol_list_t **protocols;
1201            + ptr_size          // Class firstSubclass;
1202            + ptr_size;         // Class nextSiblingClass;
1203
1204            DataBufferHeap buffer (size, '\0');
1205            Error error;
1206
1207            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1208            if (error.Fail())
1209            {
1210                return false;
1211            }
1212
1213            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1214
1215            lldb::offset_t cursor = 0;
1216
1217            m_flags             = extractor.GetU32_unchecked(&cursor);
1218            m_version           = extractor.GetU32_unchecked(&cursor);
1219            m_ro_ptr            = extractor.GetAddress_unchecked(&cursor);
1220            m_method_list_ptr   = extractor.GetAddress_unchecked(&cursor);
1221            m_properties_ptr    = extractor.GetAddress_unchecked(&cursor);
1222            m_firstSubclass     = extractor.GetAddress_unchecked(&cursor);
1223            m_nextSiblingClass  = extractor.GetAddress_unchecked(&cursor);
1224
1225            return true;
1226        }
1227    };
1228
1229    struct method_list_t
1230    {
1231        uint32_t        m_entsize;
1232        uint32_t        m_count;
1233        lldb::addr_t    m_first_ptr;
1234
1235        bool Read(Process *process, lldb::addr_t addr)
1236        {
1237            size_t size = sizeof(uint32_t)  // uint32_t entsize_NEVER_USE;
1238            + sizeof(uint32_t); // uint32_t count;
1239
1240            DataBufferHeap buffer (size, '\0');
1241            Error error;
1242
1243            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1244            if (error.Fail())
1245            {
1246                return false;
1247            }
1248
1249            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1250
1251            lldb::offset_t cursor = 0;
1252
1253            m_entsize   = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
1254            m_count     = extractor.GetU32_unchecked(&cursor);
1255            m_first_ptr  = addr + cursor;
1256
1257            return true;
1258        }
1259    };
1260
1261    struct method_t
1262    {
1263        lldb::addr_t    m_name_ptr;
1264        lldb::addr_t    m_types_ptr;
1265        lldb::addr_t    m_imp_ptr;
1266
1267        std::string     m_name;
1268        std::string     m_types;
1269
1270        static size_t GetSize(Process *process)
1271        {
1272            size_t ptr_size = process->GetAddressByteSize();
1273
1274            return ptr_size     // SEL name;
1275            + ptr_size   // const char *types;
1276            + ptr_size;  // IMP imp;
1277        }
1278
1279        bool Read(Process *process, lldb::addr_t addr)
1280        {
1281            size_t size = GetSize(process);
1282
1283            DataBufferHeap buffer (size, '\0');
1284            Error error;
1285
1286            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1287            if (error.Fail())
1288            {
1289                return false;
1290            }
1291
1292            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1293
1294            lldb::offset_t cursor = 0;
1295
1296            m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
1297            m_types_ptr  = extractor.GetAddress_unchecked(&cursor);
1298            m_imp_ptr    = extractor.GetAddress_unchecked(&cursor);
1299
1300            const size_t buffer_size = 1024;
1301            size_t count;
1302
1303            DataBufferHeap string_buf(buffer_size, 0);
1304
1305            count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
1306            m_name.assign((char*)string_buf.GetBytes(), count);
1307
1308            count = process->ReadCStringFromMemory(m_types_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
1309            m_types.assign((char*)string_buf.GetBytes(), count);
1310
1311            return true;
1312        }
1313    };
1314
1315    struct ivar_list_t
1316    {
1317        uint32_t        m_entsize;
1318        uint32_t        m_count;
1319        lldb::addr_t    m_first_ptr;
1320
1321        bool Read(Process *process, lldb::addr_t addr)
1322        {
1323            size_t size = sizeof(uint32_t)  // uint32_t entsize;
1324                        + sizeof(uint32_t); // uint32_t count;
1325
1326            DataBufferHeap buffer (size, '\0');
1327            Error error;
1328
1329            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1330            if (error.Fail())
1331            {
1332                return false;
1333            }
1334
1335            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1336
1337            lldb::offset_t cursor = 0;
1338
1339            m_entsize   = extractor.GetU32_unchecked(&cursor);
1340            m_count     = extractor.GetU32_unchecked(&cursor);
1341            m_first_ptr = addr + cursor;
1342
1343            return true;
1344        }
1345    };
1346
1347    struct ivar_t
1348    {
1349        lldb::addr_t    m_offset_ptr;
1350        lldb::addr_t    m_name_ptr;
1351        lldb::addr_t    m_type_ptr;
1352        uint32_t        m_alignment;
1353        uint32_t        m_size;
1354
1355        std::string     m_name;
1356        std::string     m_type;
1357
1358        static size_t GetSize(Process *process)
1359        {
1360            size_t ptr_size = process->GetAddressByteSize();
1361
1362            return ptr_size             // uintptr_t *offset;
1363                 + ptr_size             // const char *name;
1364                 + ptr_size             // const char *type;
1365                 + sizeof(uint32_t)     // uint32_t alignment;
1366                 + sizeof(uint32_t);    // uint32_t size;
1367        }
1368
1369        bool Read(Process *process, lldb::addr_t addr)
1370        {
1371            size_t size = GetSize(process);
1372
1373            DataBufferHeap buffer (size, '\0');
1374            Error error;
1375
1376            process->ReadMemory(addr, buffer.GetBytes(), size, error);
1377            if (error.Fail())
1378            {
1379                return false;
1380            }
1381
1382            DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
1383
1384            lldb::offset_t cursor = 0;
1385
1386            m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
1387            m_name_ptr   = extractor.GetAddress_unchecked(&cursor);
1388            m_type_ptr   = extractor.GetAddress_unchecked(&cursor);
1389            m_alignment  = extractor.GetU32_unchecked(&cursor);
1390            m_size       = extractor.GetU32_unchecked(&cursor);
1391
1392            const size_t buffer_size = 1024;
1393            size_t count;
1394
1395            DataBufferHeap string_buf(buffer_size, 0);
1396
1397            count = process->ReadCStringFromMemory(m_name_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
1398            m_name.assign((char*)string_buf.GetBytes(), count);
1399
1400            count = process->ReadCStringFromMemory(m_type_ptr, (char*)string_buf.GetBytes(), buffer_size, error);
1401            m_type.assign((char*)string_buf.GetBytes(), count);
1402
1403            return true;
1404        }
1405    };
1406
1407    bool Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class)
1408    {
1409        objc_class.reset(new objc_class_t);
1410
1411        bool ret = objc_class->Read (process, m_objc_class_ptr);
1412
1413        if (!ret)
1414            objc_class.reset();
1415
1416        return ret;
1417    }
1418
1419    bool Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw)
1420    {
1421        class_ro.reset();
1422        class_rw.reset();
1423
1424        Error error;
1425        uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
1426        if (!error.Success())
1427            return false;
1428
1429        if (class_row_t_flags & RW_REALIZED)
1430        {
1431            class_rw.reset(new class_rw_t);
1432
1433            if (!class_rw->Read(process, objc_class.m_data_ptr))
1434            {
1435                class_rw.reset();
1436                return false;
1437            }
1438
1439            class_ro.reset(new class_ro_t);
1440
1441            if (!class_ro->Read(process, class_rw->m_ro_ptr))
1442            {
1443                class_rw.reset();
1444                class_ro.reset();
1445                return false;
1446            }
1447        }
1448        else
1449        {
1450            class_ro.reset(new class_ro_t);
1451
1452            if (!class_ro->Read(process, objc_class.m_data_ptr))
1453            {
1454                class_ro.reset();
1455                return false;
1456            }
1457        }
1458
1459        return true;
1460    }
1461
1462    AppleObjCRuntimeV2 &m_runtime;          // The runtime, so we can read information lazily.
1463    lldb::addr_t        m_objc_class_ptr;   // The address of the objc_class_t.  (I.e., objects of this class type have this as their ISA)
1464    ConstString         m_name;             // May be NULL
1465};
1466
1467// tagged pointer descriptor
1468class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
1469{
1470public:
1471    ClassDescriptorV2Tagged (ConstString class_name,
1472                             uint64_t payload)
1473    {
1474        m_name = class_name;
1475        if (!m_name)
1476        {
1477            m_valid = false;
1478            return;
1479        }
1480        m_valid = true;
1481        m_payload = payload;
1482        m_info_bits = (m_payload & 0xF0ULL) >> 4;
1483        m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
1484    }
1485
1486    ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
1487                             uint64_t payload)
1488    {
1489        if (!actual_class_sp)
1490        {
1491            m_valid = false;
1492            return;
1493        }
1494        m_name = actual_class_sp->GetClassName();
1495        if (!m_name)
1496        {
1497            m_valid = false;
1498            return;
1499        }
1500        m_valid = true;
1501        m_payload = payload;
1502        m_info_bits = (m_payload & 0x0FULL);
1503        m_value_bits = (m_payload & ~0x0FULL) >> 4;
1504    }
1505
1506    virtual ConstString
1507    GetClassName ()
1508    {
1509        return m_name;
1510    }
1511
1512    virtual ObjCLanguageRuntime::ClassDescriptorSP
1513    GetSuperclass ()
1514    {
1515        // tagged pointers can represent a class that has a superclass, but since that information is not
1516        // stored in the object itself, we would have to query the runtime to discover the hierarchy
1517        // for the time being, we skip this step in the interest of static discovery
1518        return ObjCLanguageRuntime::ClassDescriptorSP();
1519    }
1520
1521    virtual bool
1522    IsValid ()
1523    {
1524        return m_valid;
1525    }
1526
1527    virtual bool
1528    IsKVO ()
1529    {
1530        return false; // tagged pointers are not KVO'ed
1531    }
1532
1533    virtual bool
1534    IsCFType ()
1535    {
1536        return false; // tagged pointers are not CF objects
1537    }
1538
1539    virtual bool
1540    GetTaggedPointerInfo (uint64_t* info_bits = NULL,
1541                          uint64_t* value_bits = NULL,
1542                          uint64_t* payload = NULL)
1543    {
1544        if (info_bits)
1545            *info_bits = GetInfoBits();
1546        if (value_bits)
1547            *value_bits = GetValueBits();
1548        if (payload)
1549            *payload = GetPayload();
1550        return true;
1551    }
1552
1553    virtual uint64_t
1554    GetInstanceSize ()
1555    {
1556        return (IsValid() ? m_pointer_size : 0);
1557    }
1558
1559    virtual ObjCLanguageRuntime::ObjCISA
1560    GetISA ()
1561    {
1562        return 0; // tagged pointers have no ISA
1563    }
1564
1565    // these calls are not part of any formal tagged pointers specification
1566    virtual uint64_t
1567    GetValueBits ()
1568    {
1569        return (IsValid() ? m_value_bits : 0);
1570    }
1571
1572    virtual uint64_t
1573    GetInfoBits ()
1574    {
1575        return (IsValid() ? m_info_bits : 0);
1576    }
1577
1578    virtual uint64_t
1579    GetPayload ()
1580    {
1581        return (IsValid() ? m_payload : 0);
1582    }
1583
1584    virtual
1585    ~ClassDescriptorV2Tagged ()
1586    {}
1587
1588private:
1589    ConstString m_name;
1590    uint8_t m_pointer_size;
1591    bool m_valid;
1592    uint64_t m_info_bits;
1593    uint64_t m_value_bits;
1594    uint64_t m_payload;
1595
1596};
1597
1598ObjCLanguageRuntime::ClassDescriptorSP
1599AppleObjCRuntimeV2::GetClassDescriptor (ObjCISA isa)
1600{
1601    ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
1602    if (m_non_pointer_isa_cache_ap.get())
1603        class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
1604    if (!class_descriptor_sp)
1605        class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
1606    return class_descriptor_sp;
1607}
1608
1609ObjCLanguageRuntime::ClassDescriptorSP
1610AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
1611{
1612    ClassDescriptorSP objc_class_sp;
1613    // if we get an invalid VO (which might still happen when playing around
1614    // with pointers returned by the expression parser, don't consider this
1615    // a valid ObjC object)
1616    if (valobj.GetClangType().IsValid())
1617    {
1618        addr_t isa_pointer = valobj.GetPointerValue();
1619
1620        // tagged pointer
1621        if (IsTaggedPointer(isa_pointer))
1622        {
1623            return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
1624        }
1625        else
1626        {
1627            ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
1628
1629            Process *process = exe_ctx.GetProcessPtr();
1630            if (process)
1631            {
1632                Error error;
1633                ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
1634                if (isa != LLDB_INVALID_ADDRESS)
1635                {
1636                    objc_class_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA (isa);
1637                    if (isa && !objc_class_sp)
1638                    {
1639                        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1640                        if (log)
1641                            log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
1642                                        isa_pointer,
1643                                        isa);
1644                    }
1645                }
1646            }
1647        }
1648    }
1649    return objc_class_sp;
1650}
1651
1652lldb::addr_t
1653AppleObjCRuntimeV2::GetISAHashTablePointer ()
1654{
1655    if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
1656    {
1657        Process *process = GetProcess();
1658
1659        ModuleSP objc_module_sp(GetObjCModule());
1660
1661        if (!objc_module_sp)
1662            return LLDB_INVALID_ADDRESS;
1663
1664        static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
1665
1666        const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeData);
1667        if (symbol)
1668        {
1669            lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetAddress().GetLoadAddress(&process->GetTarget());
1670
1671            if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
1672            {
1673                Error error;
1674                m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
1675            }
1676        }
1677    }
1678    return m_isa_hash_table_ptr;
1679}
1680
1681bool
1682AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
1683{
1684    Process *process = GetProcess();
1685
1686    if (process == NULL)
1687        return false;
1688
1689    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1690
1691    ExecutionContext exe_ctx;
1692
1693    ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
1694
1695    if (!thread_sp)
1696        return false;
1697
1698    thread_sp->CalculateExecutionContext(exe_ctx);
1699    ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1700
1701    if (!ast)
1702        return false;
1703
1704    Address function_address;
1705
1706    StreamString errors;
1707
1708    const uint32_t addr_size = process->GetAddressByteSize();
1709
1710    Error err;
1711
1712    // Read the total number of classes from the hash table
1713    const uint32_t num_classes = hash_table.GetCount();
1714    if (num_classes == 0)
1715    {
1716        if (log)
1717            log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
1718        return false;
1719    }
1720
1721    // Make some types for our arguments
1722    ClangASTType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1723    ClangASTType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1724
1725    if (!m_get_class_info_code.get())
1726    {
1727        m_get_class_info_code.reset (new ClangUtilityFunction (g_get_dynamic_class_info_body,
1728                                                               g_get_dynamic_class_info_name));
1729
1730        errors.Clear();
1731
1732        if (!m_get_class_info_code->Install(errors, exe_ctx))
1733        {
1734            if (log)
1735                log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
1736            m_get_class_info_code.reset();
1737        }
1738    }
1739
1740    if (m_get_class_info_code.get())
1741        function_address.SetOffset(m_get_class_info_code->StartAddress());
1742    else
1743        return false;
1744
1745    ValueList arguments;
1746
1747    // Next make the runner function for our implementation utility function.
1748    if (!m_get_class_info_function.get())
1749    {
1750        Value value;
1751        value.SetValueType (Value::eValueTypeScalar);
1752//        value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
1753        value.SetClangType (clang_void_pointer_type);
1754        arguments.PushValue (value);
1755        arguments.PushValue (value);
1756
1757        value.SetValueType (Value::eValueTypeScalar);
1758//        value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
1759        value.SetClangType (clang_uint32_t_type);
1760        arguments.PushValue (value);
1761
1762        m_get_class_info_function.reset(new ClangFunction (*m_process,
1763                                                           clang_uint32_t_type,
1764                                                           function_address,
1765                                                           arguments));
1766
1767        if (m_get_class_info_function.get() == NULL)
1768            return false;
1769
1770        errors.Clear();
1771
1772        unsigned num_errors = m_get_class_info_function->CompileFunction(errors);
1773        if (num_errors)
1774        {
1775            if (log)
1776                log->Printf ("Error compiling function: \"%s\".", errors.GetData());
1777            return false;
1778        }
1779
1780        errors.Clear();
1781
1782        if (!m_get_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
1783        {
1784            if (log)
1785                log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
1786            return false;
1787        }
1788    }
1789    else
1790    {
1791        arguments = m_get_class_info_function->GetArgumentValues ();
1792    }
1793
1794    const uint32_t class_info_byte_size = addr_size + 4;
1795    const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
1796    lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
1797                                                            ePermissionsReadable | ePermissionsWritable,
1798                                                            err);
1799
1800    if (class_infos_addr == LLDB_INVALID_ADDRESS)
1801        return false;
1802
1803    Mutex::Locker locker(m_get_class_info_args_mutex);
1804
1805    // Fill in our function argument values
1806    arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
1807    arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
1808    arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
1809
1810    bool success = false;
1811
1812    errors.Clear();
1813
1814    // Write our function arguments into the process so we can run our function
1815    if (m_get_class_info_function->WriteFunctionArguments (exe_ctx,
1816                                                           m_get_class_info_args,
1817                                                           function_address,
1818                                                           arguments,
1819                                                           errors))
1820    {
1821        bool stop_others = true;
1822        bool try_all_threads = false;
1823        bool unwind_on_error = true;
1824        bool ignore_breakpoints = true;
1825
1826        Value return_value;
1827        return_value.SetValueType (Value::eValueTypeScalar);
1828        //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
1829        return_value.SetClangType (clang_uint32_t_type);
1830        return_value.GetScalar() = 0;
1831
1832        errors.Clear();
1833
1834        // Run the function
1835        ExecutionResults results = m_get_class_info_function->ExecuteFunction (exe_ctx,
1836                                                                               &m_get_class_info_args,
1837                                                                               errors,
1838                                                                               stop_others,
1839                                                                               UTILITY_FUNCTION_TIMEOUT_USEC,
1840                                                                               try_all_threads,
1841                                                                               unwind_on_error,
1842                                                                               ignore_breakpoints,
1843                                                                               return_value);
1844
1845        if (results == eExecutionCompleted)
1846        {
1847            // The result is the number of ClassInfo structures that were filled in
1848            uint32_t num_class_infos = return_value.GetScalar().ULong();
1849            if (log)
1850                log->Printf("Discovered %u ObjC classes\n",num_class_infos);
1851            if (num_class_infos > 0)
1852            {
1853                // Read the ClassInfo structures
1854                DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
1855                if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
1856                {
1857                    DataExtractor class_infos_data (buffer.GetBytes(),
1858                                                    buffer.GetByteSize(),
1859                                                    process->GetByteOrder(),
1860                                                    addr_size);
1861                    ParseClassInfoArray (class_infos_data, num_class_infos);
1862                }
1863            }
1864            success = true;
1865        }
1866        else
1867        {
1868            if (log)
1869                log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
1870        }
1871    }
1872    else
1873    {
1874        if (log)
1875            log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
1876    }
1877
1878    // Deallocate the memory we allocated for the ClassInfo array
1879    process->DeallocateMemory(class_infos_addr);
1880
1881    return success;
1882}
1883
1884void
1885AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
1886{
1887    // Parses an array of "num_class_infos" packed ClassInfo structures:
1888    //
1889    //    struct ClassInfo
1890    //    {
1891    //        Class isa;
1892    //        uint32_t hash;
1893    //    } __attribute__((__packed__));
1894
1895    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1896
1897    // Iterate through all ClassInfo structures
1898    lldb::offset_t offset = 0;
1899    for (uint32_t i=0; i<num_class_infos; ++i)
1900    {
1901        ObjCISA isa = data.GetPointer(&offset);
1902
1903        if (isa == 0)
1904        {
1905            if (log)
1906                log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
1907            continue;
1908        }
1909        // Check if we already know about this ISA, if we do, the info will
1910        // never change, so we can just skip it.
1911        if (ISAIsCached(isa))
1912        {
1913            offset += 4;
1914        }
1915        else
1916        {
1917            // Read the 32 bit hash for the class name
1918            const uint32_t name_hash = data.GetU32(&offset);
1919            ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
1920            AddClass (isa, descriptor_sp, name_hash);
1921            if (log && log->GetVerbose())
1922                log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x", isa, name_hash);
1923        }
1924    }
1925}
1926
1927bool
1928AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
1929{
1930    Process *process = GetProcess();
1931
1932    if (process == NULL)
1933        return false;
1934
1935    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
1936
1937    ExecutionContext exe_ctx;
1938
1939    ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
1940
1941    if (!thread_sp)
1942        return false;
1943
1944    thread_sp->CalculateExecutionContext(exe_ctx);
1945    ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
1946
1947    if (!ast)
1948        return false;
1949
1950    Address function_address;
1951
1952    StreamString errors;
1953
1954    const uint32_t addr_size = process->GetAddressByteSize();
1955
1956    Error err;
1957
1958    const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
1959
1960    if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
1961        return false;
1962
1963    // Read the total number of classes from the hash table
1964    const uint32_t num_classes = 16*1024;
1965    if (num_classes == 0)
1966    {
1967        if (log)
1968            log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
1969        return false;
1970    }
1971
1972    // Make some types for our arguments
1973    ClangASTType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1974    ClangASTType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
1975
1976    if (!m_get_shared_cache_class_info_code.get())
1977    {
1978        m_get_shared_cache_class_info_code.reset (new ClangUtilityFunction (g_get_shared_cache_class_info_body,
1979                                                                            g_get_shared_cache_class_info_name));
1980
1981        errors.Clear();
1982
1983        if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
1984        {
1985            if (log)
1986                log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
1987            m_get_shared_cache_class_info_code.reset();
1988        }
1989    }
1990
1991    if (m_get_shared_cache_class_info_code.get())
1992        function_address.SetOffset(m_get_shared_cache_class_info_code->StartAddress());
1993    else
1994        return false;
1995
1996    ValueList arguments;
1997
1998    // Next make the runner function for our implementation utility function.
1999    if (!m_get_shared_cache_class_info_function.get())
2000    {
2001        Value value;
2002        value.SetValueType (Value::eValueTypeScalar);
2003        //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
2004        value.SetClangType (clang_void_pointer_type);
2005        arguments.PushValue (value);
2006        arguments.PushValue (value);
2007
2008        value.SetValueType (Value::eValueTypeScalar);
2009        //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
2010        value.SetClangType (clang_uint32_t_type);
2011        arguments.PushValue (value);
2012
2013        m_get_shared_cache_class_info_function.reset(new ClangFunction (*m_process,
2014                                                                        clang_uint32_t_type,
2015                                                                        function_address,
2016                                                                        arguments));
2017
2018        if (m_get_shared_cache_class_info_function.get() == NULL)
2019            return false;
2020
2021        errors.Clear();
2022
2023        unsigned num_errors = m_get_shared_cache_class_info_function->CompileFunction(errors);
2024        if (num_errors)
2025        {
2026            if (log)
2027                log->Printf ("Error compiling function: \"%s\".", errors.GetData());
2028            return false;
2029        }
2030
2031        errors.Clear();
2032
2033        if (!m_get_shared_cache_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
2034        {
2035            if (log)
2036                log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
2037            return false;
2038        }
2039    }
2040    else
2041    {
2042        arguments = m_get_shared_cache_class_info_function->GetArgumentValues ();
2043    }
2044
2045    const uint32_t class_info_byte_size = addr_size + 4;
2046    const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
2047    lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
2048                                                             ePermissionsReadable | ePermissionsWritable,
2049                                                             err);
2050
2051    if (class_infos_addr == LLDB_INVALID_ADDRESS)
2052        return false;
2053
2054    Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
2055
2056    // Fill in our function argument values
2057    arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
2058    arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
2059    arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
2060
2061    bool success = false;
2062
2063    errors.Clear();
2064
2065    // Write our function arguments into the process so we can run our function
2066    if (m_get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
2067                                                                        m_get_shared_cache_class_info_args,
2068                                                                        function_address,
2069                                                                        arguments,
2070                                                                        errors))
2071    {
2072        bool stop_others = true;
2073        bool try_all_threads = false;
2074        bool unwind_on_error = true;
2075        bool ignore_breakpoints = true;
2076
2077        Value return_value;
2078        return_value.SetValueType (Value::eValueTypeScalar);
2079        //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
2080        return_value.SetClangType (clang_uint32_t_type);
2081        return_value.GetScalar() = 0;
2082
2083        errors.Clear();
2084
2085        // Run the function
2086        ExecutionResults results = m_get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
2087                                                                                            &m_get_shared_cache_class_info_args,
2088                                                                                            errors,
2089                                                                                            stop_others,
2090                                                                                            UTILITY_FUNCTION_TIMEOUT_USEC,
2091                                                                                            try_all_threads,
2092                                                                                            unwind_on_error,
2093                                                                                            ignore_breakpoints,
2094                                                                                            return_value);
2095
2096        if (results == eExecutionCompleted)
2097        {
2098            // The result is the number of ClassInfo structures that were filled in
2099            uint32_t num_class_infos = return_value.GetScalar().ULong();
2100            if (log)
2101                log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
2102            if (num_class_infos > 0)
2103            {
2104                // Read the ClassInfo structures
2105                DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
2106                if (process->ReadMemory(class_infos_addr,
2107                                        buffer.GetBytes(),
2108                                        buffer.GetByteSize(),
2109                                        err) == buffer.GetByteSize())
2110                {
2111                    DataExtractor class_infos_data (buffer.GetBytes(),
2112                                                    buffer.GetByteSize(),
2113                                                    process->GetByteOrder(),
2114                                                    addr_size);
2115
2116                    ParseClassInfoArray (class_infos_data, num_class_infos);
2117                }
2118            }
2119            success = true;
2120        }
2121        else
2122        {
2123            if (log)
2124                log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
2125        }
2126    }
2127    else
2128    {
2129        if (log)
2130            log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
2131    }
2132
2133    // Deallocate the memory we allocated for the ClassInfo array
2134    process->DeallocateMemory(class_infos_addr);
2135
2136    return success;
2137}
2138
2139
2140bool
2141AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
2142{
2143    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
2144
2145    Process *process = GetProcess();
2146
2147    if (process == NULL)
2148        return false;
2149
2150    uint32_t num_map_table_isas = 0;
2151
2152    ModuleSP objc_module_sp(GetObjCModule());
2153
2154    if (objc_module_sp)
2155    {
2156        for (RemoteNXMapTable::element elt : hash_table)
2157        {
2158            ++num_map_table_isas;
2159
2160            if (ISAIsCached(elt.second))
2161                continue;
2162
2163            ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
2164
2165            if (log && log->GetVerbose())
2166                log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
2167
2168            AddClass (elt.second, descriptor_sp, elt.first.AsCString());
2169        }
2170    }
2171
2172    return num_map_table_isas > 0;
2173}
2174
2175lldb::addr_t
2176AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
2177{
2178    Process *process = GetProcess();
2179
2180    if (process)
2181    {
2182        ModuleSP objc_module_sp(GetObjCModule());
2183
2184        if (objc_module_sp)
2185        {
2186            ObjectFile *objc_object = objc_module_sp->GetObjectFile();
2187
2188            if (objc_object)
2189            {
2190                SectionList *section_list = objc_module_sp->GetSectionList();
2191
2192                if (section_list)
2193                {
2194                    SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
2195
2196                    if (text_segment_sp)
2197                    {
2198                        SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
2199
2200                        if (objc_opt_section_sp)
2201                        {
2202                            return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
2203                        }
2204                    }
2205                }
2206            }
2207        }
2208    }
2209    return LLDB_INVALID_ADDRESS;
2210}
2211
2212void
2213AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
2214{
2215    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
2216
2217    // Else we need to check with our process to see when the map was updated.
2218    Process *process = GetProcess();
2219
2220    if (process)
2221    {
2222        RemoteNXMapTable hash_table;
2223
2224        // Update the process stop ID that indicates the last time we updated the
2225        // map, wether it was successful or not.
2226        m_isa_to_descriptor_stop_id = process->GetStopID();
2227
2228        if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
2229            return;
2230
2231        m_hash_signature.UpdateSignature (hash_table);
2232
2233        // Grab the dynamicly loaded objc classes from the hash table in memory
2234        UpdateISAToDescriptorMapDynamic(hash_table);
2235
2236        // Now get the objc classes that are baked into the Objective C runtime
2237        // in the shared cache, but only once per process as this data never
2238        // changes
2239        if (!m_loaded_objc_opt)
2240            UpdateISAToDescriptorMapSharedCache();
2241    }
2242    else
2243    {
2244        m_isa_to_descriptor_stop_id = UINT32_MAX;
2245    }
2246}
2247
2248
2249// TODO: should we have a transparent_kvo parameter here to say if we
2250// want to replace the KVO swizzled class with the actual user-level type?
2251ConstString
2252AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
2253{
2254    if (isa == g_objc_Tagged_ISA)
2255    {
2256        static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
2257        return g_objc_tagged_isa_name;
2258    }
2259    if (isa == g_objc_Tagged_ISA_NSAtom)
2260    {
2261        static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
2262        return g_objc_tagged_isa_nsatom_name;
2263    }
2264    if (isa == g_objc_Tagged_ISA_NSNumber)
2265    {
2266        static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
2267        return g_objc_tagged_isa_nsnumber_name;
2268    }
2269    if (isa == g_objc_Tagged_ISA_NSDateTS)
2270    {
2271        static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
2272        return g_objc_tagged_isa_nsdatets_name;
2273    }
2274    if (isa == g_objc_Tagged_ISA_NSManagedObject)
2275    {
2276        static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
2277        return g_objc_tagged_isa_nsmanagedobject_name;
2278    }
2279    if (isa == g_objc_Tagged_ISA_NSDate)
2280    {
2281        static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
2282        return g_objc_tagged_isa_nsdate_name;
2283    }
2284    return ObjCLanguageRuntime::GetActualTypeName(isa);
2285}
2286
2287TypeVendor *
2288AppleObjCRuntimeV2::GetTypeVendor()
2289{
2290    if (!m_type_vendor_ap.get())
2291        m_type_vendor_ap.reset(new AppleObjCTypeVendor(*this));
2292
2293    return m_type_vendor_ap.get();
2294}
2295
2296lldb::addr_t
2297AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
2298{
2299    lldb::addr_t ret = LLDB_INVALID_ADDRESS;
2300
2301    const char *name_cstr = name.AsCString();
2302
2303    if (name_cstr)
2304    {
2305        llvm::StringRef name_strref(name_cstr);
2306
2307        static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
2308        static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
2309
2310        if (name_strref.startswith(ivar_prefix))
2311        {
2312            llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
2313            std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
2314
2315            if (class_and_ivar.first.size() && class_and_ivar.second.size())
2316            {
2317                const ConstString class_name_cs(class_and_ivar.first);
2318                ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
2319
2320                if (descriptor)
2321                {
2322                    const ConstString ivar_name_cs(class_and_ivar.second);
2323                    const char *ivar_name_cstr = ivar_name_cs.AsCString();
2324
2325                    auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
2326                    {
2327                        if (!strcmp(name, ivar_name_cstr))
2328                        {
2329                            ret = offset_addr;
2330                            return true;
2331                        }
2332                        return false;
2333                    };
2334
2335                    descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
2336                                         std::function<bool (const char *, const char *)>(nullptr),
2337                                         std::function<bool (const char *, const char *)>(nullptr),
2338                                         ivar_func);
2339                }
2340            }
2341        }
2342        else if (name_strref.startswith(class_prefix))
2343        {
2344            llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
2345            const ConstString class_name_cs(class_skipped_prefix);
2346            ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
2347
2348            if (descriptor)
2349                ret = descriptor->GetISA();
2350        }
2351    }
2352
2353    return ret;
2354}
2355
2356AppleObjCRuntimeV2::NonPointerISACache*
2357AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
2358{
2359    Process* process(runtime.GetProcess());
2360
2361    Error error;
2362
2363    auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
2364                                                                ConstString("objc_debug_isa_magic_mask"),
2365                                                                objc_module_sp,
2366                                                                error);
2367    if (error.Fail())
2368        return NULL;
2369
2370    auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
2371                                                                 ConstString("objc_debug_isa_magic_value"),
2372                                                                 objc_module_sp,
2373                                                                 error);
2374    if (error.Fail())
2375        return NULL;
2376
2377    auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
2378                                                                ConstString("objc_debug_isa_class_mask"),
2379                                                                objc_module_sp,
2380                                                                error);
2381    if (error.Fail())
2382        return NULL;
2383
2384    // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
2385
2386    return new NonPointerISACache(runtime,
2387                                  objc_debug_isa_class_mask,
2388                                  objc_debug_isa_magic_mask,
2389                                  objc_debug_isa_magic_value);
2390}
2391
2392AppleObjCRuntimeV2::TaggedPointerVendor*
2393AppleObjCRuntimeV2::TaggedPointerVendor::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
2394{
2395    Process* process(runtime.GetProcess());
2396
2397    Error error;
2398
2399    auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
2400                                                                    ConstString("objc_debug_taggedpointer_mask"),
2401                                                                    objc_module_sp,
2402                                                                    error);
2403    if (error.Fail())
2404        return new TaggedPointerVendorLegacy(runtime);
2405
2406    auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
2407                                                                          ConstString("objc_debug_taggedpointer_slot_shift"),
2408                                                                          objc_module_sp,
2409                                                                          error,
2410                                                                          true,
2411                                                                          4);
2412    if (error.Fail())
2413        return new TaggedPointerVendorLegacy(runtime);
2414
2415    auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
2416                                                                          ConstString("objc_debug_taggedpointer_slot_mask"),
2417                                                                          objc_module_sp,
2418                                                                          error,
2419                                                                          true,
2420                                                                          4);
2421    if (error.Fail())
2422        return new TaggedPointerVendorLegacy(runtime);
2423
2424    auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
2425                                                                              ConstString("objc_debug_taggedpointer_payload_lshift"),
2426                                                                              objc_module_sp,
2427                                                                              error,
2428                                                                              true,
2429                                                                              4);
2430    if (error.Fail())
2431        return new TaggedPointerVendorLegacy(runtime);
2432
2433    auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
2434                                                                              ConstString("objc_debug_taggedpointer_payload_rshift"),
2435                                                                              objc_module_sp,
2436                                                                              error,
2437                                                                              true,
2438                                                                              4);
2439    if (error.Fail())
2440        return new TaggedPointerVendorLegacy(runtime);
2441
2442    auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
2443                                                                       ConstString("objc_debug_taggedpointer_classes"),
2444                                                                       objc_module_sp,
2445                                                                       error,
2446                                                                       false);
2447    if (error.Fail())
2448        return new TaggedPointerVendorLegacy(runtime);
2449
2450
2451    // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
2452
2453    return new TaggedPointerVendorRuntimeAssisted(runtime,
2454                                                  objc_debug_taggedpointer_mask,
2455                                                  objc_debug_taggedpointer_slot_shift,
2456                                                  objc_debug_taggedpointer_slot_mask,
2457                                                  objc_debug_taggedpointer_payload_lshift,
2458                                                  objc_debug_taggedpointer_payload_rshift,
2459                                                  objc_debug_taggedpointer_classes);
2460}
2461
2462bool
2463AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
2464{
2465    return (ptr & 1);
2466}
2467
2468// we use the version of Foundation to make assumptions about the ObjC runtime on a target
2469uint32_t
2470AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetFoundationVersion (Target &target)
2471{
2472    const ModuleList& modules = target.GetImages();
2473    uint32_t major = UINT32_MAX;
2474    for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
2475    {
2476        lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
2477        if (!module_sp)
2478            continue;
2479        if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
2480        {
2481            module_sp->GetVersion(&major,1);
2482            break;
2483        }
2484    }
2485    return major;
2486}
2487
2488ObjCLanguageRuntime::ClassDescriptorSP
2489AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
2490{
2491    if (!IsPossibleTaggedPointer(ptr))
2492        return ObjCLanguageRuntime::ClassDescriptorSP();
2493
2494    Process* process(m_runtime.GetProcess());
2495
2496    if (m_Foundation_version == 0)
2497        m_Foundation_version = GetFoundationVersion(process->GetTarget());
2498
2499    if (m_Foundation_version == UINT32_MAX)
2500        return ObjCLanguageRuntime::ClassDescriptorSP();
2501
2502    uint64_t class_bits = (ptr & 0xE) >> 1;
2503    ConstString name;
2504
2505    // TODO: make a table
2506    if (m_Foundation_version >= 900)
2507    {
2508        switch (class_bits)
2509        {
2510            case 0:
2511                name = ConstString("NSAtom");
2512                break;
2513            case 3:
2514                name = ConstString("NSNumber");
2515                break;
2516            case 4:
2517                name = ConstString("NSDateTS");
2518                break;
2519            case 5:
2520                name = ConstString("NSManagedObject");
2521                break;
2522            case 6:
2523                name = ConstString("NSDate");
2524                break;
2525            default:
2526                return ObjCLanguageRuntime::ClassDescriptorSP();
2527        }
2528    }
2529    else
2530    {
2531        switch (class_bits)
2532        {
2533            case 1:
2534                name = ConstString("NSNumber");
2535                break;
2536            case 5:
2537                name = ConstString("NSManagedObject");
2538                break;
2539            case 6:
2540                name = ConstString("NSDate");
2541                break;
2542            case 7:
2543                name = ConstString("NSDateTS");
2544                break;
2545            default:
2546                return ObjCLanguageRuntime::ClassDescriptorSP();
2547        }
2548    }
2549    return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
2550}
2551
2552AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
2553                                                                                            uint64_t objc_debug_taggedpointer_mask,
2554                                                                                            uint32_t objc_debug_taggedpointer_slot_shift,
2555                                                                                            uint32_t objc_debug_taggedpointer_slot_mask,
2556                                                                                            uint32_t objc_debug_taggedpointer_payload_lshift,
2557                                                                                            uint32_t objc_debug_taggedpointer_payload_rshift,
2558                                                                                            lldb::addr_t objc_debug_taggedpointer_classes) :
2559TaggedPointerVendor(runtime),
2560m_cache(),
2561m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
2562m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
2563m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
2564m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
2565m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
2566m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
2567{
2568}
2569
2570bool
2571AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
2572{
2573    return (ptr & m_objc_debug_taggedpointer_mask) != 0;
2574}
2575
2576ObjCLanguageRuntime::ClassDescriptorSP
2577AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
2578{
2579    ClassDescriptorSP actual_class_descriptor_sp;
2580    uint64_t data_payload;
2581
2582    if (!IsPossibleTaggedPointer(ptr))
2583        return ObjCLanguageRuntime::ClassDescriptorSP();
2584
2585    uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
2586
2587    CacheIterator iterator = m_cache.find(slot),
2588    end = m_cache.end();
2589    if (iterator != end)
2590    {
2591        actual_class_descriptor_sp = iterator->second;
2592    }
2593    else
2594    {
2595        Process* process(m_runtime.GetProcess());
2596        uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
2597        Error error;
2598        uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
2599        if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
2600            return nullptr;
2601        actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
2602        if (!actual_class_descriptor_sp)
2603            return ObjCLanguageRuntime::ClassDescriptorSP();
2604        m_cache[slot] = actual_class_descriptor_sp;
2605    }
2606
2607    data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
2608
2609    return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
2610}
2611
2612AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
2613                                                            uint64_t objc_debug_isa_class_mask,
2614                                                            uint64_t objc_debug_isa_magic_mask,
2615                                                            uint64_t objc_debug_isa_magic_value) :
2616m_runtime(runtime),
2617m_cache(),
2618m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
2619m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
2620m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
2621{
2622}
2623
2624ObjCLanguageRuntime::ClassDescriptorSP
2625AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
2626{
2627    ObjCISA real_isa = 0;
2628    if (EvaluateNonPointerISA(isa, real_isa) == false)
2629        return ObjCLanguageRuntime::ClassDescriptorSP();
2630    auto cache_iter = m_cache.find(real_isa);
2631    if (cache_iter != m_cache.end())
2632        return cache_iter->second;
2633    auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
2634    if (descriptor_sp) // cache only positive matches since the table might grow
2635        m_cache[real_isa] = descriptor_sp;
2636    return descriptor_sp;
2637}
2638
2639bool
2640AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
2641{
2642    if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
2643        return false;
2644    if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
2645    {
2646        ret_isa = isa & m_objc_debug_isa_class_mask;
2647        return (ret_isa != 0); // this is a pointer so 0 is not a valid value
2648    }
2649    return false;
2650}
2651