Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c
41149 views
1
/*
2
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
#include "libproc_impl.h"
25
26
static const char* alt_root = NULL;
27
static int alt_root_len = -1;
28
29
#define SA_ALTROOT "SA_ALTROOT"
30
31
off_t ltell(int fd) {
32
return lseek(fd, 0, SEEK_CUR);
33
}
34
35
static void init_alt_root() {
36
if (alt_root_len == -1) {
37
alt_root = getenv(SA_ALTROOT);
38
if (alt_root) {
39
alt_root_len = strlen(alt_root);
40
} else {
41
alt_root_len = 0;
42
}
43
}
44
}
45
46
int pathmap_open(const char* name) {
47
int fd;
48
char alt_path[PATH_MAX + 1];
49
50
init_alt_root();
51
52
if (alt_root_len > 0) {
53
strcpy(alt_path, alt_root);
54
strcat(alt_path, name);
55
fd = open(alt_path, O_RDONLY);
56
if (fd >= 0) {
57
print_debug("path %s substituted for %s\n", alt_path, name);
58
return fd;
59
} else {
60
print_debug("can't open %s\n", alt_path);
61
}
62
63
if (strrchr(name, '/')) {
64
strcpy(alt_path, alt_root);
65
strcat(alt_path, strrchr(name, '/'));
66
fd = open(alt_path, O_RDONLY);
67
if (fd >= 0) {
68
print_debug("path %s substituted for %s\n", alt_path, name);
69
return fd;
70
} else {
71
print_debug("can't open %s\n", alt_path);
72
}
73
}
74
} else {
75
fd = open(name, O_RDONLY);
76
if (fd >= 0) {
77
return fd;
78
} else {
79
print_debug("can't open %s\n", name);
80
}
81
}
82
return -1;
83
}
84
85
static bool _libsaproc_debug;
86
87
void print_debug(const char* format,...) {
88
if (_libsaproc_debug) {
89
va_list alist;
90
91
va_start(alist, format);
92
fputs("libsaproc DEBUG: ", stderr);
93
vfprintf(stderr, format, alist);
94
va_end(alist);
95
}
96
}
97
98
void print_error(const char* format,...) {
99
va_list alist;
100
va_start(alist, format);
101
fputs("ERROR: ", stderr);
102
vfprintf(stderr, format, alist);
103
va_end(alist);
104
}
105
106
bool is_debug() {
107
return _libsaproc_debug;
108
}
109
110
#ifdef __APPLE__
111
// get arch offset in file
112
bool get_arch_off(int fd, cpu_type_t cputype, off_t *offset) {
113
struct fat_header fatheader;
114
struct fat_arch fatarch;
115
off_t img_start = 0;
116
117
off_t pos = ltell(fd);
118
if (read(fd, (void *)&fatheader, sizeof(struct fat_header)) != sizeof(struct fat_header)) {
119
return false;
120
}
121
if (fatheader.magic == FAT_CIGAM) {
122
int i;
123
for (i = 0; i < ntohl(fatheader.nfat_arch); i++) {
124
if (read(fd, (void *)&fatarch, sizeof(struct fat_arch)) != sizeof(struct fat_arch)) {
125
return false;
126
}
127
if (ntohl(fatarch.cputype) == cputype) {
128
print_debug("fat offset=%x\n", ntohl(fatarch.offset));
129
img_start = ntohl(fatarch.offset);
130
break;
131
}
132
}
133
if (img_start == 0) {
134
return false;
135
}
136
}
137
lseek(fd, pos, SEEK_SET);
138
*offset = img_start;
139
return true;
140
}
141
142
bool is_macho_file(int fd) {
143
mach_header_64 fhdr;
144
off_t x86_64_off;
145
146
if (fd < 0) {
147
print_debug("Invalid file handle passed to is_macho_file\n");
148
return false;
149
}
150
151
off_t pos = ltell(fd);
152
// check fat header
153
if (!get_arch_off(fd, CPU_TYPE_X86_64, &x86_64_off)) {
154
print_debug("failed to get fat header\n");
155
return false;
156
}
157
lseek(fd, x86_64_off, SEEK_SET);
158
if (read(fd, (void *)&fhdr, sizeof(mach_header_64)) != sizeof(mach_header_64)) {
159
return false;
160
}
161
lseek(fd, pos, SEEK_SET); // restore
162
print_debug("fhdr.magic %x\n", fhdr.magic);
163
return (fhdr.magic == MH_MAGIC_64 || fhdr.magic == MH_CIGAM_64);
164
}
165
166
#endif //__APPLE__
167
168
// initialize libproc
169
bool init_libproc(bool debug) {
170
_libsaproc_debug = debug;
171
#ifndef __APPLE__
172
// initialize the thread_db library
173
if (td_init() != TD_OK) {
174
print_debug("libthread_db's td_init failed\n");
175
return false;
176
}
177
#endif // __APPLE__
178
return true;
179
}
180
181
void destroy_lib_info(struct ps_prochandle* ph) {
182
lib_info* lib = ph->libs;
183
while (lib) {
184
lib_info* next = lib->next;
185
if (lib->symtab) {
186
destroy_symtab(lib->symtab);
187
}
188
free(lib);
189
lib = next;
190
}
191
}
192
193
void destroy_thread_info(struct ps_prochandle* ph) {
194
sa_thread_info* thr = ph->threads;
195
while (thr) {
196
sa_thread_info* n = thr->next;
197
free(thr);
198
thr = n;
199
}
200
}
201
202
// ps_prochandle cleanup
203
void Prelease(struct ps_prochandle* ph) {
204
// do the "derived class" clean-up first
205
ph->ops->release(ph);
206
destroy_lib_info(ph);
207
destroy_thread_info(ph);
208
free(ph);
209
}
210
211
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
212
return add_lib_info_fd(ph, libname, -1, base);
213
}
214
215
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
216
lib_info* newlib;
217
print_debug("add_lib_info_fd %s\n", libname);
218
219
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
220
print_debug("can't allocate memory for lib_info\n");
221
return NULL;
222
}
223
224
if (strlen(libname) >= sizeof(newlib->name)) {
225
print_debug("libname %s too long\n", libname);
226
free(newlib);
227
return NULL;
228
}
229
strcpy(newlib->name, libname);
230
231
newlib->base = base;
232
233
if (fd == -1) {
234
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
235
print_debug("can't open shared object %s\n", newlib->name);
236
free(newlib);
237
return NULL;
238
}
239
} else {
240
newlib->fd = fd;
241
}
242
243
#ifdef __APPLE__
244
// check whether we have got an Macho file.
245
if (is_macho_file(newlib->fd) == false) {
246
close(newlib->fd);
247
free(newlib);
248
print_debug("not a mach-o file\n");
249
return NULL;
250
}
251
#else
252
// check whether we have got an ELF file. /proc/<pid>/map
253
// gives out all file mappings and not just shared objects
254
if (is_elf_file(newlib->fd) == false) {
255
close(newlib->fd);
256
free(newlib);
257
return NULL;
258
}
259
#endif // __APPLE__
260
261
newlib->symtab = build_symtab(newlib->fd, &newlib->memsz);
262
if (newlib->symtab == NULL) {
263
print_debug("symbol table build failed for %s\n", newlib->name);
264
} else {
265
print_debug("built symbol table for 0x%lx memsz=0x%lx %s\n", newlib, newlib->memsz, newlib->name);
266
}
267
268
// even if symbol table building fails, we add the lib_info.
269
// This is because we may need to read from the ELF file or MachO file for core file
270
// address read functionality. lookup_symbol checks for NULL symtab.
271
if (ph->libs) {
272
ph->lib_tail->next = newlib;
273
ph->lib_tail = newlib;
274
} else {
275
ph->libs = ph->lib_tail = newlib;
276
}
277
ph->num_libs++;
278
return newlib;
279
}
280
281
// lookup for a specific symbol
282
uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
283
const char* sym_name) {
284
// ignore object_name. search in all libraries
285
// FIXME: what should we do with object_name?? The library names are obtained
286
// by parsing /proc/<pid>/maps, which may not be the same as object_name.
287
// What we need is a utility to map object_name to real file name, something
288
// dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
289
// now, we just ignore object_name and do a global search for the symbol.
290
291
lib_info* lib = ph->libs;
292
while (lib) {
293
if (lib->symtab) {
294
uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
295
if (res) return res;
296
}
297
lib = lib->next;
298
}
299
300
print_debug("lookup failed for symbol '%s' in obj '%s'\n",
301
sym_name, object_name);
302
return (uintptr_t) NULL;
303
}
304
305
const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
306
const char* res = NULL;
307
lib_info* lib = ph->libs;
308
print_debug("symbol_for_pc: addr 0x%lx\n", addr);
309
while (lib) {
310
print_debug("symbol_for_pc: checking lib 0x%lx 0x%lx %s\n", lib->base, lib->memsz, lib->name);
311
if (lib->symtab && addr >= lib->base && addr < lib->base + lib->memsz) {
312
print_debug("symbol_for_pc: address=0x%lx offset=0x%lx found inside lib base=0x%lx memsz=0x%lx %s\n",
313
addr, addr - lib->base, lib->base, lib->memsz, lib->name);
314
res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
315
if (res) return res;
316
}
317
lib = lib->next;
318
}
319
return NULL;
320
}
321
322
// add a thread to ps_prochandle
323
sa_thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwpid_t lwp_id) {
324
sa_thread_info* newthr;
325
if ( (newthr = (sa_thread_info*) calloc(1, sizeof(sa_thread_info))) == NULL) {
326
print_debug("can't allocate memory for thread_info\n");
327
return NULL;
328
}
329
330
// initialize thread info
331
newthr->pthread_id = pthread_id;
332
newthr->lwp_id = lwp_id;
333
334
// add new thread to the list
335
newthr->next = ph->threads;
336
ph->threads = newthr;
337
ph->num_threads++;
338
return newthr;
339
}
340
341
#ifndef __APPLE__
342
// struct used for client data from thread_db callback
343
struct thread_db_client_data {
344
struct ps_prochandle* ph;
345
thread_info_callback callback;
346
};
347
348
// callback function for libthread_db
349
static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
350
struct thread_db_client_data* ptr = (struct thread_db_client_data*) data;
351
td_thrinfo_t ti;
352
td_err_e err;
353
354
memset(&ti, 0, sizeof(ti));
355
err = td_thr_get_info(th_p, &ti);
356
if (err != TD_OK) {
357
print_debug("libthread_db : td_thr_get_info failed, can't get thread info\n");
358
return err;
359
}
360
361
print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
362
363
if (ptr->callback(ptr->ph, (pthread_t)ti.ti_tid, ti.ti_lid) != true)
364
return TD_ERR;
365
366
return TD_OK;
367
}
368
369
// read thread_info using libthread_db
370
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb) {
371
struct thread_db_client_data mydata;
372
td_thragent_t* thread_agent = NULL;
373
if (td_ta_new(ph, &thread_agent) != TD_OK) {
374
print_debug("can't create libthread_db agent\n");
375
return false;
376
}
377
378
mydata.ph = ph;
379
mydata.callback = cb;
380
381
// we use libthread_db iterator to iterate thru list of threads.
382
if (td_ta_thr_iter(thread_agent, thread_db_callback, &mydata,
383
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
384
TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS) != TD_OK) {
385
td_ta_delete(thread_agent);
386
return false;
387
}
388
389
// delete thread agent
390
td_ta_delete(thread_agent);
391
return true;
392
}
393
394
#endif // __APPLE__
395
396
// get number of threads
397
int get_num_threads(struct ps_prochandle* ph) {
398
return ph->num_threads;
399
}
400
401
// get lwp_id of n'th thread
402
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
403
int count = 0;
404
sa_thread_info* thr = ph->threads;
405
while (thr) {
406
if (count == index) {
407
return thr->lwp_id;
408
}
409
count++;
410
thr = thr->next;
411
}
412
return 0;
413
}
414
415
#ifdef __APPLE__
416
// set lwp_id of n'th thread
417
bool set_lwp_id(struct ps_prochandle* ph, int index, lwpid_t lwpid) {
418
int count = 0;
419
sa_thread_info* thr = ph->threads;
420
while (thr) {
421
if (count == index) {
422
thr->lwp_id = lwpid;
423
return true;
424
}
425
count++;
426
thr = thr->next;
427
}
428
return false;
429
}
430
431
// get regs of n-th thread, only used in fillThreads the first time called
432
bool get_nth_lwp_regs(struct ps_prochandle* ph, int index, struct reg* regs) {
433
int count = 0;
434
sa_thread_info* thr = ph->threads;
435
while (thr) {
436
if (count == index) {
437
break;
438
}
439
count++;
440
thr = thr->next;
441
}
442
if (thr != NULL) {
443
memcpy(regs, &thr->regs, sizeof(struct reg));
444
return true;
445
}
446
return false;
447
}
448
449
#endif // __APPLE__
450
451
// get regs for a given lwp
452
bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct reg* regs) {
453
return ph->ops->get_lwp_regs(ph, lwp_id, regs);
454
}
455
456
// get number of shared objects
457
int get_num_libs(struct ps_prochandle* ph) {
458
return ph->num_libs;
459
}
460
461
// get name of n'th solib
462
const char* get_lib_name(struct ps_prochandle* ph, int index) {
463
int count = 0;
464
lib_info* lib = ph->libs;
465
while (lib) {
466
if (count == index) {
467
return lib->name;
468
}
469
count++;
470
lib = lib->next;
471
}
472
return NULL;
473
}
474
475
// get base address of a lib
476
uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
477
int count = 0;
478
lib_info* lib = ph->libs;
479
while (lib) {
480
if (count == index) {
481
return lib->base;
482
}
483
count++;
484
lib = lib->next;
485
}
486
return (uintptr_t)NULL;
487
}
488
489
// get address range of lib
490
void get_lib_addr_range(struct ps_prochandle* ph, int index, uintptr_t* base, uintptr_t* memsz) {
491
int count = 0;
492
lib_info* lib = ph->libs;
493
while (lib) {
494
if (count == index) {
495
*base = lib->base;
496
*memsz = lib->memsz;
497
return;
498
}
499
count++;
500
lib = lib->next;
501
}
502
}
503
504
bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
505
lib_info *p = ph->libs;
506
while (p) {
507
if (strcmp(p->name, lib_name) == 0) {
508
return true;
509
}
510
p = p->next;
511
}
512
return false;
513
}
514
515
//--------------------------------------------------------------------------
516
// proc service functions
517
518
// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
519
// of the load object object_name in the target process identified by ph.
520
// It returns the symbol's value as an address in the target process in
521
// *sym_addr.
522
523
ps_err_e ps_pglobal_lookup(struct ps_prochandle *ph, const char *object_name,
524
const char *sym_name, psaddr_t *sym_addr) {
525
*sym_addr = (psaddr_t) lookup_symbol(ph, object_name, sym_name);
526
return (*sym_addr ? PS_OK : PS_NOSYM);
527
}
528
529
// read "size" bytes info "buf" from address "addr"
530
ps_err_e ps_pread(struct ps_prochandle *ph, psaddr_t addr,
531
void *buf, size_t size) {
532
return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR;
533
}
534
535
// write "size" bytes of data to debuggee at address "addr"
536
ps_err_e ps_pwrite(struct ps_prochandle *ph, psaddr_t addr,
537
const void *buf, size_t size) {
538
return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR;
539
}
540
541
// fill in ptrace_lwpinfo for lid
542
ps_err_e ps_linfo(struct ps_prochandle *ph, lwpid_t lwp_id, void *linfo) {
543
return ph->ops->get_lwp_info(ph, lwp_id, linfo)? PS_OK: PS_ERR;
544
}
545
546
// needed for when libthread_db is compiled with TD_DEBUG defined
547
void
548
ps_plog (const char *format, ...)
549
{
550
va_list alist;
551
552
va_start(alist, format);
553
vfprintf(stderr, format, alist);
554
va_end(alist);
555
}
556
557
#ifndef __APPLE__
558
// ------------------------------------------------------------------------
559
// Functions below this point are not yet implemented. They are here only
560
// to make the linker happy.
561
562
ps_err_e ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) {
563
print_debug("ps_lsetfpregs not implemented\n");
564
return PS_OK;
565
}
566
567
ps_err_e ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) {
568
print_debug("ps_lsetregs not implemented\n");
569
return PS_OK;
570
}
571
572
ps_err_e ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) {
573
print_debug("ps_lgetfpregs not implemented\n");
574
return PS_OK;
575
}
576
577
ps_err_e ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
578
print_debug("ps_lgetfpregs not implemented\n");
579
return PS_OK;
580
}
581
582
ps_err_e ps_lstop(struct ps_prochandle *ph, lwpid_t lid) {
583
print_debug("ps_lstop not implemented\n");
584
return PS_OK;
585
}
586
587
ps_err_e ps_pcontinue(struct ps_prochandle *ph) {
588
print_debug("ps_pcontinue not implemented\n");
589
return PS_OK;
590
}
591
#endif // __APPLE__
592
593