Initial stack construction

I'm having problems constructing the initial stack for the guest executable for Valgrind on macOS 12 Intel. This seemed to work OK for macOS 11 but I'm getting a bad 'apple' pointer on macOS 12.

The stack (constructed by Valgrind) looks like this

   higher address +-----------------+ <- clstack_end
                  |                 |
                  : string table    :
                  |                 |
                  +-----------------+
                  | NULL            |
                  +-----------------+
                  | executable_path | (first arg to execve())
                  +-----------------+
                  | NULL            |
                  -                 -
                  | envp            |
                  +-----------------+
                  | NULL            |
                  -                 -
                  | argv            |
                  +-----------------+
                  | argc            |
                  +-----------------+
                  | mach_header *   | (dynamic only)
   lower address  +-----------------+ <- sp
                  | undefined       |
                  :                 :

The problem that I'm having is with the executable path (or the apple pointer). This points to NULL. The actual pointer to the "executable=xxx" string is 16 bytes lower in memory.

The code for main starts with

Dump of assembler code for function main:
   0x0000000100003a90 <+0>:     push   %rbp
   0x0000000100003a91 <+1>:     mov    %rsp,%rbp
   0x0000000100003a94 <+4>:     sub    $0x60,%rsp
   0x0000000100003a98 <+8>:     movl   $0x0,-0x4(%rbp)
   0x0000000100003a9f <+15>:    mov    %edi,-0x8(%rbp)
   0x0000000100003aa2 <+18>:    mov    %rsi,-0x10(%rbp)
   0x0000000100003aa6 <+22>:    mov    %rdx,-0x18(%rbp)
   0x0000000100003aaa <+26>:    mov    %rcx,-0x20(%rbp)

That's the prefix, making space for locals, setting a local variable to 0 then getting the 4 arguments from main in edi, rsi, rdx and rcx as per the SYSV amd64 ABI.

I think that it is dyld that puts the apple pointer into rcx.

Can anyone tall me how dyld works out the address of the apple pointer?

It looks to me like this is the dyld start code

https://github.com/apple-opensource/dyld/blob/e3f88907bebb8421f50f0943595f6874de70ebe0/src/dyldInitialization.cpp#L130

As one might expect it just walks over the env pointers plus one NULL to get to the apple pointer.

Initial stack construction
 
 
Q