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.
@@ -0,0 +1,56 @@
1
+ /* -*- indent-tabs-mode: nil -*-
2
+ *
3
+ * plthook.h -- the header file of plthook
4
+ *
5
+ * URL: https://github.com/kubo/plthook
6
+ *
7
+ * ------------------------------------------------------
8
+ *
9
+ * Copyright 2013-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
+ #ifndef PLTHOOK_H
37
+ #define PLTHOOK_H 1
38
+
39
+ #define PLTHOOK_SUCCESS 0
40
+ #define PLTHOOK_FILE_NOT_FOUND 1
41
+ #define PLTHOOK_INVALID_FILE_FORMAT 2
42
+ #define PLTHOOK_FUNCTION_NOT_FOUND 3
43
+ #define PLTHOOK_INVALID_ARGUMENT 4
44
+ #define PLTHOOK_OUT_OF_MEMORY 5
45
+ #define PLTHOOK_INTERNAL_ERROR 6
46
+
47
+ typedef struct plthook plthook_t;
48
+
49
+ int plthook_open(plthook_t **plthook_out, const char *filename);
50
+ int plthook_open_by_address(plthook_t **plthook_out, void *address);
51
+ int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out);
52
+ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, void **oldfunc);
53
+ void plthook_close(plthook_t *plthook);
54
+ const char *plthook_error(void);
55
+
56
+ #endif
@@ -0,0 +1,537 @@
1
+ /* -*- indent-tabs-mode: nil -*-
2
+ *
3
+ * plthook_elf.c -- implemention of plthook for ELF format
4
+ *
5
+ * URL: https://github.com/kubo/plthook
6
+ *
7
+ * ------------------------------------------------------
8
+ *
9
+ * Copyright 2013-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
+ #define _GNU_SOURCE
37
+ #include <stdio.h>
38
+ #include <stdarg.h>
39
+ #include <stdlib.h>
40
+ #include <unistd.h>
41
+ #include <string.h>
42
+ #include <limits.h>
43
+ #include <sys/types.h>
44
+ #include <sys/stat.h>
45
+ #include <fcntl.h>
46
+ #include <errno.h>
47
+ #include <dlfcn.h>
48
+ #ifdef __sun
49
+ #include <procfs.h>
50
+ #define ELF_TARGET_ALL
51
+ #endif /* __sun */
52
+ #include <elf.h>
53
+ #include <link.h>
54
+ #include "plthook.h"
55
+
56
+ #ifndef __GNUC__
57
+ #define __attribute__(arg)
58
+ #endif
59
+
60
+ #if defined __linux__
61
+ #define ELF_OSABI ELFOSABI_SYSV
62
+ #elif defined __sun
63
+ #define ELF_OSABI ELFOSABI_SOLARIS
64
+ #elif defined __FreeBSD__
65
+ #define ELF_OSABI ELFOSABI_FREEBSD
66
+ #if defined __i386__ && __ELF_WORD_SIZE == 64
67
+ #error 32-bit application on 64-bit OS is not supported.
68
+ #endif
69
+ #else
70
+ #error unsupported OS
71
+ #endif
72
+
73
+ #if defined __x86_64__ || defined __x86_64
74
+ #define ELF_DATA ELFDATA2LSB
75
+ #define E_MACHINE EM_X86_64
76
+ #ifdef R_X86_64_JUMP_SLOT
77
+ #define R_JUMP_SLOT R_X86_64_JUMP_SLOT
78
+ #else
79
+ #define R_JUMP_SLOT R_X86_64_JMP_SLOT
80
+ #endif
81
+ #define SHT_PLT_REL SHT_RELA
82
+ #define Elf_Plt_Rel Elf_Rela
83
+ #define PLT_SECTION_NAME ".rela.plt"
84
+ #elif defined __i386__ || defined __i386
85
+ #define ELF_DATA ELFDATA2LSB
86
+ #define E_MACHINE EM_386
87
+ #define R_JUMP_SLOT R_386_JMP_SLOT
88
+ #define SHT_PLT_REL SHT_REL
89
+ #define Elf_Plt_Rel Elf_Rel
90
+ #define PLT_SECTION_NAME ".rel.plt"
91
+ #else
92
+ #error E_MACHINE is not defined.
93
+ #endif
94
+
95
+ #if defined __LP64__
96
+ #ifndef ELF_CLASS
97
+ #define ELF_CLASS ELFCLASS64
98
+ #endif
99
+ #define SIZE_T_FMT "lu"
100
+ #define Elf_Half Elf64_Half
101
+ #define Elf_Addr Elf64_Addr
102
+ #define Elf_Ehdr Elf64_Ehdr
103
+ #define Elf_Phdr Elf64_Phdr
104
+ #define Elf_Shdr Elf64_Shdr
105
+ #define Elf_Sym Elf64_Sym
106
+ #define Elf_Rel Elf64_Rel
107
+ #define Elf_Rela Elf64_Rela
108
+ #ifndef ELF_R_SYM
109
+ #define ELF_R_SYM ELF64_R_SYM
110
+ #endif
111
+ #ifndef ELF_R_TYPE
112
+ #define ELF_R_TYPE ELF64_R_TYPE
113
+ #endif
114
+ #else /* __LP64__ */
115
+ #ifndef ELF_CLASS
116
+ #define ELF_CLASS ELFCLASS32
117
+ #endif
118
+ #define SIZE_T_FMT "u"
119
+ #define Elf_Half Elf32_Half
120
+ #define Elf_Addr Elf32_Addr
121
+ #define Elf_Ehdr Elf32_Ehdr
122
+ #define Elf_Phdr Elf32_Phdr
123
+ #define Elf_Shdr Elf32_Shdr
124
+ #define Elf_Sym Elf32_Sym
125
+ #define Elf_Rel Elf32_Rel
126
+ #define Elf_Rela Elf32_Rela
127
+ #ifndef ELF_R_SYM
128
+ #define ELF_R_SYM ELF32_R_SYM
129
+ #endif
130
+ #ifndef ELF_R_TYPE
131
+ #define ELF_R_TYPE ELF32_R_TYPE
132
+ #endif
133
+ #endif /* __LP64__ */
134
+
135
+ struct plthook {
136
+ const char *base;
137
+ const Elf_Phdr *phdr;
138
+ size_t phnum;
139
+ Elf_Shdr *shdr;
140
+ size_t shnum;
141
+ char *shstrtab;
142
+ size_t shstrtab_size;
143
+ const Elf_Sym *dynsym;
144
+ size_t dynsym_cnt;
145
+ const char *dynstr;
146
+ size_t dynstr_size;
147
+ const Elf_Plt_Rel *plt;
148
+ size_t plt_cnt;
149
+ };
150
+
151
+ static char errmsg[512];
152
+
153
+ static int plthook_open_executable(plthook_t **plthook_out);
154
+ static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename);
155
+ static int plthook_open_real(plthook_t **plthook_out, const char *base, const char *filename);
156
+ static int check_elf_header(const Elf_Ehdr *ehdr);
157
+ static int find_section(plthook_t *image, const char *name, const Elf_Shdr **out);
158
+ static void set_errmsg(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
159
+
160
+ int plthook_open(plthook_t **plthook_out, const char *filename)
161
+ {
162
+ *plthook_out = NULL;
163
+ if (filename == NULL) {
164
+ return plthook_open_executable(plthook_out);
165
+ } else {
166
+ return plthook_open_shared_library(plthook_out, filename);
167
+ }
168
+ }
169
+
170
+ int plthook_open_by_address(plthook_t **plthook_out, void *address)
171
+ {
172
+ Dl_info info;
173
+
174
+ *plthook_out = NULL;
175
+ if (dladdr(address, &info) == 0) {
176
+ set_errmsg("dladdr error");
177
+ return PLTHOOK_FILE_NOT_FOUND;
178
+ }
179
+ return plthook_open_real(plthook_out, info.dli_fbase, info.dli_fname);
180
+ }
181
+
182
+ static int plthook_open_executable(plthook_t **plthook_out)
183
+ {
184
+ #if defined __linux__
185
+ /* Open the main program. */
186
+ char buf[128];
187
+ FILE *fp = fopen("/proc/self/maps", "r");
188
+ unsigned long base;
189
+
190
+ if (fp == NULL) {
191
+ set_errmsg("Could not open /proc/self/maps: %s",
192
+ strerror(errno));
193
+ return PLTHOOK_INTERNAL_ERROR;
194
+ }
195
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
196
+ set_errmsg("Could not read /proc/self/maps: %s",
197
+ strerror(errno));
198
+ fclose(fp);
199
+ return PLTHOOK_INTERNAL_ERROR;
200
+ }
201
+ fclose(fp);
202
+ if (sscanf(buf, "%lx-%*x r-xp %*x %*x:%*x %*u ", &base) != 1) {
203
+ set_errmsg("invalid /proc/self/maps format: %s", buf);
204
+ return PLTHOOK_INTERNAL_ERROR;
205
+ }
206
+ return plthook_open_real(plthook_out, (const char*)base, "/proc/self/exe");
207
+ #elif defined __sun
208
+ prmap_t prmap;
209
+ pid_t pid = getpid();
210
+ char fname[128];
211
+ int fd;
212
+
213
+ sprintf(fname, "/proc/%d/map", pid);
214
+ fd = open(fname, O_RDONLY);
215
+ if (fd == -1) {
216
+ set_errmsg("Could not open %s: %s", fname,
217
+ strerror(errno));
218
+ return PLTHOOK_INTERNAL_ERROR;
219
+ }
220
+ if (read(fd, &prmap, sizeof(prmap)) != sizeof(prmap)) {
221
+ set_errmsg("Could not read %s: %s", fname,
222
+ strerror(errno));
223
+ close(fd);
224
+ return PLTHOOK_INTERNAL_ERROR;
225
+ }
226
+ close(fd);
227
+ sprintf(fname, "/proc/%d/object/a.out", pid);
228
+ return plthook_open_real(plthook_out, (const char*)prmap.pr_vaddr, fname);
229
+ #elif defined __FreeBSD__
230
+ return plthook_open_shared_library(plthook_out, NULL);
231
+ #else
232
+ #error unsupported OS
233
+ #endif
234
+ }
235
+
236
+ static int plthook_open_shared_library(plthook_t **plthook_out, const char *filename)
237
+ {
238
+ void *hndl = dlopen(filename, RTLD_LAZY | RTLD_NOLOAD);
239
+ struct link_map *lmap = NULL;
240
+
241
+ if (hndl == NULL) {
242
+ set_errmsg("dlopen error: %s", dlerror());
243
+ return PLTHOOK_FILE_NOT_FOUND;
244
+ }
245
+ if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {
246
+ set_errmsg("dlinfo error");
247
+ dlclose(hndl);
248
+ return PLTHOOK_FILE_NOT_FOUND;
249
+ }
250
+ dlclose(hndl);
251
+ return plthook_open_real(plthook_out, (const char*)lmap->l_addr, lmap->l_name);
252
+ }
253
+
254
+ static int plthook_open_real(plthook_t **plthook_out, const char *base, const char *filename)
255
+ {
256
+ const Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
257
+ const Elf_Shdr *shdr;
258
+ size_t shdr_size;
259
+ int fd = -1;
260
+ off_t offset;
261
+ plthook_t *plthook;
262
+ int rv;
263
+
264
+ if (base == NULL) {
265
+ set_errmsg("The base address is zero.");
266
+ return PLTHOOK_FILE_NOT_FOUND;
267
+ }
268
+
269
+ if (filename == NULL) {
270
+ set_errmsg("failed to get the file name on the disk.");
271
+ return PLTHOOK_FILE_NOT_FOUND;
272
+ }
273
+
274
+ plthook = calloc(1, sizeof(plthook_t));
275
+ if (plthook == NULL) {
276
+ set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", sizeof(plthook_t));
277
+ return PLTHOOK_OUT_OF_MEMORY;
278
+ }
279
+
280
+ /* sanity check */
281
+ rv = check_elf_header(ehdr);
282
+ if (rv != 0) {
283
+ goto error_exit;
284
+ }
285
+ if (ehdr->e_type == ET_DYN) {
286
+ plthook->base = base;
287
+ }
288
+ plthook->phdr = (const Elf_Phdr *)(plthook->base + ehdr->e_phoff);
289
+ plthook->phnum = ehdr->e_phnum;
290
+ fd = open(filename, O_RDONLY, 0);
291
+ if (fd == -1) {
292
+ set_errmsg("Could not open %s: %s", filename, strerror(errno));
293
+ rv = PLTHOOK_FILE_NOT_FOUND;
294
+ goto error_exit;
295
+ }
296
+ shdr_size = ehdr->e_shnum * ehdr->e_shentsize;
297
+ plthook->shdr = calloc(1, shdr_size);
298
+ if (plthook->shdr == NULL) {
299
+ set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", shdr_size);
300
+ rv = PLTHOOK_OUT_OF_MEMORY;
301
+ goto error_exit;
302
+ }
303
+ offset = ehdr->e_shoff;
304
+ if ((rv = lseek(fd, offset, SEEK_SET)) != offset) {
305
+ set_errmsg("failed to seek to the section header table.");
306
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
307
+ goto error_exit;
308
+ }
309
+ if (read(fd, plthook->shdr, shdr_size) != shdr_size) {
310
+ set_errmsg("failed to read the section header table.");
311
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
312
+ goto error_exit;
313
+ }
314
+ plthook->shnum = ehdr->e_shnum;
315
+ plthook->shstrtab_size = plthook->shdr[ehdr->e_shstrndx].sh_size;
316
+ plthook->shstrtab = malloc(plthook->shstrtab_size);
317
+ if (plthook->shstrtab == NULL) {
318
+ set_errmsg("failed to allocate memory: %" SIZE_T_FMT " bytes", plthook->shstrtab_size);
319
+ rv = PLTHOOK_OUT_OF_MEMORY;
320
+ goto error_exit;
321
+ }
322
+ offset = plthook->shdr[ehdr->e_shstrndx].sh_offset;
323
+ if (lseek(fd, offset, SEEK_SET) != offset) {
324
+ set_errmsg("failed to seek to the section header string table.");
325
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
326
+ goto error_exit;
327
+ }
328
+ if (read(fd, plthook->shstrtab, plthook->shstrtab_size) != plthook->shstrtab_size) {
329
+ set_errmsg("failed to read the section header string table.");
330
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
331
+ goto error_exit;
332
+ }
333
+ close(fd);
334
+ fd = -1;
335
+
336
+ rv = find_section(plthook, ".dynsym", &shdr);
337
+ if (rv != 0) {
338
+ goto error_exit;
339
+ }
340
+ if (shdr->sh_type != SHT_DYNSYM) {
341
+ set_errmsg("The type of .dynsym section should be SHT_DYNSYM but %d.", shdr->sh_type);
342
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
343
+ goto error_exit;
344
+ }
345
+ if (shdr->sh_entsize != sizeof(Elf_Sym)) {
346
+ set_errmsg("The size of a section header entry should be sizeof(Elf_Sym)(%" SIZE_T_FMT ") but %" SIZE_T_FMT ".",
347
+ sizeof(Elf_Sym), shdr->sh_entsize);
348
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
349
+ goto error_exit;
350
+ }
351
+ plthook->dynsym = (const Elf_Sym*)(plthook->base + shdr->sh_addr);
352
+ plthook->dynsym_cnt = shdr->sh_size / shdr->sh_entsize;
353
+
354
+ rv = find_section(plthook, ".dynstr", &shdr);
355
+ if (rv != 0) {
356
+ goto error_exit;
357
+ }
358
+ if (shdr->sh_type != SHT_STRTAB) {
359
+ set_errmsg("The type of .dynstrx section should be SHT_STRTAB but %d.", shdr->sh_type);
360
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
361
+ goto error_exit;
362
+ }
363
+ plthook->dynstr = (const char*)(plthook->base + shdr->sh_addr);
364
+ plthook->dynstr_size = shdr->sh_size;
365
+
366
+ rv = find_section(plthook, PLT_SECTION_NAME, &shdr);
367
+ if (rv != 0) {
368
+ goto error_exit;
369
+ }
370
+ if (shdr->sh_entsize != sizeof(Elf_Plt_Rel)) {
371
+ set_errmsg("invalid " PLT_SECTION_NAME " table entry size: %" SIZE_T_FMT, shdr->sh_entsize);
372
+ rv = PLTHOOK_INVALID_FILE_FORMAT;
373
+ goto error_exit;
374
+ }
375
+ plthook->plt = (Elf_Plt_Rel *)(plthook->base + shdr->sh_addr);
376
+ plthook->plt_cnt = shdr->sh_size / sizeof(Elf_Plt_Rel);
377
+
378
+ *plthook_out = plthook;
379
+ return 0;
380
+ error_exit:
381
+ if (fd != -1) {
382
+ close(fd);
383
+ }
384
+ plthook_close(plthook);
385
+ return rv;
386
+ }
387
+
388
+ int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
389
+ {
390
+ while (*pos < plthook->plt_cnt) {
391
+ const Elf_Plt_Rel *plt = plthook->plt + *pos;
392
+ if (ELF_R_TYPE(plt->r_info) == R_JUMP_SLOT) {
393
+ size_t idx = ELF_R_SYM(plt->r_info);
394
+
395
+ if (idx >= plthook->dynsym_cnt) {
396
+ set_errmsg(".dynsym index %" SIZE_T_FMT " should be less than %" SIZE_T_FMT ".", idx, plthook->dynsym_cnt);
397
+ return PLTHOOK_INVALID_FILE_FORMAT;
398
+ }
399
+ idx = plthook->dynsym[idx].st_name;
400
+ if (idx + 1 > plthook->dynstr_size) {
401
+ set_errmsg("too big section header string table index: %" SIZE_T_FMT, idx);
402
+ return PLTHOOK_INVALID_FILE_FORMAT;
403
+ }
404
+ *name_out = plthook->dynstr + idx;
405
+ *addr_out = (void**)(plthook->base + plt->r_offset);
406
+ (*pos)++;
407
+ return 0;
408
+ }
409
+ (*pos)++;
410
+ }
411
+ *name_out = NULL;
412
+ *addr_out = NULL;
413
+ return EOF;
414
+ }
415
+
416
+ int plthook_replace(plthook_t *plthook, const char *funcname, void *funcaddr, void **oldfunc)
417
+ {
418
+ size_t funcnamelen = strlen(funcname);
419
+ unsigned int pos = 0;
420
+ const char *name;
421
+ void **addr;
422
+ int rv;
423
+
424
+ if (plthook == NULL) {
425
+ set_errmsg("invalid argument: The first argument is null.");
426
+ return PLTHOOK_INVALID_ARGUMENT;
427
+ }
428
+ while ((rv = plthook_enum(plthook, &pos, &name, &addr)) == 0) {
429
+ if (strncmp(name, funcname, funcnamelen) == 0) {
430
+ if (name[funcnamelen] == '\0' || name[funcnamelen] == '@') {
431
+ if (oldfunc) {
432
+ *oldfunc = *addr;
433
+ }
434
+ *addr = funcaddr;
435
+ return 0;
436
+ }
437
+ }
438
+ }
439
+ if (rv == EOF) {
440
+ set_errmsg("no such function: %s", funcname);
441
+ rv = PLTHOOK_FUNCTION_NOT_FOUND;
442
+ }
443
+ return rv;
444
+ }
445
+
446
+ void plthook_close(plthook_t *plthook)
447
+ {
448
+ if (plthook != NULL) {
449
+ free(plthook->shdr);
450
+ free(plthook->shstrtab);
451
+ free(plthook);
452
+ }
453
+ }
454
+
455
+ const char *plthook_error(void)
456
+ {
457
+ return errmsg;
458
+ }
459
+
460
+ static int check_elf_header(const Elf_Ehdr *ehdr)
461
+ {
462
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
463
+ set_errmsg("invalid file signature: 0x%02x,0x%02x,0x%02x,0x%02x",
464
+ ehdr->e_ident[0], ehdr->e_ident[1], ehdr->e_ident[2], ehdr->e_ident[3]);
465
+ return PLTHOOK_INVALID_FILE_FORMAT;
466
+ }
467
+ if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
468
+ set_errmsg("invalid elf class: 0x%02x", ehdr->e_ident[EI_CLASS]);
469
+ return PLTHOOK_INVALID_FILE_FORMAT;
470
+ }
471
+ if (ehdr->e_ident[EI_DATA] != ELF_DATA) {
472
+ set_errmsg("invalid elf data: 0x%02x", ehdr->e_ident[EI_DATA]);
473
+ return PLTHOOK_INVALID_FILE_FORMAT;
474
+ }
475
+ if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
476
+ set_errmsg("invalid elf version: 0x%02x", ehdr->e_ident[EI_VERSION]);
477
+ return PLTHOOK_INVALID_FILE_FORMAT;
478
+ }
479
+ if (ehdr->e_ident[EI_OSABI] != ELF_OSABI) {
480
+ set_errmsg("invalid OS ABI: 0x%02x", ehdr->e_ident[EI_OSABI]);
481
+ return PLTHOOK_INVALID_FILE_FORMAT;
482
+ }
483
+ if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
484
+ set_errmsg("invalid file type: 0x%04x", ehdr->e_type);
485
+ return PLTHOOK_INVALID_FILE_FORMAT;
486
+ }
487
+ if (ehdr->e_machine != E_MACHINE) {
488
+ set_errmsg("invalid machine type: %u", ehdr->e_machine);
489
+ return PLTHOOK_INVALID_FILE_FORMAT;
490
+ }
491
+ if (ehdr->e_version != EV_CURRENT) {
492
+ set_errmsg("invalid object file version: %u", ehdr->e_version);
493
+ return PLTHOOK_INVALID_FILE_FORMAT;
494
+ }
495
+ if (ehdr->e_ehsize != sizeof(Elf_Ehdr)) {
496
+ set_errmsg("invalid elf header size: %u", ehdr->e_ehsize);
497
+ return PLTHOOK_INVALID_FILE_FORMAT;
498
+ }
499
+ if (ehdr->e_phentsize != sizeof(Elf_Phdr)) {
500
+ set_errmsg("invalid program header table entry size: %u", ehdr->e_phentsize);
501
+ return PLTHOOK_INVALID_FILE_FORMAT;
502
+ }
503
+ if (ehdr->e_shentsize != sizeof(Elf_Shdr)) {
504
+ set_errmsg("invalid section header table entry size: %u", ehdr->e_shentsize);
505
+ return PLTHOOK_INVALID_FILE_FORMAT;
506
+ }
507
+ return 0;
508
+ }
509
+
510
+ static int find_section(plthook_t *image, const char *name, const Elf_Shdr **out)
511
+ {
512
+ const Elf_Shdr *shdr = image->shdr;
513
+ const Elf_Shdr *shdr_end = shdr + image->shnum;
514
+ size_t namelen = strlen(name);
515
+
516
+ while (shdr < shdr_end) {
517
+ if (shdr->sh_name + namelen >= image->shstrtab_size) {
518
+ set_errmsg("too big section header string table index: %u", shdr->sh_name);
519
+ return PLTHOOK_INVALID_FILE_FORMAT;
520
+ }
521
+ if (strcmp(image->shstrtab + shdr->sh_name, name) == 0) {
522
+ *out = shdr;
523
+ return 0;
524
+ }
525
+ shdr++;
526
+ }
527
+ set_errmsg("failed to find the section header: %s", name);
528
+ return PLTHOOK_INVALID_FILE_FORMAT;
529
+ }
530
+
531
+ static void set_errmsg(const char *fmt, ...)
532
+ {
533
+ va_list ap;
534
+ va_start(ap, fmt);
535
+ vsnprintf(errmsg, sizeof(errmsg) - 1, fmt, ap);
536
+ va_end(ap);
537
+ }