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?
OK I found the problem and it's on the Valgrind side. A case of the left hand not knowing what the right hand is doing.
This is the code that causes the problem
static void vg_cleanup_env(void) __attribute__((constructor));
static void vg_cleanup_env(void)
{
HChar **envp = (HChar**)*_NSGetEnviron();
env_unsetenv(envp, "VALGRIND_LAUNCHER");
env_unsetenv(envp, "DYLD_SHARED_REGION");
// GrP fixme should be more like mash_colon_env()
env_unsetenv(envp, "DYLD_INSERT_LIBRARIES");
}
'env_unsetenv' just moves down pointers in the envp table (and the apple param pointers). But it does this after dyld has put the apple pointer into the arguments for main.
The fix (from Louis Bruner's port) is to not modify the existing apple pointer table. The first element gets duplicated.
So we end up with something like
+-----------------+
| |
: string table :
| |
+-----------------+
| NULL |
+-----------------+
| executable_path |
| executable_path |
| executable_path |
+-----------------+
| NULL |
- -
| envp |