September 19, 2022
https://issues.dlang.org/show_bug.cgi?id=23347

          Issue ID: 23347
           Summary: ImportC: pragma pack causes asm label to set symbol
                    name to be ignored
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: ImportC, wrong-code
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: dave287091@gmail.com

macOS headers use the asm(“”) syntax to set the symbol name, which is important
for some functions like fstat that have both a 32 bit and 64bit version (but
now fstat in code refers to the 64 bit version). For example:

// foo.c
int fstat(int, struct stat *) asm("_" "fstat" "$INODE64");

void foo(void){
   int (*f)(int, struct stat*) = fstat;
}

$ dmd foo.c -c -offoo.o
$ nm -g foo.o
                 U __fstat$INODE64
0000000000000000 S _foo

(the extra underscore is from issue 23343).

However, if a pragma pack is active, the asm label seems to be ignored:

// foo2.c
#pragma pack(push, 4)
int fstat(int, struct stat *) asm("_" "fstat" "$INODE64");
#pragma pack(pop)

void foo(void){
   int (*f)(int, struct stat*) = fstat;
}

$ dmd foo2.c -c -offoo2.o
$ nm -g foo2.o
0000000000000000 S _foo
                 U _fstat

On macOS, this means you link against the 32 bit fstat instead of 64 bit fstat$INODE64 (so silently incorrectly link to the wrong function), which means you read garbage after stat'ing as the structure is not filled out properly. Most other symbols mangle to the wrong name even without the asm label.

--