Mercurial > pub > dyncall > dyncall
comparison dynload/dynload_syms_mach-o.c @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | 87c695673522 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3e629dc19168 |
---|---|
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 } |