ruby-oci8 2.2.11 → 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/ChangeLog +2 -0
- data/NEWS +25 -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 +7 -88
- data/ext/oci8/oci8lib.c +1 -22
- data/ext/oci8/ocihandle.c +1 -1
- data/ext/oci8/ocinumber.c +1 -2
- 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/pre-distclean.rb +1 -3
- data/test/test_metadata.rb +1 -0
- data/test/test_object.rb +0 -6
- data/test/test_oranumber.rb +3 -1
- data/test/test_package_type.rb +10 -4
- metadata +3 -3
data/ext/oci8/plthook_osx.c
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
/* -*- indent-tabs-mode: nil -*-
|
2
2
|
*
|
3
|
-
* plthook_osx.c --
|
3
|
+
* plthook_osx.c -- implementation of plthook for OS X
|
4
4
|
*
|
5
5
|
* URL: https://github.com/kubo/plthook
|
6
6
|
*
|
7
7
|
* ------------------------------------------------------
|
8
8
|
*
|
9
|
-
* Copyright 2014 Kubo Takehiro <kubo@jiubao.org>
|
9
|
+
* Copyright 2014-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:
|
@@ -37,12 +37,23 @@
|
|
37
37
|
#include <stdarg.h>
|
38
38
|
#include <stdlib.h>
|
39
39
|
#include <string.h>
|
40
|
+
#include <unistd.h>
|
41
|
+
#include <inttypes.h>
|
40
42
|
#include <dlfcn.h>
|
43
|
+
#include <errno.h>
|
41
44
|
#include <mach-o/dyld.h>
|
45
|
+
#include <sys/mman.h>
|
46
|
+
#include <mach-o/fixup-chains.h>
|
42
47
|
#include "plthook.h"
|
43
48
|
|
49
|
+
#if !defined(__x86_64__)
|
50
|
+
#error Not on macOS intel
|
51
|
+
#endif
|
52
|
+
|
44
53
|
// #define PLTHOOK_DEBUG_CMD 1
|
45
54
|
// #define PLTHOOK_DEBUG_BIND 1
|
55
|
+
// #define PLTHOOK_DEBUG_FIXUPS 1
|
56
|
+
// #define PLTHOOK_DEBUG_ADDR 1
|
46
57
|
|
47
58
|
#ifdef PLTHOOK_DEBUG_CMD
|
48
59
|
#define DEBUG_CMD(...) fprintf(stderr, __VA_ARGS__)
|
@@ -50,16 +61,90 @@
|
|
50
61
|
#define DEBUG_CMD(...)
|
51
62
|
#endif
|
52
63
|
|
64
|
+
#ifdef PLTHOOK_DEBUG_FIXUPS
|
65
|
+
#define DEBUG_FIXUPS(...) fprintf(stderr, __VA_ARGS__)
|
66
|
+
#else
|
67
|
+
#define DEBUG_FIXUPS(...)
|
68
|
+
#endif
|
69
|
+
|
53
70
|
#ifdef PLTHOOK_DEBUG_BIND
|
54
71
|
#define DEBUG_BIND(...) fprintf(stderr, __VA_ARGS__)
|
55
72
|
#else
|
56
73
|
#define DEBUG_BIND(...)
|
57
74
|
#endif
|
58
75
|
|
59
|
-
#ifdef
|
60
|
-
#
|
61
|
-
|
62
|
-
#define
|
76
|
+
#ifdef PLTHOOK_DEBUG_ADDR
|
77
|
+
#include <mach/mach.h>
|
78
|
+
|
79
|
+
#define INHERIT_MAX_SIZE 11
|
80
|
+
static char *inherit_to_str(vm_inherit_t inherit, char *buf)
|
81
|
+
{
|
82
|
+
switch (inherit) {
|
83
|
+
case VM_INHERIT_SHARE: return "share";
|
84
|
+
case VM_INHERIT_COPY: return "copy";
|
85
|
+
case VM_INHERIT_NONE: return "none";
|
86
|
+
case VM_INHERIT_DONATE_COPY: return "donate_copy";
|
87
|
+
default:
|
88
|
+
sprintf(buf, "%d", inherit);
|
89
|
+
return buf;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
#define BEHAVIOR_MAX_SIZE 16
|
94
|
+
static char *behavior_to_str(vm_behavior_t behavior, char *buf)
|
95
|
+
{
|
96
|
+
switch (behavior) {
|
97
|
+
case VM_BEHAVIOR_DEFAULT: return "default";
|
98
|
+
case VM_BEHAVIOR_RANDOM: return "random";
|
99
|
+
case VM_BEHAVIOR_SEQUENTIAL: return "sequential";
|
100
|
+
case VM_BEHAVIOR_RSEQNTL: return "rseqntl";
|
101
|
+
case VM_BEHAVIOR_WILLNEED: return "willneed";
|
102
|
+
case VM_BEHAVIOR_DONTNEED: return "dontneed";
|
103
|
+
case VM_BEHAVIOR_FREE: return "free";
|
104
|
+
case VM_BEHAVIOR_ZERO_WIRED_PAGES: return "zero";
|
105
|
+
case VM_BEHAVIOR_REUSABLE: return "reusable";
|
106
|
+
case VM_BEHAVIOR_REUSE: return "reuse";
|
107
|
+
case VM_BEHAVIOR_CAN_REUSE: return "can";
|
108
|
+
case VM_BEHAVIOR_PAGEOUT: return "pageout";
|
109
|
+
default:
|
110
|
+
sprintf(buf, "%d", behavior);
|
111
|
+
return buf;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
static void dump_maps(const char *image_name)
|
116
|
+
{
|
117
|
+
mach_port_t task = mach_task_self();
|
118
|
+
vm_region_basic_info_data_64_t info;
|
119
|
+
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
|
120
|
+
memory_object_name_t object = 0;
|
121
|
+
vm_address_t addr = 0;
|
122
|
+
vm_size_t size;
|
123
|
+
char inherit_buf[INHERIT_MAX_SIZE + 1];
|
124
|
+
char behavior_buf[BEHAVIOR_MAX_SIZE + 1];
|
125
|
+
|
126
|
+
fprintf(stderr, "MEMORY MAP(%s)\n", image_name);
|
127
|
+
fprintf(stderr, " start address end address protection max_protection inherit shared reserved offset behavior user_wired_count\n");
|
128
|
+
while (vm_region_64(task, &addr, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &info_count, &object) == KERN_SUCCESS) {
|
129
|
+
fprintf(stderr, " %016lx-%016lx %c%c%c(%08x) %c%c%c(%08x) %-*s %c %c %08llx %-*s %u\n",
|
130
|
+
addr, addr + size,
|
131
|
+
(info.protection & VM_PROT_READ) ? 'r' : '-',
|
132
|
+
(info.protection & VM_PROT_WRITE) ? 'w' : '-',
|
133
|
+
(info.protection & VM_PROT_EXECUTE) ? 'x' : '-',
|
134
|
+
info.protection,
|
135
|
+
(info.max_protection & VM_PROT_READ) ? 'r' : '-',
|
136
|
+
(info.max_protection & VM_PROT_WRITE) ? 'w' : '-',
|
137
|
+
(info.max_protection & VM_PROT_EXECUTE) ? 'x' : '-',
|
138
|
+
info.max_protection,
|
139
|
+
INHERIT_MAX_SIZE, inherit_to_str(info.inheritance, inherit_buf),
|
140
|
+
info.shared ? 'Y' : 'N',
|
141
|
+
info.reserved ? 'Y' : 'N',
|
142
|
+
info.offset,
|
143
|
+
BEHAVIOR_MAX_SIZE, behavior_to_str(info.behavior, behavior_buf),
|
144
|
+
info.user_wired_count);
|
145
|
+
addr += size;
|
146
|
+
}
|
147
|
+
}
|
63
148
|
#endif
|
64
149
|
|
65
150
|
typedef struct {
|
@@ -69,14 +154,28 @@ typedef struct {
|
|
69
154
|
|
70
155
|
struct plthook {
|
71
156
|
unsigned int num_entries;
|
72
|
-
|
157
|
+
int readonly_segment;
|
158
|
+
bind_address_t entries[1]; /* This must be the last. */
|
73
159
|
};
|
74
160
|
|
75
|
-
|
76
|
-
|
161
|
+
#define MAX_SEGMENTS 8
|
162
|
+
|
163
|
+
typedef struct {
|
164
|
+
plthook_t *plthook;
|
165
|
+
intptr_t slide;
|
166
|
+
int num_segments;
|
167
|
+
int linkedit_segment_idx;
|
168
|
+
struct segment_command_64 *segments[MAX_SEGMENTS];
|
169
|
+
struct linkedit_data_command *chained_fixups;
|
170
|
+
size_t got_addr;
|
171
|
+
} data_t;
|
172
|
+
|
173
|
+
static int plthook_open_real(plthook_t **plthook_out, uint32_t image_idx, const struct mach_header *mh, const char *image_name);
|
174
|
+
static unsigned int set_bind_addrs(data_t *d, uint32_t lazy_bind_off, uint32_t lazy_bind_size);
|
175
|
+
static void set_bind_addr(data_t *d, unsigned int *idx, const char *sym_name, int seg_index, int seg_offset);
|
176
|
+
static int read_chained_fixups(data_t *d, const struct mach_header *mh, const char *image_name);
|
77
177
|
|
78
178
|
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, uint64_t seg_offset, struct segment_command_ **segments);
|
80
179
|
|
81
180
|
static uint64_t uleb128(const uint8_t **p)
|
82
181
|
{
|
@@ -113,33 +212,40 @@ static char errmsg[512];
|
|
113
212
|
|
114
213
|
int plthook_open(plthook_t **plthook_out, const char *filename)
|
115
214
|
{
|
116
|
-
|
215
|
+
size_t namelen;
|
216
|
+
uint32_t cnt;
|
217
|
+
uint32_t idx;
|
117
218
|
|
118
|
-
if (filename
|
119
|
-
|
219
|
+
if (filename == NULL) {
|
220
|
+
return plthook_open_real(plthook_out, 0, NULL, NULL);
|
221
|
+
}
|
222
|
+
cnt = _dyld_image_count();
|
223
|
+
namelen = strlen(filename);
|
224
|
+
namelen = strlen(filename);
|
225
|
+
cnt = _dyld_image_count();
|
120
226
|
|
121
|
-
|
122
|
-
|
123
|
-
|
227
|
+
for (idx = 0; idx < cnt; idx++) {
|
228
|
+
const char *image_name = _dyld_get_image_name(idx);
|
229
|
+
size_t offset = 0;
|
124
230
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
}
|
135
|
-
}
|
136
|
-
if (strcmp(image_name + offset, filename) == 0) {
|
137
|
-
break;
|
231
|
+
if (image_name == NULL) {
|
232
|
+
*plthook_out = NULL;
|
233
|
+
set_errmsg("Cannot find file at image index %u", idx);
|
234
|
+
return PLTHOOK_INTERNAL_ERROR;
|
235
|
+
}
|
236
|
+
if (*filename != '/') {
|
237
|
+
size_t image_name_len = strlen(image_name);
|
238
|
+
if (image_name_len > namelen) {
|
239
|
+
offset = image_name_len - namelen;
|
138
240
|
}
|
139
|
-
|
241
|
+
}
|
242
|
+
if (strcmp(image_name + offset, filename) == 0) {
|
243
|
+
return plthook_open_real(plthook_out, idx, NULL, image_name);
|
140
244
|
}
|
141
245
|
}
|
142
|
-
|
246
|
+
*plthook_out = NULL;
|
247
|
+
set_errmsg("Cannot find file: %s", filename);
|
248
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
143
249
|
}
|
144
250
|
|
145
251
|
int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
@@ -148,7 +254,8 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
|
148
254
|
RTLD_LAZY | RTLD_NOLOAD,
|
149
255
|
RTLD_LAZY | RTLD_NOLOAD | RTLD_FIRST,
|
150
256
|
};
|
151
|
-
|
257
|
+
int flag_idx;
|
258
|
+
uint32_t cnt = _dyld_image_count();
|
152
259
|
#define NUM_FLAGS (sizeof(flags) / sizeof(flags[0]))
|
153
260
|
|
154
261
|
if (hndl == NULL) {
|
@@ -156,18 +263,18 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
|
156
263
|
return PLTHOOK_FILE_NOT_FOUND;
|
157
264
|
}
|
158
265
|
for (flag_idx = 0; flag_idx < NUM_FLAGS; flag_idx++) {
|
159
|
-
|
160
|
-
uint32_t idx = 0;
|
266
|
+
uint32_t idx;
|
161
267
|
|
162
|
-
|
268
|
+
for (idx = 0; idx < cnt; idx++) {
|
269
|
+
const char *image_name = idx ? _dyld_get_image_name(idx) : NULL;
|
163
270
|
void *handle = dlopen(image_name, flags[flag_idx]);
|
164
271
|
if (handle != NULL) {
|
165
272
|
dlclose(handle);
|
166
273
|
if (handle == hndl) {
|
167
|
-
return plthook_open_real(plthook_out,
|
274
|
+
return plthook_open_real(plthook_out, idx, NULL, image_name);
|
168
275
|
}
|
169
276
|
}
|
170
|
-
}
|
277
|
+
}
|
171
278
|
}
|
172
279
|
set_errmsg("Cannot find the image correspond to handle %p", hndl);
|
173
280
|
return PLTHOOK_FILE_NOT_FOUND;
|
@@ -176,43 +283,62 @@ int plthook_open_by_handle(plthook_t **plthook_out, void *hndl)
|
|
176
283
|
int plthook_open_by_address(plthook_t **plthook_out, void *address)
|
177
284
|
{
|
178
285
|
Dl_info dlinfo;
|
286
|
+
uint32_t idx = 0;
|
287
|
+
uint32_t cnt = _dyld_image_count();
|
179
288
|
|
180
289
|
if (!dladdr(address, &dlinfo)) {
|
181
290
|
*plthook_out = NULL;
|
182
291
|
set_errmsg("Cannot find address: %p", address);
|
183
292
|
return PLTHOOK_FILE_NOT_FOUND;
|
184
293
|
}
|
185
|
-
|
294
|
+
for (idx = 0; idx < cnt; idx++) {
|
295
|
+
if (dlinfo.dli_fbase == _dyld_get_image_header(idx)) {
|
296
|
+
return plthook_open_real(plthook_out, idx, dlinfo.dli_fbase, dlinfo.dli_fname);
|
297
|
+
}
|
298
|
+
}
|
299
|
+
set_errmsg("Cannot find the image index for base address: %p", dlinfo.dli_fbase);
|
300
|
+
return PLTHOOK_FILE_NOT_FOUND;
|
186
301
|
}
|
187
302
|
|
188
|
-
|
189
|
-
|
190
|
-
static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *mh)
|
303
|
+
static int plthook_open_real(plthook_t **plthook_out, uint32_t image_idx, const struct mach_header *mh, const char *image_name)
|
191
304
|
{
|
192
305
|
struct load_command *cmd;
|
193
|
-
const uint8_t *base = (const uint8_t *)mh;
|
194
306
|
uint32_t lazy_bind_off = 0;
|
195
307
|
uint32_t lazy_bind_size = 0;
|
196
|
-
struct segment_command_ *segments[NUM_SEGMENTS];
|
197
|
-
int segment_idx = 0;
|
198
308
|
unsigned int nbind;
|
199
|
-
|
200
|
-
|
309
|
+
data_t data = {NULL,};
|
310
|
+
size_t size;
|
311
|
+
int i;
|
201
312
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
313
|
+
data.linkedit_segment_idx = -1;
|
314
|
+
data.slide = _dyld_get_image_vmaddr_slide(image_idx);
|
315
|
+
if (mh == NULL) {
|
316
|
+
mh = _dyld_get_image_header(image_idx);
|
317
|
+
}
|
318
|
+
if (image_name == NULL) {
|
319
|
+
image_name = _dyld_get_image_name(image_idx);
|
320
|
+
}
|
321
|
+
#if defined(PLTHOOK_DEBUG_CMD) || defined(PLTHOOK_DEBUG_ADDR)
|
322
|
+
fprintf(stderr, "mh=%"PRIxPTR" slide=%"PRIxPTR"\n", (uintptr_t)mh, data.slide);
|
323
|
+
#endif
|
324
|
+
#ifdef PLTHOOK_DEBUG_ADDR
|
325
|
+
dump_maps(image_name);
|
207
326
|
#endif
|
327
|
+
|
328
|
+
cmd = (struct load_command *)((size_t)mh + sizeof(struct mach_header_64));
|
329
|
+
DEBUG_CMD("CMD START\n");
|
208
330
|
for (i = 0; i < mh->ncmds; i++) {
|
209
331
|
struct dyld_info_command *dyld_info;
|
332
|
+
#ifdef PLTHOOK_DEBUG_CMD
|
210
333
|
struct segment_command *segment;
|
334
|
+
#endif
|
211
335
|
struct segment_command_64 *segment64;
|
212
336
|
|
213
337
|
switch (cmd->cmd) {
|
214
338
|
case LC_SEGMENT: /* 0x1 */
|
339
|
+
#ifdef PLTHOOK_DEBUG_CMD
|
215
340
|
segment = (struct segment_command *)cmd;
|
341
|
+
#endif
|
216
342
|
DEBUG_CMD("LC_SEGMENT\n"
|
217
343
|
" segname %s\n"
|
218
344
|
" vmaddr %8x vmsize %8x\n"
|
@@ -224,12 +350,6 @@ static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *
|
|
224
350
|
segment->fileoff, segment->filesize,
|
225
351
|
segment->maxprot, segment->initprot,
|
226
352
|
segment->nsects, segment->flags);
|
227
|
-
if (strcmp(segment->segname, "__LINKEDIT") == 0) {
|
228
|
-
addrdiff = segment->vmaddr - segment->fileoff;
|
229
|
-
}
|
230
|
-
#ifndef __LP64__
|
231
|
-
segments[segment_idx++] = segment;
|
232
|
-
#endif
|
233
353
|
break;
|
234
354
|
case LC_SEGMENT_64: /* 0x19 */
|
235
355
|
segment64 = (struct segment_command_64 *)cmd;
|
@@ -245,11 +365,49 @@ static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *
|
|
245
365
|
segment64->maxprot, segment64->initprot,
|
246
366
|
segment64->nsects, segment64->flags);
|
247
367
|
if (strcmp(segment64->segname, "__LINKEDIT") == 0) {
|
248
|
-
|
368
|
+
data.linkedit_segment_idx = data.num_segments;
|
249
369
|
}
|
250
|
-
|
251
|
-
|
252
|
-
|
370
|
+
if (strcmp(segment64->segname, "__DATA_CONST") == 0) {
|
371
|
+
struct section_64 *sec = (struct section_64 *)(segment64 + 1);
|
372
|
+
uint32_t i;
|
373
|
+
for (i = 0; i < segment64->nsects; i++) {
|
374
|
+
DEBUG_CMD(" section_64 (%u)\n"
|
375
|
+
" sectname %s\n"
|
376
|
+
" segname %s\n"
|
377
|
+
" addr 0x%llx\n"
|
378
|
+
" size 0x%llx\n"
|
379
|
+
" offset 0x%x\n"
|
380
|
+
" align 0x%x\n"
|
381
|
+
" reloff 0x%x\n"
|
382
|
+
" nreloc %d\n"
|
383
|
+
" flags 0x%x\n"
|
384
|
+
" reserved1 %d\n"
|
385
|
+
" reserved2 %d\n"
|
386
|
+
" reserved3 %d\n",
|
387
|
+
i,
|
388
|
+
sec->sectname,
|
389
|
+
sec->segname,
|
390
|
+
sec->addr,
|
391
|
+
sec->size,
|
392
|
+
sec->offset,
|
393
|
+
sec->align,
|
394
|
+
sec->reloff,
|
395
|
+
sec->nreloc,
|
396
|
+
sec->flags,
|
397
|
+
sec->reserved1,
|
398
|
+
sec->reserved2,
|
399
|
+
sec->reserved3);
|
400
|
+
if (strcmp(sec->segname, "__DATA_CONST") == 0 && strcmp(sec->sectname, "__got") == 0) {
|
401
|
+
data.got_addr = sec->addr + data.slide;
|
402
|
+
}
|
403
|
+
sec++;
|
404
|
+
}
|
405
|
+
}
|
406
|
+
if (data.num_segments == MAX_SEGMENTS) {
|
407
|
+
set_errmsg("Too many segments: %s", image_name);
|
408
|
+
return PLTHOOK_INTERNAL_ERROR;
|
409
|
+
}
|
410
|
+
data.segments[data.num_segments++] = segment64;
|
253
411
|
break;
|
254
412
|
case LC_DYLD_INFO_ONLY: /* (0x22|LC_REQ_DYLD) */
|
255
413
|
dyld_info= (struct dyld_info_command *)cmd;
|
@@ -289,6 +447,9 @@ static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *
|
|
289
447
|
case LC_UUID: /* 0x1b */
|
290
448
|
DEBUG_CMD("LC_UUID\n");
|
291
449
|
break;
|
450
|
+
case LC_CODE_SIGNATURE: /* 0x1d */
|
451
|
+
DEBUG_CMD("LC_CODE_SIGNATURE\n");
|
452
|
+
break;
|
292
453
|
case LC_VERSION_MIN_MACOSX: /* 0x24 */
|
293
454
|
DEBUG_CMD("LC_VERSION_MIN_MACOSX\n");
|
294
455
|
break;
|
@@ -307,41 +468,69 @@ static int plthook_open_real(plthook_t **plthook_out, const struct mach_header *
|
|
307
468
|
case LC_DYLIB_CODE_SIGN_DRS: /* 0x2B */
|
308
469
|
DEBUG_CMD("LC_DYLIB_CODE_SIGN_DRS\n");
|
309
470
|
break;
|
471
|
+
case LC_BUILD_VERSION: /* 0x32 */
|
472
|
+
DEBUG_CMD("LC_BUILD_VERSION\n");
|
473
|
+
break;
|
474
|
+
case LC_DYLD_EXPORTS_TRIE: /* (0x33|LC_REQ_DYLD) */
|
475
|
+
DEBUG_CMD("LC_DYLD_EXPORTS_TRIE\n");
|
476
|
+
break;
|
477
|
+
case LC_DYLD_CHAINED_FIXUPS: /* (0x34|LC_REQ_DYLD) */
|
478
|
+
data.chained_fixups = (struct linkedit_data_command *)cmd;
|
479
|
+
DEBUG_CMD("LC_DYLD_CHAINED_FIXUPS\n"
|
480
|
+
" cmdsize %u\n"
|
481
|
+
" dataoff %u (0x%x)\n"
|
482
|
+
" datasize %u\n",
|
483
|
+
data.chained_fixups->cmdsize,
|
484
|
+
data.chained_fixups->dataoff,
|
485
|
+
data.chained_fixups->dataoff,
|
486
|
+
data.chained_fixups->datasize);
|
487
|
+
break;
|
310
488
|
default:
|
311
489
|
DEBUG_CMD("LC_? (0x%x)\n", cmd->cmd);
|
312
490
|
}
|
313
491
|
cmd = (struct load_command *)((size_t)cmd + cmd->cmdsize);
|
314
492
|
}
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
493
|
+
DEBUG_CMD("CMD END\n");
|
494
|
+
if (data.linkedit_segment_idx == -1) {
|
495
|
+
set_errmsg("Cannot find the linkedit segment: %s", image_name);
|
496
|
+
return PLTHOOK_INVALID_FILE_FORMAT;
|
497
|
+
}
|
498
|
+
if (data.chained_fixups != NULL) {
|
499
|
+
int rv = read_chained_fixups(&data, mh, image_name);
|
500
|
+
if (rv != 0) {
|
501
|
+
return rv;
|
502
|
+
}
|
503
|
+
} else {
|
504
|
+
nbind = set_bind_addrs(&data, lazy_bind_off, lazy_bind_size);
|
505
|
+
size = offsetof(plthook_t, entries) + sizeof(bind_address_t) * nbind;
|
506
|
+
data.plthook = (plthook_t*)calloc(1, size);
|
507
|
+
if (data.plthook == NULL) {
|
508
|
+
set_errmsg("failed to allocate memory: %" PRIuPTR " bytes", size);
|
509
|
+
return PLTHOOK_OUT_OF_MEMORY;
|
510
|
+
}
|
511
|
+
data.plthook->num_entries = nbind;
|
512
|
+
set_bind_addrs(&data, lazy_bind_off, lazy_bind_size);
|
513
|
+
}
|
319
514
|
|
515
|
+
*plthook_out = data.plthook;
|
320
516
|
return 0;
|
321
517
|
}
|
322
518
|
|
323
|
-
static unsigned int
|
519
|
+
static unsigned int set_bind_addrs(data_t *data, uint32_t lazy_bind_off, uint32_t lazy_bind_size)
|
324
520
|
{
|
325
|
-
|
521
|
+
struct segment_command_64 *linkedit = data->segments[data->linkedit_segment_idx];
|
522
|
+
const uint8_t *ptr = (uint8_t*)(linkedit->vmaddr - linkedit->fileoff + data->slide + lazy_bind_off);
|
326
523
|
const uint8_t *end = ptr + lazy_bind_size;
|
327
524
|
const char *sym_name;
|
328
525
|
int seg_index = 0;
|
329
526
|
uint64_t seg_offset = 0;
|
330
|
-
|
331
|
-
unsigned int idx;
|
332
|
-
DEBUG_BIND("get_bind_addr(%p, 0x%x, 0x%x", base, lazy_bind_off, lazy_bind_size);
|
333
|
-
for (idx = 0; segments[idx] != NULL; idx++) {
|
334
|
-
DEBUG_BIND(", [%s]", segments[idx]->segname);
|
335
|
-
}
|
336
|
-
DEBUG_BIND(")\n");
|
527
|
+
int count, skip;
|
528
|
+
unsigned int idx = 0;
|
337
529
|
|
338
|
-
idx = 0;
|
339
530
|
while (ptr < end) {
|
340
531
|
uint8_t op = *ptr & BIND_OPCODE_MASK;
|
341
532
|
uint8_t imm = *ptr & BIND_IMMEDIATE_MASK;
|
342
|
-
|
343
|
-
int64_t slebval;
|
344
|
-
uint64_t i;
|
533
|
+
int i;
|
345
534
|
|
346
535
|
DEBUG_BIND("0x%02x: ", *ptr);
|
347
536
|
ptr++;
|
@@ -353,8 +542,11 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
353
542
|
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: ordinal = %u\n", imm);
|
354
543
|
break;
|
355
544
|
case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
|
356
|
-
|
357
|
-
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: ordinal = %llu\n",
|
545
|
+
#ifdef PLTHOOK_DEBUG_BIND
|
546
|
+
DEBUG_BIND("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: ordinal = %llu\n", uleb128(&ptr));
|
547
|
+
#else
|
548
|
+
uleb128(&ptr);
|
549
|
+
#endif
|
358
550
|
break;
|
359
551
|
case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
|
360
552
|
if (imm == 0) {
|
@@ -371,8 +563,11 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
371
563
|
DEBUG_BIND("BIND_OPCODE_SET_TYPE_IMM: type = %u\n", imm);
|
372
564
|
break;
|
373
565
|
case BIND_OPCODE_SET_ADDEND_SLEB:
|
374
|
-
|
375
|
-
DEBUG_BIND("BIND_OPCODE_SET_ADDEND_SLEB: ordinal = %lld\n",
|
566
|
+
#ifdef PLTHOOK_DEBUG_BIND
|
567
|
+
DEBUG_BIND("BIND_OPCODE_SET_ADDEND_SLEB: ordinal = %lld\n", sleb128(&ptr));
|
568
|
+
#else
|
569
|
+
sleb128(&ptr);
|
570
|
+
#endif
|
376
571
|
break;
|
377
572
|
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
|
378
573
|
seg_index = imm;
|
@@ -384,7 +579,7 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
384
579
|
DEBUG_BIND("BIND_OPCODE_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
|
385
580
|
break;
|
386
581
|
case BIND_OPCODE_DO_BIND:
|
387
|
-
set_bind_addr(&idx,
|
582
|
+
set_bind_addr(data, &idx, sym_name, seg_index, seg_offset);
|
388
583
|
DEBUG_BIND("BIND_OPCODE_DO_BIND\n");
|
389
584
|
break;
|
390
585
|
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
|
@@ -392,7 +587,7 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
392
587
|
DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: seg_offset = 0x%llx\n", seg_offset);
|
393
588
|
break;
|
394
589
|
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
|
395
|
-
set_bind_addr(&idx,
|
590
|
+
set_bind_addr(data, &idx, sym_name, seg_index, seg_offset);
|
396
591
|
seg_offset += imm * sizeof(void *);
|
397
592
|
DEBUG_BIND("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED\n");
|
398
593
|
break;
|
@@ -400,7 +595,7 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
400
595
|
count = uleb128(&ptr);
|
401
596
|
skip = uleb128(&ptr);
|
402
597
|
for (i = 0; i < count; i++) {
|
403
|
-
set_bind_addr(&idx,
|
598
|
+
set_bind_addr(data, &idx, sym_name, seg_index, seg_offset);
|
404
599
|
seg_offset += skip;
|
405
600
|
}
|
406
601
|
DEBUG_BIND("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB\n");
|
@@ -410,16 +605,368 @@ static unsigned int get_bind_addr(plthook_t *plthook, const uint8_t *base, uint3
|
|
410
605
|
return idx;
|
411
606
|
}
|
412
607
|
|
413
|
-
static void set_bind_addr(
|
608
|
+
static void set_bind_addr(data_t *data, unsigned int *idx, const char *sym_name, int seg_index, int seg_offset)
|
414
609
|
{
|
415
|
-
if (plthook != NULL) {
|
416
|
-
|
417
|
-
plthook->entries[*idx].name = sym_name;
|
418
|
-
plthook->entries[*idx].addr = (void**)(
|
610
|
+
if (data->plthook != NULL) {
|
611
|
+
size_t vmaddr = data->segments[seg_index]->vmaddr;
|
612
|
+
data->plthook->entries[*idx].name = sym_name;
|
613
|
+
data->plthook->entries[*idx].addr = (void**)(vmaddr + data->slide + seg_offset);
|
419
614
|
}
|
420
615
|
(*idx)++;
|
421
616
|
}
|
422
617
|
|
618
|
+
static int read_chained_fixups(data_t *d, const struct mach_header *mh, const char *image_name)
|
619
|
+
{
|
620
|
+
const uint8_t *ptr = (const uint8_t *)mh + d->chained_fixups->dataoff;
|
621
|
+
const uint8_t *end = ptr + d->chained_fixups->datasize;
|
622
|
+
const struct dyld_chained_fixups_header *header = (const struct dyld_chained_fixups_header *)ptr;
|
623
|
+
const struct dyld_chained_import *import = (const struct dyld_chained_import *)(ptr + header->imports_offset);
|
624
|
+
const struct dyld_chained_import_addend *import_addend = (const struct dyld_chained_import_addend *)(ptr + header->imports_offset);
|
625
|
+
const struct dyld_chained_import_addend64 *import_addend64 = (const struct dyld_chained_import_addend64 *)(ptr + header->imports_offset);
|
626
|
+
const char *symbol_pool = (const char*)ptr + header->symbols_offset;
|
627
|
+
int rv = PLTHOOK_INTERNAL_ERROR;
|
628
|
+
size_t size;
|
629
|
+
uint32_t i;
|
630
|
+
#ifdef PLTHOOK_DEBUG_FIXUPS
|
631
|
+
const struct dyld_chained_starts_in_image *starts = (const struct dyld_chained_starts_in_image *)(ptr + header->starts_offset);
|
632
|
+
FILE *fp = NULL;
|
633
|
+
#endif
|
634
|
+
if (d->got_addr == 0) {
|
635
|
+
set_errmsg("__got section is not found in %s", image_name);
|
636
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
637
|
+
goto cleanup;
|
638
|
+
}
|
639
|
+
|
640
|
+
DEBUG_FIXUPS("dyld_chained_fixups_header\n"
|
641
|
+
" fixups_version %u\n"
|
642
|
+
" starts_offset %u\n"
|
643
|
+
" imports_offset %u\n"
|
644
|
+
" symbols_offset %u\n"
|
645
|
+
" imports_count %u\n"
|
646
|
+
" imports_format %u\n"
|
647
|
+
" symbols_format %u\n",
|
648
|
+
header->fixups_version,
|
649
|
+
header->starts_offset,
|
650
|
+
header->imports_offset,
|
651
|
+
header->symbols_offset,
|
652
|
+
header->imports_count,
|
653
|
+
header->imports_format,
|
654
|
+
header->symbols_format);
|
655
|
+
if (header->fixups_version != 0) {
|
656
|
+
set_errmsg("unknown chained fixups version %u", header->fixups_version);
|
657
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
658
|
+
goto cleanup;
|
659
|
+
}
|
660
|
+
|
661
|
+
size = offsetof(plthook_t, entries) + sizeof(bind_address_t) * header->imports_count;
|
662
|
+
d->plthook = (plthook_t*)calloc(1, size);
|
663
|
+
if (d->plthook == NULL) {
|
664
|
+
set_errmsg("failed to allocate memory: %" PRIuPTR " bytes", size);
|
665
|
+
rv = PLTHOOK_OUT_OF_MEMORY;
|
666
|
+
goto cleanup;
|
667
|
+
}
|
668
|
+
d->plthook->num_entries = header->imports_count;
|
669
|
+
d->plthook->readonly_segment = 1;
|
670
|
+
|
671
|
+
switch (header->imports_format) {
|
672
|
+
case DYLD_CHAINED_IMPORT:
|
673
|
+
DEBUG_FIXUPS("dyld_chained_import\n");
|
674
|
+
break;
|
675
|
+
case DYLD_CHAINED_IMPORT_ADDEND:
|
676
|
+
DEBUG_FIXUPS("dyld_chained_import_addend\n");
|
677
|
+
break;
|
678
|
+
case DYLD_CHAINED_IMPORT_ADDEND64:
|
679
|
+
DEBUG_FIXUPS("dyld_chained_import_addend64\n");
|
680
|
+
break;
|
681
|
+
default:
|
682
|
+
set_errmsg("unknown imports format %u", header->imports_format);
|
683
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
684
|
+
goto cleanup;
|
685
|
+
}
|
686
|
+
|
687
|
+
for (i = 0; i < header->imports_count; i++) {
|
688
|
+
struct dyld_chained_import_addend64 imp;
|
689
|
+
switch (header->imports_format) {
|
690
|
+
case DYLD_CHAINED_IMPORT:
|
691
|
+
imp.lib_ordinal = import[i].lib_ordinal;
|
692
|
+
imp.weak_import = import[i].weak_import;
|
693
|
+
imp.name_offset = import[i].name_offset;
|
694
|
+
imp.addend = 0;
|
695
|
+
break;
|
696
|
+
case DYLD_CHAINED_IMPORT_ADDEND:
|
697
|
+
imp.lib_ordinal = import_addend[i].lib_ordinal;
|
698
|
+
imp.weak_import = import_addend[i].weak_import;
|
699
|
+
imp.name_offset = import_addend[i].name_offset;
|
700
|
+
imp.addend = import_addend[i].addend;
|
701
|
+
break;
|
702
|
+
case DYLD_CHAINED_IMPORT_ADDEND64:
|
703
|
+
imp = import_addend64[i];
|
704
|
+
break;
|
705
|
+
}
|
706
|
+
const char *name = symbol_pool + imp.name_offset;
|
707
|
+
if (name > (const char*)end) {
|
708
|
+
DEBUG_FIXUPS(" lib_ordinal %u, weak_import %u, name_offset %u, addend %llu\n",
|
709
|
+
imp.lib_ordinal, imp.weak_import, imp.name_offset, imp.addend);
|
710
|
+
set_errmsg("invalid symbol name address");
|
711
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
712
|
+
goto cleanup;
|
713
|
+
}
|
714
|
+
DEBUG_FIXUPS(" lib_ordinal %u, weak_import %u, name_offset %u (%s), addend %llu\n",
|
715
|
+
imp.lib_ordinal, imp.weak_import, imp.name_offset, name, imp.addend);
|
716
|
+
d->plthook->entries[i].name = name;
|
717
|
+
d->plthook->entries[i].addr = (void**)(d->got_addr + i * sizeof(void*));
|
718
|
+
}
|
719
|
+
|
720
|
+
#ifdef PLTHOOK_DEBUG_FIXUPS
|
721
|
+
fp = fopen(image_name, "r");
|
722
|
+
if (fp == NULL) {
|
723
|
+
set_errmsg("failed to open file %s (error: %s)", image_name, strerror(errno));
|
724
|
+
rv = PLTHOOK_FILE_NOT_FOUND;
|
725
|
+
goto cleanup;
|
726
|
+
}
|
727
|
+
|
728
|
+
DEBUG_FIXUPS("dyld_chained_starts_in_image\n"
|
729
|
+
" seg_count %u\n",
|
730
|
+
starts->seg_count);
|
731
|
+
for (i = 0; i < starts->seg_count; i++) {
|
732
|
+
DEBUG_FIXUPS(" seg_info_offset[%u] %u\n",
|
733
|
+
i, starts->seg_info_offset[i]);
|
734
|
+
if (starts->seg_info_offset[i] == 0) {
|
735
|
+
continue;
|
736
|
+
}
|
737
|
+
const struct dyld_chained_starts_in_segment* seg = (const struct dyld_chained_starts_in_segment*)((char*)starts + starts->seg_info_offset[i]);
|
738
|
+
uint16_t j;
|
739
|
+
DEBUG_FIXUPS(" dyld_chained_starts_in_segment\n"
|
740
|
+
" size %u\n"
|
741
|
+
" page_size 0x%x\n"
|
742
|
+
" pointer_format %u\n"
|
743
|
+
" segment_offset %llu (0x%llx)\n"
|
744
|
+
" max_valid_pointer %u\n"
|
745
|
+
" page_count %u\n",
|
746
|
+
seg->size, seg->page_size, seg->pointer_format, seg->segment_offset, seg->segment_offset, seg->max_valid_pointer, seg->page_count);
|
747
|
+
for (j = 0; j < seg->page_count; j++) {
|
748
|
+
uint16_t index = j;
|
749
|
+
uint16_t break_loop = 1;
|
750
|
+
off_t offset;
|
751
|
+
|
752
|
+
if (seg->page_start[j] == DYLD_CHAINED_PTR_START_NONE) {
|
753
|
+
DEBUG_FIXUPS(" page_start[%u] DYLD_CHAINED_PTR_START_NONE\n", j);
|
754
|
+
continue;
|
755
|
+
}
|
756
|
+
if (seg->page_start[j] & DYLD_CHAINED_PTR_START_MULTI) {
|
757
|
+
index = seg->page_start[j] & ~DYLD_CHAINED_PTR_START_MULTI;
|
758
|
+
DEBUG_FIXUPS(" page_start[%u] (DYLD_CHAINED_PTR_START_MULTI | %u)\n", j, index);
|
759
|
+
break_loop = 0;
|
760
|
+
}
|
761
|
+
while (1) {
|
762
|
+
if (index != j) {
|
763
|
+
DEBUG_FIXUPS(" page_start[%u] %u\n", index, seg->page_start[index]);
|
764
|
+
}
|
765
|
+
offset = seg->segment_offset + j * seg->page_size + (seg->page_start[index] & ~DYLD_CHAINED_PTR_START_MULTI);
|
766
|
+
switch (seg->pointer_format) {
|
767
|
+
case DYLD_CHAINED_PTR_64_OFFSET: {
|
768
|
+
union {
|
769
|
+
struct dyld_chained_ptr_64_rebase rebase;
|
770
|
+
struct dyld_chained_ptr_64_bind bind;
|
771
|
+
} buf;
|
772
|
+
|
773
|
+
do {
|
774
|
+
if (fseeko(fp, offset, SEEK_SET) != 0) {
|
775
|
+
set_errmsg("failed to seek to %lld in %s", offset, image_name);
|
776
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
777
|
+
goto cleanup;
|
778
|
+
}
|
779
|
+
if (fread(&buf, sizeof(buf), 1, fp) != 1) {
|
780
|
+
set_errmsg("failed to read fixup chain from %s", image_name);
|
781
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
782
|
+
goto cleanup;
|
783
|
+
}
|
784
|
+
if (buf.rebase.bind) {
|
785
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_64_bind\n"
|
786
|
+
" ordinal %d\n"
|
787
|
+
" addend %d\n"
|
788
|
+
" reserved %d\n"
|
789
|
+
" next %d\n"
|
790
|
+
" bind %d\n",
|
791
|
+
buf.bind.ordinal,
|
792
|
+
buf.bind.addend,
|
793
|
+
buf.bind.reserved,
|
794
|
+
buf.bind.next,
|
795
|
+
buf.bind.bind);
|
796
|
+
} else {
|
797
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_64_rebase\n"
|
798
|
+
" target %llu\n"
|
799
|
+
" high8 %d\n"
|
800
|
+
" reserved %d\n"
|
801
|
+
" next %d\n"
|
802
|
+
" bind %d\n",
|
803
|
+
buf.rebase.target,
|
804
|
+
buf.rebase.high8,
|
805
|
+
buf.rebase.reserved,
|
806
|
+
buf.rebase.next,
|
807
|
+
buf.rebase.bind);
|
808
|
+
}
|
809
|
+
offset += buf.bind.next * 4;
|
810
|
+
} while (buf.bind.next != 0);
|
811
|
+
break;
|
812
|
+
}
|
813
|
+
case DYLD_CHAINED_PTR_ARM64E:
|
814
|
+
case DYLD_CHAINED_PTR_ARM64E_KERNEL:
|
815
|
+
case DYLD_CHAINED_PTR_ARM64E_USERLAND:
|
816
|
+
case DYLD_CHAINED_PTR_ARM64E_USERLAND24: {
|
817
|
+
// The following code isn't tested.
|
818
|
+
union {
|
819
|
+
struct dyld_chained_ptr_arm64e_rebase rebase;
|
820
|
+
struct dyld_chained_ptr_arm64e_bind bind;
|
821
|
+
struct dyld_chained_ptr_arm64e_bind24 bind24;
|
822
|
+
struct dyld_chained_ptr_arm64e_auth_rebase auth_rebase;
|
823
|
+
struct dyld_chained_ptr_arm64e_auth_bind auth_bind;
|
824
|
+
struct dyld_chained_ptr_arm64e_auth_bind24 auth_bind24;
|
825
|
+
} buf;
|
826
|
+
|
827
|
+
do {
|
828
|
+
if (fseeko(fp, offset, SEEK_SET) != 0) {
|
829
|
+
set_errmsg("failed to seek to %lld in %s", offset, image_name);
|
830
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
831
|
+
goto cleanup;
|
832
|
+
}
|
833
|
+
if (fread(&buf, sizeof(buf), 1, fp) != 1) {
|
834
|
+
set_errmsg("failed to read fixup chain from %s", image_name);
|
835
|
+
rv = PLTHOOK_INVALID_FILE_FORMAT;
|
836
|
+
goto cleanup;
|
837
|
+
}
|
838
|
+
if (!buf.rebase.auth) {
|
839
|
+
if (!buf.rebase.bind) {
|
840
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_rebase\n"
|
841
|
+
" target %llu\n"
|
842
|
+
" high8 %d\n"
|
843
|
+
" next %d\n"
|
844
|
+
" bind %d\n" // == 0
|
845
|
+
" auth %d\n", // == 0
|
846
|
+
buf.rebase.target,
|
847
|
+
buf.rebase.high8,
|
848
|
+
buf.rebase.next,
|
849
|
+
buf.rebase.bind,
|
850
|
+
buf.rebase.auth);
|
851
|
+
} else if (seg->pointer_format != DYLD_CHAINED_PTR_ARM64E_USERLAND24) {
|
852
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_bind\n"
|
853
|
+
" ordinal %d\n"
|
854
|
+
" zero %d\n"
|
855
|
+
" addend %d\n"
|
856
|
+
" next %d\n"
|
857
|
+
" bind %d\n" // == 1
|
858
|
+
" auth %d\n", // == 0
|
859
|
+
buf.bind.ordinal,
|
860
|
+
buf.bind.zero,
|
861
|
+
buf.bind.addend,
|
862
|
+
buf.bind.next,
|
863
|
+
buf.bind.bind,
|
864
|
+
buf.bind.auth);
|
865
|
+
} else {
|
866
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_bind24\n"
|
867
|
+
" ordinal %d\n"
|
868
|
+
" zero %d\n"
|
869
|
+
" addend %d\n"
|
870
|
+
" next %d\n"
|
871
|
+
" bind %d\n" // == 1
|
872
|
+
" auth %d\n", // == 0
|
873
|
+
buf.bind24.ordinal,
|
874
|
+
buf.bind24.zero,
|
875
|
+
buf.bind24.addend,
|
876
|
+
buf.bind24.next,
|
877
|
+
buf.bind24.bind,
|
878
|
+
buf.bind24.auth);
|
879
|
+
}
|
880
|
+
} else {
|
881
|
+
if (!buf.rebase.bind) {
|
882
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_auth_rebase\n"
|
883
|
+
" target %u\n"
|
884
|
+
" diversity %d\n"
|
885
|
+
" addrDiv %d\n"
|
886
|
+
" key %d\n"
|
887
|
+
" next %d\n"
|
888
|
+
" bind %d\n" // == 0
|
889
|
+
" auth %d\n", // == 1
|
890
|
+
buf.auth_rebase.target,
|
891
|
+
buf.auth_rebase.diversity,
|
892
|
+
buf.auth_rebase.addrDiv,
|
893
|
+
buf.auth_rebase.key,
|
894
|
+
buf.auth_rebase.next,
|
895
|
+
buf.auth_rebase.bind,
|
896
|
+
buf.auth_rebase.auth);
|
897
|
+
} else if (seg->pointer_format != DYLD_CHAINED_PTR_ARM64E_USERLAND24) {
|
898
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_auth_bind\n"
|
899
|
+
" ordinal %d\n"
|
900
|
+
" zero %d\n"
|
901
|
+
" diversity %d\n"
|
902
|
+
" addrDiv %d\n"
|
903
|
+
" key %d\n"
|
904
|
+
" next %d\n"
|
905
|
+
" bind %d\n" // == 1
|
906
|
+
" auth %d\n", // == 1
|
907
|
+
buf.auth_bind.ordinal,
|
908
|
+
buf.auth_bind.zero,
|
909
|
+
buf.auth_bind.diversity,
|
910
|
+
buf.auth_bind.addrDiv,
|
911
|
+
buf.auth_bind.key,
|
912
|
+
buf.auth_bind.next,
|
913
|
+
buf.auth_bind.bind,
|
914
|
+
buf.auth_bind.auth);
|
915
|
+
} else {
|
916
|
+
DEBUG_FIXUPS(" dyld_chained_ptr_arm64e_auth_bind24\n"
|
917
|
+
" ordinal %d\n"
|
918
|
+
" zero %d\n"
|
919
|
+
" diversity %d\n"
|
920
|
+
" addrDiv %d\n"
|
921
|
+
" key %d\n"
|
922
|
+
" next %d\n"
|
923
|
+
" bind %d\n" // == 1
|
924
|
+
" auth %d\n", // == 1
|
925
|
+
buf.auth_bind24.ordinal,
|
926
|
+
buf.auth_bind24.zero,
|
927
|
+
buf.auth_bind24.diversity,
|
928
|
+
buf.auth_bind24.addrDiv,
|
929
|
+
buf.auth_bind24.key,
|
930
|
+
buf.auth_bind24.next,
|
931
|
+
buf.auth_bind24.bind,
|
932
|
+
buf.auth_bind24.auth);
|
933
|
+
}
|
934
|
+
}
|
935
|
+
if (seg->pointer_format == DYLD_CHAINED_PTR_ARM64E_KERNEL) {
|
936
|
+
offset += buf.rebase.next * 4;
|
937
|
+
} else {
|
938
|
+
offset += buf.rebase.next * 8;
|
939
|
+
}
|
940
|
+
} while (buf.rebase.next != 0);
|
941
|
+
break;
|
942
|
+
}
|
943
|
+
default:
|
944
|
+
DEBUG_FIXUPS("unsupported pointer_format: %u\n", seg->pointer_format);
|
945
|
+
break_loop = 1;
|
946
|
+
break;
|
947
|
+
}
|
948
|
+
if (break_loop) {
|
949
|
+
break;
|
950
|
+
}
|
951
|
+
break_loop = seg->page_start[++index] & DYLD_CHAINED_PTR_START_MULTI;
|
952
|
+
} // while (1) */
|
953
|
+
}
|
954
|
+
}
|
955
|
+
#endif
|
956
|
+
rv = 0;
|
957
|
+
cleanup:
|
958
|
+
#ifdef PLTHOOK_DEBUG_FIXUPS
|
959
|
+
if (fp != NULL) {
|
960
|
+
fclose(fp);
|
961
|
+
}
|
962
|
+
#endif
|
963
|
+
if (rv != 0 && d->plthook) {
|
964
|
+
free(d->plthook);
|
965
|
+
d->plthook = NULL;
|
966
|
+
}
|
967
|
+
return rv;
|
968
|
+
}
|
969
|
+
|
423
970
|
int plthook_enum(plthook_t *plthook, unsigned int *pos, const char **name_out, void ***addr_out)
|
424
971
|
{
|
425
972
|
if (*pos >= plthook->num_entries) {
|
@@ -473,7 +1020,18 @@ matched:
|
|
473
1020
|
if (oldfunc) {
|
474
1021
|
*oldfunc = *addr;
|
475
1022
|
}
|
476
|
-
|
1023
|
+
if (plthook->readonly_segment) {
|
1024
|
+
size_t page_size = sysconf(_SC_PAGESIZE);
|
1025
|
+
void *base = (void*)((size_t)addr & ~(page_size - 1));
|
1026
|
+
if (mprotect(base, page_size, PROT_READ | PROT_WRITE) != 0) {
|
1027
|
+
set_errmsg("Cannot change memory protection at address %p", base);
|
1028
|
+
return PLTHOOK_INTERNAL_ERROR;
|
1029
|
+
}
|
1030
|
+
*addr = funcaddr;
|
1031
|
+
mprotect(base, page_size, PROT_READ);
|
1032
|
+
} else {
|
1033
|
+
*addr = funcaddr;
|
1034
|
+
}
|
477
1035
|
return 0;
|
478
1036
|
}
|
479
1037
|
if (rv == EOF) {
|