ruby-oci8 2.2.12 → 2.2.13
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.
- checksums.yaml +4 -4
- data/NEWS +18 -0
- data/docs/hanging-after-inactivity.md +1 -1
- data/ext/oci8/extconf.rb +1 -0
- data/ext/oci8/oci8.c +2 -2
- data/ext/oci8/oci8.h +6 -5
- data/ext/oci8/oci8lib.c +0 -21
- data/ext/oci8/oraconf.rb +4 -0
- data/ext/oci8/oradate.c +0 -11
- data/ext/oci8/plthook_elf.c +312 -183
- data/ext/oci8/plthook_osx.c +649 -91
- data/ext/oci8/plthook_win32.c +39 -25
- data/lib/oci8/oracle_version.rb +9 -1
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +2 -0
- data/test/test_metadata.rb +1 -0
- data/test/test_oranumber.rb +3 -1
- data/test/test_package_type.rb +10 -4
- metadata +3 -3
data/ext/oci8/plthook_elf.c
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
/* -*- indent-tabs-mode: nil -*-
|
2
2
|
*
|
3
|
-
* plthook_elf.c --
|
3
|
+
* plthook_elf.c -- implementation of plthook for ELF format
|
4
4
|
*
|
5
5
|
* URL: https://github.com/kubo/plthook
|
6
6
|
*
|
7
7
|
* ------------------------------------------------------
|
8
8
|
*
|
9
|
-
* Copyright 2013-
|
9
|
+
* Copyright 2013-2019 Kubo Takehiro <kubo@jiubao.org>
|
10
10
|
*
|
11
11
|
* Redistribution and use in source and binary forms, with or without modification, are
|
12
12
|
* permitted provided that the following conditions are met:
|
@@ -50,6 +50,7 @@
|
|
50
50
|
#include <dlfcn.h>
|
51
51
|
#ifdef __sun
|
52
52
|
#include <sys/auxv.h>
|
53
|
+
#include <procfs.h>
|
53
54
|
#define ELF_TARGET_ALL
|
54
55
|
#endif /* __sun */
|
55
56
|
#ifdef __FreeBSD__
|
@@ -61,6 +62,10 @@
|
|
61
62
|
#include <link.h>
|
62
63
|
#include "plthook.h"
|
63
64
|
|
65
|
+
#if defined __UCLIBC__ && !defined RTLD_NOLOAD
|
66
|
+
#define RTLD_NOLOAD 0
|
67
|
+
#endif
|
68
|
+
|
64
69
|
#ifndef __GNUC__
|
65
70
|
#define __attribute__(arg)
|
66
71
|
#endif
|
@@ -75,46 +80,66 @@
|
|
75
80
|
|
76
81
|
#if defined __x86_64__ || defined __x86_64
|
77
82
|
#define R_JUMP_SLOT R_X86_64_JUMP_SLOT
|
78
|
-
#define Elf_Plt_Rel Elf_Rela
|
79
|
-
#define PLT_DT_REL DT_RELA
|
80
83
|
#define R_GLOBAL_DATA R_X86_64_GLOB_DAT
|
81
84
|
#elif defined __i386__ || defined __i386
|
82
85
|
#define R_JUMP_SLOT R_386_JMP_SLOT
|
83
|
-
#define Elf_Plt_Rel Elf_Rel
|
84
|
-
#define PLT_DT_REL DT_REL
|
85
86
|
#define R_GLOBAL_DATA R_386_GLOB_DAT
|
87
|
+
#define USE_REL
|
86
88
|
#elif defined __arm__ || defined __arm
|
87
89
|
#define R_JUMP_SLOT R_ARM_JUMP_SLOT
|
88
|
-
#define
|
90
|
+
#define R_GLOBAL_DATA R_ARM_GLOB_DAT
|
91
|
+
#define USE_REL
|
89
92
|
#elif defined __aarch64__ || defined __aarch64 /* ARM64 */
|
90
93
|
#define R_JUMP_SLOT R_AARCH64_JUMP_SLOT
|
91
|
-
#define
|
94
|
+
#define R_GLOBAL_DATA R_AARCH64_GLOB_DAT
|
92
95
|
#elif defined __powerpc64__
|
93
96
|
#define R_JUMP_SLOT R_PPC64_JMP_SLOT
|
94
|
-
#define
|
97
|
+
#define R_GLOBAL_DATA R_PPC64_GLOB_DAT
|
95
98
|
#elif defined __powerpc__
|
96
99
|
#define R_JUMP_SLOT R_PPC_JMP_SLOT
|
97
|
-
#define
|
100
|
+
#define R_GLOBAL_DATA R_PPC_GLOB_DAT
|
101
|
+
#elif defined __riscv
|
102
|
+
#define R_JUMP_SLOT R_RISCV_JUMP_SLOT
|
103
|
+
#if __riscv_xlen == 32
|
104
|
+
#define R_GLOBAL_DATA R_RISCV_32
|
105
|
+
#elif __riscv_xlen == 64
|
106
|
+
#define R_GLOBAL_DATA R_RISCV_64
|
107
|
+
#else
|
108
|
+
#error unsupported RISCV implementation
|
109
|
+
#endif
|
98
110
|
#elif 0 /* disabled because not tested */ && (defined __sparcv9 || defined __sparc_v9__)
|
99
111
|
#define R_JUMP_SLOT R_SPARC_JMP_SLOT
|
100
|
-
#define Elf_Plt_Rel Elf_Rela
|
101
112
|
#elif 0 /* disabled because not tested */ && (defined __sparc || defined __sparc__)
|
102
113
|
#define R_JUMP_SLOT R_SPARC_JMP_SLOT
|
103
|
-
#define Elf_Plt_Rel Elf_Rela
|
104
114
|
#elif 0 /* disabled because not tested */ && (defined __ia64 || defined __ia64__)
|
105
115
|
#define R_JUMP_SLOT R_IA64_IPLTMSB
|
106
|
-
#define Elf_Plt_Rel Elf_Rela
|
107
116
|
#else
|
108
117
|
#error unsupported OS
|
109
118
|
#endif
|
110
119
|
|
120
|
+
#ifdef USE_REL
|
121
|
+
#define Elf_Plt_Rel Elf_Rel
|
122
|
+
#define PLT_DT_REL DT_REL
|
123
|
+
#define PLT_DT_RELSZ DT_RELSZ
|
124
|
+
#define PLT_DT_RELENT DT_RELENT
|
125
|
+
#else
|
126
|
+
#define Elf_Plt_Rel Elf_Rela
|
127
|
+
#define PLT_DT_REL DT_RELA
|
128
|
+
#define PLT_DT_RELSZ DT_RELASZ
|
129
|
+
#define PLT_DT_RELENT DT_RELAENT
|
130
|
+
#endif
|
131
|
+
|
111
132
|
#if defined __LP64__
|
112
133
|
#ifndef ELF_CLASS
|
113
134
|
#define ELF_CLASS ELFCLASS64
|
114
135
|
#endif
|
115
136
|
#define SIZE_T_FMT "lu"
|
116
137
|
#define ELF_WORD_FMT "u"
|
138
|
+
#ifdef __ANDROID__
|
139
|
+
#define ELF_XWORD_FMT "llu"
|
140
|
+
#else
|
117
141
|
#define ELF_XWORD_FMT "lu"
|
142
|
+
#endif
|
118
143
|
#define ELF_SXWORD_FMT "ld"
|
119
144
|
#define Elf_Half Elf64_Half
|
120
145
|
#define Elf_Xword Elf64_Xword
|
@@ -162,43 +187,65 @@
|
|
162
187
|
#endif
|
163
188
|
#endif /* __LP64__ */
|
164
189
|
|
165
|
-
#if defined(PT_GNU_RELRO) && !defined(__sun)
|
166
|
-
#define SUPPORT_RELRO /* RELRO (RELocation Read-Only) */
|
167
|
-
#if !defined(DF_1_NOW) && defined(DF_1_BIND_NOW)
|
168
|
-
#define DF_1_NOW DF_1_BIND_NOW
|
169
|
-
#endif
|
170
|
-
#endif
|
171
|
-
|
172
190
|
struct plthook {
|
173
191
|
const Elf_Sym *dynsym;
|
174
192
|
const char *dynstr;
|
175
193
|
size_t dynstr_size;
|
176
194
|
const char *plt_addr_base;
|
177
|
-
const Elf_Plt_Rel *
|
178
|
-
size_t
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
const char *relro_end;
|
195
|
+
const Elf_Plt_Rel *rela_plt;
|
196
|
+
size_t rela_plt_cnt;
|
197
|
+
#ifdef R_GLOBAL_DATA
|
198
|
+
const Elf_Plt_Rel *rela_dyn;
|
199
|
+
size_t rela_dyn_cnt;
|
183
200
|
#endif
|
184
201
|
};
|
185
202
|
|
186
203
|
static char errmsg[512];
|
187
|
-
|
188
|
-
#ifdef SUPPORT_RELRO
|
189
204
|
static size_t page_size;
|
190
|
-
#
|
205
|
+
#define ALIGN_ADDR(addr) ((void*)((size_t)(addr) & ~(page_size - 1)))
|
191
206
|
|
192
207
|
static int plthook_open_executable(plthook_t **plthook_out);
|
193
208
|
static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename);
|
194
209
|
static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag);
|
195
|
-
#ifdef SUPPORT_RELRO
|
196
|
-
static int set_relro_members(plthook_t *plthook, struct link_map *lmap);
|
197
|
-
#endif
|
198
210
|
static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap);
|
211
|
+
#if defined __FreeBSD__ || defined __sun
|
199
212
|
static int check_elf_header(const Elf_Ehdr *ehdr);
|
213
|
+
#endif
|
200
214
|
static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
|
201
215
|
|
216
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
217
|
+
struct dl_iterate_data {
|
218
|
+
char* addr;
|
219
|
+
struct link_map lmap;
|
220
|
+
};
|
221
|
+
|
222
|
+
static int dl_iterate_cb(struct dl_phdr_info *info, size_t size, void *cb_data)
|
223
|
+
{
|
224
|
+
struct dl_iterate_data *data = (struct dl_iterate_data*)cb_data;
|
225
|
+
Elf_Half idx = 0;
|
226
|
+
|
227
|
+
for (idx = 0; idx < info->dlpi_phnum; ++idx) {
|
228
|
+
const Elf_Phdr *phdr = &info->dlpi_phdr[idx];
|
229
|
+
char* base = (char*)info->dlpi_addr + phdr->p_vaddr;
|
230
|
+
if (base <= data->addr && data->addr < base + phdr->p_memsz) {
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
if (idx == info->dlpi_phnum) {
|
235
|
+
return 0;
|
236
|
+
}
|
237
|
+
for (idx = 0; idx < info->dlpi_phnum; ++idx) {
|
238
|
+
const Elf_Phdr *phdr = &info->dlpi_phdr[idx];
|
239
|
+
if (phdr->p_type == PT_DYNAMIC) {
|
240
|
+
data->lmap.l_addr = info->dlpi_addr;
|
241
|
+
data->lmap.l_ld = (Elf_Dyn*)(info->dlpi_addr + phdr->p_vaddr);
|
242
|
+
return 1;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
return 0;
|
246
|
+
}
|
247
|
+
#endif
|
248
|
+
|
202
249
|
int plthook_open(plthook_t **plthook_out, const char *filename)
|
203
250
|
{
|
204
251
|
*plthook_out = NULL;
|
@@ -211,6 +258,27 @@ int plthook_open(plthook_t **plthook_out, const char *filename)
|
|
211
258
|
|
212
259
|
int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
213
260
|
{
|
261
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
262
|
+
const static char *symbols[] = {
|
263
|
+
"__INIT_ARRAY__",
|
264
|
+
"_end",
|
265
|
+
"_start"
|
266
|
+
};
|
267
|
+
size_t i;
|
268
|
+
|
269
|
+
if (hndl == NULL) {
|
270
|
+
set_errmsg("NULL handle");
|
271
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
272
|
+
}
|
273
|
+
for (i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
|
274
|
+
char *addr = dlsym(hndl, symbols[i]);
|
275
|
+
if (addr != NULL) {
|
276
|
+
return plthook_open_by_address(plthook_out, addr - 1);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
set_errmsg("Could not find an address in the specified handle.");
|
280
|
+
return PLTHOOK_INTERNAL_ERROR;
|
281
|
+
#else
|
214
282
|
struct link_map *lmap = NULL;
|
215
283
|
|
216
284
|
if (hndl == NULL) {
|
@@ -222,12 +290,22 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
|
222
290
|
return PLTHOOK_FILE_NOT_FOUND;
|
223
291
|
}
|
224
292
|
return plthook_open_real(plthook_out, lmap);
|
293
|
+
#endif
|
225
294
|
}
|
226
295
|
|
227
296
|
int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
228
297
|
{
|
229
298
|
#if defined __FreeBSD__
|
230
299
|
return PLTHOOK_NOT_IMPLEMENTED;
|
300
|
+
#elif defined __ANDROID__ || defined __UCLIBC__
|
301
|
+
struct dl_iterate_data data = {0,};
|
302
|
+
data.addr = address;
|
303
|
+
dl_iterate_phdr(dl_iterate_cb, &data);
|
304
|
+
if (data.lmap.l_ld == NULL) {
|
305
|
+
set_errmsg("Could not find memory region containing address %p", address);
|
306
|
+
return PLTHOOK_INTERNAL_ERROR;
|
307
|
+
}
|
308
|
+
return plthook_open_real(plthook_out, &data.lmap);
|
231
309
|
#else
|
232
310
|
Dl_info info;
|
233
311
|
struct link_map *lmap = NULL;
|
@@ -243,7 +321,9 @@ int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
|
243
321
|
|
244
322
|
static int plthook_open_executable(plthook_t **plthook_out)
|
245
323
|
{
|
246
|
-
#if defined
|
324
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
325
|
+
return plthook_open_shared_library(plthook_out, NULL);
|
326
|
+
#elif defined __linux__
|
247
327
|
return plthook_open_real(plthook_out, _r_debug.r_map);
|
248
328
|
#elif defined __sun
|
249
329
|
const char *auxv_file = "/proc/self/auxv";
|
@@ -280,12 +360,21 @@ static int plthook_open_executable(plthook_t **plthook_out)
|
|
280
360
|
static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename)
|
281
361
|
{
|
282
362
|
void *hndl = dlopen(filename, RTLD_LAZY | RTLD_NOLOAD);
|
363
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
364
|
+
int rv;
|
365
|
+
#else
|
283
366
|
struct link_map *lmap = NULL;
|
367
|
+
#endif
|
284
368
|
|
285
369
|
if (hndl == NULL) {
|
286
370
|
set_errmsg("dlopen error: %s", dlerror());
|
287
371
|
return PLTHOOK_FILE_NOT_FOUND;
|
288
372
|
}
|
373
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
374
|
+
rv = plthook_open_by_handle(plthook_out, hndl);
|
375
|
+
dlclose(hndl);
|
376
|
+
return rv;
|
377
|
+
#else
|
289
378
|
if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {
|
290
379
|
set_errmsg("dlinfo error");
|
291
380
|
dlclose(hndl);
|
@@ -293,6 +382,7 @@ static int plthook_open_shared_library(plthook_t **plthook_out, const char *file
|
|
293
382
|
}
|
294
383
|
dlclose(hndl);
|
295
384
|
return plthook_open_real(plthook_out, lmap);
|
385
|
+
#endif
|
296
386
|
}
|
297
387
|
|
298
388
|
static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
|
@@ -306,47 +396,79 @@ static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
|
|
306
396
|
return NULL;
|
307
397
|
}
|
308
398
|
|
309
|
-
#ifdef
|
310
|
-
|
311
|
-
static const char *get_mapped_file(const void *address, char *buf, int *err)
|
399
|
+
#ifdef __linux__
|
400
|
+
static int get_memory_permission(void *address)
|
312
401
|
{
|
313
402
|
unsigned long addr = (unsigned long)address;
|
314
403
|
FILE *fp;
|
404
|
+
char buf[PATH_MAX];
|
405
|
+
char perms[5];
|
406
|
+
int bol = 1;
|
315
407
|
|
316
408
|
fp = fopen("/proc/self/maps", "r");
|
317
409
|
if (fp == NULL) {
|
318
410
|
set_errmsg("failed to open /proc/self/maps");
|
319
|
-
|
320
|
-
return NULL;
|
411
|
+
return 0;
|
321
412
|
}
|
322
413
|
while (fgets(buf, PATH_MAX, fp) != NULL) {
|
323
414
|
unsigned long start, end;
|
324
|
-
int
|
415
|
+
int eol = (strchr(buf, '\n') != NULL);
|
416
|
+
if (bol) {
|
417
|
+
/* The fgets reads from the beginning of a line. */
|
418
|
+
if (!eol) {
|
419
|
+
/* The next fgets reads from the middle of the same line. */
|
420
|
+
bol = 0;
|
421
|
+
}
|
422
|
+
} else {
|
423
|
+
/* The fgets reads from the middle of a line. */
|
424
|
+
if (eol) {
|
425
|
+
/* The next fgets reads from the beginning of a line. */
|
426
|
+
bol = 1;
|
427
|
+
}
|
428
|
+
continue;
|
429
|
+
}
|
325
430
|
|
326
|
-
sscanf(buf, "%lx-%lx
|
327
|
-
if (offset == 0) {
|
431
|
+
if (sscanf(buf, "%lx-%lx %4s", &start, &end, perms) != 3) {
|
328
432
|
continue;
|
329
433
|
}
|
330
|
-
if (start
|
331
|
-
|
332
|
-
|
333
|
-
|
434
|
+
if (start <= addr && addr < end) {
|
435
|
+
int prot = 0;
|
436
|
+
if (perms[0] == 'r') {
|
437
|
+
prot |= PROT_READ;
|
438
|
+
} else if (perms[0] != '-') {
|
439
|
+
goto unknown_perms;
|
334
440
|
}
|
335
|
-
if (
|
336
|
-
|
441
|
+
if (perms[1] == 'w') {
|
442
|
+
prot |= PROT_WRITE;
|
443
|
+
} else if (perms[1] != '-') {
|
444
|
+
goto unknown_perms;
|
445
|
+
}
|
446
|
+
if (perms[2] == 'x') {
|
447
|
+
prot |= PROT_EXEC;
|
448
|
+
} else if (perms[2] != '-') {
|
449
|
+
goto unknown_perms;
|
450
|
+
}
|
451
|
+
if (perms[3] != 'p') {
|
452
|
+
goto unknown_perms;
|
453
|
+
}
|
454
|
+
if (perms[4] != '\0') {
|
455
|
+
perms[4] = '\0';
|
456
|
+
goto unknown_perms;
|
337
457
|
}
|
338
|
-
p[strlen(p) - 1] = '\0'; /* remove '\n' */
|
339
458
|
fclose(fp);
|
340
|
-
return
|
459
|
+
return prot;
|
341
460
|
}
|
342
461
|
}
|
343
462
|
fclose(fp);
|
344
|
-
set_errmsg("Could not find
|
345
|
-
|
346
|
-
|
463
|
+
set_errmsg("Could not find memory region containing %p", (void*)addr);
|
464
|
+
return 0;
|
465
|
+
unknown_perms:
|
466
|
+
fclose(fp);
|
467
|
+
set_errmsg("Unexcepted memory permission %s at %p", perms, (void*)addr);
|
468
|
+
return 0;
|
347
469
|
}
|
348
470
|
#elif defined __FreeBSD__
|
349
|
-
static
|
471
|
+
static int get_memory_permission(void *address)
|
350
472
|
{
|
351
473
|
uint64_t addr = (uint64_t)address;
|
352
474
|
struct kinfo_vmentry *top;
|
@@ -354,87 +476,78 @@ static const char *get_mapped_file(const void *address, char *buf, int *err)
|
|
354
476
|
|
355
477
|
top = kinfo_getvmmap(getpid(), &cnt);
|
356
478
|
if (top == NULL) {
|
357
|
-
|
358
|
-
|
359
|
-
return NULL;
|
479
|
+
set_errmsg("failed to call kinfo_getvmmap()\n");
|
480
|
+
return 0;
|
360
481
|
}
|
361
482
|
for (i = 0; i < cnt; i++) {
|
362
483
|
struct kinfo_vmentry *kve = top + i;
|
363
484
|
|
364
|
-
if (kve->kve_start
|
365
|
-
|
485
|
+
if (kve->kve_start <= addr && addr < kve->kve_end) {
|
486
|
+
int prot = 0;
|
487
|
+
if (kve->kve_protection & KVME_PROT_READ) {
|
488
|
+
prot |= PROT_READ;
|
489
|
+
}
|
490
|
+
if (kve->kve_protection & KVME_PROT_WRITE) {
|
491
|
+
prot |= PROT_WRITE;
|
492
|
+
}
|
493
|
+
if (kve->kve_protection & KVME_PROT_EXEC) {
|
494
|
+
prot |= PROT_EXEC;
|
495
|
+
}
|
496
|
+
if (prot == 0) {
|
497
|
+
set_errmsg("Unknown kve_protection 0x%x at %p", kve->kve_protection, (void*)addr);
|
498
|
+
}
|
366
499
|
free(top);
|
367
|
-
return
|
500
|
+
return prot;
|
368
501
|
}
|
369
502
|
}
|
370
503
|
free(top);
|
371
|
-
set_errmsg("Could not find
|
372
|
-
|
373
|
-
return NULL;
|
374
|
-
}
|
375
|
-
#else
|
376
|
-
static const char *get_mapped_file(const void *address, char *buf, int *err)
|
377
|
-
{
|
378
|
-
set_errmsg("Could not find a mapped file reagion containing %p", address);
|
379
|
-
*err = PLTHOOK_INTERNAL_ERROR;
|
380
|
-
return NULL;
|
504
|
+
set_errmsg("Could not find memory region containing %p", (void*)addr);
|
505
|
+
return 0;
|
381
506
|
}
|
382
|
-
#
|
383
|
-
|
384
|
-
static int
|
507
|
+
#elif defined(__sun)
|
508
|
+
#define NUM_MAPS 20
|
509
|
+
static int get_memory_permission(void *address)
|
385
510
|
{
|
386
|
-
|
387
|
-
const char *fname;
|
511
|
+
unsigned long addr = (unsigned long)address;
|
388
512
|
FILE *fp;
|
389
|
-
|
390
|
-
|
391
|
-
int rv;
|
392
|
-
|
393
|
-
if (lmap->l_name[0] == '/') {
|
394
|
-
fname = lmap->l_name;
|
395
|
-
} else {
|
396
|
-
int err;
|
513
|
+
prmap_t maps[NUM_MAPS];
|
514
|
+
size_t num;
|
397
515
|
|
398
|
-
|
399
|
-
if (fname == NULL) {
|
400
|
-
return err;
|
401
|
-
}
|
402
|
-
}
|
403
|
-
fp = fopen(fname, "r");
|
516
|
+
fp = fopen("/proc/self/map", "r");
|
404
517
|
if (fp == NULL) {
|
405
|
-
set_errmsg("failed to open
|
406
|
-
return
|
407
|
-
}
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
plthook->relro_start = plthook->plt_addr_base + phdr.p_vaddr;
|
431
|
-
plthook->relro_end = plthook->relro_start + phdr.p_memsz;
|
432
|
-
break;
|
518
|
+
set_errmsg("failed to open /proc/self/map");
|
519
|
+
return 0;
|
520
|
+
}
|
521
|
+
while ((num = fread(maps, sizeof(prmap_t), NUM_MAPS, fp)) > 0) {
|
522
|
+
size_t i;
|
523
|
+
for (i = 0; i < num; i++) {
|
524
|
+
prmap_t *map = &maps[i];
|
525
|
+
|
526
|
+
if (map->pr_vaddr <= addr && addr < map->pr_vaddr + map->pr_size) {
|
527
|
+
int prot = 0;
|
528
|
+
if (map->pr_mflags & MA_READ) {
|
529
|
+
prot |= PROT_READ;
|
530
|
+
}
|
531
|
+
if (map->pr_mflags & MA_WRITE) {
|
532
|
+
prot |= PROT_WRITE;
|
533
|
+
}
|
534
|
+
if (map->pr_mflags & MA_EXEC) {
|
535
|
+
prot |= PROT_EXEC;
|
536
|
+
}
|
537
|
+
if (prot == 0) {
|
538
|
+
set_errmsg("Unknown pr_mflags 0x%x at %p", map->pr_mflags, (void*)addr);
|
539
|
+
}
|
540
|
+
fclose(fp);
|
541
|
+
return prot;
|
542
|
+
}
|
433
543
|
}
|
434
544
|
}
|
435
545
|
fclose(fp);
|
546
|
+
set_errmsg("Could not find memory region containing %p", (void*)addr);
|
436
547
|
return 0;
|
437
548
|
}
|
549
|
+
#else
|
550
|
+
#error Unsupported platform
|
438
551
|
#endif
|
439
552
|
|
440
553
|
static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
@@ -443,13 +556,26 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
443
556
|
const Elf_Dyn *dyn;
|
444
557
|
const char *dyn_addr_base = NULL;
|
445
558
|
|
559
|
+
if (page_size == 0) {
|
560
|
+
page_size = sysconf(_SC_PAGESIZE);
|
561
|
+
}
|
562
|
+
|
446
563
|
#if defined __linux__
|
447
564
|
plthook.plt_addr_base = (char*)lmap->l_addr;
|
565
|
+
#if defined __riscv
|
566
|
+
const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
|
567
|
+
if (ehdr->e_type == ET_DYN) {
|
568
|
+
dyn_addr_base = (const char*)lmap->l_addr;
|
569
|
+
}
|
570
|
+
#endif
|
571
|
+
#if defined __ANDROID__ || defined __UCLIBC__
|
572
|
+
dyn_addr_base = (const char*)lmap->l_addr;
|
573
|
+
#endif
|
448
574
|
#elif defined __FreeBSD__ || defined __sun
|
449
575
|
const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
|
450
|
-
int
|
451
|
-
if (
|
452
|
-
return
|
576
|
+
int rv_ = check_elf_header(ehdr);
|
577
|
+
if (rv_ != 0) {
|
578
|
+
return rv_;
|
453
579
|
}
|
454
580
|
if (ehdr->e_type == ET_DYN) {
|
455
581
|
dyn_addr_base = (const char*)lmap->l_addr;
|
@@ -496,62 +622,48 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
496
622
|
|
497
623
|
/* get .rela.plt or .rel.plt section */
|
498
624
|
dyn = find_dyn_by_tag(lmap->l_ld, DT_JMPREL);
|
499
|
-
|
500
|
-
|
501
|
-
if (dyn == NULL) {
|
502
|
-
/* get .rela.dyn or .rel.dyn section */
|
503
|
-
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_REL);
|
504
|
-
plthook.r_type = R_GLOBAL_DATA;
|
505
|
-
}
|
506
|
-
#endif
|
507
|
-
if (dyn == NULL) {
|
508
|
-
set_errmsg("failed to find DT_JMPREL");
|
509
|
-
return PLTHOOK_INTERNAL_ERROR;
|
510
|
-
}
|
511
|
-
plthook.plt = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
512
|
-
|
513
|
-
if (plthook.r_type == R_JUMP_SLOT) {
|
514
|
-
/* get total size of .rela.plt or .rel.plt */
|
625
|
+
if (dyn != NULL) {
|
626
|
+
plthook.rela_plt = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
515
627
|
dyn = find_dyn_by_tag(lmap->l_ld, DT_PLTRELSZ);
|
516
628
|
if (dyn == NULL) {
|
517
629
|
set_errmsg("failed to find DT_PLTRELSZ");
|
518
630
|
return PLTHOOK_INTERNAL_ERROR;
|
519
631
|
}
|
520
|
-
|
521
|
-
|
522
|
-
#ifdef
|
523
|
-
|
524
|
-
|
525
|
-
|
632
|
+
plthook.rela_plt_cnt = dyn->d_un.d_val / sizeof(Elf_Plt_Rel);
|
633
|
+
}
|
634
|
+
#ifdef R_GLOBAL_DATA
|
635
|
+
/* get .rela.dyn or .rel.dyn section */
|
636
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_REL);
|
637
|
+
if (dyn != NULL) {
|
526
638
|
size_t total_size, elem_size;
|
527
639
|
|
528
|
-
|
640
|
+
plthook.rela_dyn = (const Elf_Plt_Rel *)(dyn_addr_base + dyn->d_un.d_ptr);
|
641
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_RELSZ);
|
529
642
|
if (dyn == NULL) {
|
530
|
-
set_errmsg("failed to find
|
643
|
+
set_errmsg("failed to find PLT_DT_RELSZ");
|
531
644
|
return PLTHOOK_INTERNAL_ERROR;
|
532
645
|
}
|
533
646
|
total_size = dyn->d_un.d_ptr;
|
534
647
|
|
535
|
-
dyn = find_dyn_by_tag(lmap->l_ld,
|
648
|
+
dyn = find_dyn_by_tag(lmap->l_ld, PLT_DT_RELENT);
|
536
649
|
if (dyn == NULL) {
|
537
|
-
set_errmsg("failed to find
|
650
|
+
set_errmsg("failed to find PLT_DT_RELENT");
|
538
651
|
return PLTHOOK_INTERNAL_ERROR;
|
539
652
|
}
|
540
653
|
elem_size = dyn->d_un.d_ptr;
|
541
|
-
plthook.
|
542
|
-
#endif
|
654
|
+
plthook.rela_dyn_cnt = total_size / elem_size;
|
543
655
|
}
|
656
|
+
#endif
|
544
657
|
|
545
|
-
#ifdef
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
}
|
658
|
+
#ifdef R_GLOBAL_DATA
|
659
|
+
if (plthook.rela_plt == NULL && plthook.rela_dyn == NULL) {
|
660
|
+
set_errmsg("failed to find either of DT_JMPREL and DT_REL");
|
661
|
+
return PLTHOOK_INTERNAL_ERROR;
|
662
|
+
}
|
663
|
+
#else
|
664
|
+
if (plthook.rela_plt == NULL) {
|
665
|
+
set_errmsg("failed to find DT_JMPREL");
|
666
|
+
return PLTHOOK_INTERNAL_ERROR;
|
555
667
|
}
|
556
668
|
#endif
|
557
669
|
|
@@ -564,6 +676,7 @@ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
|
|
564
676
|
return 0;
|
565
677
|
}
|
566
678
|
|
679
|
+
#if defined __FreeBSD__ || defined __sun
|
567
680
|
static int check_elf_header(const Elf_Ehdr *ehdr)
|
568
681
|
{
|
569
682
|
static const unsigned short s = 1;
|
@@ -610,26 +723,44 @@ static int check_elf_header(const Elf_Ehdr *ehdr)
|
|
610
723
|
}
|
611
724
|
return 0;
|
612
725
|
}
|
726
|
+
#endif
|
727
|
+
|
728
|
+
static int check_rel(const plthook_t *plthook, const Elf_Plt_Rel *plt, Elf_Xword r_type, const char **name_out, void ***addr_out)
|
729
|
+
{
|
730
|
+
if (ELF_R_TYPE(plt->r_info) == r_type) {
|
731
|
+
size_t idx = ELF_R_SYM(plt->r_info);
|
732
|
+
idx = plthook->dynsym[idx].st_name;
|
733
|
+
if (idx + 1 > plthook->dynstr_size) {
|
734
|
+
set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
|
735
|
+
return PLTHOOK_INVALID_FILE_FORMAT;
|
736
|
+
}
|
737
|
+
*name_out = plthook->dynstr + idx;
|
738
|
+
*addr_out = (void**)(plthook->plt_addr_base + plt->r_offset);
|
739
|
+
return 0;
|
740
|
+
}
|
741
|
+
return -1;
|
742
|
+
}
|
613
743
|
|
614
744
|
int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
|
615
745
|
{
|
616
|
-
while (*pos < plthook->
|
617
|
-
const Elf_Plt_Rel *plt = plthook->
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
if (idx + 1 > plthook->dynstr_size) {
|
623
|
-
set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
|
624
|
-
return PLTHOOK_INVALID_FILE_FORMAT;
|
625
|
-
}
|
626
|
-
*name_out = plthook->dynstr + idx;
|
627
|
-
*addr_out = (void**)(plthook->plt_addr_base + plt->r_offset);
|
628
|
-
(*pos)++;
|
629
|
-
return 0;
|
746
|
+
while (*pos < plthook->rela_plt_cnt) {
|
747
|
+
const Elf_Plt_Rel *plt = plthook->rela_plt + *pos;
|
748
|
+
int rv = check_rel(plthook, plt, R_JUMP_SLOT, name_out, addr_out);
|
749
|
+
(*pos)++;
|
750
|
+
if (rv >= 0) {
|
751
|
+
return rv;
|
630
752
|
}
|
753
|
+
}
|
754
|
+
#ifdef R_GLOBAL_DATA
|
755
|
+
while (*pos < plthook->rela_plt_cnt + plthook->rela_dyn_cnt) {
|
756
|
+
const Elf_Plt_Rel *plt = plthook->rela_dyn + (*pos - plthook->rela_plt_cnt);
|
757
|
+
int rv = check_rel(plthook, plt, R_GLOBAL_DATA, name_out, addr_out);
|
631
758
|
(*pos)++;
|
759
|
+
if (rv >= 0) {
|
760
|
+
return rv;
|
761
|
+
}
|
632
762
|
}
|
763
|
+
#endif
|
633
764
|
*name_out = NULL;
|
634
765
|
*addr_out = NULL;
|
635
766
|
return EOF;
|
@@ -650,26 +781,24 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
|
|
650
781
|
while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
|
651
782
|
if (strncmp(name, funcname, funcnamelen) == 0) {
|
652
783
|
if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
784
|
+
int prot = get_memory_permission(addr);
|
785
|
+
if (prot == 0) {
|
786
|
+
return PLTHOOK_INTERNAL_ERROR;
|
787
|
+
}
|
788
|
+
if (!(prot & PROT_WRITE)) {
|
789
|
+
if (mprotect(ALIGN_ADDR(addr), page_size, PROT_READ | PROT_WRITE) != 0) {
|
790
|
+
set_errmsg("Could not change the process memory permission at %p: %s",
|
791
|
+
ALIGN_ADDR(addr), strerror(errno));
|
660
792
|
return PLTHOOK_INTERNAL_ERROR;
|
661
793
|
}
|
662
794
|
}
|
663
|
-
#endif
|
664
795
|
if (oldfunc) {
|
665
796
|
*oldfunc = *addr;
|
666
797
|
}
|
667
798
|
*addr = funcaddr;
|
668
|
-
|
669
|
-
|
670
|
-
mprotect(maddr, page_size, PROT_READ);
|
799
|
+
if (!(prot & PROT_WRITE)) {
|
800
|
+
mprotect(ALIGN_ADDR(addr), page_size, prot);
|
671
801
|
}
|
672
|
-
#endif
|
673
802
|
return 0;
|
674
803
|
}
|
675
804
|
}
|