Q:

Getting the size of the __TEXT section at link time on macOS

With gold and other linkers, it's possible to have the linker write the start/end of the .text section into the binary as constants using a linker script, e.g.
PROVIDE_HIDDEN(linker_script_start_of_text = ADDR(.text));
PROVIDE_HIDDEN(linker_script_end_of_text = ADDR(.text) + SIZEOF(.text));

linked with ld -Tmy_linker_script.lds ....
I know it's possible to call getsectdata or similar to get information about the .text section or parse it from the mach-o header, but is there a way to have the linker insert this data as a constant?

A:

You can get the Darwin linker to insert this data with a bit of trickery using __asm:
#include <stdio.h>

extern int start_text __asm("section$start$__TEXT$__text");
extern int end_text __asm("section$end$__TEXT$__text");

int main() {
  size_t text_section_size_bytes =
    (intptr_t)&end_text - (intptr_t)&start_text;

  printf("__TEXT.__text section size: 0x%lx\n", text_section_size_bytes);

  return 0;
}

On my machine, this prints:
$ clang -o test ./test.c
$ ./test
__TEXT.__text section size: 0x43

Which matches up with what objdump reports:
$ objdump -h ./test
./foo2: file format Mach-O 64-bit x86-64

Sections:
Idx Name          Size      Address          Type
  0 __text        00000043 0000000100000f30 TEXT
  [...]

You can also do the same trick to get the size of whole segments (as opposed to sections) by using the syntax segment$start$__TEXT / segment$end$__TEXT.

