0
|
1 /*
|
|
2
|
|
3 Package: dyncall
|
|
4 Library: dynload
|
|
5 File: dynload/dynload_syms_mach-o.c
|
|
6 Description:
|
|
7 License:
|
|
8
|
217
|
9 Copyright (c) 2007-2015 Olivier Chafik <olivier.chafik@gmail.com>,
|
|
10 2017 refactored for stability, API consistency
|
|
11 and portability by Tassilo Philipp.
|
0
|
12
|
|
13 Permission to use, copy, modify, and distribute this software for any
|
|
14 purpose with or without fee is hereby granted, provided that the above
|
|
15 copyright notice and this permission notice appear in all copies.
|
|
16
|
|
17 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
18 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
19 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
20 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
21 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
22 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
23 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
24
|
|
25 */
|
|
26
|
|
27
|
|
28
|
|
29 /*
|
|
30
|
|
31 dynamic symbol resolver for Mach-O
|
|
32
|
|
33 */
|
|
34
|
|
35 #include "dynload.h"
|
|
36 #include "dynload_alloc.h"
|
217
|
37 #include "../autovar/autovar_ARCH.h"
|
0
|
38
|
|
39 #include <mach-o/dyld.h>
|
|
40 #include <mach-o/nlist.h>
|
217
|
41 #include <sys/stat.h>
|
0
|
42 #include <dlfcn.h>
|
|
43 #include <string.h>
|
|
44
|
217
|
45 #if defined(ARCH_X64) || defined(ARCH_PPC64) || defined(ARCH_ARM64) //@@@ use dyncall_macros.h
|
0
|
46 #define MACH_HEADER_TYPE mach_header_64
|
|
47 #define NLIST_TYPE nlist_64
|
|
48 #else
|
|
49 #define MACH_HEADER_TYPE mach_header
|
|
50 #define NLIST_TYPE nlist
|
|
51 #endif
|
|
52
|
|
53
|
|
54 struct DLSyms_
|
|
55 {
|
217
|
56 DLLib* pLib;
|
|
57 const char* pStringTable;
|
0
|
58 const struct NLIST_TYPE* pSymbolTable;
|
217
|
59 uint32_t symbolCount;
|
0
|
60 };
|
|
61
|
|
62
|
217
|
63 DLSyms* dlSymsInit(const char* libPath)
|
0
|
64 {
|
217
|
65 DLLib* pLib;
|
|
66 DLSyms* pSyms;
|
0
|
67 uint32_t iImage, nImages;
|
217
|
68 struct stat st0;
|
|
69
|
|
70 if(stat(libPath, &st0) == -1)
|
|
71 return NULL;
|
|
72
|
|
73 pLib = dlLoadLibrary(libPath);
|
|
74 if(!pLib)
|
|
75 return NULL;
|
|
76
|
|
77 // Loop over all dynamically linked images.
|
0
|
78 for (iImage = 0, nImages = _dyld_image_count(); iImage < nImages; iImage++)
|
|
79 {
|
217
|
80 struct stat st1;
|
0
|
81 const char* name = _dyld_get_image_name(iImage);
|
217
|
82
|
|
83 if(name && (stat(name, &st1) != -1))
|
0
|
84 {
|
217
|
85 // Don't rely on name comparison alone, as libPath might be relative, symlink, differently
|
|
86 // cased, etc., but compare inode number with the one of the mapped dyld image.
|
|
87 if (st0.st_ino == st1.st_ino/*!strcmp(name, libPath)*/)
|
0
|
88 {
|
217
|
89 const struct MACH_HEADER_TYPE* pHeader = (const struct MACH_HEADER_TYPE*) _dyld_get_image_header(iImage);
|
|
90 const char* pBase = ((const char*)pHeader);
|
|
91 if (pHeader->filetype != MH_DYLIB)
|
|
92 return NULL;
|
|
93 if (pHeader->flags & MH_SPLIT_SEGS)
|
|
94 return NULL;
|
|
95
|
|
96 if (pHeader)
|
0
|
97 {
|
217
|
98 uint32_t iCmd, nCmds = pHeader->ncmds;
|
|
99 const struct load_command* cmd = (const struct load_command*)(pBase + sizeof(struct MACH_HEADER_TYPE));
|
|
100
|
|
101 for (iCmd = 0; iCmd < nCmds; iCmd++)
|
0
|
102 {
|
217
|
103 if (cmd->cmd == LC_SYMTAB)
|
|
104 {
|
|
105 const struct symtab_command* scmd = (const struct symtab_command*)cmd;
|
|
106
|
|
107 pSyms = (DLSyms*)( dlAllocMem(sizeof(DLSyms)) );
|
|
108 pSyms->symbolCount = scmd->nsyms;
|
|
109 pSyms->pStringTable = pBase + scmd->stroff;
|
|
110 pSyms->pSymbolTable = (struct NLIST_TYPE*)(pBase + scmd->symoff);
|
|
111 pSyms->pLib = pLib;
|
|
112
|
|
113 return pSyms;
|
|
114 }
|
|
115 cmd = (const struct load_command*)(((char*)cmd) + cmd->cmdsize);
|
0
|
116 }
|
|
117 }
|
217
|
118 break;
|
0
|
119 }
|
|
120 }
|
|
121 }
|
|
122 return NULL;
|
|
123 }
|
|
124
|
|
125
|
|
126 void dlSymsCleanup(DLSyms* pSyms)
|
|
127 {
|
217
|
128 if(pSyms) {
|
|
129 dlFreeLibrary(pSyms->pLib);
|
|
130 dlFreeMem(pSyms);
|
|
131 }
|
0
|
132 }
|
|
133
|
|
134 int dlSymsCount(DLSyms* pSyms)
|
|
135 {
|
217
|
136 return pSyms ? pSyms->symbolCount : 0;
|
0
|
137 }
|
|
138
|
|
139 static const struct NLIST_TYPE* get_nlist(DLSyms* pSyms, int index)
|
|
140 {
|
|
141 const struct NLIST_TYPE* nl;
|
|
142 if (!pSyms)
|
|
143 return NULL;
|
217
|
144
|
0
|
145 nl = pSyms->pSymbolTable + index;
|
|
146 if (nl->n_un.n_strx <= 1)
|
|
147 return NULL; // would be empty string anyway
|
217
|
148
|
0
|
149 //TODO skip more symbols based on nl->n_desc and nl->n_type ?
|
|
150 return nl;
|
|
151 }
|
|
152
|
|
153
|
|
154 const char* dlSymsName(DLSyms* pSyms, int index)
|
|
155 {
|
|
156 const struct NLIST_TYPE* nl = get_nlist(pSyms, index);
|
217
|
157 return nl ? pSyms->pStringTable + nl->n_un.n_strx : NULL;
|
0
|
158 }
|
|
159
|
|
160
|
|
161 const char* dlSymsNameFromValue(DLSyms* pSyms, void* value)
|
|
162 {
|
|
163 Dl_info info;
|
|
164 if (!dladdr(value, &info) || (value != info.dli_saddr))
|
|
165 return NULL;
|
217
|
166
|
0
|
167 return info.dli_sname;
|
|
168 }
|
217
|
169
|