Skip to content

Commit

Permalink
Greatly simplify dlpath() implementation on OSX
Browse files Browse the repository at this point in the history
  • Loading branch information
staticfloat committed May 17, 2015
1 parent 1b2f4fa commit 64237b2
Showing 1 changed file with 10 additions and 69 deletions.
79 changes: 10 additions & 69 deletions src/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,66 +561,6 @@ DLLEXPORT size_t jl_get_alignment(jl_datatype_t *ty)
return ty->alignment;
}


// Dynamic Library interrogation

#ifdef __APPLE__
// This code gratefully lifted from: http://stackoverflow.com/questions/20481058
#ifdef __LP64__
typedef struct mach_header_64 mach_header_t;
typedef struct segment_command_64 segment_command_t;
typedef struct nlist_64 nlist_t;
#else
typedef struct mach_header mach_header_t;
typedef struct segment_command segment_command_t;
typedef struct nlist nlist_t;
#endif

static const char *first_external_symbol_for_image(const mach_header_t *header)
{
Dl_info info;
if (dladdr(header, &info) == 0)
return NULL;

segment_command_t *seg_linkedit = NULL;
segment_command_t *seg_text = NULL;
struct symtab_command *symtab = NULL;

struct load_command *cmd = (struct load_command *)((intptr_t)header + sizeof(mach_header_t));
for (uint32_t i = 0; i < header->ncmds; i++, cmd = (struct load_command *)((intptr_t)cmd + cmd->cmdsize)) {
switch(cmd->cmd) {
case LC_SEGMENT:
case LC_SEGMENT_64:
if (!strcmp(((segment_command_t *)cmd)->segname, SEG_TEXT))
seg_text = (segment_command_t *)cmd;
else if (!strcmp(((segment_command_t *)cmd)->segname, SEG_LINKEDIT))
seg_linkedit = (segment_command_t *)cmd;
break;

case LC_SYMTAB:
symtab = (struct symtab_command *)cmd;
break;
}
}

if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL))
return NULL;

intptr_t file_slide = ((intptr_t)seg_linkedit->vmaddr - (intptr_t)seg_text->vmaddr) - seg_linkedit->fileoff;
intptr_t strings = (intptr_t)header + (symtab->stroff + file_slide);
nlist_t *sym = (nlist_t *)((intptr_t)header + (symtab->symoff + file_slide));

for (uint32_t i = 0; i < symtab->nsyms; i++, sym++) {
if ((sym->n_type & N_EXT) != N_EXT || !sym->n_value)
continue;

return (const char*)strings + sym->n_un.n_strx;
}

return NULL;
}
#endif

// Takes a handle (as returned from dlopen()) and returns the absolute path to the image loaded
DLLEXPORT const char *jl_pathname_for_handle(uv_lib_t *uv_lib)
{
Expand All @@ -629,16 +569,17 @@ DLLEXPORT const char *jl_pathname_for_handle(uv_lib_t *uv_lib)

void *handle = uv_lib->handle;
#ifdef __APPLE__
// Iterate through all images currently in memory
for (int32_t i = _dyld_image_count(); i >= 0 ; i--) {
const char *first_symbol = first_external_symbol_for_image((const mach_header_t *)_dyld_get_image_header(i));
if (first_symbol && strlen(first_symbol) > 1) {
handle = (void*)((intptr_t)handle | 1); // in order to trigger findExportedSymbol instead of findExportedSymbolInImageOrDependentImages. See `dlsym` implementation at http://opensource.apple.com/source/dyld/dyld-239.3/src/dyldAPIs.cpp
first_symbol++; // in order to remove the leading underscore
void *address = dlsym(handle, first_symbol);
Dl_info info;
if (dladdr(address, &info))
return info.dli_fname;
}
// dlopen() each image, check handle
const char *image_name = _dyld_get_image_name(i);
uv_lib_t *probe_lib = jl_load_dynamic_library(image_name, JL_RTLD_DEFAULT);
void *probe_handle = probe_lib->handle;
uv_dlclose(probe_lib);

// If the handle is the same as what was passed in, return this image name
if (handle == probe_handle)
return image_name;
}

#elif defined(_OS_WINDOWS_)
Expand Down

0 comments on commit 64237b2

Please sign in to comment.