Skip to content

Commit 19d86e8

Browse files
committed
[Runtime] Use dyld SPI for getting macho sections when available.
When available, use objc_addLoadImageFunc2 and _dyld_register_func_for_add_image to look up mach-o sections instead of using getsectiondata. When not available, we fall back to objc_addLoadImageFunc or _dyld_register_func_for_add_image and getsectiondata as before. rdar://51760462
1 parent 3bf7805 commit 19d86e8

File tree

1 file changed

+112
-16
lines changed

1 file changed

+112
-16
lines changed

stdlib/public/runtime/ImageInspectionMachO.cpp

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@
3030
#include <assert.h>
3131
#include <dlfcn.h>
3232

33+
#if __has_include(<objc/objc-internal.h>) && __has_include(<mach-o/dyld_priv.h>)
34+
#include <mach-o/dyld_priv.h>
35+
#include <objc/objc-internal.h>
36+
#else
37+
38+
// Bring our own definition of enum _dyld_section_location_kind and some of its
39+
// values. They'll be unused when we can't include dyld_priv.h, but the code
40+
// needs them in order to compile.
41+
enum _dyld_section_location_kind {
42+
_dyld_section_location_text_swift5_protos,
43+
_dyld_section_location_text_swift5_proto,
44+
_dyld_section_location_text_swift5_types,
45+
_dyld_section_location_text_swift5_replace,
46+
_dyld_section_location_text_swift5_replace2,
47+
_dyld_section_location_text_swift5_ac_funcs,
48+
};
49+
50+
#endif
51+
52+
#if !OBJC_ADDLOADIMAGEFUNC2_DEFINED
53+
// If we don't have objc_addLoadImageFunc2, fall back to objc_addLoadImageFunc.
54+
// Use a #define so we don't have to conditionalize the calling code below.
55+
#define objc_addLoadImageFunc2 objc_addLoadImageFunc
56+
#endif
57+
3358
using namespace swift;
3459

3560
namespace {
@@ -53,35 +78,62 @@ using mach_header_platform = mach_header_64;
5378
using mach_header_platform = mach_header;
5479
#endif
5580

81+
// Callback for objc_addLoadImageFunc that just takes a mach_header.
5682
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
57-
void CONSUME_BLOCK(const void *baseAddress,
58-
const void *start, uintptr_t size)>
83+
enum _dyld_section_location_kind SECTION_KIND,
84+
void CONSUME_BLOCK(const void *baseAddress, const void *start,
85+
uintptr_t size)>
5986
void addImageCallback(const mach_header *mh) {
6087
#if __POINTER_WIDTH__ == 64
6188
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
6289
#endif
63-
64-
// Look for a __swift5_proto section.
90+
6591
unsigned long size;
6692
const uint8_t *section =
6793
getsectiondata(reinterpret_cast<const mach_header_platform *>(mh),
6894
SEGMENT_NAME, SECTION_NAME,
6995
&size);
70-
96+
7197
if (!section)
7298
return;
73-
99+
74100
CONSUME_BLOCK(mh, section, size);
75101
}
102+
103+
// Callback for objc_addLoadImageFunc2 that takes a mach_header and dyld info.
104+
#if OBJC_ADDLOADIMAGEFUNC2_DEFINED
105+
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
106+
enum _dyld_section_location_kind SECTION_KIND,
107+
void CONSUME_BLOCK(const void *baseAddress, const void *start,
108+
uintptr_t size)>
109+
void addImageCallback(const mach_header *mh,
110+
struct _dyld_section_location_info_s *dyldInfo) {
111+
#if __POINTER_WIDTH__ == 64
112+
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
113+
#endif
114+
115+
auto result = _dyld_lookup_section_info(mh, dyldInfo, SECTION_KIND);
116+
if (result.buffer)
117+
CONSUME_BLOCK(mh, result.buffer, result.bufferSize);
118+
}
119+
#endif
120+
121+
// Callback for _dyld_register_func_for_add_image that takes a mach_header and a
122+
// slide.
76123
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
77-
void CONSUME_BLOCK(const void *baseAddress,
78-
const void *start, uintptr_t size)>
124+
enum _dyld_section_location_kind SECTION_KIND,
125+
void CONSUME_BLOCK(const void *baseAddress, const void *start,
126+
uintptr_t size)>
79127
void addImageCallback(const mach_header *mh, intptr_t vmaddr_slide) {
80-
addImageCallback<SEGMENT_NAME, SECTION_NAME, CONSUME_BLOCK>(mh);
128+
addImageCallback<SEGMENT_NAME, SECTION_NAME, SECTION_KIND, CONSUME_BLOCK>(mh);
81129
}
82130

131+
// Callback for objc_addLoadImageFunc that just takes a mach_header.
132+
83133
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
84134
const char *SEGMENT_NAME2, const char *SECTION_NAME2,
135+
enum _dyld_section_location_kind SECTION_KIND,
136+
enum _dyld_section_location_kind SECTION_KIND2,
85137
void CONSUME_BLOCK(const void *baseAddress,
86138
const void *start, uintptr_t size,
87139
const void *start2, uintptr_t size2)>
@@ -111,25 +163,63 @@ void addImageCallback2Sections(const mach_header *mh) {
111163

112164
CONSUME_BLOCK(mh, section, size, section2, size2);
113165
}
166+
167+
// Callback for objc_addLoadImageFunc2 that takes a mach_header and dyld info.
168+
#if OBJC_ADDLOADIMAGEFUNC2_DEFINED
114169
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
115170
const char *SEGMENT_NAME2, const char *SECTION_NAME2,
171+
enum _dyld_section_location_kind SECTION_KIND,
172+
enum _dyld_section_location_kind SECTION_KIND2,
116173
void CONSUME_BLOCK(const void *baseAddress,
117174
const void *start, uintptr_t size,
118175
const void *start2, uintptr_t size2)>
176+
void addImageCallback2Sections(const mach_header *mh,
177+
struct _dyld_section_location_info_s *dyldInfo) {
178+
#if __POINTER_WIDTH__ == 64
179+
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
180+
#endif
181+
182+
// Look for a section.
183+
auto result = _dyld_lookup_section_info(mh, dyldInfo, SECTION_KIND);
184+
if (!result.buffer)
185+
return;
186+
187+
auto result2 = _dyld_lookup_section_info(mh, dyldInfo, SECTION_KIND2);
188+
// No NULL check here, we allow this one not to be present. dyld gives us
189+
// a NULL pointer and 0 size when the section isn't in the dylib so we don't
190+
// need to zero anything out.
191+
192+
CONSUME_BLOCK(mh, result.buffer, result.bufferSize, result2.buffer,
193+
result2.bufferSize);
194+
}
195+
#endif
196+
197+
// Callback for _dyld_register_func_for_add_image that takes a mach_header and a
198+
// slide.
199+
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
200+
const char *SEGMENT_NAME2, const char *SECTION_NAME2,
201+
enum _dyld_section_location_kind SECTION_KIND,
202+
enum _dyld_section_location_kind SECTION_KIND2,
203+
void CONSUME_BLOCK(const void *baseAddress, const void *start,
204+
uintptr_t size, const void *start2,
205+
uintptr_t size2)>
119206
void addImageCallback2Sections(const mach_header *mh, intptr_t vmaddr_slide) {
120-
addImageCallback2Sections<SEGMENT_NAME, SECTION_NAME,
121-
SEGMENT_NAME2, SECTION_NAME2,
207+
addImageCallback2Sections<SEGMENT_NAME, SECTION_NAME, SEGMENT_NAME2,
208+
SECTION_NAME2, SECTION_KIND, SECTION_KIND2,
122209
CONSUME_BLOCK>(mh);
123210
}
124211

125212
} // end anonymous namespace
126213

127214
#if OBJC_ADDLOADIMAGEFUNC_DEFINED && SWIFT_OBJC_INTEROP
128-
#define REGISTER_FUNC(...) \
129-
if (__builtin_available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)) { \
130-
objc_addLoadImageFunc(__VA_ARGS__); \
131-
} else { \
132-
_dyld_register_func_for_add_image(__VA_ARGS__); \
215+
#define REGISTER_FUNC(...) \
216+
if (SWIFT_RUNTIME_WEAK_CHECK(objc_addLoadImageFunc2)) { \
217+
SWIFT_RUNTIME_WEAK_USE(objc_addLoadImageFunc2(__VA_ARGS__)); \
218+
} else if (__builtin_available(macOS 10.15, iOS 13, tvOS 13, \
219+
watchOS 6, *)) { \
220+
objc_addLoadImageFunc(__VA_ARGS__); \
221+
} else { \
222+
_dyld_register_func_for_add_image(__VA_ARGS__); \
133223
}
134224
#else
135225
#define REGISTER_FUNC(...) _dyld_register_func_for_add_image(__VA_ARGS__)
@@ -144,30 +234,36 @@ void addImageCallback2Sections(const mach_header *mh, intptr_t vmaddr_slide) {
144234

145235
void swift::initializeProtocolLookup() {
146236
REGISTER_FUNC(addImageCallback<TextSegment, ProtocolsSection,
237+
_dyld_section_location_text_swift5_protos,
147238
addImageProtocolsBlockCallbackUnsafe>);
148239
}
149240

150241
void swift::initializeProtocolConformanceLookup() {
151242
REGISTER_FUNC(
152243
addImageCallback<TextSegment, ProtocolConformancesSection,
244+
_dyld_section_location_text_swift5_proto,
153245
addImageProtocolConformanceBlockCallbackUnsafe>);
154246
}
155247
void swift::initializeTypeMetadataRecordLookup() {
156248
REGISTER_FUNC(
157249
addImageCallback<TextSegment, TypeMetadataRecordSection,
250+
_dyld_section_location_text_swift5_types,
158251
addImageTypeMetadataRecordBlockCallbackUnsafe>);
159252
}
160253

161254
void swift::initializeDynamicReplacementLookup() {
162255
REGISTER_FUNC(
163256
addImageCallback2Sections<TextSegment, DynamicReplacementSection,
164257
TextSegment, DynamicReplacementSomeSection,
258+
_dyld_section_location_text_swift5_replace,
259+
_dyld_section_location_text_swift5_replace2,
165260
addImageDynamicReplacementBlockCallback>);
166261
}
167262

168263
void swift::initializeAccessibleFunctionsLookup() {
169264
REGISTER_FUNC(
170265
addImageCallback<TextSegment, AccessibleFunctionsSection,
266+
_dyld_section_location_text_swift5_ac_funcs,
171267
addImageAccessibleFunctionsBlockCallbackUnsafe>);
172268
}
173269

0 commit comments

Comments
 (0)