0

In the file /usr/include/dirent.h of MacOSX10.14 I see this line:

struct _telldir;        /* forward reference */

In the same file the identifier is used:

 struct _telldir *__dd_td;

Nowhere else in the include files is _telldir defined but in the same file the function telldir is declared:

long telldir(DIR *) __DARWIN_ALIAS_I(telldir);

I see the __DARWIN_ALIAS_I macro is defined as

#define __DARWIN_ALIAS_I(sym)       __asm("_" __STRING(sym) __DARWIN_SUF_64_BIT_INO_T __DARWIN_SUF_UNIX03)**

I understand this is "inline assembler" and that this defines _telldir but I would like to know more about this definition.

Thanks in advance

diciotto
  • 41
  • 3

1 Answers1

0

It's not exactly inline asm as in instructions, it's just overriding the name mangling for symbol names. (e.g. static int foo on MacOS normally has a symbol name of _foo. e.g. in the compiler asm output, you'd have _foo: .long 0).

In GNU C, int foo asm("foobar"); has an asm symbol name of foobar instead of the default _foo. See https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html and this SO answer: Adding leading underscores to assembly symbols with GCC on Win32?

Try it yourself on https://godbolt.org/ if you're curious.


In this case, we have C preprocessor string literal concatenation of the macro expansions. e.g.

"_" "telldir" "_ino64"

is exactly equivalent to "_telldir_ino64" in all contexts, including in
long telldir(DIR *dirp) asm("_" "telldir" "_ino64");

This use-case appears to be choosing which telldir implementation in libc by setting the name based on a few other CPP macros. So if __DARWIN_SUF_64_BIT_INO_T is defined as "_ino64" and __DARWIN_SUF_UNIX03 is defined as empty or /**/, then this sets the symbol name to "_telldir_ino64"

(No idea how MacOS would typically actually define those other macros, but the syntax of the line you show is just string literal concatenation inside an asm("") to set the symbol name.)

Peter Cordes
  • 286,368
  • 41
  • 520
  • 731