ruby-oci8 2.1.7 → 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|