Mercurial > pub > dyncall > dyncall
comparison dynload/dynload_syms_mach-o.c @ 220:94dc0bdd7dbe
- make dynload symbol iteration return symbol names as in C code, on Darwin
- use C comments
author | Tassilo Philipp |
---|---|
date | Tue, 11 Apr 2017 15:13:32 +0200 |
parents | 912efa3cfd4b |
children | 7076f551faf5 |
comparison
equal
deleted
inserted
replaced
219:912efa3cfd4b | 220:94dc0bdd7dbe |
---|---|
33 */ | 33 */ |
34 | 34 |
35 #include "dynload.h" | 35 #include "dynload.h" |
36 #include "dynload_alloc.h" | 36 #include "dynload_alloc.h" |
37 #include "../autovar/autovar_ARCH.h" | 37 #include "../autovar/autovar_ARCH.h" |
38 #include "../autovar/autovar_OS.h" | |
38 | 39 |
39 #include <mach-o/dyld.h> | 40 #include <mach-o/dyld.h> |
40 #include <mach-o/nlist.h> | 41 #include <mach-o/nlist.h> |
41 #include <sys/stat.h> | 42 #include <sys/stat.h> |
42 #include <dlfcn.h> | 43 #include <dlfcn.h> |
43 #include <string.h> | 44 #include <string.h> |
44 | 45 |
45 #if defined(ARCH_X64) || defined(ARCH_PPC64) || defined(ARCH_ARM64) //@@@ use dyncall_macros.h | 46 #if defined(ARCH_X64) || defined(ARCH_PPC64) || defined(ARCH_ARM64) /*@@@ use dyncall_macros.h*/ |
46 #define MACH_HEADER_TYPE mach_header_64 | 47 #define MACH_HEADER_TYPE mach_header_64 |
47 #define SEGMENT_COMMAND segment_command_64 | 48 #define SEGMENT_COMMAND segment_command_64 |
48 #define NLIST_TYPE nlist_64 | 49 #define NLIST_TYPE nlist_64 |
49 #else | 50 #else |
50 #define MACH_HEADER_TYPE mach_header | 51 #define MACH_HEADER_TYPE mach_header |
75 | 76 |
76 pLib = dlLoadLibrary(libPath); | 77 pLib = dlLoadLibrary(libPath); |
77 if(!pLib) | 78 if(!pLib) |
78 return NULL; | 79 return NULL; |
79 | 80 |
80 // Loop over all dynamically linked images to find ours. | 81 /* Loop over all dynamically linked images to find ours. */ |
81 for(i = 0, n = _dyld_image_count(); i < n; ++i) | 82 for(i = 0, n = _dyld_image_count(); i < n; ++i) |
82 { | 83 { |
83 struct stat st1; | 84 struct stat st1; |
84 const char* name = _dyld_get_image_name(i); | 85 const char* name = _dyld_get_image_name(i); |
85 | 86 |
86 if(name && (stat(name, &st1) != -1)) | 87 if(name && (stat(name, &st1) != -1)) |
87 { | 88 { |
88 // Don't rely on name comparison alone, as libPath might be relative, symlink, differently | 89 /* Don't rely on name comparison alone, as libPath might be relative, symlink, differently */ |
89 // cased, etc., but compare inode number with the one of the mapped dyld image. | 90 /* cased, etc., but compare inode number with the one of the mapped dyld image. */ |
90 if(st0.st_ino == st1.st_ino/*!strcmp(name, libPath)*/) | 91 if(st0.st_ino == st1.st_ino/*!strcmp(name, libPath)*/) |
91 { | 92 { |
92 pHeader = (const struct MACH_HEADER_TYPE*) _dyld_get_image_header(i); | 93 pHeader = (const struct MACH_HEADER_TYPE*) _dyld_get_image_header(i); |
93 break; // found header | 94 break; /* found header */ |
94 } | 95 } |
95 } | 96 } |
96 } | 97 } |
97 | 98 |
98 if(pHeader && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS)) | 99 if(pHeader && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS)) |
104 for(i = 0, n = pHeader->ncmds; i < n; ++i, cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize)) | 105 for(i = 0, n = pHeader->ncmds; i < n; ++i, cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize)) |
105 { | 106 { |
106 if(cmd->cmd == LC_SEGMENT) | 107 if(cmd->cmd == LC_SEGMENT) |
107 { | 108 { |
108 const struct SEGMENT_COMMAND* seg = (struct SEGMENT_COMMAND*)cmd; | 109 const struct SEGMENT_COMMAND* seg = (struct SEGMENT_COMMAND*)cmd; |
109 if((seg->fileoff == 0) && (seg->filesize != 0)) // Count segment sizes to slide over...@@@? | 110 if((seg->fileoff == 0) && (seg->filesize != 0)) /* Count segment sizes to slide over...@@@? */ |
110 slide = (uintptr_t)pHeader - seg->vmaddr; | 111 slide = (uintptr_t)pHeader - seg->vmaddr; |
111 if(strcmp(seg->segname, "__LINKEDIT") == 0) | 112 if(strcmp(seg->segname, "__LINKEDIT") == 0) |
112 pBase = (const char*)(seg->vmaddr - seg->fileoff + slide); // Adjust pBase depending on __LINKEDIT segment | 113 pBase = (const char*)(seg->vmaddr - seg->fileoff + slide); /* Adjust pBase depending on __LINKEDIT segment */ |
113 } | 114 } |
114 else if(cmd->cmd == LC_SYMTAB) | 115 else if(cmd->cmd == LC_SYMTAB) |
115 { | 116 { |
116 const struct symtab_command* scmd = (const struct symtab_command*)cmd; | 117 const struct symtab_command* scmd = (const struct symtab_command*)cmd; |
117 | 118 |
118 // cmd->cmdsize must be size of struct, otherwise something is off; abort | 119 /* cmd->cmdsize must be size of struct, otherwise something is off; abort */ |
119 if(cmd->cmdsize != sizeof(struct symtab_command)) | 120 if(cmd->cmdsize != sizeof(struct symtab_command)) |
120 break; | 121 break; |
121 | 122 |
122 pSyms = (DLSyms*)dlAllocMem(sizeof(DLSyms)); | 123 pSyms = (DLSyms*)dlAllocMem(sizeof(DLSyms)); |
123 pSyms->symbolCount = scmd->nsyms; | 124 pSyms->symbolCount = scmd->nsyms; |
125 pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff); | 126 pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff); |
126 pSyms->pLib = pLib; | 127 pSyms->pLib = pLib; |
127 | 128 |
128 return pSyms; | 129 return pSyms; |
129 } | 130 } |
130 //@@@ handle also LC_DYSYMTAB | 131 /*@@@ handle also LC_DYSYMTAB */ |
131 } | 132 } |
132 } | 133 } |
133 | 134 |
134 // Couldn't init syms, so free lib and return error. | 135 /* Couldn't init syms, so free lib and return error. */ |
135 dlFreeLibrary(pLib); | 136 dlFreeLibrary(pLib); |
136 return NULL; | 137 return NULL; |
137 } | 138 } |
138 | 139 |
139 | 140 |
154 const char* dlSymsName(DLSyms* pSyms, int index) | 155 const char* dlSymsName(DLSyms* pSyms, int index) |
155 { | 156 { |
156 const struct NLIST_TYPE* nl; | 157 const struct NLIST_TYPE* nl; |
157 unsigned char t; | 158 unsigned char t; |
158 | 159 |
159 //@@@ mach-o ref: http://www.cilinder.be/docs/next/NeXTStep/3.3/nd/DevTools/14_MachO/MachO.htmld/index.html | |
160 | |
161 if(!pSyms) | 160 if(!pSyms) |
162 return NULL; | 161 return NULL; |
163 | 162 |
164 nl = pSyms->pSymbolTable + index; | 163 nl = pSyms->pSymbolTable + index; |
165 | 164 |
166 // Mach-O manual: Symbols with an index into the string table of zero | 165 /* Mach-O manual: Symbols with an index into the string table of zero */ |
167 // (n_un.n_strx == 0) are defined to have a null ("") name. | 166 /* (n_un.n_strx == 0) are defined to have a null ("") name. */ |
168 if(nl->n_un.n_strx == 0) | 167 if(nl->n_un.n_strx == 0) |
169 return NULL; //@@@ have return pointer to some static "" string? | 168 return NULL; /*@@@ have return pointer to some static "" string? */ |
170 | 169 |
171 // Skip undefined symbols. @@@ should we? | 170 /* Skip undefined symbols. @@@ should we? */ |
172 t = nl->n_type & N_TYPE; | 171 t = nl->n_type & N_TYPE; |
173 if(t == N_UNDF || t == N_PBUD) // @@@ check if N_PBUD is defined, it's not in the NeXT manual, but on Darwin 8.0.1 | 172 if(t == N_UNDF || t == N_PBUD) /* @@@ check if N_PBUD is defined, it's not in the NeXT manual, but on Darwin 8.0.1 */ |
174 return NULL; | 173 return NULL; |
175 | 174 |
176 //TODO skip more symbols based on nl->n_desc and nl->n_type ? | 175 /*TODO skip more symbols based on nl->n_desc and nl->n_type ? */ |
177 | 176 |
178 // Return name - handles lookup of indirect names. | 177 /* Return name - handles lookup of indirect names. */ |
179 return &pSyms->pStringTable[t == N_INDR ? nl->n_value : nl->n_un.n_strx]; | 178 return &pSyms->pStringTable[(t == N_INDR ? nl->n_value : nl->n_un.n_strx) |
179 #if defined(OS_Darwin) | |
180 + 1 /* Skip '_'-prefix */ | |
181 #endif | |
182 ]; | |
180 } | 183 } |
181 | 184 |
182 | 185 |
183 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value) | 186 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value) |
184 { | 187 { |