@@ -98,7 +98,7 @@ cleanup_proc_handle(proc_handle_t *handle) {
9898
9999#if defined(__APPLE__ ) && TARGET_OS_OSX
100100static uintptr_t
101- return_section_address (
101+ return_section_address64 (
102102 const char * section ,
103103 mach_port_t proc_ref ,
104104 uintptr_t base ,
@@ -161,6 +161,126 @@ return_section_address(
161161 return 0 ;
162162}
163163
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 (uint32_t 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+
164284static uintptr_t
165285search_section_in_file (const char * secname , char * path , uintptr_t base , mach_vm_size_t size , mach_port_t proc_ref )
166286{
@@ -185,18 +305,20 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
185305 }
186306
187307 uintptr_t result = 0 ;
308+ uint32_t magic = * (uint32_t * )map ;
188309
189- struct mach_header_64 * hdr = (struct mach_header_64 * )map ;
190- switch (hdr -> magic ) {
310+ switch (magic ) {
191311 case MH_MAGIC :
192312 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 );
196314 break ;
197315 case MH_MAGIC_64 :
198316 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 );
200322 break ;
201323 default :
202324 PyErr_SetString (PyExc_RuntimeError , "Unknown Mach-O magic" );
0 commit comments