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