Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a pointer to a binary section in Mac OS X?

Tags:

linker

ld

I'm writing some code which stores some data structures in a special named binary section. These are all instances of the same struct which are scattered across many C files and are not within scope of each other. By placing them all in the named section I can iterate over all of them.

This works perfectly with GCC and GNU ld. Fails on Mac OS X due to missing __start___mysection and __stop___mysection symbols. I guess llvm ld is not smart enough to provide them automatically.

In GCC and GNU ld, I use __attribute__((section(...)) plus some specially named extern pointers which are magically filled in by the linker. Here's a trivial example:

#include <stdio.h>

extern int __start___mysection[];
extern int __stop___mysection[];

static int x __attribute__((section("__mysection"))) = 4;
static int y __attribute__((section("__mysection"))) = 10;
static int z __attribute__((section("__mysection"))) = 22;

#define SECTION_SIZE(sect) \
    ((size_t)((__stop_##sect - __start_##sect)))

int main(void)
{
    size_t sz = SECTION_SIZE(__mysection);
    int i;

    printf("Section size is %u\n", sz);

    for (i=0; i < sz; i++) {
        printf("%d\n", __start___mysection[i]);
    }

    return 0;
}

What is the general way to get a pointer to the beginning/end of a section with FreeBSD linker. Anyone have any ideas?

For reference linker is:

@(#)PROGRAM:ld  PROJECT:ld64-127.2
llvm version 3.0svn, from Apple Clang 3.0 (build 211.12)

Similar question was asked about MSVC here: How to get a pointer to a binary section in MSVC?

like image 395
Gracjan Polak Avatar asked Jul 16 '13 06:07

Gracjan Polak


2 Answers

You can get the Darwin linker to do this for you.

#include <stdio.h>

extern int start_mysection __asm("section$start$__DATA$__mysection");
extern int stop_mysection  __asm("section$end$__DATA$__mysection");

// If you don't reference x, y and z explicitly, they'll be dead-stripped.
// Prevent that with the "used" attribute.
static int x __attribute__((used,section("__DATA,__mysection"))) = 4;
static int y __attribute__((used,section("__DATA,__mysection"))) = 10;
static int z __attribute__((used,section("__DATA,__mysection"))) = 22;

int main(void)
{
    long sz = &stop_mysection - &start_mysection;
    long i;

    printf("Section size is %ld\n", sz);

    for (i=0; i < sz; ++i) {
        printf("%d\n", (&start_mysection)[i]);
    }

    return 0;
}
like image 78
dpnes Avatar answered Oct 19 '22 20:10

dpnes


Using Mach-O information:

#include <mach-o/getsect.h>

char *secstart;
unsigned long secsize;
secstart = getsectdata("__SEGMENT", "__section", &secsize);

The above gives information about section declared as:

int x __attribute__((section("__SEGMENT,__section"))) = 123;

More information: https://developer.apple.com/library/mac/documentation/developertools/conceptual/machoruntime/Reference/reference.html

like image 36
Gracjan Polak Avatar answered Oct 19 '22 19:10

Gracjan Polak