@@ -98,7 +98,7 @@ cleanup_proc_handle(proc_handle_t *handle) {
98
98
99
99
#if defined(__APPLE__ ) && TARGET_OS_OSX
100
100
static uintptr_t
101
- return_section_address (
101
+ return_section_address64 (
102
102
const char * section ,
103
103
mach_port_t proc_ref ,
104
104
uintptr_t base ,
@@ -161,6 +161,126 @@ return_section_address(
161
161
return 0 ;
162
162
}
163
163
164
+ static uintptr_t
165
+ return_section_address32 (
166
+ const char * section ,
167
+ mach_port_t proc_ref ,
168
+ uintptr_t base ,
169
+ void * map
170
+ ) {
171
+ struct mach_header * hdr = (struct mach_header * )map ;
172
+ int ncmds = hdr -> ncmds ;
173
+
174
+ int cmd_cnt = 0 ;
175
+ struct segment_command * cmd = map + sizeof (struct mach_header );
176
+
177
+ mach_vm_size_t size = 0 ;
178
+ mach_msg_type_number_t count = sizeof (vm_region_basic_info_data_t );
179
+ mach_vm_address_t address = (mach_vm_address_t )base ;
180
+ vm_region_basic_info_data_t r_info ;
181
+ mach_port_t object_name ;
182
+ uintptr_t vmaddr = 0 ;
183
+
184
+ for (int i = 0 ; cmd_cnt < 2 && i < ncmds ; i ++ ) {
185
+ if (cmd -> cmd == LC_SEGMENT && strcmp (cmd -> segname , "__TEXT" ) == 0 ) {
186
+ vmaddr = cmd -> vmaddr ;
187
+ }
188
+ if (cmd -> cmd == LC_SEGMENT && strcmp (cmd -> segname , "__DATA" ) == 0 ) {
189
+ while (cmd -> filesize != size ) {
190
+ address += size ;
191
+ kern_return_t ret = mach_vm_region (
192
+ proc_ref ,
193
+ & address ,
194
+ & size ,
195
+ VM_REGION_BASIC_INFO ,
196
+ (vm_region_info_t )& r_info , // cppcheck-suppress [uninitvar]
197
+ & count ,
198
+ & object_name
199
+ );
200
+ if (ret != KERN_SUCCESS ) {
201
+ PyErr_SetString (
202
+ PyExc_RuntimeError , "Cannot get any more VM maps.\n" );
203
+ return 0 ;
204
+ }
205
+ }
206
+
207
+ int nsects = cmd -> nsects ;
208
+ struct section * sec = (struct section * )(
209
+ (void * )cmd + sizeof (struct segment_command )
210
+ );
211
+ for (int j = 0 ; j < nsects ; j ++ ) {
212
+ if (strcmp (sec [j ].sectname , section ) == 0 ) {
213
+ return base + sec [j ].addr - vmaddr ;
214
+ }
215
+ }
216
+ cmd_cnt ++ ;
217
+ }
218
+
219
+ cmd = (struct segment_command * )((void * )cmd + cmd -> cmdsize );
220
+ }
221
+
222
+ // We should not be here, but if we are there, we should say about this
223
+ PyErr_SetString (
224
+ PyExc_RuntimeError , "Cannot find section address.\n" );
225
+ return 0 ;
226
+ }
227
+
228
+ static uintptr_t
229
+ return_section_address_fat (
230
+ const char * section ,
231
+ mach_port_t proc_ref ,
232
+ uintptr_t base ,
233
+ void * map
234
+ ) {
235
+ struct fat_header * fat_hdr = (struct fat_header * )map ;
236
+
237
+ // Determine host CPU type for architecture selection
238
+ cpu_type_t cpu ;
239
+ int is_abi64 ;
240
+ size_t cpu_size = sizeof (cpu ), abi64_size = sizeof (is_abi64 );
241
+
242
+ sysctlbyname ("hw.cputype" , & cpu , & cpu_size , NULL , 0 );
243
+ sysctlbyname ("hw.cpu64bit_capable" , & is_abi64 , & abi64_size , NULL , 0 );
244
+
245
+ cpu |= is_abi64 * CPU_ARCH_ABI64 ;
246
+
247
+ // Check endianness
248
+ int swap = fat_hdr -> magic == FAT_CIGAM ;
249
+ struct fat_arch * arch = (struct fat_arch * )(map + sizeof (struct fat_header ));
250
+
251
+ // Get number of architectures in fat binary
252
+ uint32_t nfat_arch = swap ? __builtin_bswap32 (fat_hdr -> nfat_arch ) : fat_hdr -> nfat_arch ;
253
+
254
+ // Search for matching architecture
255
+ for (int i = 0 ; i < nfat_arch ; i ++ ) {
256
+ cpu_type_t arch_cpu = swap ? __builtin_bswap32 (arch [i ].cputype ) : arch [i ].cputype ;
257
+
258
+ if (arch_cpu == cpu ) {
259
+ // Found matching architecture, now process it
260
+ uint32_t offset = swap ? __builtin_bswap32 (arch [i ].offset ) : arch [i ].offset ;
261
+ struct mach_header_64 * hdr = (struct mach_header_64 * )(map + offset );
262
+
263
+ // Determine which type of Mach-O it is and process accordingly
264
+ switch (hdr -> magic ) {
265
+ case MH_MAGIC :
266
+ case MH_CIGAM :
267
+ return return_section_address32 (section , proc_ref , base , (void * )hdr );
268
+
269
+ case MH_MAGIC_64 :
270
+ case MH_CIGAM_64 :
271
+ return return_section_address64 (section , proc_ref , base , (void * )hdr );
272
+
273
+ default :
274
+ PyErr_SetString (PyExc_RuntimeError , "Unknown Mach-O magic in fat binary.\n" );
275
+ return 0 ;
276
+ }
277
+ }
278
+ }
279
+
280
+ PyErr_SetString (PyExc_RuntimeError , "No matching architecture found in fat binary.\n" );
281
+ return 0 ;
282
+ }
283
+
164
284
static uintptr_t
165
285
search_section_in_file (const char * secname , char * path , uintptr_t base , mach_vm_size_t size , mach_port_t proc_ref )
166
286
{
@@ -185,18 +305,20 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
185
305
}
186
306
187
307
uintptr_t result = 0 ;
308
+ uint32_t magic = * (uint32_t * )map ;
188
309
189
- struct mach_header_64 * hdr = (struct mach_header_64 * )map ;
190
- switch (hdr -> magic ) {
310
+ switch (magic ) {
191
311
case MH_MAGIC :
192
312
case MH_CIGAM :
193
- case FAT_MAGIC :
194
- case FAT_CIGAM :
195
- PyErr_SetString (PyExc_RuntimeError , "32-bit Mach-O binaries are not supported" );
313
+ result = return_section_address32 (secname , proc_ref , base , map );
196
314
break ;
197
315
case MH_MAGIC_64 :
198
316
case MH_CIGAM_64 :
199
- result = return_section_address (secname , proc_ref , base , map );
317
+ result = return_section_address64 (secname , proc_ref , base , map );
318
+ break ;
319
+ case FAT_MAGIC :
320
+ case FAT_CIGAM :
321
+ result = return_section_address_fat (secname , proc_ref , base , map );
200
322
break ;
201
323
default :
202
324
PyErr_SetString (PyExc_RuntimeError , "Unknown Mach-O magic" );
0 commit comments