@@ -593,14 +593,14 @@ void MachInfo::findSectionBounds(void *ptr, size_t sourceSize, vm_address_t &vms
593593 if (!strncmp (sect->sectname , sectionName, sizeof (sect->sectname ))) {
594594 auto sptr = static_cast <uint8_t *>(ptr) + sect->offset ;
595595 if (sptr + sect->size > endaddr) {
596- SYSLOG (" mach" , " found section %s size %u in segment %llu is invalid" , sectionName, sno, ( uint64_t )vmsegment );
596+ SYSLOG (" mach" , " found section %s size %u in segment %u is invalid" , sectionName, sect-> size , sno );
597597 return ;
598598 }
599599 vmsegment = scmd->vmaddr ;
600600 vmsection = sect->addr ;
601601 sectionptr = sptr;
602602 sectionSize = static_cast <size_t >(sect->size );
603- DBGLOG (" mach" , " found section %s size %u in segment %llu " , sectionName, sno, ( uint64_t )vmsegment );
603+ DBGLOG (" mach" , " found section %s size %u in segment %u " , sectionName, sect-> size , sno );
604604 return ;
605605 }
606606
@@ -622,14 +622,14 @@ void MachInfo::findSectionBounds(void *ptr, size_t sourceSize, vm_address_t &vms
622622 if (!strncmp (sect->sectname , sectionName, sizeof (sect->sectname ))) {
623623 auto sptr = static_cast <uint8_t *>(ptr) + sect->offset ;
624624 if (sptr + sect->size > endaddr) {
625- SYSLOG (" mach" , " found section %s size %u in segment %llu is invalid" , sectionName, sno, ( uint64_t )vmsegment );
625+ SYSLOG (" mach" , " found section %s size %llu in segment %u is invalid" , sectionName, sect-> size , sno );
626626 return ;
627627 }
628628 vmsegment = (vm_address_t )scmd->vmaddr ;
629629 vmsection = (vm_address_t )sect->addr ;
630630 sectionptr = sptr;
631631 sectionSize = static_cast <size_t >(sect->size );
632- DBGLOG (" mach" , " found section %s size %u in segment %llu " , sectionName, sno, ( uint64_t )vmsegment );
632+ DBGLOG (" mach" , " found section %s size %llu in segment %u " , sectionName, sect-> size , sno );
633633 return ;
634634 }
635635
@@ -802,6 +802,47 @@ uint8_t *MachInfo::findImage(const char *identifier, uint32_t &imageSize, mach_v
802802 return nullptr ;
803803}
804804
805+ kern_return_t MachInfo::getAddressSlots (mach_header_64 *hdr, segment_command_64 *segment) {
806+ auto section = reinterpret_cast <section_64 *>(segment + 1 );
807+ mach_vm_address_t last_slot_start = 0 ;
808+ mach_vm_address_t last_slot_end = 0 ;
809+ size_t idx = 0 ;
810+
811+ if (segment->nsects == 0 ) {
812+ return KERN_FAILURE;
813+ }
814+
815+ // First space is between the mach load commands and first section (usually __text)
816+ if (section->addr < reinterpret_cast <mach_vm_address_t >(hdr) + sizeof (*hdr) + hdr->sizeofcmds ) {
817+ SYSLOG (" mach" , " Invalid section address for address slots" );
818+ return KERN_FAILURE;
819+ }
820+
821+ address_slots = reinterpret_cast <mach_vm_address_t >(hdr) + sizeof (*hdr) + hdr->sizeofcmds ;
822+ address_slots_end = section->addr ;
823+
824+ // Find last section
825+ for (idx = 0 ; idx < segment->nsects - 1 ; section++, idx++) {}
826+
827+ // Second potential space is between the last section and the end of the segment
828+ last_slot_start = section->addr + section->size ;
829+ last_slot_end = segment->vmaddr + segment->vmsize ;
830+
831+ DBGLOG (" mach" , " Potential slots: " PRIKADDR " - " PRIKADDR " : " PRIKADDR " - " PRIKADDR,
832+ CASTKADDR (address_slots), CASTKADDR (address_slots_end),
833+ CASTKADDR (last_slot_start), CASTKADDR (last_slot_end));
834+
835+ if (last_slot_start > segment->vmaddr &&
836+ (last_slot_end - last_slot_start) > (address_slots_end - address_slots)) {
837+ address_slots = last_slot_start;
838+ address_slots_end = last_slot_end;
839+ }
840+
841+ DBGLOG (" mach" , " activating slots for %s in " PRIKADDR " - " PRIKADDR, objectId, CASTKADDR (address_slots), CASTKADDR (address_slots_end));
842+
843+ return KERN_SUCCESS;
844+ }
845+
805846kern_return_t MachInfo::kcGetRunningAddresses (mach_vm_address_t slide) {
806847#if defined (__i386__)
807848 // KC is not supported on 32-bit.
@@ -856,6 +897,12 @@ kern_return_t MachInfo::kcGetRunningAddresses(mach_vm_address_t slide) {
856897 auto segCmd = reinterpret_cast <segment_command_64 *>(loadCmd);
857898 DBGLOG (" mach" , " %s has segment is %s from " PRIKADDR " to " PRIKADDR, objectId, segCmd->segname ,
858899 CASTKADDR (segCmd->vmaddr ), CASTKADDR (segCmd->vmaddr + segCmd->vmsize ));
900+
901+ // Try to find space for address slots in __TEXT segment
902+ if (!strncmp (segCmd->segname , " __TEXT" , sizeof (segCmd->segname )) && (slide || isKernel)) {
903+ (void ) getAddressSlots (inner, segCmd);
904+ }
905+
859906 if (!sym_buf && !strncmp (segCmd->segname , " __LINKEDIT" , sizeof (segCmd->segname ))) {
860907 sym_buf = reinterpret_cast <uint8_t *>(segCmd->vmaddr );
861908 sym_fileoff = segCmd->fileoff ;
@@ -891,15 +938,6 @@ kern_return_t MachInfo::kcGetRunningAddresses(mach_vm_address_t slide) {
891938 prelink_slid = true ;
892939 running_mh = inner;
893940 memory_size = (size_t )(last_addr - reinterpret_cast <mach_vm_address_t >(inner));
894- if (slide != 0 || isKernel) {
895- address_slots = reinterpret_cast <mach_vm_address_t >(inner + 1 ) + inner->sizeofcmds ;
896- address_slots_end = (address_slots + (PAGE_SIZE - 1 )) & ~PAGE_SIZE;
897- while (*reinterpret_cast <uint32_t *>(address_slots_end) == 0 ) {
898- address_slots_end += PAGE_SIZE;
899- }
900-
901- DBGLOG (" mach" , " activating slots for %s in " PRIKADDR " - " PRIKADDR, objectId, CASTKADDR (address_slots), CASTKADDR (address_slots_end));
902- }
903941 return KERN_SUCCESS;
904942
905943#else
@@ -960,6 +998,10 @@ kern_return_t MachInfo::getRunningAddresses(mach_vm_address_t slide, size_t size
960998 if (!strncmp (segCmd->segname , " __TEXT" , sizeof (segCmd->segname ))) {
961999 running_text_addr = segCmd->vmaddr ;
9621000 running_mh = mh;
1001+
1002+ #if defined(__x86_64__)
1003+ (void ) getAddressSlots (mh, segCmd);
1004+ #endif
9631005 break ;
9641006 }
9651007#if defined(__i386__)
@@ -1000,14 +1042,6 @@ kern_return_t MachInfo::getRunningAddresses(mach_vm_address_t slide, size_t size
10001042 kaslr_slide_set = true ;
10011043
10021044 DBGLOG (" mach" , " aslr/load slide is 0x%llx" , kaslr_slide);
1003-
1004- #if defined(__x86_64__)
1005- address_slots = reinterpret_cast <mach_vm_address_t >(running_mh + 1 ) + running_mh->sizeofcmds ;
1006- address_slots_end = (address_slots + (PAGE_SIZE - 1 )) & ~PAGE_SIZE;
1007- while (*reinterpret_cast <uint32_t *>(address_slots_end) == 0 ) {
1008- address_slots_end += PAGE_SIZE;
1009- }
1010- #endif
10111045 } else {
10121046 SYSLOG (" mach" , " couldn't find the running addresses" );
10131047 return KERN_FAILURE;
0 commit comments