Mercurial > pub > dyncall > dyncall
comparison dynload/dynload_syms_mach-o.c @ 226:6e40eb9fb261
- different strategy for mach-o files to lookup symbol names, in order to be consistent with other functions (that use dladdr() and dlsym() calls, which mostly don't use '_' prefixes)
author | Tassilo Philipp |
---|---|
date | Sat, 15 Apr 2017 22:02:58 +0200 |
parents | 7076f551faf5 |
children | 85b61e8facfe |
comparison
equal
deleted
inserted
replaced
225:bde22cd2034d | 226:6e40eb9fb261 |
---|---|
62 { | 62 { |
63 DLLib* pLib; | 63 DLLib* pLib; |
64 const char* pStringTable; | 64 const char* pStringTable; |
65 const struct NLIST_TYPE* pSymbolTable; | 65 const struct NLIST_TYPE* pSymbolTable; |
66 uint32_t symbolCount; | 66 uint32_t symbolCount; |
67 uintptr_t symOffset; | |
67 }; | 68 }; |
68 | 69 |
69 | 70 |
70 DLSyms* dlSymsInit(const char* libPath) | 71 DLSyms* dlSymsInit(const char* libPath) |
71 { | 72 { |
102 } | 103 } |
103 | 104 |
104 if(pHeader && (pHeader->magic == MACH_HEADER_MAGIC_NR) && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS)) | 105 if(pHeader && (pHeader->magic == MACH_HEADER_MAGIC_NR) && (pHeader->filetype == MH_DYLIB) && !(pHeader->flags & MH_SPLIT_SEGS)) |
105 { | 106 { |
106 const char* pBase = (const char*)pHeader; | 107 const char* pBase = (const char*)pHeader; |
107 uintptr_t slide = 0; | 108 uintptr_t slide = 0, symOffset = 0; |
108 const struct load_command* cmd = (const struct load_command*)(pBase + sizeof(struct MACH_HEADER_TYPE)); | 109 const struct load_command* cmd = (const struct load_command*)(pBase + sizeof(struct MACH_HEADER_TYPE)); |
109 | 110 |
110 for(i = 0, n = pHeader->ncmds; i < n; ++i, cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize)) | 111 for(i = 0, n = pHeader->ncmds; i < n; ++i, cmd = (const struct load_command*)((const char*)cmd + cmd->cmdsize)) |
111 { | 112 { |
112 if(cmd->cmd == SEGMEND_COMMAND_ID) | 113 if(cmd->cmd == SEGMEND_COMMAND_ID) |
113 { | 114 { |
114 const struct SEGMENT_COMMAND* seg = (struct SEGMENT_COMMAND*)cmd; | 115 const struct SEGMENT_COMMAND* seg = (struct SEGMENT_COMMAND*)cmd; |
115 if((seg->fileoff == 0) && (seg->filesize != 0)) /* Count segment sizes to slide over...@@@? */ | 116 if((seg->fileoff == 0) && (seg->filesize != 0)) |
116 slide = (uintptr_t)pHeader - seg->vmaddr; | 117 slide = (uintptr_t)pHeader - seg->vmaddr; /* effective offset of segment from header */ |
117 if(strcmp(seg->segname, "__LINKEDIT") == 0) | 118 |
118 pBase = (const char*)(seg->vmaddr - seg->fileoff + slide); /* Adjust pBase depending on __LINKEDIT segment */ | 119 if(strcmp(seg->segname, "__LINKEDIT") == 0) { |
120 /* Adjust pBase depending on where __LINKEDIT segment is */ | |
121 pBase = (const char*)(seg->vmaddr - seg->fileoff) + slide; | |
122 symOffset = slide; /* this is also offset of symbols */ | |
123 } | |
119 } | 124 } |
120 else if(cmd->cmd == LC_SYMTAB && !pSyms/* only init once - just safety check */) | 125 else if(cmd->cmd == LC_SYMTAB && !pSyms/* only init once - just safety check */) |
121 { | 126 { |
122 const struct symtab_command* scmd = (const struct symtab_command*)cmd; | 127 const struct symtab_command* scmd = (const struct symtab_command*)cmd; |
123 | 128 |
127 | 132 |
128 pSyms = (DLSyms*)dlAllocMem(sizeof(DLSyms)); | 133 pSyms = (DLSyms*)dlAllocMem(sizeof(DLSyms)); |
129 pSyms->symbolCount = scmd->nsyms; | 134 pSyms->symbolCount = scmd->nsyms; |
130 pSyms->pStringTable = pBase + scmd->stroff; | 135 pSyms->pStringTable = pBase + scmd->stroff; |
131 pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff); | 136 pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff); |
137 pSyms->symOffset = symOffset; | |
132 pSyms->pLib = pLib; | 138 pSyms->pLib = pLib; |
133 } | 139 } |
134 else if(cmd->cmd == LC_DYSYMTAB) | 140 else if(cmd->cmd == LC_DYSYMTAB) |
135 { | 141 { |
136 dysymtab_cmd = (const struct dysymtab_command*)cmd; | 142 dysymtab_cmd = (const struct dysymtab_command*)cmd; |
180 | 186 |
181 if(!pSyms) | 187 if(!pSyms) |
182 return NULL; | 188 return NULL; |
183 | 189 |
184 nl = pSyms->pSymbolTable + index; | 190 nl = pSyms->pSymbolTable + index; |
185 | 191 t = nl->n_type & N_TYPE; |
192 | |
193 /* Return name by lookup through it's address. This guarantees to be consistent with dlsym and dladdr */ | |
194 /* calls as used in dlFindAddress and dlSymsNameFromValue - the "#if 0"-ed code below returns the */ | |
195 /* name directly, but assumes wrongly that everything is prefixed with an underscore on Darwin. */ | |
196 | |
197 /* only handle symbols that are in a section and aren't symbolic debug entries */ | |
198 if((t == N_SECT) && (nl->n_type & N_STAB) == 0) | |
199 return dlSymsNameFromValue(pSyms, (void*)(nl->n_value + pSyms->symOffset)); | |
200 | |
201 return NULL; /* @@@ handle N_INDR, etc.? */ | |
202 | |
203 #if 0 | |
186 /* Mach-O manual: Symbols with an index into the string table of zero */ | 204 /* Mach-O manual: Symbols with an index into the string table of zero */ |
187 /* (n_un.n_strx == 0) are defined to have a null ("") name. */ | 205 /* (n_un.n_strx == 0) are defined to have a null ("") name. */ |
188 if(nl->n_un.n_strx == 0) | 206 if(nl->n_un.n_strx == 0) |
189 return NULL; /*@@@ have return pointer to some static "" string? */ | 207 return NULL; /*@@@ have return pointer to some static "" string? */ |
190 | 208 |
191 /* Skip undefined symbols. @@@ should we? */ | 209 /* Skip undefined symbols. @@@ should we? */ |
192 t = nl->n_type & N_TYPE; | |
193 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 */ | 210 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 */ |
194 return NULL; | 211 return NULL; |
195 | 212 |
196 /*TODO skip more symbols based on nl->n_desc and nl->n_type ? */ | 213 /*TODO skip more symbols based on nl->n_desc and nl->n_type ? */ |
197 | 214 |
199 return &pSyms->pStringTable[(t == N_INDR ? nl->n_value : nl->n_un.n_strx) | 216 return &pSyms->pStringTable[(t == N_INDR ? nl->n_value : nl->n_un.n_strx) |
200 #if defined(OS_Darwin) | 217 #if defined(OS_Darwin) |
201 + 1 /* Skip '_'-prefix */ | 218 + 1 /* Skip '_'-prefix */ |
202 #endif | 219 #endif |
203 ]; | 220 ]; |
221 #endif | |
204 } | 222 } |
205 | 223 |
206 | 224 |
207 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value) | 225 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value) |
208 { | 226 { |