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 {