Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c
41152 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 <stdarg.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <fcntl.h>
29
#include <sys/procfs.h>
30
#include "libproc_impl.h"
31
#include "proc_service.h"
32
#include "salibelf.h"
33
34
#define SA_ALTROOT "SA_ALTROOT"
35
36
int pathmap_open(const char* name) {
37
static const char *alt_root = NULL;
38
static int alt_root_initialized = 0;
39
40
int fd;
41
char alt_path[PATH_MAX + 1], *alt_path_end;
42
const char *s;
43
int free_space;
44
45
if (!alt_root_initialized) {
46
alt_root_initialized = -1;
47
alt_root = getenv(SA_ALTROOT);
48
}
49
50
if (alt_root == NULL) {
51
return open(name, O_RDONLY);
52
}
53
54
55
if (strlen(alt_root) + strlen(name) > PATH_MAX) {
56
// Buffer too small.
57
return -1;
58
}
59
60
strncpy(alt_path, alt_root, PATH_MAX);
61
alt_path[PATH_MAX] = '\0';
62
alt_path_end = alt_path + strlen(alt_path);
63
free_space = PATH_MAX + 1 - (alt_path_end-alt_path);
64
65
// Strip path items one by one and try to open file with alt_root prepended.
66
s = name;
67
while (1) {
68
strncat(alt_path, s, free_space);
69
s += 1; // Skip /.
70
71
fd = open(alt_path, O_RDONLY);
72
if (fd >= 0) {
73
print_debug("path %s substituted for %s\n", alt_path, name);
74
return fd;
75
}
76
77
// Linker always put full path to solib to process, so we can rely
78
// on presence of /. If slash is not present, it means, that SOlib doesn't
79
// physically exist (e.g. linux-gate.so) and we fail opening it anyway
80
if ((s = strchr(s, '/')) == NULL) {
81
break;
82
}
83
84
// Cut off what we appended above.
85
*alt_path_end = '\0';
86
}
87
88
return -1;
89
}
90
91
static bool _libsaproc_debug;
92
93
void print_debug(const char* format,...) {
94
if (_libsaproc_debug) {
95
va_list alist;
96
97
va_start(alist, format);
98
fputs("libsaproc DEBUG: ", stderr);
99
vfprintf(stderr, format, alist);
100
va_end(alist);
101
}
102
}
103
104
void print_error(const char* format,...) {
105
va_list alist;
106
va_start(alist, format);
107
fputs("ERROR: ", stderr);
108
vfprintf(stderr, format, alist);
109
va_end(alist);
110
}
111
112
bool is_debug() {
113
return _libsaproc_debug;
114
}
115
116
// initialize libproc
117
JNIEXPORT bool JNICALL
118
init_libproc(bool debug) {
119
// init debug mode
120
_libsaproc_debug = debug;
121
return true;
122
}
123
124
static void destroy_lib_info(struct ps_prochandle* ph) {
125
lib_info* lib = ph->libs;
126
while (lib) {
127
lib_info *next = lib->next;
128
if (lib->symtab) {
129
destroy_symtab(lib->symtab);
130
}
131
free(lib->eh_frame.data);
132
free(lib);
133
lib = next;
134
}
135
}
136
137
static void destroy_thread_info(struct ps_prochandle* ph) {
138
thread_info* thr = ph->threads;
139
while (thr) {
140
thread_info *next = thr->next;
141
free(thr);
142
thr = next;
143
}
144
}
145
146
// ps_prochandle cleanup
147
148
// ps_prochandle cleanup
149
JNIEXPORT void JNICALL
150
Prelease(struct ps_prochandle* ph) {
151
// do the "derived class" clean-up first
152
ph->ops->release(ph);
153
destroy_lib_info(ph);
154
destroy_thread_info(ph);
155
free(ph);
156
}
157
158
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base) {
159
return add_lib_info_fd(ph, libname, -1, base);
160
}
161
162
static inline uintptr_t align_down(uintptr_t ptr, size_t page_size) {
163
return (ptr & ~(page_size - 1));
164
}
165
166
static inline uintptr_t align_up(uintptr_t ptr, size_t page_size) {
167
return ((ptr + page_size - 1) & ~(page_size - 1));
168
}
169
170
static bool fill_addr_info(lib_info* lib) {
171
off_t current_pos;
172
ELF_EHDR ehdr;
173
ELF_PHDR* phbuf = NULL;
174
ELF_PHDR* ph = NULL;
175
int cnt;
176
177
current_pos = lseek(lib->fd, (off_t)0L, SEEK_CUR);
178
lseek(lib->fd, (off_t)0L, SEEK_SET);
179
read_elf_header(lib->fd, &ehdr);
180
if ((phbuf = read_program_header_table(lib->fd, &ehdr)) == NULL) {
181
lseek(lib->fd, current_pos, SEEK_SET);
182
return false;
183
}
184
185
lib->end = (uintptr_t)-1L;
186
lib->exec_start = (uintptr_t)-1L;
187
lib->exec_end = (uintptr_t)-1L;
188
for (ph = phbuf, cnt = 0; cnt < ehdr.e_phnum; cnt++, ph++) {
189
if (ph->p_type == PT_LOAD) {
190
uintptr_t unaligned_start = lib->base + ph->p_vaddr;
191
uintptr_t aligned_start = align_down(unaligned_start, ph->p_align);
192
uintptr_t aligned_end = align_up(unaligned_start + ph->p_memsz, ph->p_align);
193
if ((lib->end == (uintptr_t)-1L) || (lib->end < aligned_end)) {
194
lib->end = aligned_end;
195
}
196
print_debug("%s [%d] 0x%lx-0x%lx: base = 0x%lx, "
197
"vaddr = 0x%lx, memsz = 0x%lx, filesz = 0x%lx\n",
198
lib->name, cnt, aligned_start, aligned_end, lib->base,
199
ph->p_vaddr, ph->p_memsz, ph->p_filesz);
200
if (ph->p_flags & PF_X) {
201
if ((lib->exec_start == -1L) || (lib->exec_start > aligned_start)) {
202
lib->exec_start = aligned_start;
203
}
204
if ((lib->exec_end == (uintptr_t)-1L) || (lib->exec_end < aligned_end)) {
205
lib->exec_end = aligned_end;
206
}
207
}
208
}
209
}
210
211
free(phbuf);
212
lseek(lib->fd, current_pos, SEEK_SET);
213
214
return (lib->end != -1L) && (lib->exec_start != -1L) && (lib->exec_end != -1L);
215
}
216
217
bool read_eh_frame(struct ps_prochandle* ph, lib_info* lib) {
218
off_t current_pos = -1;
219
ELF_EHDR ehdr;
220
ELF_SHDR* shbuf = NULL;
221
ELF_SHDR* sh = NULL;
222
char* strtab = NULL;
223
void* result = NULL;
224
int cnt;
225
226
current_pos = lseek(lib->fd, (off_t)0L, SEEK_CUR);
227
lseek(lib->fd, (off_t)0L, SEEK_SET);
228
229
read_elf_header(lib->fd, &ehdr);
230
shbuf = read_section_header_table(lib->fd, &ehdr);
231
strtab = read_section_data(lib->fd, &ehdr, &shbuf[ehdr.e_shstrndx]);
232
233
for (cnt = 0, sh = shbuf; cnt < ehdr.e_shnum; cnt++, sh++) {
234
if (strcmp(".eh_frame", sh->sh_name + strtab) == 0) {
235
lib->eh_frame.library_base_addr = lib->base;
236
lib->eh_frame.v_addr = sh->sh_addr;
237
lib->eh_frame.data = read_section_data(lib->fd, &ehdr, sh);
238
lib->eh_frame.size = sh->sh_size;
239
break;
240
}
241
}
242
243
free(strtab);
244
free(shbuf);
245
lseek(lib->fd, current_pos, SEEK_SET);
246
return lib->eh_frame.data != NULL;
247
}
248
249
lib_info* add_lib_info_fd(struct ps_prochandle* ph, const char* libname, int fd, uintptr_t base) {
250
lib_info* newlib;
251
252
if ( (newlib = (lib_info*) calloc(1, sizeof(struct lib_info))) == NULL) {
253
print_debug("can't allocate memory for lib_info\n");
254
return NULL;
255
}
256
257
if (strlen(libname) >= sizeof(newlib->name)) {
258
print_debug("libname %s too long\n", libname);
259
free(newlib);
260
return NULL;
261
}
262
strcpy(newlib->name, libname);
263
264
newlib->base = base;
265
266
if (fd == -1) {
267
if ( (newlib->fd = pathmap_open(newlib->name)) < 0) {
268
print_debug("can't open shared object %s\n", newlib->name);
269
free(newlib);
270
return NULL;
271
}
272
} else {
273
newlib->fd = fd;
274
}
275
276
// check whether we have got an ELF file. /proc/<pid>/map
277
// gives out all file mappings and not just shared objects
278
if (is_elf_file(newlib->fd) == false) {
279
close(newlib->fd);
280
free(newlib);
281
return NULL;
282
}
283
284
newlib->symtab = build_symtab(newlib->fd, libname);
285
if (newlib->symtab == NULL) {
286
print_debug("symbol table build failed for %s\n", newlib->name);
287
}
288
289
if (fill_addr_info(newlib)) {
290
if (!read_eh_frame(ph, newlib)) {
291
print_debug("Could not find .eh_frame section in %s\n", newlib->name);
292
}
293
} else {
294
print_debug("Could not find executable section in %s\n", newlib->name);
295
}
296
297
// even if symbol table building fails, we add the lib_info.
298
// This is because we may need to read from the ELF file for core file
299
// address read functionality. lookup_symbol checks for NULL symtab.
300
if (ph->libs) {
301
ph->lib_tail->next = newlib;
302
ph->lib_tail = newlib;
303
} else {
304
ph->libs = ph->lib_tail = newlib;
305
}
306
ph->num_libs++;
307
308
return newlib;
309
}
310
311
// lookup for a specific symbol
312
uintptr_t lookup_symbol(struct ps_prochandle* ph, const char* object_name,
313
const char* sym_name) {
314
// ignore object_name. search in all libraries
315
// FIXME: what should we do with object_name?? The library names are obtained
316
// by parsing /proc/<pid>/maps, which may not be the same as object_name.
317
// What we need is a utility to map object_name to real file name, something
318
// dlopen() does by looking at LD_LIBRARY_PATH and /etc/ld.so.cache. For
319
// now, we just ignore object_name and do a global search for the symbol.
320
321
lib_info* lib = ph->libs;
322
while (lib) {
323
if (lib->symtab) {
324
uintptr_t res = search_symbol(lib->symtab, lib->base, sym_name, NULL);
325
if (res) return res;
326
}
327
lib = lib->next;
328
}
329
330
print_debug("lookup failed for symbol '%s' in obj '%s'\n",
331
sym_name, object_name);
332
return (uintptr_t) NULL;
333
}
334
335
336
const char* symbol_for_pc(struct ps_prochandle* ph, uintptr_t addr, uintptr_t* poffset) {
337
const char* res = NULL;
338
lib_info* lib = ph->libs;
339
while (lib) {
340
if (lib->symtab && addr >= lib->base) {
341
res = nearest_symbol(lib->symtab, addr - lib->base, poffset);
342
if (res) return res;
343
}
344
lib = lib->next;
345
}
346
return NULL;
347
}
348
349
// add a thread to ps_prochandle
350
thread_info* add_thread_info(struct ps_prochandle* ph, lwpid_t lwp_id) {
351
thread_info* newthr;
352
if ( (newthr = (thread_info*) calloc(1, sizeof(thread_info))) == NULL) {
353
print_debug("can't allocate memory for thread_info\n");
354
return NULL;
355
}
356
357
// initialize thread info
358
newthr->lwp_id = lwp_id;
359
360
// add new thread to the list
361
newthr->next = ph->threads;
362
ph->threads = newthr;
363
ph->num_threads++;
364
return newthr;
365
}
366
367
void delete_thread_info(struct ps_prochandle* ph, thread_info* thr_to_be_removed) {
368
thread_info* current_thr = ph->threads;
369
370
if (thr_to_be_removed == ph->threads) {
371
ph->threads = ph->threads->next;
372
} else {
373
thread_info* previous_thr = NULL;
374
while (current_thr && current_thr != thr_to_be_removed) {
375
previous_thr = current_thr;
376
current_thr = current_thr->next;
377
}
378
if (current_thr == NULL) {
379
print_error("Could not find the thread to be removed");
380
return;
381
}
382
previous_thr->next = current_thr->next;
383
}
384
ph->num_threads--;
385
free(current_thr);
386
}
387
388
// get number of threads
389
int get_num_threads(struct ps_prochandle* ph) {
390
return ph->num_threads;
391
}
392
393
// get lwp_id of n'th thread
394
lwpid_t get_lwp_id(struct ps_prochandle* ph, int index) {
395
int count = 0;
396
thread_info* thr = ph->threads;
397
while (thr) {
398
if (count == index) {
399
return thr->lwp_id;
400
}
401
count++;
402
thr = thr->next;
403
}
404
return -1;
405
}
406
407
// get regs for a given lwp
408
bool get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id, struct user_regs_struct* regs) {
409
return ph->ops->get_lwp_regs(ph, lwp_id, regs);
410
}
411
412
// get number of shared objects
413
int get_num_libs(struct ps_prochandle* ph) {
414
return ph->num_libs;
415
}
416
417
// get name of n'th solib
418
const char* get_lib_name(struct ps_prochandle* ph, int index) {
419
int count = 0;
420
lib_info* lib = ph->libs;
421
while (lib) {
422
if (count == index) {
423
return lib->name;
424
}
425
count++;
426
lib = lib->next;
427
}
428
return NULL;
429
}
430
431
// get base address of a lib
432
uintptr_t get_lib_base(struct ps_prochandle* ph, int index) {
433
int count = 0;
434
lib_info* lib = ph->libs;
435
while (lib) {
436
if (count == index) {
437
return lib->base;
438
}
439
count++;
440
lib = lib->next;
441
}
442
return (uintptr_t)NULL;
443
}
444
445
// get address range of lib
446
void get_lib_addr_range(struct ps_prochandle* ph, int index, uintptr_t* base, uintptr_t* memsz) {
447
int count = 0;
448
lib_info* lib = ph->libs;
449
while (lib) {
450
if (count == index) {
451
*base = lib->base;
452
*memsz = lib->end - lib->base;
453
return;
454
}
455
count++;
456
lib = lib->next;
457
}
458
}
459
460
bool find_lib(struct ps_prochandle* ph, const char *lib_name) {
461
lib_info *p = ph->libs;
462
while (p) {
463
if (strcmp(p->name, lib_name) == 0) {
464
return true;
465
}
466
p = p->next;
467
}
468
return false;
469
}
470
471
struct lib_info *find_lib_by_address(struct ps_prochandle* ph, uintptr_t pc) {
472
lib_info *p = ph->libs;
473
while (p) {
474
if ((p->exec_start <= pc) && (pc < p->exec_end)) {
475
return p;
476
}
477
p = p->next;
478
}
479
return NULL;
480
}
481
482
//--------------------------------------------------------------------------
483
// proc service functions
484
485
// get process id
486
JNIEXPORT pid_t JNICALL
487
ps_getpid(struct ps_prochandle *ph) {
488
return ph->pid;
489
}
490
491
// ps_pglobal_lookup() looks up the symbol sym_name in the symbol table
492
// of the load object object_name in the target process identified by ph.
493
// It returns the symbol's value as an address in the target process in
494
// *sym_addr.
495
496
JNIEXPORT ps_err_e JNICALL
497
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
JNIEXPORT ps_err_e JNICALL
505
ps_pdread(struct ps_prochandle *ph, psaddr_t addr,
506
void *buf, size_t size) {
507
return ph->ops->p_pread(ph, (uintptr_t) addr, buf, size)? PS_OK: PS_ERR;
508
}
509
510
// write "size" bytes of data to debuggee at address "addr"
511
JNIEXPORT ps_err_e JNICALL
512
ps_pdwrite(struct ps_prochandle *ph, psaddr_t addr,
513
const void *buf, size_t size) {
514
return ph->ops->p_pwrite(ph, (uintptr_t)addr, buf, size)? PS_OK: PS_ERR;
515
}
516
517
// ------------------------------------------------------------------------
518
// Functions below this point are not yet implemented. They are here only
519
// to make the linker happy.
520
521
JNIEXPORT ps_err_e JNICALL
522
ps_lsetfpregs(struct ps_prochandle *ph, lwpid_t lid, const prfpregset_t *fpregs) {
523
print_debug("ps_lsetfpregs not implemented\n");
524
return PS_OK;
525
}
526
527
JNIEXPORT ps_err_e JNICALL
528
ps_lsetregs(struct ps_prochandle *ph, lwpid_t lid, const prgregset_t gregset) {
529
print_debug("ps_lsetregs not implemented\n");
530
return PS_OK;
531
}
532
533
JNIEXPORT ps_err_e JNICALL
534
ps_lgetfpregs(struct ps_prochandle *ph, lwpid_t lid, prfpregset_t *fpregs) {
535
print_debug("ps_lgetfpregs not implemented\n");
536
return PS_OK;
537
}
538
539
JNIEXPORT ps_err_e JNICALL
540
ps_lgetregs(struct ps_prochandle *ph, lwpid_t lid, prgregset_t gregset) {
541
print_debug("ps_lgetfpregs not implemented\n");
542
return PS_OK;
543
}
544
545