Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/dbgext/j9dbgext.c
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <stdarg.h>
27
28
#include "j9dbgext.h"
29
30
#include "j9consts.h"
31
#include "j9cp.h"
32
#include "j9port.h"
33
#include "stackwalk.h"
34
#include "util_api.h"
35
36
37
/* Note: must be 8-aligned */
38
typedef struct dbgNode {
39
struct dbgNode * link;
40
void * originalAddress;
41
void * allocatedAddress;
42
UDATA size;
43
UDATA relocated;
44
} dbgNode;
45
46
dbgNode * memoryList = NULL;
47
48
#ifdef J9VM_ENV_DATA64
49
static struct {
50
J9PortVmemIdentifier vmemIdentifier;
51
UDATA size;
52
void* basePointer;
53
void* currentPointer;
54
void* commitPointer;
55
} smallDbgAddressSpace;
56
#endif
57
58
J9JavaVM* cachedVM = NULL;
59
60
/* old file_write function */
61
static IDATA (*old_write)(OMRPortLibrary *portLibrary, IDATA fd, const void * buf, IDATA nbytes);
62
63
/* error handler */
64
static DBG_JMPBUF * dbgErrorHandler;
65
66
/* verbose mode */
67
static int dbgVerboseMode = 1;
68
69
static int testJavaVMPtr (J9JavaVM* ptr);
70
static IDATA dbg_write (OMRPortLibrary *portLibrary, IDATA fd, const void * buf, IDATA nbytes);
71
#if defined(J9ZOS390)
72
static IDATA dbg_write_text (OMRPortLibrary *portLibrary, IDATA fd, const char * buf, IDATA nbytes);
73
#endif
74
75
static IDATA hexValue(char c);
76
77
#define LOCAL_MEMORY_ALIGNMENT 16
78
79
void *
80
dbgMalloc(UDATA size, void *originalAddress)
81
{
82
PORT_ACCESS_FROM_PORT(dbgGetPortLibrary());
83
dbgNode * node;
84
void * allocatedAddress;
85
86
#ifdef J9VM_ENV_DATA64
87
/* On 64 bit platforms, use a simple allocation scheme which keeps all pointers within 2GB of each other.
88
* This guarantees that SRP relocations between two allocated blocks will always be valid.
89
* See CMVC defect 94818
90
*/
91
92
/* initialize the memory region */
93
if (smallDbgAddressSpace.basePointer == NULL) {
94
UDATA pageSize = j9vmem_supported_page_sizes()[0];
95
96
if (smallDbgAddressSpace.size == 0) {
97
char envBuf[16];
98
99
/* use a default of 1G, since 2G is too much for most ZOs users to be able to allocate
100
* (see CMVC 122069) */
101
smallDbgAddressSpace.size = (U_64)1 * 1024 * 1024 * 1024;
102
103
if (0 == j9sysinfo_get_env("J9DBGEXT_SCRATCH_SIZE", envBuf, sizeof(envBuf))) {
104
if (strlen(envBuf) > 0) {
105
smallDbgAddressSpace.size = (U_64)atol(envBuf) * 1024 * 1024;
106
dbgPrint("\nEnvironment variable J9DBGEXT_SCRATCH_SIZE set, requested size is %zu MB\n", smallDbgAddressSpace.size / (1024 * 1024));
107
}
108
}
109
} else if (smallDbgAddressSpace.size == (UDATA)-1) {
110
return NULL;
111
}
112
113
smallDbgAddressSpace.basePointer = j9vmem_reserve_memory(
114
NULL,
115
smallDbgAddressSpace.size,
116
&smallDbgAddressSpace.vmemIdentifier,
117
J9PORT_VMEM_MEMORY_MODE_READ | J9PORT_VMEM_MEMORY_MODE_WRITE,
118
pageSize,
119
OMRMEM_CATEGORY_VM);
120
if (smallDbgAddressSpace.basePointer == NULL) {
121
dbgError("\nError: Unable to allocate debug scratch space (%zu MB).\n"
122
"Try setting the J9DBGEXT_SCRATCH_SIZE environment variable to a smaller value.\n",
123
smallDbgAddressSpace.size / (1024 * 1024));
124
smallDbgAddressSpace.size = (UDATA)-1;
125
/* This is fatal, any further dbgMalloc() calls would fail, so just exit */
126
exit(1);
127
}
128
smallDbgAddressSpace.currentPointer = smallDbgAddressSpace.commitPointer = smallDbgAddressSpace.basePointer ;
129
}
130
131
/* check for overflow */
132
if ( ( size > smallDbgAddressSpace.size - (sizeof(dbgNode) + LOCAL_MEMORY_ALIGNMENT) ) ||
133
((void *)((U_8*)smallDbgAddressSpace.basePointer + smallDbgAddressSpace.size - (size + sizeof(dbgNode))) < smallDbgAddressSpace.currentPointer ) )
134
{
135
if (dbgVerboseMode) {
136
dbgPrint(
137
"Unable to allocate requested %zu bytes in debug scratch space (%zu MB).\n",
138
size + + LOCAL_MEMORY_ALIGNMENT + sizeof(dbgNode),
139
smallDbgAddressSpace.size / (1024 * 1024));
140
}
141
return NULL;
142
}
143
144
/* allocate and round up for alignment */
145
allocatedAddress = smallDbgAddressSpace.currentPointer;
146
smallDbgAddressSpace.currentPointer = (void*)(((UDATA)allocatedAddress + size + LOCAL_MEMORY_ALIGNMENT + sizeof(dbgNode) + sizeof(U_64) - 1) & ~(sizeof(U_64) - 1));
147
148
/* commit the allocated memory */
149
while (smallDbgAddressSpace.commitPointer < smallDbgAddressSpace.currentPointer) {
150
UDATA pageSize = j9vmem_supported_page_sizes()[0];
151
152
if (NULL == j9vmem_commit_memory(smallDbgAddressSpace.commitPointer, pageSize, &smallDbgAddressSpace.vmemIdentifier)) {
153
return NULL;
154
}
155
smallDbgAddressSpace.commitPointer = (U_8*)smallDbgAddressSpace.commitPointer + pageSize;
156
}
157
158
#else
159
allocatedAddress = j9mem_allocate_memory(size + LOCAL_MEMORY_ALIGNMENT + sizeof(dbgNode), OMRMEM_CATEGORY_VM);
160
if (allocatedAddress == NULL) {
161
return NULL;
162
}
163
#endif
164
165
node = allocatedAddress;
166
while (((UDATA)(node + 1) & (UDATA)(LOCAL_MEMORY_ALIGNMENT - 1)) != 0) {
167
node = (dbgNode *) ((UDATA *) node + 1);
168
}
169
node->originalAddress = originalAddress;
170
node->allocatedAddress = allocatedAddress;
171
node->size = size;
172
node->link = memoryList;
173
node->relocated = 0;
174
175
memoryList = node;
176
177
return node + 1;
178
}
179
180
void
181
dbgFree(void * addr)
182
{
183
PORT_ACCESS_FROM_PORT(dbgGetPortLibrary());
184
dbgNode * node = ((dbgNode *) addr) - 1;
185
186
if (memoryList == node) {
187
memoryList = node->link;
188
#ifndef J9VM_ENV_DATA64
189
j9mem_free_memory(node->allocatedAddress);
190
#endif
191
} else {
192
dbgNode * current = memoryList;
193
194
while (current) {
195
dbgNode * next = current->link;
196
197
if (next == node) {
198
current->link = node->link;
199
#ifndef J9VM_ENV_DATA64
200
j9mem_free_memory(node->allocatedAddress);
201
#endif
202
break;
203
}
204
current = next;
205
}
206
}
207
208
#ifdef J9VM_ENV_DATA64
209
if (memoryList == NULL) {
210
smallDbgAddressSpace.currentPointer = smallDbgAddressSpace.basePointer ;
211
}
212
#endif
213
}
214
215
void *
216
dbgLocalToTarget(void * addr)
217
{
218
dbgNode * current = memoryList;
219
220
if (addr == NULL) return NULL;
221
222
while (current) {
223
U_8 * lowAddr = (U_8 *) (current + 1);
224
U_8 * highAddr = lowAddr + current->size;
225
226
if (((U_8 *)addr >= lowAddr) && ((U_8 *)addr < highAddr))
227
return ((U_8*) addr) - lowAddr + ((U_8*) (current->originalAddress));
228
229
current = current->link;
230
}
231
232
dbgError("Local memory %p has no mapping to target memory\n", addr);
233
return NULL;
234
}
235
236
237
238
void *
239
dbgTargetToLocal(void * addr)
240
{
241
return dbgTargetToLocalWithSize(addr, 0);
242
}
243
244
/*
245
* Returns a program space pointer to the J9JavaVM.
246
*/
247
J9JavaVM*
248
dbgSniffForJavaVM(void)
249
{
250
U_8* startFrom = NULL;
251
UDATA bytesRead;
252
UDATA totalBytesSearched = 0;
253
U_8* eyecatcher;
254
255
if (cachedVM) {
256
return cachedVM;
257
}
258
259
dbgPrint("Searching for J9JavaVM...\n");
260
261
while (NULL != (eyecatcher = dbgFindPattern((U_8*)"J9VMRAS", sizeof("J9VMRAS"), 8, startFrom, &bytesRead))) {
262
J9RAS ras;
263
totalBytesSearched += bytesRead;
264
265
dbgReadMemory((UDATA)eyecatcher, &ras, sizeof(ras), &bytesRead);
266
if (bytesRead == sizeof(ras)) {
267
if (ras.bitpattern1 == 0xaa55aa55 && ras.bitpattern2 == 0xaa55aa55) {
268
cachedVM = (J9JavaVM *) ras.vm;
269
dbgPrint("Found eyecatcher -- VM set to !setvm 0x%p\n", cachedVM);
270
return cachedVM;
271
}
272
}
273
274
/* this isn't it -- look for the next occurrence */
275
startFrom = eyecatcher + 8;
276
}
277
totalBytesSearched += bytesRead;
278
279
if (totalBytesSearched == 0) {
280
/*
281
* The debugger didn't even try -- probably because it's a 64 bit platform and doesn't know how
282
* to find out which memory has been mapped. Try again with a more heavyweight API, but only
283
* in the low 4GB.
284
*/
285
UDATA bytesToSearch = 0xFFFFFFFF;
286
287
startFrom = NULL;
288
289
while (NULL != (eyecatcher = dbgFindPatternInRange((U_8*)"J9VMRAS", sizeof("J9VMRAS"), 8, startFrom, bytesToSearch, &bytesRead))) {
290
J9RAS ras;
291
totalBytesSearched += bytesRead;
292
293
dbgReadMemory((UDATA)eyecatcher, &ras, sizeof(ras), &bytesRead);
294
if (bytesRead == sizeof(ras)) {
295
if (ras.bitpattern1 == 0xaa55aa55 && ras.bitpattern2 == 0xaa55aa55) {
296
cachedVM = (J9JavaVM *) ras.vm;
297
dbgPrint("Searched %zu bytes -- VM set to !setvm 0x%p\n", totalBytesSearched, cachedVM);
298
return cachedVM;
299
}
300
}
301
302
/* this isn't it -- look for the next occurrence */
303
startFrom = eyecatcher + 8;
304
if ((UDATA)eyecatcher > 0xFFFFFFFF - 8) {
305
bytesToSearch = 0;
306
} else {
307
bytesToSearch = 0xFFFFFFFF - (UDATA)startFrom;
308
}
309
}
310
totalBytesSearched += bytesRead;
311
}
312
313
if (totalBytesSearched == 0) {
314
dbgPrint("Cannot scan for eyecatchers on this platform -- use setvm instead\n");
315
} else {
316
dbgPrint("Could not locate J9JavaVM (searched %zu bytes)\n", totalBytesSearched);
317
dbgPrint("Use setvm if you know (or suspect) the address of the J9JavaVM or a J9VMThread\n");
318
}
319
return NULL;
320
}
321
322
323
324
/*
325
* Returns a program space pointer to the J9JavaVM.
326
* Tries to find the VM from ptr. ptr may point to a J9VMThread, a J9JavaVM,
327
* or maybe something else.
328
*/
329
static int
330
testJavaVMPtr(J9JavaVM* ptr)
331
{
332
void* bytes = 0;
333
UDATA bytesRead = 0;
334
335
/* try to read the reserved slot */
336
dbgReadMemory((UDATA)&ptr->reserved1_identifier, &bytes, sizeof(ptr->reserved1_identifier), &bytesRead);
337
return ((bytesRead == sizeof(ptr->reserved1_identifier)) && (bytes == (void*)J9VM_IDENTIFIER));
338
}
339
340
341
342
U_8 dbgReadByte(U_8 * remoteAddress)
343
{
344
U_8 byte = 0;
345
UDATA bytesRead = 0;
346
347
dbgReadMemory((UDATA) remoteAddress, &byte, 1, &bytesRead);
348
if (bytesRead != 1) dbgError("could not read byte at %p\n", remoteAddress);
349
return byte;
350
}
351
352
353
void
354
dbgFreeAll(void)
355
{
356
while (memoryList) {
357
dbgFree(memoryList + 1);
358
}
359
}
360
361
362
void *dbgMallocAndRead(UDATA size, void * remoteAddress)
363
{
364
void * localAddress;
365
366
localAddress = dbgTargetToLocalWithSize(remoteAddress, size);
367
if (!localAddress) {
368
UDATA bytesRead;
369
370
localAddress = dbgMalloc(size, remoteAddress);
371
if (!localAddress) {
372
dbgError("could not allocate temp space (%zu bytes for %p)\n", size, remoteAddress);
373
return NULL;
374
}
375
dbgReadMemory((UDATA) remoteAddress, localAddress, size, &bytesRead);
376
if (bytesRead != size) {
377
dbgFree(localAddress);
378
dbgError("could not read memory (%zu bytes from %p)\n", size, remoteAddress);
379
return NULL;
380
}
381
}
382
return localAddress;
383
}
384
385
J9JavaVM *
386
dbgReadJavaVM(J9JavaVM * remoteVM)
387
{
388
J9JavaVM * localVM;
389
390
localVM = (J9JavaVM *) dbgTargetToLocalWithSize(remoteVM, sizeof(J9JavaVM));
391
if (!localVM) {
392
localVM = dbgMallocAndRead(sizeof(J9JavaVM), remoteVM);
393
if (localVM) {
394
localVM->portLibrary = dbgGetPortLibrary();
395
396
#ifdef J9VM_INTERP_NATIVE_SUPPORT
397
if (localVM->jitConfig) {
398
DBG_TRY {
399
localVM->jitConfig = (J9JITConfig *) dbgMallocAndRead(sizeof(J9JITConfig), localVM->jitConfig);
400
} DBG_CATCH {
401
dbgError("could not read jitconfig");
402
dbgFree(localVM);
403
return NULL;
404
} DBG_FINALLY;
405
406
if (localVM->jitConfig->i2jReturnTable) {
407
DBG_TRY {
408
localVM->jitConfig->i2jReturnTable = dbgMallocAndRead(J9SW_JIT_RETURN_TABLE_SIZE * sizeof(UDATA), localVM->jitConfig->i2jReturnTable);
409
} DBG_CATCH {
410
dbgError("could not read jitconfig->i2jReturnTable");
411
dbgFree(localVM);
412
return NULL;
413
} DBG_FINALLY;
414
}
415
}
416
#endif
417
localVM->walkStackFrames = NULL;
418
localVM->localMapFunction = NULL;
419
#ifdef J9VM_INTERP_VERBOSE
420
localVM->verboseStackDump = NULL;
421
#endif
422
} else {
423
dbgError("Could not read java VM\n");
424
}
425
}
426
cachedVM = remoteVM;
427
return localVM;
428
}
429
430
UDATA
431
dbgReadUDATA(UDATA * remoteAddress)
432
{
433
UDATA data = 0;
434
UDATA bytesRead = 0;
435
436
dbgReadMemory((UDATA) remoteAddress, &data, sizeof(UDATA), &bytesRead);
437
if (bytesRead != sizeof(UDATA)) dbgError("could not read UDATA at %p\n", remoteAddress);
438
return data;
439
}
440
441
U_64
442
dbgReadU64(U_64 * remoteAddress)
443
{
444
U_64 data = 0;
445
UDATA bytesRead = 0;
446
447
dbgReadMemory((UDATA) remoteAddress, &data, sizeof(U_64), &bytesRead);
448
if (bytesRead != sizeof(U_64)) dbgError("could not read U_64 at %p\n", remoteAddress);
449
return data;
450
}
451
452
/**
453
* Read a primitive data type from the target memory.
454
* Does not support reading data types larger than UDATA.
455
*
456
* @param[in] remoteAddress Address in the target memory.
457
* @param[in] size sizeof the primitive data type to return
458
* @returns content of target memory
459
*/
460
UDATA
461
dbgReadPrimitiveType(UDATA remoteAddress, UDATA size)
462
{
463
UDATA value = 0;
464
UDATA bytesActuallyRead = 0;
465
466
dbgReadMemory(remoteAddress, &value, size, &bytesActuallyRead);
467
468
if (bytesActuallyRead != size) {
469
dbgError("could not read %zu bytes at %p\n", size, remoteAddress);
470
}
471
472
#if !defined(J9VM_ENV_LITTLE_ENDIAN)
473
/* On big endian, shift datatypes smaller than UDATA down in the buffer
474
* to correctly widen to UDATA.
475
*/
476
value = value >> (8 * (sizeof(UDATA) - size));
477
#endif
478
return value;
479
}
480
481
UDATA
482
dbgParseArgs(const char * originalArgs, UDATA * argValues, UDATA maxArgs)
483
{
484
UDATA anyArgs = FALSE;
485
UDATA argCount = 0;
486
char c;
487
const char * argStart;
488
char *args;
489
char *copiedArgs;
490
UDATA len;
491
PORT_ACCESS_FROM_PORT(dbgGetPortLibrary());
492
493
len = strlen(originalArgs);
494
argStart = args = copiedArgs = j9mem_allocate_memory(len + 1, OMRMEM_CATEGORY_VM);
495
if (copiedArgs == NULL) {
496
return 0;
497
}
498
strcpy(copiedArgs, originalArgs);
499
500
do {
501
c = *(args++);
502
if ( (c == '\0') && !anyArgs) {
503
break;
504
}
505
if (c != ' ') {
506
anyArgs = TRUE;
507
}
508
if ( (c == '\0') || (c == ',')) {
509
if (argCount < maxArgs) {
510
511
/* NUL terminate the argument */
512
args[-1] = '\0';
513
514
argValues[argCount] = dbgGetExpression(argStart);
515
argStart = args;
516
}
517
++argCount;
518
}
519
} while (c != '\0');
520
521
j9mem_free_memory(copiedArgs);
522
523
return argCount;
524
}
525
526
/**
527
* Read the contents of size bytes of memory. The result is 0-extended to UDATA
528
* @param srcaddr the address of the memory to be read
529
* @param size the number of bytes to read
530
* @return the memory contents
531
*/
532
UDATA dbgReadSlot(UDATA srcaddr, UDATA size)
533
{
534
UDATA value = 0;
535
UDATA bytesActuallyRead = 0;
536
537
if (size > sizeof(UDATA)) {
538
dbgError("size (%d) > sizeof(UDATA) (%d)\n", size, sizeof(UDATA));
539
}
540
dbgReadMemory(srcaddr, &value, size, &bytesActuallyRead);
541
542
if (bytesActuallyRead != size) {
543
dbgError("unable to read %zu bytes at %p\n", size, srcaddr);
544
}
545
546
/* since the order and size of the data are both orthogonally variable, we need an ifdef to split out the endian from the problem */
547
#if !defined(J9VM_ENV_LITTLE_ENDIAN)
548
value = value >> (8* (sizeof(UDATA)-size));
549
#endif /* !defined(J9VM_ENV_LITTLE_ENDIAN) */
550
return value;
551
}
552
553
U_16 dbgReadU16(U_16 * remoteAddress)
554
{
555
U_16 data = 0;
556
UDATA bytesRead = 0;
557
558
dbgReadMemory((UDATA) remoteAddress, &data, sizeof(U_16), &bytesRead);
559
if (bytesRead != sizeof(U_16)) dbgError("could not read U_16 at %p\n", remoteAddress);
560
return data;
561
}
562
563
U_32 dbgReadU32(U_32 * remoteAddress)
564
{
565
U_32 data = 0;
566
UDATA bytesRead = 0;
567
568
dbgReadMemory((UDATA) remoteAddress, &data, sizeof(U_32), &bytesRead);
569
if (bytesRead != sizeof(U_32)) dbgError("could not read U_32 at %p\n", remoteAddress);
570
return data;
571
}
572
573
void *
574
dbgReadSRP(J9SRP * remoteSRPAddress)
575
{
576
J9SRP srpValue;
577
578
srpValue = (J9SRP)dbgReadU32((U_32*)remoteSRPAddress);
579
if (!srpValue) {
580
return NULL;
581
}
582
return ((U_8 *) remoteSRPAddress) + srpValue;
583
}
584
585
J9PortLibrary * dbgGetPortLibrary(void)
586
{
587
static int initialized;
588
static J9PortLibrary port;
589
static J9PortLibraryVersion portLibraryVersion;
590
J9PortLibrary * portLib = &port;
591
592
if (!initialized) {
593
initialized = 1;
594
595
/* Use portlibrary version which we compiled against, and have allocated space
596
* for on the stack. This version may be different from the one in the linked DLL.
597
*/
598
J9PORT_SET_VERSION(&portLibraryVersion, J9PORT_CAPABILITY_MASK);
599
dbg_j9port_create_library(portLib, &portLibraryVersion, sizeof(J9PortLibrary));
600
601
old_write = OMRPORT_FROM_J9PORT(portLib)->file_write;
602
OMRPORT_FROM_J9PORT(portLib)->file_write = dbg_write;
603
#ifdef J9ZOS390
604
OMRPORT_FROM_J9PORT(portLib)->file_write_text = dbg_write_text;
605
#endif
606
607
portLib->port_startup_library(portLib);
608
609
}
610
611
return portLib;
612
}
613
614
void dbgext_findvm(const char *args)
615
{
616
cachedVM = NULL;
617
dbgSniffForJavaVM();
618
}
619
620
void
621
dbgext_setvm(const char *args)
622
{
623
dbgSetVM((void*)dbgGetExpression(args));
624
}
625
626
void
627
dbgext_j9help(const char *args)
628
{
629
dbgPrint("J9 DBG Extension - FOR INTERNAL USE ONLY\n");
630
dbgPrint("%s\n", J9_COPYRIGHT_STRING);
631
dbgPrint("Options: \n");
632
dbgPrint("\n");
633
dbgPrint("findvm - find the JavaVM struct.\n");
634
dbgPrint("setvm <address> - set the JavaVM address.\n");
635
}
636
637
638
void * dbgTargetToLocalWithSize(void * addr, UDATA size)
639
{
640
dbgNode * current = memoryList;
641
642
while (current) {
643
U_8 * lowAddr = (U_8 *) (current->originalAddress);
644
U_8 * highAddr = lowAddr + current->size;
645
646
if (((U_8 *)addr >= lowAddr) && ((U_8 *)addr < highAddr)) {
647
if ( (U_8*)addr + size > highAddr ) {
648
dbgError("Found partial memory match for %p at %p, but it only has %d bytes (needed %d)\n", addr, current, highAddr - (U_8*)addr, size);
649
return NULL;
650
} else {
651
return ((U_8*) addr) - lowAddr + ((U_8*) (current + 1));
652
}
653
}
654
655
current = current->link;
656
}
657
658
return NULL;
659
}
660
661
#if defined(J9ZOS390)
662
/* on z/OS, we redefine the portlib file_write_text as well as file_write so create this wrapper to satisfy the type system */
663
static IDATA
664
dbg_write_text(OMRPortLibrary *portLibrary, IDATA fd, const char * buf, IDATA nbytes)
665
{
666
return dbg_write(portLibrary, fd, buf, nbytes);
667
}
668
#endif /* defined(J9ZOS390) */
669
670
671
static IDATA
672
dbg_write(OMRPortLibrary *portLibrary, IDATA fd, const void * buf, IDATA nbytes)
673
{
674
if (fd == J9PORT_TTY_OUT || fd == J9PORT_TTY_ERR) {
675
dbgPrint("%.*s", nbytes, buf);
676
return nbytes;
677
} else {
678
return old_write(portLibrary, fd, buf, nbytes);
679
}
680
}
681
682
void*
683
dbgSetHandler(void* bufPointer) {
684
DBG_JMPBUF* oldHandler = dbgErrorHandler;
685
dbgErrorHandler = bufPointer;
686
return oldHandler;
687
}
688
689
void
690
dbgSetVerboseMode(int verboseMode) {
691
dbgVerboseMode = verboseMode;
692
}
693
694
void
695
dbgError(const char* format, ...) {
696
PORT_ACCESS_FROM_PORT(dbgGetPortLibrary());
697
va_list args;
698
699
if (dbgVerboseMode) {
700
va_start( args, format );
701
j9tty_vprintf(format, args);
702
va_end( args );
703
}
704
705
if (dbgErrorHandler) {
706
longjmp(dbgErrorHandler->buf, 0);
707
}
708
}
709
710
711
/* returns an ALLOCATED string */
712
char*
713
dbgReadString(char* remoteAddress)
714
{
715
UDATA len = 0;
716
while (dbgReadByte((U_8*)remoteAddress + len)) len++;
717
return dbgMallocAndRead(len + 1, remoteAddress);
718
}
719
720
721
static J9PoolPuddle *
722
dbgReadPoolPuddle(J9Pool* head, J9PoolPuddle* remotePuddle)
723
{
724
J9PoolPuddle * localPuddle;
725
726
localPuddle = dbgTargetToLocalWithSize(remotePuddle, head->puddleAllocSize);
727
if (!localPuddle) {
728
IDATA offset;
729
730
localPuddle = dbgMallocAndRead(head->puddleAllocSize, remotePuddle);
731
if (!localPuddle) {
732
dbgError("could not read puddle\n");
733
return NULL;
734
}
735
736
offset = (UDATA)remotePuddle - (UDATA)localPuddle;
737
if (localPuddle->nextPuddle) {
738
IDATA nextPuddle;
739
740
nextPuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddle->nextPuddle, J9PoolPuddle*) + offset;
741
WSRP_SET(localPuddle->nextPuddle, dbgReadPoolPuddle(head, (J9PoolPuddle*)nextPuddle));
742
}
743
if (localPuddle->prevPuddle) {
744
IDATA prevPuddle;
745
746
prevPuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddle->prevPuddle, J9PoolPuddle*) + offset;
747
WSRP_SET(localPuddle->prevPuddle, dbgReadPoolPuddle(head, (J9PoolPuddle*)prevPuddle));
748
}
749
if (localPuddle->nextAvailablePuddle) {
750
IDATA nextAvailablePuddle;
751
752
nextAvailablePuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddle->nextAvailablePuddle, J9PoolPuddle*) + offset;
753
WSRP_SET(localPuddle->nextAvailablePuddle, dbgReadPoolPuddle(head, (J9PoolPuddle*)nextAvailablePuddle));
754
}
755
if (localPuddle->prevAvailablePuddle) {
756
IDATA prevAvailablePuddle;
757
758
prevAvailablePuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddle->prevAvailablePuddle, J9PoolPuddle*) + offset;
759
WSRP_SET(localPuddle->prevAvailablePuddle, dbgReadPoolPuddle(head, (J9PoolPuddle*)prevAvailablePuddle));
760
}
761
}
762
return localPuddle;
763
}
764
765
static J9PoolPuddleList *
766
dbgReadPoolPuddleList(J9Pool* pool, J9PoolPuddleList* removePuddleList)
767
{
768
J9PoolPuddleList * localPuddleList;
769
770
localPuddleList = dbgTargetToLocalWithSize(removePuddleList, sizeof(J9PoolPuddleList));
771
if (!localPuddleList) {
772
IDATA offset;
773
774
localPuddleList = dbgMallocAndRead(sizeof(J9PoolPuddleList), removePuddleList);
775
if (!localPuddleList) {
776
dbgError("could not read puddleList\n");
777
return NULL;
778
}
779
780
offset = (UDATA)removePuddleList - (UDATA)localPuddleList;
781
if (localPuddleList->nextPuddle) {
782
IDATA nextPuddle;
783
784
nextPuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddleList->nextPuddle, J9PoolPuddle*) + offset;
785
WSRP_SET(localPuddleList->nextPuddle, dbgReadPoolPuddle(pool, (J9PoolPuddle*)nextPuddle));
786
}
787
if (localPuddleList->nextAvailablePuddle) {
788
IDATA nextAvailablePuddle;
789
790
nextAvailablePuddle = (IDATA)LOCAL_NNWSRP_GET(localPuddleList->nextAvailablePuddle, J9PoolPuddle*) + offset;
791
WSRP_SET(localPuddleList->nextAvailablePuddle, dbgReadPoolPuddle(pool, (J9PoolPuddle*)nextAvailablePuddle));
792
}
793
}
794
return localPuddleList;
795
}
796
797
/* returns a copy of the specified pool in local memory space
798
* The pool is walkable in local space.
799
* Note that elements in the pool are not fixed up in any way, so
800
* the result of walking the pool will be local, but non-relocated
801
* copies of the elements of the pool
802
*/
803
J9Pool *
804
dbgReadPool(J9Pool* remotePool)
805
{
806
J9Pool * localPool;
807
808
localPool = dbgTargetToLocalWithSize(remotePool, sizeof(J9Pool));
809
if (!localPool) {
810
IDATA offset;
811
IDATA puddleList;
812
813
localPool = dbgMallocAndRead(sizeof(J9Pool), remotePool);
814
if (!localPool) {
815
dbgError("could not read pool\n");
816
return NULL;
817
}
818
819
offset = (UDATA)remotePool - (UDATA)localPool;
820
puddleList = (IDATA) LOCAL_NNWSRP_GET(localPool->puddleList, J9PoolPuddle*) + offset;
821
WSRP_SET(localPool->puddleList, dbgReadPoolPuddleList(localPool, (J9PoolPuddleList*)puddleList));
822
}
823
return localPool;
824
}
825
826
/* returns a target process pointer to the J9ThreadLibrary */
827
void*
828
dbgGetThreadLibrary(void) {
829
J9JavaVM* remoteVM = dbgSniffForJavaVM();
830
if (remoteVM) {
831
J9VMThread* remoteThread = (J9VMThread*)dbgReadUDATA((UDATA*)&remoteVM->mainThread);
832
if (remoteThread) {
833
J9AbstractThread* remoteOSThread = (J9AbstractThread*)dbgReadUDATA((UDATA*)&remoteThread->osThread);
834
if (remoteOSThread) {
835
return (void*)dbgReadUDATA((UDATA*)&remoteOSThread->library);
836
}
837
}
838
}
839
dbgError("Unable to find thread library\n");
840
return NULL;
841
}
842
843
void
844
dbgSetLocalBlockRelocated(void * addr, UDATA value)
845
{
846
dbgNode * current = memoryList;
847
848
while (current) {
849
U_8 * lowAddr = (U_8 *) (current + 1);
850
U_8 * highAddr = lowAddr + current->size;
851
852
if (((U_8 *)addr >= lowAddr) && ((U_8 *)addr < highAddr)) {
853
current->relocated = value;
854
return;
855
}
856
857
current = current->link;
858
}
859
860
dbgError("dbgSetLocalBlockRelocated: Local memory %p has no mapping to target memory\n", addr);
861
}
862
863
UDATA
864
dbgGetLocalBlockRelocated(void * addr)
865
{
866
dbgNode * current = memoryList;
867
868
if (addr == NULL) return 1;
869
870
while (current) {
871
U_8 * lowAddr = (U_8 *) (current + 1);
872
U_8 * highAddr = lowAddr + current->size;
873
874
if (((U_8 *)addr >= lowAddr) && ((U_8 *)addr < highAddr))
875
return current->relocated;
876
877
current = current->link;
878
}
879
880
dbgError("dbgGetLocalBlockRelocated: Local memory %p has no mapping to target memory\n", addr);
881
return 0;
882
}
883
884
885
886
/*
887
* pattern: a pointer to the eyecatcher pattern to search for
888
* patternLength: length of pattern
889
* patternAlignment: guaranteed minimum alignment of the pattern (must be a power of 2)
890
* startSearchFrom: minimum address to search at (useful for multiple occurrences of the pattern)
891
* bytesToSearch: maximum number of bytes to search
892
* bytesSearched: number of bytes searched is returned through this pointer. 0 indicates that no attempt was made to find the pattern.
893
*
894
* Returns:
895
* The address of the eyecatcher in TARGET memory space
896
* or NULL if it was not found.
897
*
898
* NOTES:
899
* Currently, this may fail to find the pattern if patternLength > patternAlignment
900
* Generally, dbgFindPattern should be called instead of dbgFindPatternInRange. It can be
901
* more clever about not searching ranges which aren't in use.
902
*/
903
void*
904
dbgFindPatternInRange(U_8* pattern, UDATA patternLength, UDATA patternAlignment, U_8* startSearchFrom, UDATA bytesToSearch, UDATA* bytesSearched)
905
{
906
U_8* page = startSearchFrom;
907
UDATA align;
908
909
/* round to a page */
910
align = (UDATA)page & 4095;
911
page -= align;
912
bytesToSearch += align;
913
914
*bytesSearched = 0;
915
916
for (;;) {
917
U_8 data[4096];
918
UDATA bytesRead = 0;
919
920
dbgReadMemory((UDATA)page, data, sizeof(data), &bytesRead);
921
if (0 != bytesRead) {
922
UDATA i;
923
if (bytesRead > bytesToSearch) {
924
bytesRead = bytesToSearch;
925
}
926
*bytesSearched += bytesRead;
927
for (i = 0; (IDATA)i < (IDATA)(bytesRead - patternLength); i += patternAlignment) {
928
if (memcmp(data + i, pattern, patternLength) == 0) {
929
/* in case the page started before startSearchFrom */
930
if (page + i >= startSearchFrom) {
931
return page + i;
932
}
933
}
934
}
935
}
936
937
if (bytesToSearch < 4096) {
938
break;
939
}
940
941
page += 4096;
942
bytesToSearch -= 4096;
943
}
944
945
return NULL;
946
}
947
948
void
949
dbgSetVM(void* vmPtr)
950
{
951
J9JavaVM * ptr = (J9JavaVM *)vmPtr;
952
J9VMThread* vmThread;
953
J9JavaVM* bytes;
954
UDATA bytesRead;
955
956
if (testJavaVMPtr(ptr)) {
957
cachedVM = ptr;
958
found:
959
dbgPrint("VM set to %p\n", cachedVM);
960
return;
961
}
962
963
/* hmm. It's not a J9JavaVM. Maybe it's a vmThread? */
964
/* try to read the VM slot */
965
vmThread = (J9VMThread *) ptr;
966
bytesRead = 0;
967
dbgReadMemory((UDATA)&vmThread->javaVM, &bytes, sizeof(vmThread->javaVM), &bytesRead);
968
if (bytesRead == sizeof(vmThread->javaVM)) {
969
if (testJavaVMPtr(bytes)) {
970
cachedVM = bytes;
971
goto found;
972
}
973
}
974
975
dbgError("Error: Specified value is not a javaVM or vmThread pointer, VM not set\n");
976
}
977
978
static IDATA
979
hexValue(char c)
980
{
981
if (c >= '0' && c <= '9') {
982
return c - '0';
983
} else if (c >= 'a' && c <= 'f') {
984
return 10 + c - 'a';
985
} else if (c >= 'A' && c <= 'F') {
986
return 10 + c - 'A';
987
} else {
988
return -1;
989
}
990
}
991
992
void
993
dbgext_findpattern(const char *args)
994
{
995
UDATA argCount;
996
UDATA argValues[3];
997
const char* hexend;
998
U_8 pattern[1024];
999
UDATA i;
1000
UDATA length;
1001
UDATA bytesSearched;
1002
void* result;
1003
1004
hexend = strchr(args, ',');
1005
1006
if (hexend == NULL) {
1007
dbgPrint("Usage: \n");
1008
dbgPrint(" !findpattern hexstring,alignment\n");
1009
dbgPrint(" !findpattern hexstring,alignment,startPtr\n");
1010
dbgPrint(" !findpattern hexstring,alignment,startPtr,bytesToSearch\n");
1011
return;
1012
}
1013
1014
argCount = dbgParseArgs(hexend + 1, argValues, 3);
1015
if (argCount == 0) {
1016
dbgError("Error: must specify alignment\n");
1017
return;
1018
} else if (argCount == 1) {
1019
argValues[1] = 0;
1020
argValues[2] = (UDATA)-1;
1021
} else if (argCount == 2) {
1022
argValues[2] = (UDATA)-1 - argValues[1];
1023
} else if (argCount > 3) {
1024
dbgError("Error: too many arguments\n");
1025
return;
1026
}
1027
1028
length = (hexend - args) / 2;
1029
if (length > sizeof(pattern)) {
1030
dbgPrint("Pattern is too long. Truncating to %d bytes\n", sizeof(pattern));
1031
length = sizeof(pattern);
1032
}
1033
1034
for (i = 0; i < length; i++) {
1035
IDATA hex1 = hexValue(args[i * 2]);
1036
IDATA hex2 = hexValue(args[i * 2 + 1]);
1037
1038
if ( (hex1 < 0) || (hex2 < 0) ) {
1039
dbgError("Error: non-hex value found in hex string\n");
1040
return;
1041
}
1042
1043
pattern[i] = (U_8) ((hex1 << 4) + hex2);
1044
1045
#if 0
1046
dbgPrint("%c%c = (%u << 4) + %u = %u\n", args[i * 2], args[i * 2 + 1], hex1, hex2, pattern[i]);
1047
#endif
1048
}
1049
1050
/* ensure that alignment is > 0 */
1051
if (argValues[0] == 0) {
1052
argValues[0] = 1;
1053
}
1054
1055
dbgPrint("Searching for %zu bytes. Alignment = %zu, start = 0x%p, bytesToSearch = %zu ...\n", length, argValues[0], argValues[1], argValues[2]);
1056
1057
result = dbgFindPatternInRange(pattern, length, argValues[0], (U_8 *) argValues[1], argValues[2], &bytesSearched);
1058
1059
dbgPrint("Searched %zu bytes -- result = 0x%p\n", bytesSearched, result);
1060
}
1061
1062
/*
1063
* Prints message to the debug print screen
1064
*/
1065
void
1066
dbgVPrint (const char* message, va_list arg_ptr)
1067
{
1068
char printBuf[4096];
1069
PORT_ACCESS_FROM_PORT(dbgGetPortLibrary());
1070
1071
j9str_vprintf(printBuf, sizeof(printBuf), message, arg_ptr );
1072
1073
dbgWriteString(printBuf);
1074
}
1075
1076
1077
/*
1078
* Prints message to the debug print screen
1079
*/
1080
void
1081
dbgPrint (const char* message, ...)
1082
{
1083
va_list arg_ptr;
1084
1085
va_start(arg_ptr, message);
1086
1087
dbgVPrint(message, arg_ptr);
1088
1089
va_end(arg_ptr);
1090
}
1091
1092
/*
1093
* Parse the args for dumping a structure.
1094
* The args may consist of just an address, or a field name (with wildcards)
1095
* followed by a command and an address.
1096
*
1097
* e.g. "0x3738000" or "foo*,0x3738000"
1098
*
1099
* See parseWildcard() for doc on how to use needle, needleLength and matchFlag
1100
*
1101
*/
1102
IDATA
1103
dbgParseArgForStructDump(const char * args, UDATA* structAddress, const char** needle, UDATA* needleLength, U_32 * matchFlag)
1104
{
1105
const char* comma = strchr(args, ',');
1106
IDATA result = 0;
1107
1108
if (comma == NULL) {
1109
*structAddress = dbgGetExpression(args);
1110
result = parseWildcard("*", 1, needle, needleLength, matchFlag);
1111
} else {
1112
*structAddress = dbgGetExpression(comma + 1);
1113
result = parseWildcard(args, comma - args, needle, needleLength, matchFlag);
1114
}
1115
1116
if (result != 0) {
1117
dbgPrint("unable to parse field name\n");
1118
result = -1;
1119
}
1120
1121
if (*structAddress == 0) {
1122
dbgPrint("bad or missing address\n");
1123
result = -1;
1124
}
1125
1126
return result;
1127
}
1128
1129