Address issue with LC_DYLD_CHAINED_FIXUPS linker command

Usecase:

Our application parses the dependent binary and fetches some data from different segments of dependent binary.

Due to the introduction of LC_DYLD_CHAINED_FIXUPS, our application is failing to get correct address due to which it is failing to fetch correct data. The same works fine if the dependent binary is built with '-no_fixup_chains' linker flag.

Sample program to demonstrate the same:

/* This is a program to access different locations in the dependent binary called 'myBinary' */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>

/* Parent structure */

typedef struct

  {
        unsigned int    tag;
        uintptr_t   childAddr; /* Child location */

  }  ParentStructure;


int main(int argc, char **argv) {

      unsigned int k = 0;
      char * childPtr = NULL;
      ParentStructure * parentLoc = NULL;

	/* Dissect the binary 'myBinary' to find Parent and Child */

    int fd = open("myBinary", O_RDONLY);


    if (fd < 0) {

        perror("open");
        return 1;
    }

    off_t length = lseek(fd, 0, SEEK_END);


	/* Map the binary 'myBinary' into current process */

    void *map = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0);

    if (map == MAP_FAILED) {
        perror("mmap");
        return 1;

    }


    struct mach_header_64 *hdr = (struct mach_header_64 *) map;

    struct load_command *lc = (struct load_command *) (hdr + 1);


    for (int i = 0; i < hdr->ncmds; i++) {

        if (lc->cmd == LC_SEGMENT_64) {

            struct segment_command_64 *seg = (struct segment_command_64 *) lc;

            if (strcmp(seg->segname, "__DATA") == 0) {

                struct section_64 *sec = (struct section_64 *) (seg + 1);

                for (int j = 0; j < seg->nsects; j++) {			

					/* Find the 'childPtr' which is at the location __find_Child */

                    if (strcmp(sec->sectname, "__find_Child") == 0) {

						childPtr = (char *) map + sec->offset;

                    }

					/* Find the 'ParentStructure' in __find_Parent section */

					if (strcmp(sec->sectname, "__find_Parent") == 0) {

						parentLoc = (ParentStructure *) map + sec->offset;

					}

				}

				if ((parentLoc->childAddr) >= seg.vmaddr && (parentLoc->childAddr) < seg.vmaddr + seg.vmsize){

                    printf("SUCCESS\n");

                }

				else	{

					printf("FAILED\n");

				}

			}

		}

        lc = (struct load_command *) ((char *) lc + lc->cmdsize);

    }

    munmap(map, length);

    close(fd);
    return 0;
}

Output:

With '-no_fixup_chains'

SUCCESS

Without '-no_fixup_chains'

FAILED

Queries:

  1. Why the seg.vmaddr remain unchanged, but the pointers of that segment have huge values?
  2. How to fix this?
Address issue with LC_DYLD_CHAINED_FIXUPS linker command
 
 
Q