[D-runtime] OS X getsectdatafromheader

Michel Fortin michel.fortin at michelf.com
Mon Nov 8 17:56:13 PST 2010


So the way the Objective-C runtime gets the pointer to the start of a section and the size of a section on Mac OS X seems to be this function:

// from "/usr/include/mach-o/getsect.h"

extern char *getsectdatafromheader(
    const struct mach_header *mhp,
    const char *segname,
    const char *sectname,
    uint32_t *size);

extern char *getsectdatafromheader_64(
    const struct mach_header_64 *mhp,
    const char *segname,
    const char *sectname,
    uint64_t *size);

Note: the the size of the section is written through the 'size' pointer.

The functions above require that you know the pointer to the mach_header struct for the corresponding image. A couple more variants are found in that same header file; this one for instance goes straight to the main executable file:

char* getsectdata(
   const char* segname,
   const char* sectname,
   unsigned long* size);

For dealing with other images than the main executable, you need to get the mach_header pointer. The simplest way to do it is to register a callback. Upon registration, the callback should be called for all loaded images, and if an image is loaded later it'll automatically be called for that image too. The callback receives the mach_header pointer you need to call getsectdatafromheader.

// from "/usr/include/mach-o/dyld.h"

/*
 * The following functions allow you to install callbacks which will be called   
 * by dyld whenever an image is loaded or unloaded.  During a call to _dyld_register_func_for_add_image()
 * the callback func is called for every existing image.  Later, it is called as each new image
 * is loaded and bound (but initializers not yet run).  The callback registered with
 * _dyld_register_func_for_remove_image() is called after any terminators in an image are run
 * and before the image is un-memory-mapped.
 */
extern void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide));
extern void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) ;

This is the approach taken by the Objective-C runtime. There's a slight difference in that it seems like it's using an equivalent private API to register two different '_add_image' callbacks for different stage of dynamic linking, but it looks otherwise equivalent. It does use '_remove_image' though, which is how I found the '_add_image'.

There are other functions in this same header file allowing you to iterate manually over each loaded image (and get a mach_header pointer), but I'd suggest trying the callback approach first.

I haven't tested any of this, and I'm not sure how well this approach will fit with druntime, but if it works it'd certainly be an improvement over the current implementation. And it looks like it work for the Objective-C runtime.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/





More information about the D-runtime mailing list