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 {