1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 #define OBJC_IMAGE_SUPPORTS_GC (1<<1)
26 #define OBJC_IMAGE_REQUIRES_GC (1<<2)
29 struct objc_image_info
{
33 uint32_t getFlags() INLINE
{ return A::P::E::get32(flags
); }
35 bool supportsGCFlagSet() INLINE
{ return getFlags() & OBJC_IMAGE_SUPPORTS_GC
; }
36 bool requiresGCFlagSet() INLINE
{ return getFlags() & OBJC_IMAGE_REQUIRES_GC
; }
38 void setFlag(uint32_t bits
) INLINE
{ uint32_t old
= A::P::E::get32(flags
); A::P::E::set32(flags
, old
| bits
); }
39 void setOptimizedByDyld() INLINE
{ setFlag(1<<3); }
44 uint32_t method_name
; // SEL
45 uint32_t method_types
; // char *
46 uint32_t method_imp
; // IMP
48 uint32_t getName() const INLINE
{ return A::P::E::get32(method_name
); }
49 void setName(uint32_t newName
) INLINE
{ A::P::E::set32(method_name
, newName
); }
53 struct objc_method_list
{
54 enum { OBJC_FIXED_UP
= 1771 };
55 uint32_t obsolete
; // struct objc_method_list *
56 uint32_t method_count
; // int
57 struct objc_method
<A
> method_list
[0];
59 uint32_t getCount() const INLINE
{ return A::P::E::get32(method_count
); }
60 void setFixedUp(bool fixed
) INLINE
{ A::P::E::set32(obsolete
, fixed
? OBJC_FIXED_UP
: 0); }
65 uint32_t isa
; // struct objc_class *
66 uint32_t super_class
; // struct objc_class *
67 uint32_t name
; // const char *
68 uint32_t version
; // long
69 uint32_t info
; // long
70 uint32_t instance_size
; // long
71 uint32_t ivars
; // struct objc_ivar_list *
72 uint32_t methodList
; // struct objc_method_list *
73 uint32_t method_cache
; // struct objc_cache *
74 uint32_t protocols
; // objc_protocol_list *
75 uint32_t ivar_layout
; // const char *
76 uint32_t ext
; // struct objc_class_ext *
78 struct objc_class
<A
> *getIsa(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_class
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(isa
)); }
79 struct objc_method_list
<A
> *getMethodList(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_method_list
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(methodList
)); }
83 struct objc_category
{
84 uint32_t category_name
; // char *
85 uint32_t class_name
; // char *
86 uint32_t instance_methods
; // struct objc_method_list *
87 uint32_t class_methods
; // struct objc_method_list *
88 uint32_t protocols
; // objc_protocol_list *
89 uint32_t size
; // uint32_t
90 uint32_t instance_properties
; // struct objc_property_list *
92 struct objc_method_list
<A
> *getInstanceMethods(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_method_list
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(instance_methods
)); }
93 struct objc_method_list
<A
> *getClassMethods(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_method_list
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(class_methods
)); }
98 uint32_t sel_ref_cnt
; // unsigned long
99 uint32_t refs
; // SEL *
100 uint16_t cls_def_cnt
; // unsigned short
101 uint16_t cat_def_cnt
; // unsigned short
102 uint32_t defs
[0]; // void *
104 uint16_t getClassCount(void) const INLINE
{ return A::P::E::get16(cls_def_cnt
); }
105 uint16_t getCategoryCount(void) const INLINE
{ return A::P::E::get16(cat_def_cnt
); }
106 struct objc_class
<A
> *getClass(SharedCache
<A
> *cache
, int index
) const INLINE
{ return (struct objc_class
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(defs
[index
])); }
107 struct objc_category
<A
> *getCategory(SharedCache
<A
> *cache
, int index
) const INLINE
{ return (struct objc_category
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(defs
[getClassCount() + index
])); }
110 template <typename A
>
112 uint32_t version
; // unsigned long
113 uint32_t size
; // unsigned long
114 uint32_t name
; // char*
115 uint32_t symtab
; // Symtab
117 struct objc_symtab
<A
> *getSymtab(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_symtab
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(symtab
)); }
120 template <typename A
>
121 struct objc_method_description
{
122 uint32_t name
; // SEL
123 uint32_t types
; // char *
125 uint32_t getName() const INLINE
{ return A::P::E::get32(name
); }
126 void setName(uint32_t newName
) INLINE
{ A::P::E::set32(name
, newName
); }
129 template <typename A
>
130 struct objc_method_description_list
{
131 uint32_t count
; // int
132 struct objc_method_description
<A
> list
[0];
134 uint32_t getCount() const INLINE
{ return A::P::E::get32(count
); }
137 template <typename A
>
138 struct objc_protocol
{
139 uint32_t isa
; // danger! contains strange values!
140 uint32_t protocol_name
; // const char *
141 uint32_t protocol_list
; // struct objc_protocol_list
142 uint32_t instance_methods
; // struct objc_method_description_list *
143 uint32_t class_methods
; // struct objc_method_description_list *
145 struct objc_method_description_list
<A
> *getInstanceMethodDescriptions(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_method_description_list
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(instance_methods
)); }
146 struct objc_method_description_list
<A
> *getClassMethodDescriptions(SharedCache
<A
> *cache
) const INLINE
{ return (struct objc_method_description_list
<A
> *)cache
->mappedAddressForVMAddress(A::P::E::get32(class_methods
)); }
150 template <typename A
, typename V
>
151 class LegacySelectorUpdater
{
153 typedef typename
A::P P
;
155 static void visitMethodList(objc_method_list
<A
> *mlist
, V
& visitor
)
157 for (uint32_t m
= 0; m
< mlist
->getCount(); m
++) {
158 uint64_t oldValue
= mlist
->method_list
[m
].getName();
159 uint64_t newValue
= visitor
.visit(oldValue
);
160 mlist
->method_list
[m
].setName(newValue
);
162 mlist
->setFixedUp(true);
165 static void visitMethodDescriptionList(objc_method_description_list
<A
> *mlist
, V
& visitor
)
167 for (uint32_t m
= 0; m
< mlist
->getCount(); m
++) {
168 uint64_t oldValue
= mlist
->list
[m
].getName();
169 uint64_t newValue
= visitor
.visit(oldValue
);
170 mlist
->list
[m
].setName(newValue
);
176 static void update(SharedCache
<A
>* cache
, const macho_header
<P
>* header
,
179 ArraySection
<A
, objc_module
<A
> >
180 modules(cache
, header
, "__OBJC", "__module_info");
181 for (uint64_t m
= 0; m
< modules
.count(); m
++) {
182 objc_symtab
<A
> *symtab
= modules
.get(m
).getSymtab(cache
);
183 if (!symtab
) continue;
185 // Method lists in classes
186 for (uint64_t c
= 0; c
< symtab
->getClassCount(); c
++) {
187 objc_class
<A
> *cls
= symtab
->getClass(cache
, c
);
188 objc_class
<A
> *isa
= cls
->getIsa(cache
);
189 objc_method_list
<A
> *mlist
;
190 if ((mlist
= cls
->getMethodList(cache
))) {
191 visitMethodList(mlist
, visitor
);
193 if ((mlist
= isa
->getMethodList(cache
))) {
194 visitMethodList(mlist
, visitor
);
198 // Method lists from categories
199 for (uint64_t c
= 0; c
< symtab
->getCategoryCount(); c
++) {
200 objc_category
<A
> *cat
= symtab
->getCategory(cache
, c
);
201 objc_method_list
<A
> *mlist
;
202 if ((mlist
= cat
->getInstanceMethods(cache
))) {
203 visitMethodList(mlist
, visitor
);
205 if ((mlist
= cat
->getClassMethods(cache
))) {
206 visitMethodList(mlist
, visitor
);
211 // Method description lists from protocols
212 ArraySection
<A
, objc_protocol
<A
> >
213 protocols(cache
, header
, "__OBJC", "__protocol");
214 for (uint64_t p
= 0; p
< protocols
.count(); p
++) {
215 objc_protocol
<A
>& protocol
= protocols
.get(p
);
216 objc_method_description_list
<A
> *mlist
;
217 if ((mlist
= protocol
.getInstanceMethodDescriptions(cache
))) {
218 visitMethodDescriptionList(mlist
, visitor
);
220 if ((mlist
= protocol
.getClassMethodDescriptions(cache
))) {
221 visitMethodDescriptionList(mlist
, visitor
);
226 PointerSection
<A
, const char *> selrefs(cache
, header
, "__OBJC", "__message_refs");
227 for (uint64_t s
= 0; s
< selrefs
.count(); s
++) {
228 uint64_t oldValue
= selrefs
.getUnmapped(s
);
229 uint64_t newValue
= visitor
.visit(oldValue
);
230 selrefs
.set(s
, newValue
);