gh-131591: Implement PEP 768 support for FAT mac binaries and 32 bit binaries (#132892)
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
This commit is contained in:
parent
797b29b1b5
commit
22c9886c8e
@ -98,7 +98,7 @@ cleanup_proc_handle(proc_handle_t *handle) {
|
|||||||
|
|
||||||
#if defined(__APPLE__) && TARGET_OS_OSX
|
#if defined(__APPLE__) && TARGET_OS_OSX
|
||||||
static uintptr_t
|
static uintptr_t
|
||||||
return_section_address(
|
return_section_address64(
|
||||||
const char* section,
|
const char* section,
|
||||||
mach_port_t proc_ref,
|
mach_port_t proc_ref,
|
||||||
uintptr_t base,
|
uintptr_t base,
|
||||||
@ -161,6 +161,126 @@ return_section_address(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uintptr_t
|
||||||
|
return_section_address32(
|
||||||
|
const char* section,
|
||||||
|
mach_port_t proc_ref,
|
||||||
|
uintptr_t base,
|
||||||
|
void* map
|
||||||
|
) {
|
||||||
|
struct mach_header* hdr = (struct mach_header*)map;
|
||||||
|
int ncmds = hdr->ncmds;
|
||||||
|
|
||||||
|
int cmd_cnt = 0;
|
||||||
|
struct segment_command* cmd = map + sizeof(struct mach_header);
|
||||||
|
|
||||||
|
mach_vm_size_t size = 0;
|
||||||
|
mach_msg_type_number_t count = sizeof(vm_region_basic_info_data_t);
|
||||||
|
mach_vm_address_t address = (mach_vm_address_t)base;
|
||||||
|
vm_region_basic_info_data_t r_info;
|
||||||
|
mach_port_t object_name;
|
||||||
|
uintptr_t vmaddr = 0;
|
||||||
|
|
||||||
|
for (int i = 0; cmd_cnt < 2 && i < ncmds; i++) {
|
||||||
|
if (cmd->cmd == LC_SEGMENT && strcmp(cmd->segname, "__TEXT") == 0) {
|
||||||
|
vmaddr = cmd->vmaddr;
|
||||||
|
}
|
||||||
|
if (cmd->cmd == LC_SEGMENT && strcmp(cmd->segname, "__DATA") == 0) {
|
||||||
|
while (cmd->filesize != size) {
|
||||||
|
address += size;
|
||||||
|
kern_return_t ret = mach_vm_region(
|
||||||
|
proc_ref,
|
||||||
|
&address,
|
||||||
|
&size,
|
||||||
|
VM_REGION_BASIC_INFO,
|
||||||
|
(vm_region_info_t)&r_info, // cppcheck-suppress [uninitvar]
|
||||||
|
&count,
|
||||||
|
&object_name
|
||||||
|
);
|
||||||
|
if (ret != KERN_SUCCESS) {
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_RuntimeError, "Cannot get any more VM maps.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nsects = cmd->nsects;
|
||||||
|
struct section* sec = (struct section*)(
|
||||||
|
(void*)cmd + sizeof(struct segment_command)
|
||||||
|
);
|
||||||
|
for (int j = 0; j < nsects; j++) {
|
||||||
|
if (strcmp(sec[j].sectname, section) == 0) {
|
||||||
|
return base + sec[j].addr - vmaddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = (struct segment_command*)((void*)cmd + cmd->cmdsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should not be here, but if we are there, we should say about this
|
||||||
|
PyErr_SetString(
|
||||||
|
PyExc_RuntimeError, "Cannot find section address.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t
|
||||||
|
return_section_address_fat(
|
||||||
|
const char* section,
|
||||||
|
mach_port_t proc_ref,
|
||||||
|
uintptr_t base,
|
||||||
|
void* map
|
||||||
|
) {
|
||||||
|
struct fat_header* fat_hdr = (struct fat_header*)map;
|
||||||
|
|
||||||
|
// Determine host CPU type for architecture selection
|
||||||
|
cpu_type_t cpu;
|
||||||
|
int is_abi64;
|
||||||
|
size_t cpu_size = sizeof(cpu), abi64_size = sizeof(is_abi64);
|
||||||
|
|
||||||
|
sysctlbyname("hw.cputype", &cpu, &cpu_size, NULL, 0);
|
||||||
|
sysctlbyname("hw.cpu64bit_capable", &is_abi64, &abi64_size, NULL, 0);
|
||||||
|
|
||||||
|
cpu |= is_abi64 * CPU_ARCH_ABI64;
|
||||||
|
|
||||||
|
// Check endianness
|
||||||
|
int swap = fat_hdr->magic == FAT_CIGAM;
|
||||||
|
struct fat_arch* arch = (struct fat_arch*)(map + sizeof(struct fat_header));
|
||||||
|
|
||||||
|
// Get number of architectures in fat binary
|
||||||
|
uint32_t nfat_arch = swap ? __builtin_bswap32(fat_hdr->nfat_arch) : fat_hdr->nfat_arch;
|
||||||
|
|
||||||
|
// Search for matching architecture
|
||||||
|
for (uint32_t i = 0; i < nfat_arch; i++) {
|
||||||
|
cpu_type_t arch_cpu = swap ? __builtin_bswap32(arch[i].cputype) : arch[i].cputype;
|
||||||
|
|
||||||
|
if (arch_cpu == cpu) {
|
||||||
|
// Found matching architecture, now process it
|
||||||
|
uint32_t offset = swap ? __builtin_bswap32(arch[i].offset) : arch[i].offset;
|
||||||
|
struct mach_header_64* hdr = (struct mach_header_64*)(map + offset);
|
||||||
|
|
||||||
|
// Determine which type of Mach-O it is and process accordingly
|
||||||
|
switch (hdr->magic) {
|
||||||
|
case MH_MAGIC:
|
||||||
|
case MH_CIGAM:
|
||||||
|
return return_section_address32(section, proc_ref, base, (void*)hdr);
|
||||||
|
|
||||||
|
case MH_MAGIC_64:
|
||||||
|
case MH_CIGAM_64:
|
||||||
|
return return_section_address64(section, proc_ref, base, (void*)hdr);
|
||||||
|
|
||||||
|
default:
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Unknown Mach-O magic in fat binary.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "No matching architecture found in fat binary.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static uintptr_t
|
static uintptr_t
|
||||||
search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_size_t size, mach_port_t proc_ref)
|
search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_size_t size, mach_port_t proc_ref)
|
||||||
{
|
{
|
||||||
@ -185,18 +305,20 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t result = 0;
|
uintptr_t result = 0;
|
||||||
|
uint32_t magic = *(uint32_t*)map;
|
||||||
|
|
||||||
struct mach_header_64* hdr = (struct mach_header_64*)map;
|
switch (magic) {
|
||||||
switch (hdr->magic) {
|
|
||||||
case MH_MAGIC:
|
case MH_MAGIC:
|
||||||
case MH_CIGAM:
|
case MH_CIGAM:
|
||||||
case FAT_MAGIC:
|
result = return_section_address32(secname, proc_ref, base, map);
|
||||||
case FAT_CIGAM:
|
|
||||||
PyErr_SetString(PyExc_RuntimeError, "32-bit Mach-O binaries are not supported");
|
|
||||||
break;
|
break;
|
||||||
case MH_MAGIC_64:
|
case MH_MAGIC_64:
|
||||||
case MH_CIGAM_64:
|
case MH_CIGAM_64:
|
||||||
result = return_section_address(secname, proc_ref, base, map);
|
result = return_section_address64(secname, proc_ref, base, map);
|
||||||
|
break;
|
||||||
|
case FAT_MAGIC:
|
||||||
|
case FAT_CIGAM:
|
||||||
|
result = return_section_address_fat(secname, proc_ref, base, map);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PyErr_SetString(PyExc_RuntimeError, "Unknown Mach-O magic");
|
PyErr_SetString(PyExc_RuntimeError, "Unknown Mach-O magic");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user