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