ruby-oci8 2.2.4.1 → 2.2.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -424,49 +424,6 @@ static VALUE oci8_parse_connect_string(VALUE self, VALUE conn_str)
424
424
  return rb_ary_new3(4, user, pass, dbname, mode);
425
425
  }
426
426
 
427
- /*
428
- * Logoff strategy for sessions connected by OCILogon.
429
- */
430
- typedef struct {
431
- OCISvcCtx *svchp;
432
- OCISession *usrhp;
433
- OCIServer *srvhp;
434
- } simple_logoff_arg_t;
435
-
436
- static void *simple_logoff_prepare(oci8_svcctx_t *svcctx)
437
- {
438
- simple_logoff_arg_t *sla = xmalloc(sizeof(simple_logoff_arg_t));
439
- sla->svchp = svcctx->base.hp.svc;
440
- sla->usrhp = svcctx->usrhp;
441
- sla->srvhp = svcctx->srvhp;
442
- svcctx->usrhp = NULL;
443
- svcctx->srvhp = NULL;
444
- return sla;
445
- }
446
-
447
- static void *simple_logoff_execute(void *arg)
448
- {
449
- simple_logoff_arg_t *sla = (simple_logoff_arg_t *)arg;
450
- OCIError *errhp = oci8_errhp;
451
- boolean txn = TRUE;
452
- sword rv;
453
-
454
- if (oracle_client_version >= ORAVER_12_1) {
455
- OCIAttrGet(sla->usrhp, OCI_HTYPE_SESSION, &txn, NULL, OCI_ATTR_TRANSACTION_IN_PROGRESS, errhp);
456
- }
457
- if (txn) {
458
- OCITransRollback(sla->svchp, errhp, OCI_DEFAULT);
459
- }
460
- rv = OCILogoff(sla->svchp, errhp);
461
- xfree(sla);
462
- return (void*)(VALUE)rv;
463
- }
464
-
465
- static const oci8_logoff_strategy_t simple_logoff = {
466
- simple_logoff_prepare,
467
- simple_logoff_execute,
468
- };
469
-
470
427
  /*
471
428
  * Logoff strategy for sessions connected by OCIServerAttach and OCISessionBegin.
472
429
  */
@@ -531,61 +488,6 @@ static const oci8_logoff_strategy_t complex_logoff = {
531
488
  complex_logoff_execute,
532
489
  };
533
490
 
534
- /*
535
- * @overload logon2(username, password, dbname, mode)
536
- *
537
- * Creates a simple logon session by the OCI function OCILogon2().
538
- *
539
- * @param [String] username
540
- * @param [String] password
541
- * @param [String] dbname
542
- * @param [Integer] mode
543
- * @private
544
- */
545
- static VALUE oci8_logon2(VALUE self, VALUE username, VALUE password, VALUE dbname, VALUE mode)
546
- {
547
- oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
548
- ub4 logon2_mode;
549
-
550
- if (svcctx->logoff_strategy != NULL) {
551
- rb_raise(rb_eRuntimeError, "Could not reuse the session.");
552
- }
553
-
554
- /* check arugmnets */
555
- OCI8SafeStringValue(username);
556
- OCI8SafeStringValue(password);
557
- if (!NIL_P(dbname)) {
558
- OCI8SafeStringValue(dbname);
559
- }
560
- logon2_mode = NUM2UINT(mode);
561
-
562
- /* logon */
563
- svcctx->base.type = OCI_HTYPE_SVCCTX;
564
- chker2(OCILogon2_nb(svcctx, oci8_envhp, oci8_errhp, &svcctx->base.hp.svc,
565
- RSTRING_ORATEXT(username), RSTRING_LEN(username),
566
- RSTRING_ORATEXT(password), RSTRING_LEN(password),
567
- NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
568
- NIL_P(dbname) ? 0 : RSTRING_LEN(dbname), logon2_mode),
569
- &svcctx->base);
570
- svcctx->logoff_strategy = &simple_logoff;
571
-
572
- if (logon2_mode & OCI_LOGON2_CPOOL) {
573
- svcctx->state |= OCI8_STATE_CPOOL;
574
- }
575
-
576
- /* setup the session handle */
577
- chker2(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->usrhp, 0, OCI_ATTR_SESSION, oci8_errhp),
578
- &svcctx->base);
579
- copy_session_handle(svcctx);
580
-
581
- /* setup the server handle */
582
- chker2(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp),
583
- &svcctx->base);
584
- copy_server_handle(svcctx);
585
-
586
- return Qnil;
587
- }
588
-
589
491
  /*
590
492
  * @overload allocate_handles()
591
493
  *
@@ -1107,7 +1009,6 @@ void Init_oci8(VALUE *out)
1107
1009
  rb_define_singleton_method_nodoc(cOCI8, "__set_prop", oci8_s_set_prop, 2);
1108
1010
  rb_define_singleton_method(cOCI8, "error_message", oci8_s_error_message, 1);
1109
1011
  rb_define_private_method(cOCI8, "parse_connect_string", oci8_parse_connect_string, 1);
1110
- rb_define_private_method(cOCI8, "logon2", oci8_logon2, 4);
1111
1012
  rb_define_private_method(cOCI8, "allocate_handles", oci8_allocate_handles, 0);
1112
1013
  rb_define_private_method(cOCI8, "server_attach", oci8_server_attach, 2);
1113
1014
  rb_define_private_method(cOCI8, "session_begin", oci8_session_begin, 2);
@@ -558,6 +558,24 @@ static VALUE ensure_func(cb_arg_t *arg)
558
558
 
559
559
  #ifndef _WIN32
560
560
  #include <dlfcn.h>
561
+ static void *load_file(const char *filename, int flags, VALUE errors)
562
+ {
563
+ void *handle = dlopen(filename, flags);
564
+
565
+ if (handle == NULL) {
566
+ char *err = dlerror();
567
+ VALUE msg;
568
+
569
+ if (strstr(err, filename) == NULL) {
570
+ msg = rb_sprintf("%s: %s", filename, err);
571
+ msg = rb_enc_associate_index(msg, rb_locale_encindex());
572
+ } else {
573
+ msg = rb_locale_str_new_cstr(err);
574
+ }
575
+ rb_ary_push(errors, msg);
576
+ }
577
+ return handle;
578
+ }
561
579
  #endif
562
580
 
563
581
  void *oci8_find_symbol(const char *symbol_name)
@@ -600,8 +618,6 @@ void *oci8_find_symbol(const char *symbol_name)
600
618
  "libclntsh.sl.12.1",
601
619
  "libclntsh.sl.11.1",
602
620
  "libclntsh.sl.10.1",
603
- "libclntsh.sl.9.0",
604
- "libclntsh.sl.8.0",
605
621
  #elif defined(__APPLE__)
606
622
  /* Mac OS X */
607
623
  "libclntsh.dylib.12.1",
@@ -612,46 +628,38 @@ void *oci8_find_symbol(const char *symbol_name)
612
628
  "libclntsh.so.12.1",
613
629
  "libclntsh.so.11.1",
614
630
  "libclntsh.so.10.1",
615
- "libclntsh.so.9.0",
616
- "libclntsh.so.8.0",
617
631
  #endif
618
632
  };
619
633
  #define NUM_SONAMES (sizeof(sonames)/sizeof(sonames[0]))
634
+ #if defined(_AIX) /* AIX */
635
+ #define BASE_SONAME "libclntsh.a(shr.o)"
636
+ #elif defined(__hppa) /* HP-UX(PA-RISC) */
637
+ #define BASE_SONAME "libclntsh.sl"
638
+ #elif !defined(__CYGWIN__) && !defined(__APPLE__)
639
+ #define BASE_SONAME "libclntsh.so"
640
+ #endif
620
641
  size_t idx;
621
- volatile VALUE err = rb_ary_new();
642
+ VALUE err = rb_ary_new();
622
643
 
623
644
  #ifdef _AIX
624
645
  #define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL|RTLD_MEMBER)
625
646
  #else
626
647
  #define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL)
627
648
  #endif
628
- for (idx = 0; idx < NUM_SONAMES; idx++) {
629
- handle = dlopen(sonames[idx], DLOPEN_FLAG);
630
- if (handle != NULL) {
631
- break;
632
- }
633
- rb_ary_push(err, rb_locale_str_new_cstr(dlerror()));
649
+ #ifdef BASE_SONAME
650
+ char *oracle_home = getenv("ORACLE_HOME");
651
+
652
+ if (oracle_home != NULL) {
653
+ VALUE fname = rb_str_buf_cat2(rb_str_buf_new_cstr(oracle_home), "/lib/" BASE_SONAME);
654
+ handle = load_file(StringValueCStr(fname), DLOPEN_FLAG, err);
655
+ RB_GC_GUARD(fname);
656
+ }
657
+ #endif
658
+ for (idx = 0; handle == NULL && idx < NUM_SONAMES; idx++) {
659
+ handle = load_file(sonames[idx], DLOPEN_FLAG, err);
634
660
  }
635
661
  if (handle == NULL) {
636
- VALUE msg;
637
- const VALUE *arr = RARRAY_CONST_PTR(err);
638
-
639
- msg = rb_str_buf_new(NUM_SONAMES * 50);
640
- for (idx = 0; idx < NUM_SONAMES; idx++) {
641
- const char *errmsg = RSTRING_PTR(arr[idx]);
642
- if (idx != 0) {
643
- rb_str_buf_cat2(msg, " ");
644
- }
645
- if (strstr(errmsg, sonames[idx]) == NULL) {
646
- /* prepend "soname: " if soname is not found in
647
- * the error message.
648
- */
649
- rb_str_buf_cat2(msg, sonames[idx]);
650
- rb_str_buf_cat2(msg, ": ");
651
- }
652
- rb_str_buf_append(msg, arr[idx]);
653
- rb_str_buf_cat2(msg, ";");
654
- }
662
+ VALUE msg = rb_ary_join(err, rb_usascii_str_new_cstr("; "));
655
663
  rb_exc_raise(rb_exc_new3(rb_eLoadError, msg));
656
664
  }
657
665
  }
@@ -1441,17 +1441,17 @@ static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp)
1441
1441
  }
1442
1442
 
1443
1443
  /*
1444
- * @overload has_decimal_part?
1444
+ * @overload has_fractional_part?
1445
1445
  *
1446
- * Returns <code>true</code> if <i>self</i> has a decimal part.
1446
+ * Returns <code>true</code> if <i>self</i> has a fractional part.
1447
1447
  *
1448
1448
  * @example
1449
- * OraNumber(10).has_decimal_part? # => false
1450
- * OraNumber(10.1).has_decimal_part? # => true
1449
+ * OraNumber(10).has_fractional_part? # => false
1450
+ * OraNumber(10.1).has_fractional_part? # => true
1451
1451
  *
1452
- * @since 2.0.5
1452
+ * @since 2.2.5
1453
1453
  */
1454
- static VALUE onum_has_decimal_part_p(VALUE self)
1454
+ static VALUE onum_has_fractional_part_p(VALUE self)
1455
1455
  {
1456
1456
  OCIError *errhp = oci8_errhp;
1457
1457
  boolean result;
@@ -1873,7 +1873,7 @@ Init_oci_number(VALUE cOCI8, OCIError *errhp)
1873
1873
  rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
1874
1874
  rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
1875
1875
  rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
1876
- rb_define_method(cOCINumber, "has_decimal_part?", onum_has_decimal_part_p, 0);
1876
+ rb_define_method(cOCINumber, "has_fractional_part?", onum_has_fractional_part_p, 0);
1877
1877
  rb_define_method(cOCINumber, "to_onum", onum_to_onum, 0);
1878
1878
 
1879
1879
  rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
@@ -1902,6 +1902,10 @@ Init_oci_number(VALUE cOCI8, OCIError *errhp)
1902
1902
  dummy2 = rb_define_class_under(mOCI8BindType, "Integer", cOCI8BindTypeBase);
1903
1903
  dummy3 = rb_define_class_under(mOCI8BindType, "Float", cOCI8BindTypeBase);
1904
1904
  #endif
1905
+
1906
+ /* The following method definition is for backward-compatibility.
1907
+ I misunderstood the name of numbers after a decimal point. */
1908
+ rb_define_method_nodoc(cOCINumber, "has_decimal_part?", onum_has_fractional_part_p, 0);
1905
1909
  }
1906
1910
 
1907
1911
  /*
@@ -36,23 +36,27 @@
36
36
  #if defined(__sun) && defined(_XOPEN_SOURCE) && !defined(__EXTENSIONS__)
37
37
  #define __EXTENSIONS__
38
38
  #endif
39
+ #if defined(__linux__) && !defined(_GNU_SOURCE)
39
40
  #define _GNU_SOURCE
41
+ #endif
40
42
  #include <stdio.h>
41
43
  #include <stdarg.h>
42
44
  #include <stdlib.h>
43
45
  #include <unistd.h>
44
46
  #include <string.h>
45
47
  #include <limits.h>
46
- #include <sys/types.h>
47
- #include <sys/stat.h>
48
48
  #include <sys/mman.h>
49
- #include <fcntl.h>
50
49
  #include <errno.h>
51
50
  #include <dlfcn.h>
52
51
  #ifdef __sun
53
- #include <procfs.h>
52
+ #include <sys/auxv.h>
54
53
  #define ELF_TARGET_ALL
55
54
  #endif /* __sun */
55
+ #ifdef __FreeBSD__
56
+ #include <sys/types.h>
57
+ #include <sys/user.h>
58
+ #include <libutil.h>
59
+ #endif
56
60
  #include <elf.h>
57
61
  #include <link.h>
58
62
  #include "plthook.h"
@@ -61,40 +65,47 @@
61
65
  #define __attribute__(arg)
62
66
  #endif
63
67
 
64
- #if defined __linux__
65
- #define ELF_OSABI ELFOSABI_SYSV
66
- #define ELF_OSABI_ALT ELFOSABI_LINUX
67
- #elif defined __sun
68
- #define ELF_OSABI ELFOSABI_SOLARIS
69
- #elif defined __FreeBSD__
70
- #define ELF_OSABI ELFOSABI_FREEBSD
71
- #if defined __i386__ && __ELF_WORD_SIZE == 64
68
+ #if defined __FreeBSD__ && defined __i386__ && __ELF_WORD_SIZE == 64
72
69
  #error 32-bit application on 64-bit OS is not supported.
73
70
  #endif
74
- #else
75
- #error unsupported OS
71
+
72
+ #if !defined(R_X86_64_JUMP_SLOT) && defined(R_X86_64_JMP_SLOT)
73
+ #define R_X86_64_JUMP_SLOT R_X86_64_JMP_SLOT
76
74
  #endif
77
75
 
78
76
  #if defined __x86_64__ || defined __x86_64
79
- #define ELF_DATA ELFDATA2LSB
80
- #define E_MACHINE EM_X86_64
81
- #ifdef R_X86_64_JUMP_SLOT
82
77
  #define R_JUMP_SLOT R_X86_64_JUMP_SLOT
83
- #else
84
- #define R_JUMP_SLOT R_X86_64_JMP_SLOT
85
- #endif
86
- #define SHT_PLT_REL SHT_RELA
87
78
  #define Elf_Plt_Rel Elf_Rela
88
- #define PLT_SECTION_NAME ".rela.plt"
79
+ #define PLT_DT_REL DT_RELA
80
+ #define R_GLOBAL_DATA R_X86_64_GLOB_DAT
89
81
  #elif defined __i386__ || defined __i386
90
- #define ELF_DATA ELFDATA2LSB
91
- #define E_MACHINE EM_386
92
82
  #define R_JUMP_SLOT R_386_JMP_SLOT
93
- #define SHT_PLT_REL SHT_REL
94
83
  #define Elf_Plt_Rel Elf_Rel
95
- #define PLT_SECTION_NAME ".rel.plt"
84
+ #define PLT_DT_REL DT_REL
85
+ #define R_GLOBAL_DATA R_386_GLOB_DAT
86
+ #elif defined __arm__ || defined __arm
87
+ #define R_JUMP_SLOT R_ARM_JUMP_SLOT
88
+ #define Elf_Plt_Rel Elf_Rel
89
+ #elif defined __aarch64__ || defined __aarch64 /* ARM64 */
90
+ #define R_JUMP_SLOT R_AARCH64_JUMP_SLOT
91
+ #define Elf_Plt_Rel Elf_Rela
92
+ #elif defined __powerpc64__
93
+ #define R_JUMP_SLOT R_PPC64_JMP_SLOT
94
+ #define Elf_Plt_Rel Elf_Rela
95
+ #elif defined __powerpc__
96
+ #define R_JUMP_SLOT R_PPC_JMP_SLOT
97
+ #define Elf_Plt_Rel Elf_Rela
98
+ #elif 0 /* disabled because not tested */ && (defined __sparcv9 || defined __sparc_v9__)
99
+ #define R_JUMP_SLOT R_SPARC_JMP_SLOT
100
+ #define Elf_Plt_Rel Elf_Rela
101
+ #elif 0 /* disabled because not tested */ && (defined __sparc || defined __sparc__)
102
+ #define R_JUMP_SLOT R_SPARC_JMP_SLOT
103
+ #define Elf_Plt_Rel Elf_Rela
104
+ #elif 0 /* disabled because not tested */ && (defined __ia64 || defined __ia64__)
105
+ #define R_JUMP_SLOT R_IA64_IPLTMSB
106
+ #define Elf_Plt_Rel Elf_Rela
96
107
  #else
97
- #error E_MACHINE is not defined.
108
+ #error unsupported OS
98
109
  #endif
99
110
 
100
111
  #if defined __LP64__
@@ -102,12 +113,16 @@
102
113
  #define ELF_CLASS ELFCLASS64
103
114
  #endif
104
115
  #define SIZE_T_FMT "lu"
116
+ #define ELF_WORD_FMT "u"
117
+ #define ELF_XWORD_FMT "lu"
118
+ #define ELF_SXWORD_FMT "ld"
105
119
  #define Elf_Half Elf64_Half
106
- #define Elf_Addr Elf64_Addr
120
+ #define Elf_Xword Elf64_Xword
121
+ #define Elf_Sxword Elf64_Sxword
107
122
  #define Elf_Ehdr Elf64_Ehdr
108
123
  #define Elf_Phdr Elf64_Phdr
109
- #define Elf_Shdr Elf64_Shdr
110
124
  #define Elf_Sym Elf64_Sym
125
+ #define Elf_Dyn Elf64_Dyn
111
126
  #define Elf_Rel Elf64_Rel
112
127
  #define Elf_Rela Elf64_Rela
113
128
  #ifndef ELF_R_SYM
@@ -121,12 +136,22 @@
121
136
  #define ELF_CLASS ELFCLASS32
122
137
  #endif
123
138
  #define SIZE_T_FMT "u"
139
+ #ifdef __sun
140
+ #define ELF_WORD_FMT "lu"
141
+ #define ELF_XWORD_FMT "lu"
142
+ #define ELF_SXWORD_FMT "ld"
143
+ #else
144
+ #define ELF_WORD_FMT "u"
145
+ #define ELF_XWORD_FMT "u"
146
+ #define ELF_SXWORD_FMT "d"
147
+ #endif
124
148
  #define Elf_Half Elf32_Half
125
- #define Elf_Addr Elf32_Addr
149
+ #define Elf_Xword Elf32_Word
150
+ #define Elf_Sxword Elf32_Sword
126
151
  #define Elf_Ehdr Elf32_Ehdr
127
152
  #define Elf_Phdr Elf32_Phdr
128
- #define Elf_Shdr Elf32_Shdr
129
153
  #define Elf_Sym Elf32_Sym
154
+ #define Elf_Dyn Elf32_Dyn
130
155
  #define Elf_Rel Elf32_Rel
131
156
  #define Elf_Rela Elf32_Rela
132
157
  #ifndef ELF_R_SYM
@@ -137,21 +162,22 @@
137
162
  #endif
138
163
  #endif /* __LP64__ */
139
164
 
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
+
140
172
  struct plthook {
141
- const char *base;
142
- const Elf_Phdr *phdr;
143
- size_t phnum;
144
- Elf_Shdr *shdr;
145
- size_t shnum;
146
- char *shstrtab;
147
- size_t shstrtab_size;
148
173
  const Elf_Sym *dynsym;
149
- size_t dynsym_cnt;
150
174
  const char *dynstr;
151
175
  size_t dynstr_size;
176
+ const char *plt_addr_base;
152
177
  const Elf_Plt_Rel *plt;
153
178
  size_t plt_cnt;
154
- #ifdef PT_GNU_RELRO
179
+ Elf_Xword r_type;
180
+ #ifdef SUPPORT_RELRO
155
181
  const char *relro_start;
156
182
  const char *relro_end;
157
183
  #endif
@@ -159,15 +185,18 @@ struct plthook {
159
185
 
160
186
  static char errmsg[512];
161
187
 
162
- #ifdef PT_GNU_RELRO
188
+ #ifdef SUPPORT_RELRO
163
189
  static size_t page_size;
164
190
  #endif
165
191
 
166
192
  static int plthook_open_executable(plthook_t **plthook_out);
167
193
  static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename);
168
- static int plthook_open_real(plthook_t **plthook_out, const char *base, const char *filename);
194
+ 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
+ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap);
169
199
  static int check_elf_header(const Elf_Ehdr *ehdr);
170
- static int find_section(plthook_t *image, const char *name, const Elf_Shdr **out);
171
200
  static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
172
201
 
173
202
  int plthook_open(plthook_t **plthook_out, const char *filename)
@@ -192,71 +221,54 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
192
221
  set_errmsg("dlinfo error");
193
222
  return PLTHOOK_FILE_NOT_FOUND;
194
223
  }
195
- if (lmap->l_addr == 0 && *lmap->l_name == 0) {
196
- return plthook_open_executable(plthook_out);
197
- }
198
- return plthook_open_real(plthook_out, (const char*)lmap->l_addr, lmap->l_name);
224
+ return plthook_open_real(plthook_out, lmap);
199
225
  }
200
226
 
201
227
  int plthook_open_by_address(plthook_t **plthook_out, void *address)
202
228
  {
229
+ #if defined __FreeBSD__
230
+ return PLTHOOK_NOT_IMPLEMENTED;
231
+ #else
203
232
  Dl_info info;
233
+ struct link_map *lmap = NULL;
204
234
 
205
235
  *plthook_out = NULL;
206
- if (dladdr(address, &info) == 0) {
236
+ if (dladdr1(address, &info, (void**)&lmap, RTLD_DL_LINKMAP) == 0) {
207
237
  set_errmsg("dladdr error");
208
238
  return PLTHOOK_FILE_NOT_FOUND;
209
239
  }
210
- return plthook_open_real(plthook_out, info.dli_fbase, info.dli_fname);
240
+ return plthook_open_real(plthook_out, lmap);
241
+ #endif
211
242
  }
212
243
 
213
244
  static int plthook_open_executable(plthook_t **plthook_out)
214
245
  {
215
246
  #if defined __linux__
216
- /* Open the main program. */
217
- char buf[128];
218
- FILE *fp = fopen("/proc/self/maps", "r");
219
- unsigned long base;
247
+ return plthook_open_real(plthook_out, _r_debug.r_map);
248
+ #elif defined __sun
249
+ const char *auxv_file = "/proc/self/auxv";
250
+ #define NUM_AUXV_CNT 10
251
+ FILE *fp = fopen(auxv_file, "r");
252
+ auxv_t auxv;
253
+ struct r_debug *r_debug = NULL;
220
254
 
221
255
  if (fp == NULL) {
222
- set_errmsg("Could not open /proc/self/maps: %s",
256
+ set_errmsg("Could not open %s: %s", auxv_file,
223
257
  strerror(errno));
224
258
  return PLTHOOK_INTERNAL_ERROR;
225
259
  }
226
- if (fgets(buf, sizeof(buf), fp) == NULL) {
227
- set_errmsg("Could not read /proc/self/maps: %s",
228
- strerror(errno));
229
- fclose(fp);
230
- return PLTHOOK_INTERNAL_ERROR;
260
+ while (fread(&auxv, sizeof(auxv_t), 1, fp) == 1) {
261
+ if (auxv.a_type == AT_SUN_LDDATA) {
262
+ r_debug = (struct r_debug *)auxv.a_un.a_ptr;
263
+ break;
264
+ }
231
265
  }
232
266
  fclose(fp);
233
- if (sscanf(buf, "%lx-%*x r-xp %*x %*x:%*x %*u ", &base) != 1) {
234
- set_errmsg("invalid /proc/self/maps format: %s", buf);
267
+ if (r_debug == NULL) {
268
+ set_errmsg("Could not find r_debug");
235
269
  return PLTHOOK_INTERNAL_ERROR;
236
270
  }
237
- return plthook_open_real(plthook_out, (const char*)base, "/proc/self/exe");
238
- #elif defined __sun
239
- prmap_t prmap;
240
- pid_t pid = getpid();
241
- char fname[128];
242
- int fd;
243
-
244
- sprintf(fname, "/proc/%d/map", pid);
245
- fd = open(fname, O_RDONLY);
246
- if (fd == -1) {
247
- set_errmsg("Could not open %s: %s", fname,
248
- strerror(errno));
249
- return PLTHOOK_INTERNAL_ERROR;
250
- }
251
- if (read(fd, &prmap, sizeof(prmap)) != sizeof(prmap)) {
252
- set_errmsg("Could not read %s: %s", fname,
253
- strerror(errno));
254
- close(fd);
255
- return PLTHOOK_INTERNAL_ERROR;
256
- }
257
- close(fd);
258
- sprintf(fname, "/proc/%d/object/a.out", pid);
259
- return plthook_open_real(plthook_out, (const char*)prmap.pr_vaddr, fname);
271
+ return plthook_open_real(plthook_out, r_debug->r_map);
260
272
  #elif defined __FreeBSD__
261
273
  return plthook_open_shared_library(plthook_out, NULL);
262
274
  #else
@@ -280,187 +292,339 @@ static int plthook_open_shared_library(plthook_t **plthook_out, const char *file
280
292
  return PLTHOOK_FILE_NOT_FOUND;
281
293
  }
282
294
  dlclose(hndl);
283
- return plthook_open_real(plthook_out, (const char*)lmap->l_addr, lmap->l_name);
295
+ return plthook_open_real(plthook_out, lmap);
284
296
  }
285
297
 
286
- static int plthook_open_real(plthook_t **plthook_out, const char *base, const char *filename)
298
+ static const Elf_Dyn *find_dyn_by_tag(const Elf_Dyn *dyn, Elf_Sxword tag)
287
299
  {
288
- const Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
289
- const Elf_Shdr *shdr;
290
- size_t shdr_size;
291
- int fd = -1;
292
- off_t offset;
293
- plthook_t *plthook;
294
- int rv;
295
- #ifdef PT_GNU_RELRO
296
- size_t idx;
297
- #endif
298
-
299
- if (base == NULL) {
300
- set_errmsg("The base address is zero.");
301
- return PLTHOOK_FILE_NOT_FOUND;
300
+ while (dyn->d_tag != DT_NULL) {
301
+ if (dyn->d_tag == tag) {
302
+ return dyn;
303
+ }
304
+ dyn++;
302
305
  }
306
+ return NULL;
307
+ }
303
308
 
304
- if (filename == NULL) {
305
- set_errmsg("failed to get the file name on the disk.");
306
- return PLTHOOK_FILE_NOT_FOUND;
309
+ #ifdef SUPPORT_RELRO
310
+ #if defined __linux__
311
+ static const char *get_mapped_file(const void *address, char *buf, int *err)
312
+ {
313
+ unsigned long addr = (unsigned long)address;
314
+ FILE *fp;
315
+
316
+ fp = fopen("/proc/self/maps", "r");
317
+ if (fp == NULL) {
318
+ set_errmsg("failed to open /proc/self/maps");
319
+ *err = PLTHOOK_INTERNAL_ERROR;
320
+ return NULL;
307
321
  }
322
+ while (fgets(buf, PATH_MAX, fp) != NULL) {
323
+ unsigned long start, end;
324
+ int offset = 0;
308
325
 
309
- plthook = calloc(1, sizeof(plthook_t));
310
- if (plthook == NULL) {
311
- set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", sizeof(plthook_t));
312
- return PLTHOOK_OUT_OF_MEMORY;
326
+ sscanf(buf, "%lx-%lx %*s %*x %*x:%*x %*u %n", &start, &end, &offset);
327
+ if (offset == 0) {
328
+ continue;
329
+ }
330
+ if (start < addr && addr < end) {
331
+ char *p = buf + offset;
332
+ while (*p == ' ') {
333
+ p++;
334
+ }
335
+ if (*p != '/') {
336
+ continue;
337
+ }
338
+ p[strlen(p) - 1] = '\0'; /* remove '\n' */
339
+ fclose(fp);
340
+ return p;
341
+ }
313
342
  }
343
+ fclose(fp);
344
+ set_errmsg("Could not find a mapped file reagion containing %p", address);
345
+ *err = PLTHOOK_INTERNAL_ERROR;
346
+ return NULL;
347
+ }
348
+ #elif defined __FreeBSD__
349
+ static const char *get_mapped_file(const void *address, char *buf, int *err)
350
+ {
351
+ uint64_t addr = (uint64_t)address;
352
+ struct kinfo_vmentry *top;
353
+ int i, cnt;
354
+
355
+ top = kinfo_getvmmap(getpid(), &cnt);
356
+ if (top == NULL) {
357
+ fprintf(stderr, "failed to call kinfo_getvmmap()\n");
358
+ *err = PLTHOOK_INTERNAL_ERROR;
359
+ return NULL;
360
+ }
361
+ for (i = 0; i < cnt; i++) {
362
+ struct kinfo_vmentry *kve = top + i;
363
+
364
+ if (kve->kve_start < addr && addr < kve->kve_end) {
365
+ strncpy(buf, kve->kve_path, PATH_MAX);
366
+ free(top);
367
+ return buf;
368
+ }
369
+ }
370
+ free(top);
371
+ set_errmsg("Could not find a mapped file reagion containing %p", address);
372
+ *err = PLTHOOK_INTERNAL_ERROR;
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;
381
+ }
382
+ #endif
383
+
384
+ static int set_relro_members(plthook_t *plthook, struct link_map *lmap)
385
+ {
386
+ char fnamebuf[PATH_MAX];
387
+ const char *fname;
388
+ FILE *fp;
389
+ Elf_Ehdr ehdr;
390
+ Elf_Half idx;
391
+ int rv;
392
+
393
+ if (lmap->l_name[0] == '/') {
394
+ fname = lmap->l_name;
395
+ } else {
396
+ int err;
314
397
 
315
- /* sanity check */
316
- rv = check_elf_header(ehdr);
398
+ fname = get_mapped_file(plthook->dynstr, fnamebuf, &err);
399
+ if (fname == NULL) {
400
+ return err;
401
+ }
402
+ }
403
+ fp = fopen(fname, "r");
404
+ if (fp == NULL) {
405
+ set_errmsg("failed to open %s", fname);
406
+ return PLTHOOK_INTERNAL_ERROR;
407
+ }
408
+ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
409
+ set_errmsg("failed to read the ELF header.");
410
+ fclose(fp);
411
+ return PLTHOOK_INVALID_FILE_FORMAT;
412
+ }
413
+ rv = check_elf_header(&ehdr);
317
414
  if (rv != 0) {
318
- goto error_exit;
415
+ fclose(fp);
416
+ return rv;
319
417
  }
320
- if (ehdr->e_type == ET_DYN) {
321
- plthook->base = base;
322
- }
323
- plthook->phdr = (const Elf_Phdr *)(plthook->base + ehdr->e_phoff);
324
- plthook->phnum = ehdr->e_phnum;
325
- fd = open(filename, O_RDONLY, 0);
326
- if (fd == -1) {
327
- set_errmsg("Could not open %s: %s", filename, strerror(errno));
328
- rv = PLTHOOK_FILE_NOT_FOUND;
329
- goto error_exit;
330
- }
331
- shdr_size = ehdr->e_shnum * ehdr->e_shentsize;
332
- plthook->shdr = calloc(1, shdr_size);
333
- if (plthook->shdr == NULL) {
334
- set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", shdr_size);
335
- rv = PLTHOOK_OUT_OF_MEMORY;
336
- goto error_exit;
337
- }
338
- offset = ehdr->e_shoff;
339
- if ((rv = lseek(fd, offset, SEEK_SET)) != offset) {
340
- set_errmsg("failed to seek to the section header table.");
341
- rv = PLTHOOK_INVALID_FILE_FORMAT;
342
- goto error_exit;
343
- }
344
- if (read(fd, plthook->shdr, shdr_size) != shdr_size) {
345
- set_errmsg("failed to read the section header table.");
346
- rv = PLTHOOK_INVALID_FILE_FORMAT;
347
- goto error_exit;
348
- }
349
- plthook->shnum = ehdr->e_shnum;
350
- plthook->shstrtab_size = plthook->shdr[ehdr->e_shstrndx].sh_size;
351
- plthook->shstrtab = malloc(plthook->shstrtab_size);
352
- if (plthook->shstrtab == NULL) {
353
- set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", plthook->shstrtab_size);
354
- rv = PLTHOOK_OUT_OF_MEMORY;
355
- goto error_exit;
356
- }
357
- offset = plthook->shdr[ehdr->e_shstrndx].sh_offset;
358
- if (lseek(fd, offset, SEEK_SET) != offset) {
359
- set_errmsg("failed to seek to the section header string table.");
360
- rv = PLTHOOK_INVALID_FILE_FORMAT;
361
- goto error_exit;
362
- }
363
- if (read(fd, plthook->shstrtab, plthook->shstrtab_size) != plthook->shstrtab_size) {
364
- set_errmsg("failed to read the section header string table.");
365
- rv = PLTHOOK_INVALID_FILE_FORMAT;
366
- goto error_exit;
367
- }
368
- #ifdef PT_GNU_RELRO
369
- if (page_size == 0) {
370
- page_size = sysconf(_SC_PAGESIZE);
371
- }
372
- offset = ehdr->e_phoff;
373
- if ((rv = lseek(fd, offset, SEEK_SET)) != offset) {
374
- set_errmsg("failed to seek to the program header table.");
375
- rv = PLTHOOK_INVALID_FILE_FORMAT;
376
- goto error_exit;
377
- }
378
- for (idx = 0; idx < ehdr->e_phnum; idx++) {
418
+
419
+ fseek(fp, ehdr.e_phoff, SEEK_SET);
420
+
421
+ for (idx = 0; idx < ehdr.e_phnum; idx++) {
379
422
  Elf_Phdr phdr;
380
- if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
423
+
424
+ if (fread(&phdr, sizeof(phdr), 1, fp) != 1) {
381
425
  set_errmsg("failed to read the program header table.");
382
- rv = PLTHOOK_INVALID_FILE_FORMAT;
383
- goto error_exit;
426
+ fclose(fp);
427
+ return PLTHOOK_INVALID_FILE_FORMAT;
384
428
  }
385
429
  if (phdr.p_type == PT_GNU_RELRO) {
386
- plthook->relro_start = plthook->base + phdr.p_vaddr;
430
+ plthook->relro_start = plthook->plt_addr_base + phdr.p_vaddr;
387
431
  plthook->relro_end = plthook->relro_start + phdr.p_memsz;
432
+ break;
388
433
  }
389
434
  }
435
+ fclose(fp);
436
+ return 0;
437
+ }
390
438
  #endif
391
- close(fd);
392
- fd = -1;
393
439
 
394
- rv = find_section(plthook, ".dynsym", &shdr);
440
+ static int plthook_open_real(plthook_t **plthook_out, struct link_map *lmap)
441
+ {
442
+ plthook_t plthook = {NULL,};
443
+ const Elf_Dyn *dyn;
444
+ const char *dyn_addr_base = NULL;
445
+
446
+ #if defined __linux__
447
+ plthook.plt_addr_base = (char*)lmap->l_addr;
448
+ #elif defined __FreeBSD__ || defined __sun
449
+ const Elf_Ehdr *ehdr = (const Elf_Ehdr*)lmap->l_addr;
450
+ int rv = check_elf_header(ehdr);
395
451
  if (rv != 0) {
396
- goto error_exit;
452
+ return rv;
397
453
  }
398
- if (shdr->sh_type != SHT_DYNSYM) {
399
- set_errmsg("The type of .dynsym section should be SHT_DYNSYM but %d.", shdr->sh_type);
400
- rv = PLTHOOK_INVALID_FILE_FORMAT;
401
- goto error_exit;
454
+ if (ehdr->e_type == ET_DYN) {
455
+ dyn_addr_base = (const char*)lmap->l_addr;
456
+ plthook.plt_addr_base = (const char*)lmap->l_addr;
402
457
  }
403
- if (shdr->sh_entsize != sizeof(Elf_Sym)) {
404
- set_errmsg("The size of a section header entry should be sizeof(Elf_Sym)(%" SIZE_T_FMT ") but %" SIZE_T_FMT ".",
405
- sizeof(Elf_Sym), shdr->sh_entsize);
406
- rv = PLTHOOK_INVALID_FILE_FORMAT;
407
- goto error_exit;
458
+ #else
459
+ #error unsupported OS
460
+ #endif
461
+
462
+ /* get .dynsym section */
463
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_SYMTAB);
464
+ if (dyn == NULL) {
465
+ set_errmsg("failed to find DT_SYMTAB");
466
+ return PLTHOOK_INTERNAL_ERROR;
408
467
  }
409
- plthook->dynsym = (const Elf_Sym*)(plthook->base + shdr->sh_addr);
410
- plthook->dynsym_cnt = shdr->sh_size / shdr->sh_entsize;
468
+ plthook.dynsym = (const Elf_Sym*)(dyn_addr_base + dyn->d_un.d_ptr);
411
469
 
412
- rv = find_section(plthook, ".dynstr", &shdr);
413
- if (rv != 0) {
414
- goto error_exit;
470
+ /* Check sizeof(Elf_Sym) */
471
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_SYMENT);
472
+ if (dyn == NULL) {
473
+ set_errmsg("failed to find DT_SYMTAB");
474
+ return PLTHOOK_INTERNAL_ERROR;
475
+ }
476
+ if (dyn->d_un.d_val != sizeof(Elf_Sym)) {
477
+ set_errmsg("DT_SYMENT size %" ELF_XWORD_FMT " != %" SIZE_T_FMT, dyn->d_un.d_val, sizeof(Elf_Sym));
478
+ return PLTHOOK_INTERNAL_ERROR;
415
479
  }
416
- if (shdr->sh_type != SHT_STRTAB) {
417
- set_errmsg("The type of .dynstrx section should be SHT_STRTAB but %d.", shdr->sh_type);
418
- rv = PLTHOOK_INVALID_FILE_FORMAT;
419
- goto error_exit;
480
+
481
+ /* get .dynstr section */
482
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_STRTAB);
483
+ if (dyn == NULL) {
484
+ set_errmsg("failed to find DT_STRTAB");
485
+ return PLTHOOK_INTERNAL_ERROR;
420
486
  }
421
- plthook->dynstr = (const char*)(plthook->base + shdr->sh_addr);
422
- plthook->dynstr_size = shdr->sh_size;
487
+ plthook.dynstr = dyn_addr_base + dyn->d_un.d_ptr;
423
488
 
424
- rv = find_section(plthook, PLT_SECTION_NAME, &shdr);
425
- if (rv != 0) {
426
- goto error_exit;
489
+ /* get .dynstr size */
490
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_STRSZ);
491
+ if (dyn == NULL) {
492
+ set_errmsg("failed to find DT_STRSZ");
493
+ return PLTHOOK_INTERNAL_ERROR;
494
+ }
495
+ plthook.dynstr_size = dyn->d_un.d_val;
496
+
497
+ /* get .rela.plt or .rel.plt section */
498
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_JMPREL);
499
+ plthook.r_type = R_JUMP_SLOT;
500
+ #ifdef PLT_DT_REL
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;
427
505
  }
428
- if (shdr->sh_entsize != sizeof(Elf_Plt_Rel)) {
429
- set_errmsg("invalid " PLT_SECTION_NAME " table entry size: %" SIZE_T_FMT, shdr->sh_entsize);
430
- rv = PLTHOOK_INVALID_FILE_FORMAT;
431
- goto error_exit;
506
+ #endif
507
+ if (dyn == NULL) {
508
+ set_errmsg("failed to find DT_JMPREL");
509
+ return PLTHOOK_INTERNAL_ERROR;
432
510
  }
433
- plthook->plt = (Elf_Plt_Rel *)(plthook->base + shdr->sh_addr);
434
- plthook->plt_cnt = shdr->sh_size / sizeof(Elf_Plt_Rel);
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 */
515
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_PLTRELSZ);
516
+ if (dyn == NULL) {
517
+ set_errmsg("failed to find DT_PLTRELSZ");
518
+ return PLTHOOK_INTERNAL_ERROR;
519
+ }
435
520
 
436
- *plthook_out = plthook;
521
+ plthook.plt_cnt = dyn->d_un.d_val / sizeof(Elf_Plt_Rel);
522
+ #ifdef PLT_DT_REL
523
+ } else {
524
+ int total_size_tag = PLT_DT_REL == DT_RELA ? DT_RELASZ : DT_RELSZ;
525
+ int elem_size_tag = PLT_DT_REL == DT_RELA ? DT_RELAENT : DT_RELENT;
526
+ size_t total_size, elem_size;
527
+
528
+ dyn = find_dyn_by_tag(lmap->l_ld, total_size_tag);
529
+ if (dyn == NULL) {
530
+ set_errmsg("failed to find 0x%x", total_size_tag);
531
+ return PLTHOOK_INTERNAL_ERROR;
532
+ }
533
+ total_size = dyn->d_un.d_ptr;
534
+
535
+ dyn = find_dyn_by_tag(lmap->l_ld, elem_size_tag);
536
+ if (dyn == NULL) {
537
+ set_errmsg("failed to find 0x%x", elem_size_tag);
538
+ return PLTHOOK_INTERNAL_ERROR;
539
+ }
540
+ elem_size = dyn->d_un.d_ptr;
541
+ plthook.plt_cnt = total_size / elem_size;
542
+ #endif
543
+ }
544
+
545
+ #ifdef SUPPORT_RELRO
546
+ dyn = find_dyn_by_tag(lmap->l_ld, DT_FLAGS_1);
547
+ if (dyn != NULL && (dyn->d_un.d_val & DF_1_NOW)) {
548
+ int rv = set_relro_members(&plthook, lmap);
549
+ if (rv != 0) {
550
+ return rv;
551
+ }
552
+ if (page_size == 0) {
553
+ page_size = sysconf(_SC_PAGESIZE);
554
+ }
555
+ }
556
+ #endif
557
+
558
+ *plthook_out = malloc(sizeof(plthook_t));
559
+ if (*plthook_out == NULL) {
560
+ set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", sizeof(plthook_t));
561
+ return PLTHOOK_OUT_OF_MEMORY;
562
+ }
563
+ **plthook_out = plthook;
437
564
  return 0;
438
- error_exit:
439
- if (fd != -1) {
440
- close(fd);
565
+ }
566
+
567
+ static int check_elf_header(const Elf_Ehdr *ehdr)
568
+ {
569
+ static const unsigned short s = 1;
570
+ /* Check endianness at runtime. */
571
+ unsigned char elfdata = (*(const char*)&s) ? ELFDATA2LSB : ELFDATA2MSB;
572
+
573
+ if (ehdr == NULL) {
574
+ set_errmsg("invalid elf header address: NULL");
575
+ return PLTHOOK_INTERNAL_ERROR;
441
576
  }
442
- plthook_close(plthook);
443
- return rv;
577
+
578
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
579
+ set_errmsg("invalid file signature: 0x%02x,0x%02x,0x%02x,0x%02x",
580
+ ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
581
+ return PLTHOOK_INVALID_FILE_FORMAT;
582
+ }
583
+ if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
584
+ set_errmsg("invalid elf class: 0x%02x", ehdr->e_ident[EI_CLASS]);
585
+ return PLTHOOK_INVALID_FILE_FORMAT;
586
+ }
587
+ if (ehdr->e_ident[EI_DATA] != elfdata) {
588
+ set_errmsg("invalid elf data: 0x%02x", ehdr->e_ident[EI_DATA]);
589
+ return PLTHOOK_INVALID_FILE_FORMAT;
590
+ }
591
+ if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
592
+ set_errmsg("invalid elf version: 0x%02x", ehdr->e_ident[EI_VERSION]);
593
+ return PLTHOOK_INVALID_FILE_FORMAT;
594
+ }
595
+ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
596
+ set_errmsg("invalid file type: 0x%04x", ehdr->e_type);
597
+ return PLTHOOK_INVALID_FILE_FORMAT;
598
+ }
599
+ if (ehdr->e_version != EV_CURRENT) {
600
+ set_errmsg("invalid object file version: %" ELF_WORD_FMT, ehdr->e_version);
601
+ return PLTHOOK_INVALID_FILE_FORMAT;
602
+ }
603
+ if (ehdr->e_ehsize != sizeof(Elf_Ehdr)) {
604
+ set_errmsg("invalid elf header size: %u", ehdr->e_ehsize);
605
+ return PLTHOOK_INVALID_FILE_FORMAT;
606
+ }
607
+ if (ehdr->e_phentsize != sizeof(Elf_Phdr)) {
608
+ set_errmsg("invalid program header table entry size: %u", ehdr->e_phentsize);
609
+ return PLTHOOK_INVALID_FILE_FORMAT;
610
+ }
611
+ return 0;
444
612
  }
445
613
 
446
614
  int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
447
615
  {
448
616
  while (*pos < plthook->plt_cnt) {
449
617
  const Elf_Plt_Rel *plt = plthook->plt + *pos;
450
- if (ELF_R_TYPE(plt->r_info) == R_JUMP_SLOT) {
618
+ if (ELF_R_TYPE(plt->r_info) == plthook->r_type) {
451
619
  size_t idx = ELF_R_SYM(plt->r_info);
452
620
 
453
- if (idx >= plthook->dynsym_cnt) {
454
- set_errmsg(".dynsym index %" SIZE_T_FMT " should be less than %" SIZE_T_FMT ".", idx, plthook->dynsym_cnt);
455
- return PLTHOOK_INVALID_FILE_FORMAT;
456
- }
457
621
  idx = plthook->dynsym[idx].st_name;
458
622
  if (idx + 1 > plthook->dynstr_size) {
459
623
  set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
460
624
  return PLTHOOK_INVALID_FILE_FORMAT;
461
625
  }
462
626
  *name_out = plthook->dynstr + idx;
463
- *addr_out = (void**)(plthook->base + plt->r_offset);
627
+ *addr_out = (void**)(plthook->plt_addr_base + plt->r_offset);
464
628
  (*pos)++;
465
629
  return 0;
466
630
  }
@@ -486,7 +650,7 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
486
650
  while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
487
651
  if (strncmp(name, funcname, funcnamelen) == 0) {
488
652
  if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
489
- #ifdef PT_GNU_RELRO
653
+ #ifdef SUPPORT_RELRO
490
654
  void *maddr = NULL;
491
655
  if (plthook->relro_start <= (char*)addr && (char*)addr < plthook->relro_end) {
492
656
  maddr = (void*)((size_t)addr & ~(page_size - 1));
@@ -501,7 +665,7 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
501
665
  *oldfunc = *addr;
502
666
  }
503
667
  *addr = funcaddr;
504
- #ifdef PT_GNU_RELRO
668
+ #ifdef SUPPORT_RELRO
505
669
  if (maddr != NULL) {
506
670
  mprotect(maddr, page_size, PROT_READ);
507
671
  }
@@ -520,8 +684,6 @@ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, vo
520
684
  void plthook_close(plthook_t *plthook)
521
685
  {
522
686
  if (plthook != NULL) {
523
- free(plthook->shdr);
524
- free(plthook->shstrtab);
525
687
  free(plthook);
526
688
  }
527
689
  }
@@ -531,84 +693,6 @@ const char *plthook_error(void)
531
693
  return errmsg;
532
694
  }
533
695
 
534
- static int check_elf_header(const Elf_Ehdr *ehdr)
535
- {
536
- if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
537
- set_errmsg("invalid file signature: 0x%02x,0x%02x,0x%02x,0x%02x",
538
- ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
539
- return PLTHOOK_INVALID_FILE_FORMAT;
540
- }
541
- if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
542
- set_errmsg("invalid elf class: 0x%02x", ehdr->e_ident[EI_CLASS]);
543
- return PLTHOOK_INVALID_FILE_FORMAT;
544
- }
545
- if (ehdr->e_ident[EI_DATA] != ELF_DATA) {
546
- set_errmsg("invalid elf data: 0x%02x", ehdr->e_ident[EI_DATA]);
547
- return PLTHOOK_INVALID_FILE_FORMAT;
548
- }
549
- if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
550
- set_errmsg("invalid elf version: 0x%02x", ehdr->e_ident[EI_VERSION]);
551
- return PLTHOOK_INVALID_FILE_FORMAT;
552
- }
553
- if (ehdr->e_ident[EI_OSABI] != ELF_OSABI) {
554
- #ifdef ELF_OSABI_ALT
555
- if (ehdr->e_ident[EI_OSABI] != ELF_OSABI_ALT) {
556
- set_errmsg("invalid OS ABI: 0x%02x", ehdr->e_ident[EI_OSABI]);
557
- return PLTHOOK_INVALID_FILE_FORMAT;
558
- }
559
- #else
560
- set_errmsg("invalid OS ABI: 0x%02x", ehdr->e_ident[EI_OSABI]);
561
- return PLTHOOK_INVALID_FILE_FORMAT;
562
- #endif
563
- }
564
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
565
- set_errmsg("invalid file type: 0x%04x", ehdr->e_type);
566
- return PLTHOOK_INVALID_FILE_FORMAT;
567
- }
568
- if (ehdr->e_machine != E_MACHINE) {
569
- set_errmsg("invalid machine type: %u", ehdr->e_machine);
570
- return PLTHOOK_INVALID_FILE_FORMAT;
571
- }
572
- if (ehdr->e_version != EV_CURRENT) {
573
- set_errmsg("invalid object file version: %u", ehdr->e_version);
574
- return PLTHOOK_INVALID_FILE_FORMAT;
575
- }
576
- if (ehdr->e_ehsize != sizeof(Elf_Ehdr)) {
577
- set_errmsg("invalid elf header size: %u", ehdr->e_ehsize);
578
- return PLTHOOK_INVALID_FILE_FORMAT;
579
- }
580
- if (ehdr->e_phentsize != sizeof(Elf_Phdr)) {
581
- set_errmsg("invalid program header table entry size: %u", ehdr->e_phentsize);
582
- return PLTHOOK_INVALID_FILE_FORMAT;
583
- }
584
- if (ehdr->e_shentsize != sizeof(Elf_Shdr)) {
585
- set_errmsg("invalid section header table entry size: %u", ehdr->e_shentsize);
586
- return PLTHOOK_INVALID_FILE_FORMAT;
587
- }
588
- return 0;
589
- }
590
-
591
- static int find_section(plthook_t *image, const char *name, const Elf_Shdr **out)
592
- {
593
- const Elf_Shdr *shdr = image->shdr;
594
- const Elf_Shdr *shdr_end = shdr + image->shnum;
595
- size_t namelen = strlen(name);
596
-
597
- while (shdr < shdr_end) {
598
- if (shdr->sh_name + namelen >= image->shstrtab_size) {
599
- set_errmsg("too big section header string table index: %u", shdr->sh_name);
600
- return PLTHOOK_INVALID_FILE_FORMAT;
601
- }
602
- if (strcmp(image->shstrtab + shdr->sh_name, name) == 0) {
603
- *out = shdr;
604
- return 0;
605
- }
606
- shdr++;
607
- }
608
- set_errmsg("failed to find the section header: %s", name);
609
- return PLTHOOK_INVALID_FILE_FORMAT;
610
- }
611
-
612
696
  static void set_errmsg(const char *fmt, ...)
613
697
  {
614
698
  va_list ap;