ruby-oci8 2.1.7 → 2.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +136 -0
- data/NEWS +61 -0
- data/README.md +2 -2
- data/VERSION +1 -1
- data/dist-files +5 -0
- data/docs/install-instant-client.md +2 -0
- data/ext/oci8/attr.c +0 -9
- data/ext/oci8/bind.c +86 -28
- data/ext/oci8/connection_pool.c +32 -17
- data/ext/oci8/extconf.rb +21 -0
- data/ext/oci8/hook_funcs.c +215 -0
- data/ext/oci8/lob.c +363 -168
- data/ext/oci8/metadata.c +43 -26
- data/ext/oci8/object.c +115 -36
- data/ext/oci8/oci8.c +392 -269
- data/ext/oci8/oci8.h +88 -33
- data/ext/oci8/oci8lib.c +59 -28
- data/ext/oci8/ocidatetime.c +100 -36
- data/ext/oci8/ocihandle.c +288 -286
- data/ext/oci8/ocinumber.c +172 -112
- data/ext/oci8/oradate.c +129 -87
- data/ext/oci8/plthook.h +56 -0
- data/ext/oci8/plthook_elf.c +537 -0
- data/ext/oci8/plthook_osx.c +474 -0
- data/ext/oci8/plthook_win32.c +376 -0
- data/ext/oci8/stmt.c +112 -75
- data/lib/oci8/cursor.rb +1 -1
- data/lib/oci8/oci8.rb +71 -0
- data/lib/oci8/properties.rb +18 -3
- metadata +10 -16
@@ -0,0 +1,474 @@
|
|
1
|
+
/* -*- indent-tabs-mode: nil -*-
|
2
|
+
*
|
3
|
+
* plthook_osx.c -- implemention of plthook for OS X
|
4
|
+
*
|
5
|
+
* URL: https://github.com/kubo/plthook
|
6
|
+
*
|
7
|
+
* ------------------------------------------------------
|
8
|
+
*
|
9
|
+
* Copyright 2014 Kubo Takehiro <kubo@jiubao.org>
|
10
|
+
*
|
11
|
+
* Redistribution and use in source and binary forms, with or without modification, are
|
12
|
+
* permitted provided that the following conditions are met:
|
13
|
+
*
|
14
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
15
|
+
* conditions and the following disclaimer.
|
16
|
+
*
|
17
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
18
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
19
|
+
* provided with the distribution.
|
20
|
+
*
|
21
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
22
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
23
|
+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
|
24
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
27
|
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
29
|
+
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
*
|
31
|
+
* The views and conclusions contained in the software and documentation are those of the
|
32
|
+
* authors and should not be interpreted as representing official policies, either expressed
|
33
|
+
* or implied, of the authors.
|
34
|
+
*
|
35
|
+
*/
|
36
|
+
#include <stdio.h>
|
37
|
+
#include <stdarg.h>
|
38
|
+
#include <stdlib.h>
|
39
|
+
#include <string.h>
|
40
|
+
#include <dlfcn.h>
|
41
|
+
#include <mach-o/dyld.h>
|
42
|
+
#include "plthook.h"
|
43
|
+
|
44
|
+
// #define PLTHOOK_DEBUG_CMD 1
|
45
|
+
// #define PLTHOOK_DEBUG_BIND 1
|
46
|
+
|
47
|
+
#ifdef PLTHOOK_DEBUG_CMD
|
48
|
+
#define DEBUG_CMD(...) fprintf(stderr, __VA_ARGS__)
|
49
|
+
#else
|
50
|
+
#define DEBUG_CMD(...)
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#ifdef PLTHOOK_DEBUG_BIND
|
54
|
+
#define DEBUG_BIND(...) fprintf(stderr, __VA_ARGS__)
|
55
|
+
#else
|
56
|
+
#define DEBUG_BIND(...)
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#ifdef __LP64__
|
60
|
+
#define segment_command_ segment_command_64
|
61
|
+
#else
|
62
|
+
#define segment_command_ segment_command
|
63
|
+
#endif
|
64
|
+
|
65
|
+
typedef struct {
|
66
|
+
const char *name;
|
67
|
+
void **addr;
|
68
|
+
} bind_address_t;
|
69
|
+
|
70
|
+
struct plthook {
|
71
|
+
unsigned int num_entries;
|
72
|
+
bind_address_t entries[1];
|
73
|
+
};
|
74
|
+
|
75
|
+
static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *mh);
|
76
|
+
static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint32_t lazy_bind_off, uint32_t lazy_bind_size, struct segment_command_ **segments, int addrdiff);
|
77
|
+
|
78
|
+
static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
|
79
|
+
static void set_bind_addr(unsigned int *idx, plthook_t *plthook, const uint8_t *base, const char *sym_name, int seg_index, int seg_offset, struct segment_command_ **segments);
|
80
|
+
|
81
|
+
static uint64_t uleb128(const uint8_t **p)
|
82
|
+
{
|
83
|
+
uint64_t r = 0;
|
84
|
+
int s = 0;
|
85
|
+
do {
|
86
|
+
r |= (uint64_t)(**p & 0x7f) << s;
|
87
|
+
s += 7;
|
88
|
+
} while (*(*p)++ >= 0x80);
|
89
|
+
return r;
|
90
|
+
}
|
91
|
+
|
92
|
+
static int64_t sleb128(const uint8_t** p)
|
93
|
+
{
|
94
|
+
int64_t r = 0;
|
95
|
+
int s = 0;
|
96
|
+
for (;;) {
|
97
|
+
uint8_t b = *(*p)++;
|
98
|
+
if (b < 0x80) {
|
99
|
+
if (b & 0x40) {
|
100
|
+
r -= (0x80 - b) << s;
|
101
|
+
} else {
|
102
|
+
r |= (b & 0x3f) << s;
|
103
|
+
}
|
104
|
+
break;
|
105
|
+
}
|
106
|
+
r |= (b & 0x7f) << s;
|
107
|
+
s += 7;
|
108
|
+
}
|
109
|
+
return r;
|
110
|
+
}
|
111
|
+
|
112
|
+
static char errmsg[512];
|
113
|
+
|
114
|
+
int plthook_open(plthook_t **plthook_out, const char *filename)
|
115
|
+
{
|
116
|
+
uint32_t idx = 0;
|
117
|
+
|
118
|
+
if (filename != NULL) {
|
119
|
+
size_t namelen = strlen(filename);
|
120
|
+
|
121
|
+
while (1) {
|
122
|
+
const char *image_name = _dyld_get_image_name(idx);
|
123
|
+
size_t offset = 0;
|
124
|
+
|
125
|
+
if (image_name == NULL) {
|
126
|
+
*plthook_out = NULL;
|
127
|
+
set_errmsg("Cannot find file: %s", filename);
|
128
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
129
|
+
}
|
130
|
+
if (*filename != '/') {
|
131
|
+
size_t image_name_len = strlen(image_name);
|
132
|
+
if (image_name_len > namelen) {
|
133
|
+
offset = image_name_len - namelen;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
if (strcmp(image_name + offset, filename) == 0) {
|
137
|
+
break;
|
138
|
+
}
|
139
|
+
idx++;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
return plthook_open_real(plthook_out, _dyld_get_image_header(idx));
|
143
|
+
}
|
144
|
+
|
145
|
+
int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
146
|
+
{
|
147
|
+
Dl_info dlinfo;
|
148
|
+
|
149
|
+
if (!dladdr(address, &dlinfo)) {
|
150
|
+
*plthook_out = NULL;
|
151
|
+
set_errmsg("Cannot find address: %p", address);
|
152
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
153
|
+
}
|
154
|
+
return plthook_open_real(plthook_out, dlinfo.dli_fbase);
|
155
|
+
}
|
156
|
+
|
157
|
+
#define NUM_SEGMENTS 10
|
158
|
+
|
159
|
+
static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *mh)
|
160
|
+
{
|
161
|
+
struct load_command *cmd;
|
162
|
+
const uint8_t *base = (const uint8_t *)mh;
|
163
|
+
uint32_t lazy_bind_off = 0;
|
164
|
+
uint32_t lazy_bind_size = 0;
|
165
|
+
struct segment_command_ *segments[NUM_SEGMENTS];
|
166
|
+
int segment_idx = 0;
|
167
|
+
unsigned int nbind;
|
168
|
+
int addrdiff = 0;
|
169
|
+
int i;
|
170
|
+
|
171
|
+
memset(segments, 0, sizeof(segments));
|
172
|
+
#ifdef __LP64__
|
173
|
+
cmd = (struct load_command *)((size_t)mh + sizeof(struct mach_header_64));
|
174
|
+
#else
|
175
|
+
cmd = (struct load_command *)((size_t)mh + sizeof(struct mach_header));
|
176
|
+
#endif
|
177
|
+
for (i = 0; i < mh->ncmds; i++) {
|
178
|
+
struct dyld_info_command *dyld_info;
|
179
|
+
struct segment_command *segment;
|
180
|
+
struct segment_command_64 *segment64;
|
181
|
+
|
182
|
+
switch (cmd->cmd) {
|
183
|
+
case LC_SEGMENT: /* 0x1 */
|
184
|
+
segment = (struct segment_command *)cmd;
|
185
|
+
DEBUG_CMD("LC_SEGMENT\n"
|
186
|
+
" segname %s\n"
|
187
|
+
" vmaddr %8x vmsize %8x\n"
|
188
|
+
" fileoff %8x filesize %8x\n"
|
189
|
+
" maxprot %8x initprot %8x\n"
|
190
|
+
" nsects %8d flags %8x\n",
|
191
|
+
segment->segname,
|
192
|
+
segment->vmaddr, segment->vmsize,
|
193
|
+
segment->fileoff, segment->filesize,
|
194
|
+
segment->maxprot, segment->initprot,
|
195
|
+
segment->nsects, segment->flags);
|
196
|
+
if (strcmp(segment->segname, "__LINKEDIT") == 0) {
|
197
|
+
addrdiff = segment->vmaddr - segment->fileoff;
|
198
|
+
}
|
199
|
+
#ifndef __LP64__
|
200
|
+
segments[segment_idx++] = segment;
|
201
|
+
#endif
|
202
|
+
break;
|
203
|
+
case LC_SEGMENT_64: /* 0x19 */
|
204
|
+
segment64 = (struct segment_command_64 *)cmd;
|
205
|
+
DEBUG_CMD("LC_SEGMENT_64\n"
|
206
|
+
" segname %s\n"
|
207
|
+
" vmaddr %8llx vmsize %8llx\n"
|
208
|
+
" fileoff %8llx filesize %8llx\n"
|
209
|
+
" maxprot %8x initprot %8x\n"
|
210
|
+
" nsects %8d flags %8x\n",
|
211
|
+
segment64->segname,
|
212
|
+
segment64->vmaddr, segment64->vmsize,
|
213
|
+
segment64->fileoff, segment64->filesize,
|
214
|
+
segment64->maxprot, segment64->initprot,
|
215
|
+
segment64->nsects, segment64->flags);
|
216
|
+
if (strcmp(segment64->segname, "__LINKEDIT") == 0) {
|
217
|
+
addrdiff = segment64->vmaddr - segment64->fileoff;
|
218
|
+
}
|
219
|
+
#ifdef __LP64__
|
220
|
+
segments[segment_idx++] = segment64;
|
221
|
+
#endif
|
222
|
+
break;
|
223
|
+
case LC_DYLD_INFO_ONLY: /* (0x22|LC_REQ_DYLD) */
|
224
|
+
dyld_info= (struct dyld_info_command *)cmd;
|
225
|
+
lazy_bind_off = dyld_info->lazy_bind_off;
|
226
|
+
lazy_bind_size = dyld_info->lazy_bind_size;
|
227
|
+
DEBUG_CMD("LC_DYLD_INFO_ONLY\n"
|
228
|
+
" offset size\n"
|
229
|
+
" rebase %8x %8x\n"
|
230
|
+
" bind %8x %8x\n"
|
231
|
+
" weak_bind %8x %8x\n"
|
232
|
+
" lazy_bind %8x %8x\n"
|
233
|
+
" export_bind %8x %8x\n",
|
234
|
+
dyld_info->rebase_off, dyld_info->rebase_size,
|
235
|
+
dyld_info->bind_off, dyld_info->bind_size,
|
236
|
+
dyld_info->weak_bind_off, dyld_info->weak_bind_size,
|
237
|
+
dyld_info->lazy_bind_off, dyld_info->lazy_bind_size,
|
238
|
+
dyld_info->export_off, dyld_info->export_size);
|
239
|
+
break;
|
240
|
+
case LC_SYMTAB: /* 0x2 */
|
241
|
+
DEBUG_CMD("LC_SYMTAB\n");
|
242
|
+
break;
|
243
|
+
case LC_DYSYMTAB: /* 0xb */
|
244
|
+
DEBUG_CMD("LC_DYSYMTAB\n");
|
245
|
+
break;
|
246
|
+
case LC_LOAD_DYLIB: /* 0xc */
|
247
|
+
DEBUG_CMD("LC_LOAD_DYLIB\n");
|
248
|
+
break;
|
249
|
+
case LC_ID_DYLIB: /* 0xd */
|
250
|
+
DEBUG_CMD("LC_ID_DYLIB\n");
|
251
|
+
break;
|
252
|
+
case LC_LOAD_DYLINKER: /* 0xe */
|
253
|
+
DEBUG_CMD("LC_LOAD_DYLINKER\n");
|
254
|
+
break;
|
255
|
+
case LC_ROUTINES_64: /* 0x1a */
|
256
|
+
DEBUG_CMD("LC_ROUTINES_64\n");
|
257
|
+
break;
|
258
|
+
case LC_UUID: /* 0x1b */
|
259
|
+
DEBUG_CMD("LC_UUID\n");
|
260
|
+
break;
|
261
|
+
case LC_VERSION_MIN_MACOSX: /* 0x24 */
|
262
|
+
DEBUG_CMD("LC_VERSION_MIN_MACOSX\n");
|
263
|
+
break;
|
264
|
+
case LC_FUNCTION_STARTS: /* 0x26 */
|
265
|
+
DEBUG_CMD("LC_FUNCTION_STARTS\n");
|
266
|
+
break;
|
267
|
+
case LC_MAIN: /* 0x28|LC_REQ_DYLD */
|
268
|
+
DEBUG_CMD("LC_MAIN\n");
|
269
|
+
break;
|
270
|
+
case LC_DATA_IN_CODE: /* 0x29 */
|
271
|
+
DEBUG_CMD("LC_DATA_IN_CODE\n");
|
272
|
+
break;
|
273
|
+
case LC_SOURCE_VERSION: /* 0x2A */
|
274
|
+
DEBUG_CMD("LC_SOURCE_VERSION\n");
|
275
|
+
break;
|
276
|
+
case LC_DYLIB_CODE_SIGN_DRS: /* 0x2B */
|
277
|
+
DEBUG_CMD("LC_DYLIB_CODE_SIGN_DRS\n");
|
278
|
+
break;
|
279
|
+
default:
|
280
|
+
DEBUG_CMD("LC_? (0x%x)\n", cmd->cmd);
|
281
|
+
}
|
282
|
+
cmd = (struct load_command *)((size_t)cmd + cmd->cmdsize);
|
283
|
+
}
|
284
|
+
nbind = get_bind_addr(NULL, base, lazy_bind_off, lazy_bind_size, segments, addrdiff);
|
285
|
+
*plthook_out = (plthook_t*)malloc(offsetof(plthook_t, entries) + sizeof(bind_address_t) * nbind);
|
286
|
+
(*plthook_out)->num_entries = nbind;
|
287
|
+
get_bind_addr(*plthook_out, base, lazy_bind_off, lazy_bind_size, segments, addrdiff);
|
288
|
+
|
289
|
+
return 0;
|
290
|
+
}
|
291
|
+
|
292
|
+
static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint32_t lazy_bind_off, uint32_t lazy_bind_size, struct segment_command_ **segments, int addrdiff)
|
293
|
+
{
|
294
|
+
const uint8_t *ptr = base + lazy_bind_off + addrdiff;
|
295
|
+
const uint8_t *end = ptr + lazy_bind_size;
|
296
|
+
const char *sym_name;
|
297
|
+
int seg_index = 0;
|
298
|
+
uint64_t seg_offset = 0;
|
299
|
+
int count, skip;
|
300
|
+
unsigned int idx;
|
301
|
+
DEBUG_BIND("get_bind_addr(%p, 0x%x, 0x%x", base, lazy_bind_off, lazy_bind_size);
|
302
|
+
for (idx = 0; segments[idx] != NULL; idx++) {
|
303
|
+
DEBUG_BIND(", [%s]", segments[idx]->segname);
|
304
|
+
}
|
305
|
+
DEBUG_BIND(")\n");
|
306
|
+
|
307
|
+
idx = 0;
|
308
|
+
while (ptr < end) {
|
309
|
+
uint8_t op = *ptr & BIND_OPCODE_MASK;
|
310
|
+
uint8_t imm = *ptr & BIND_IMMEDIATE_MASK;
|
311
|
+
uint64_t ulebval;
|
312
|
+
int64_t slebval;
|
313
|
+
int i;
|
314
|
+
|
315
|
+
DEBUG_BIND("0x%02x: ", *ptr);
|
316
|
+
ptr++;
|
317
|
+
switch (op) {
|
318
|
+
case BIND_OPCODE_DONE:
|
319
|
+
DEBUG_BIND("BIND_OPCODE_DONE\n");
|
320
|
+
break;
|
321
|
+
case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
|
322
|
+
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: ordinal = %u\n", imm);
|
323
|
+
break;
|
324
|
+
case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
|
325
|
+
ulebval = uleb128(&ptr);
|
326
|
+
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: ordinal = %llu\n", ulebval);
|
327
|
+
break;
|
328
|
+
case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
|
329
|
+
if (imm == 0) {
|
330
|
+
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: ordinal = 0\n");
|
331
|
+
} else {
|
332
|
+
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: ordinal = %u\n", BIND_OPCODE_MASK | imm);
|
333
|
+
}
|
334
|
+
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
|
335
|
+
sym_name = (const char*)ptr;
|
336
|
+
ptr += strlen(sym_name) + 1;
|
337
|
+
DEBUG_BIND("BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: sym_name = %s\n", sym_name);
|
338
|
+
break;
|
339
|
+
case BIND_OPCODE_SET_TYPE_IMM:
|
340
|
+
DEBUG_BIND("BIND_OPCODE_SET_TYPE_IMM: type = %u\n", imm);
|
341
|
+
break;
|
342
|
+
case BIND_OPCODE_SET_ADDEND_SLEB:
|
343
|
+
slebval = sleb128(&ptr);
|
344
|
+
DEBUG_BIND("BIND_OPCODE_SET_ADDEND_SLEB: ordinal = %lld\n", slebval);
|
345
|
+
break;
|
346
|
+
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
347
|
+
seg_index = imm;
|
348
|
+
seg_offset = uleb128(&ptr);
|
349
|
+
DEBUG_BIND("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: seg_index = %u, seg_offset = 0x%llx\n", seg_index, seg_offset);
|
350
|
+
break;
|
351
|
+
case BIND_OPCODE_ADD_ADDR_ULEB:
|
352
|
+
seg_offset += uleb128(&ptr);
|
353
|
+
DEBUG_BIND("BIND_OPCODE_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
|
354
|
+
break;
|
355
|
+
case BIND_OPCODE_DO_BIND:
|
356
|
+
set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
|
357
|
+
DEBUG_BIND("BIND_OPCODE_DO_BIND\n");
|
358
|
+
break;
|
359
|
+
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
|
360
|
+
seg_offset += uleb128(&ptr);
|
361
|
+
DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
|
362
|
+
break;
|
363
|
+
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
|
364
|
+
set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
|
365
|
+
seg_offset += imm * sizeof(void *);
|
366
|
+
DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
|
367
|
+
break;
|
368
|
+
case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
|
369
|
+
count = uleb128(&ptr);
|
370
|
+
skip = uleb128(&ptr);
|
371
|
+
for (i = 0; i < count; i++) {
|
372
|
+
set_bind_addr(&idx, plthook, base, sym_name, seg_index, seg_offset, segments);
|
373
|
+
seg_offset += skip;
|
374
|
+
}
|
375
|
+
DEBUG_BIND("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB\n");
|
376
|
+
break;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
return idx;
|
380
|
+
}
|
381
|
+
|
382
|
+
static void set_bind_addr(unsigned int *idx, plthook_t *plthook, const uint8_t *base, const char *sym_name, int seg_index, int seg_offset, struct segment_command_ **segments)
|
383
|
+
{
|
384
|
+
if (plthook != NULL) {
|
385
|
+
uint32_t vmaddr = segments[seg_index]->vmaddr;
|
386
|
+
plthook->entries[*idx].name = sym_name;
|
387
|
+
plthook->entries[*idx].addr = (void**)(base + vmaddr + seg_offset);
|
388
|
+
}
|
389
|
+
(*idx)++;
|
390
|
+
}
|
391
|
+
|
392
|
+
int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
|
393
|
+
{
|
394
|
+
if (*pos >= plthook->num_entries) {
|
395
|
+
*name_out = NULL;
|
396
|
+
*addr_out = NULL;
|
397
|
+
return EOF;
|
398
|
+
}
|
399
|
+
*name_out = plthook->entries[*pos].name;
|
400
|
+
*addr_out = plthook->entries[*pos].addr;
|
401
|
+
(*pos)++;
|
402
|
+
return 0;
|
403
|
+
}
|
404
|
+
|
405
|
+
int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, void **oldfunc)
|
406
|
+
{
|
407
|
+
size_t funcnamelen = strlen(funcname);
|
408
|
+
unsigned int pos = 0;
|
409
|
+
const char *name;
|
410
|
+
void **addr;
|
411
|
+
int rv;
|
412
|
+
|
413
|
+
if (plthook == NULL) {
|
414
|
+
set_errmsg("invalid argument: The first argument is null.");
|
415
|
+
return PLTHOOK_INVALID_ARGUMENT;
|
416
|
+
}
|
417
|
+
while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
|
418
|
+
if (strncmp(name, funcname, funcnamelen) == 0) {
|
419
|
+
if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
|
420
|
+
goto matched;
|
421
|
+
}
|
422
|
+
}
|
423
|
+
if (name[0] == '@') {
|
424
|
+
/* Oracle libclntsh.dylib imports 'read' as '@_read'. */
|
425
|
+
name++;
|
426
|
+
if (strncmp(name, funcname, funcnamelen) == 0) {
|
427
|
+
if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
|
428
|
+
goto matched;
|
429
|
+
}
|
430
|
+
}
|
431
|
+
}
|
432
|
+
if (name[0] == '_') {
|
433
|
+
name++;
|
434
|
+
if (strncmp(name, funcname, funcnamelen) == 0) {
|
435
|
+
if (name[funcnamelen] == '\0' || name[funcnamelen] == '$') {
|
436
|
+
goto matched;
|
437
|
+
}
|
438
|
+
}
|
439
|
+
}
|
440
|
+
continue;
|
441
|
+
matched:
|
442
|
+
if (oldfunc) {
|
443
|
+
*oldfunc = *addr;
|
444
|
+
}
|
445
|
+
*addr = funcaddr;
|
446
|
+
return 0;
|
447
|
+
}
|
448
|
+
if (rv == EOF) {
|
449
|
+
set_errmsg("no such function: %s", funcname);
|
450
|
+
rv = PLTHOOK_FUNCTION_NOT_FOUND;
|
451
|
+
}
|
452
|
+
return rv;
|
453
|
+
}
|
454
|
+
|
455
|
+
void plthook_close(plthook_t *plthook)
|
456
|
+
{
|
457
|
+
if (plthook != NULL) {
|
458
|
+
free(plthook);
|
459
|
+
}
|
460
|
+
return;
|
461
|
+
}
|
462
|
+
|
463
|
+
const char *plthook_error(void)
|
464
|
+
{
|
465
|
+
return errmsg;
|
466
|
+
}
|
467
|
+
|
468
|
+
static void set_errmsg(const char *fmt, ...)
|
469
|
+
{
|
470
|
+
va_list ap;
|
471
|
+
va_start(ap, fmt);
|
472
|
+
vsnprintf(errmsg, sizeof(errmsg) - 1, fmt, ap);
|
473
|
+
va_end(ap);
|
474
|
+
}
|