Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/cfdumper/romdump.c
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 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 "j9.h"
24
#include "cfdumper_internal.h"
25
#include "util_api.h"
26
#include "romclasswalk.h"
27
28
#include <stdlib.h>
29
#include <ctype.h>
30
31
/* Constants and types. */
32
33
#define J9ROM_SECTION_START 1000
34
#define J9ROM_SECTION_END 2000
35
36
typedef struct J9ROMClassRegion {
37
UDATA offset;
38
UDATA length;
39
UDATA type;
40
BOOLEAN pointsToUTF8;
41
const char *name;
42
} J9ROMClassRegion;
43
44
typedef struct J9ROMClassGatherLayoutInfoState {
45
J9ROMClassValidateRangeCallback validateRangeCallback;
46
J9Pool *regionsPool;
47
J9ROMClassRegion **sortedRegions;
48
UDATA numRegions;
49
J9UTF8 *firstUTF8;
50
J9UTF8 *lastUTF8;
51
} J9ROMClassGatherLayoutInfoState;
52
53
typedef struct J9ROMClassQueryComponent {
54
UDATA componentIndex;
55
const char *name;
56
UDATA nameLength;
57
UDATA arrayIndex;
58
struct J9ROMClassQueryComponent *prev;
59
struct J9ROMClassQueryComponent *next;
60
} J9ROMClassQueryComponent;
61
62
63
/* Private function declarations. */
64
65
static const char *getTypeName(UDATA type);
66
static UDATA getTypeSize(UDATA type);
67
static J9ROMClassRegion* addRegion(J9Pool *regionPool, UDATA offset, UDATA length, UDATA type, const char *name);
68
static UDATA getUTF8Length(J9UTF8 *utf8);
69
static void escapeUTF8(J9PortLibrary *portLib, J9UTF8 *utf8, char *str, size_t strSize);
70
static void addUTF8Region(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9UTF8 *utf8, const char *name);
71
static void addUTF8RegionSRP(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9SRP *srpPtr, const char *name);
72
static void addNASRegion(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9SRP *srpPtr, const char *name);
73
static void addSlotCallback(J9ROMClass *romClass, U_32 type, void *slotPtr, const char *slotName, void *userData);
74
static void addSectionCallback(J9ROMClass *romClass, void *address, UDATA length, const char *name, void *userData);
75
static int compareRegions(const void *s1, const void *s2);
76
static BOOLEAN gatherROMClassLayoutInfo(J9PortLibrary *portLib, J9ROMClass *romClass,
77
J9ROMClassValidateRangeCallback validateRangeCallback, J9ROMClassGatherLayoutInfoState *state);
78
static void cleanupGatherROMClassLayoutInfoState(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state);
79
static void getRegionValueString(J9PortLibrary *portLib, J9ROMClass *romClass, J9ROMClassRegion *region,
80
char *str, size_t strSize);
81
static void getRegionDetailString(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state,
82
J9ROMClass *romClass, J9ROMClassRegion *region, char *str, size_t strSize, UDATA base);
83
static void printRegionLine(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state,
84
J9ROMClass *romClass, J9ROMClassRegion *section, UDATA base);
85
static BOOLEAN isSameRegion(J9ROMClassRegion *region1, J9ROMClassRegion *region2);
86
static void reportSuspectedPadding(J9PortLibrary *portLib, J9ROMClass *romClass,
87
J9ROMClassGatherLayoutInfoState *state, UDATA lastOffset, UDATA offset, UDATA base);
88
static J9ROMClassQueryComponent* parseROMQuery(J9Pool *allocator, const char *query);
89
static BOOLEAN regionNameMatchesComponent(J9ROMClassRegion *region, J9ROMClassQueryComponent *component);
90
91
/* Function definitions. */
92
93
static const char*
94
getTypeName(UDATA type)
95
{
96
switch (type) {
97
case J9ROM_U8:
98
return "U_8";
99
case J9ROM_U16:
100
return "U_16";
101
case J9ROM_U32:
102
return "U_32";
103
case J9ROM_U64:
104
return "U_64";
105
case J9ROM_UTF8:
106
return "J9UTF8";
107
case J9ROM_SRP:
108
return "J9SRP";
109
case J9ROM_WSRP:
110
return "J9WSRP";
111
}
112
113
return "unknown";
114
}
115
116
static UDATA
117
getTypeSize(UDATA type)
118
{
119
switch (type) {
120
case J9ROM_U8:
121
return sizeof(U_8);
122
case J9ROM_U16:
123
return sizeof(U_16);
124
case J9ROM_U32:
125
return sizeof(U_32);
126
case J9ROM_U64:
127
return sizeof(U_64);
128
case J9ROM_SRP:
129
return sizeof(J9SRP);
130
case J9ROM_WSRP:
131
return sizeof(J9WSRP);
132
}
133
134
return 0;
135
}
136
137
static J9ROMClassRegion*
138
addRegion(J9Pool *regionPool, UDATA offset, UDATA length, UDATA type, const char *name)
139
{
140
J9ROMClassRegion *region;
141
142
region = pool_newElement(regionPool);
143
if (NULL != region) {
144
region->offset = offset;
145
region->length = length;
146
region->type = type;
147
region->pointsToUTF8 = FALSE;
148
region->name = name;
149
}
150
151
return region;
152
}
153
154
static UDATA
155
getUTF8Length(J9UTF8 *utf8)
156
{
157
UDATA length = sizeof(J9UTF8) + J9UTF8_LENGTH(utf8);
158
/* Keep UTFs aligned to 2 bytes */
159
if (0 != (length & 1)) {
160
length += 1;
161
}
162
return length;
163
}
164
165
static void
166
escapeUTF8(J9PortLibrary *portLib, J9UTF8 *utf8, char *str, size_t strSize)
167
{
168
U_8 *data = (U_8 *) J9UTF8_DATA(utf8);
169
const U_8 *end = data + J9UTF8_LENGTH(utf8);
170
171
PORT_ACCESS_FROM_PORT(portLib);
172
173
while ((data < end) && (strSize > 0)) {
174
U_16 c;
175
U_32 charLength;
176
UDATA escapedLength;
177
178
charLength = decodeUTF8Char(data, &c);
179
180
if ((charLength > 1) || !isprint((int)c)) {
181
182
if (strSize < 6) {
183
/* Truncate on character boundaries only. */
184
break;
185
}
186
187
escapedLength = j9str_printf(PORTLIB, str, strSize, "\\u%04x", (UDATA)c);
188
} else {
189
escapedLength = j9str_printf(PORTLIB, str, strSize, "%c", (char)c);
190
}
191
192
strSize -= (size_t)escapedLength;
193
str += escapedLength;
194
data += charLength;
195
}
196
}
197
198
static void
199
addUTF8Region(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9UTF8 *utf8, const char *name)
200
{
201
UDATA base, offset, length;
202
if (NULL != utf8) {
203
204
base = (UDATA)romClass;
205
offset = (UDATA)utf8;
206
207
if ((offset >= base) && (offset < (base + romClass->romSize))) {
208
length = getUTF8Length(utf8);
209
addRegion(state->regionsPool, offset - base, length, J9ROM_UTF8, name);
210
if (NULL == state->firstUTF8) {
211
state->firstUTF8 = utf8;
212
state->lastUTF8 = utf8;
213
} else if (utf8 < state->firstUTF8) {
214
state->firstUTF8 = utf8;
215
} else if (utf8 > state->lastUTF8) {
216
state->lastUTF8 = utf8;
217
}
218
}
219
}
220
}
221
222
static void
223
addUTF8RegionSRP(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9SRP *srpPtr, const char *name)
224
{
225
J9UTF8 *utf8;
226
utf8 = SRP_PTR_GET(srpPtr, J9UTF8 *);
227
228
if (NULL != utf8) {
229
addUTF8Region(state, romClass, utf8, name);
230
}
231
}
232
233
static void
234
addNASRegion(J9ROMClassGatherLayoutInfoState *state, J9ROMClass *romClass, J9SRP *srpPtr, const char *name)
235
{
236
J9ROMNameAndSignature *nas;
237
UDATA base, offset;
238
239
nas = SRP_PTR_GET(srpPtr, J9ROMNameAndSignature *);
240
241
if (NULL != nas) {
242
243
base = (UDATA)romClass;
244
offset = (UDATA)nas;
245
246
if ((offset >= base) && (offset < (base + romClass->romSize))) {
247
addRegion(state->regionsPool, offset - base, sizeof(J9ROMNameAndSignature), J9ROM_SRP, "nameAndSignatureSRP");
248
addUTF8RegionSRP(state, romClass, &nas->name, "name");
249
addUTF8RegionSRP(state, romClass, &nas->signature, "signature");
250
}
251
}
252
}
253
254
static void
255
addSlotCallback(J9ROMClass *romClass, U_32 type, void *slotPtr, const char *slotName, void *userData)
256
{
257
J9ROMClassGatherLayoutInfoState *state = userData;
258
J9Pool *regionPool = state->regionsPool;
259
J9ROMClassRegion *region;
260
UDATA base, size;
261
262
base = (UDATA)slotPtr - (UDATA)romClass;
263
size = getTypeSize(type);
264
265
/* Simple types. */
266
if (0 != size) {
267
addRegion(regionPool, base, size, type, slotName);
268
return;
269
}
270
271
/* Mapped types. */
272
switch (type) {
273
case J9ROM_UTF8:
274
addUTF8RegionSRP(state, romClass, (J9SRP *)slotPtr, slotName);
275
region = addRegion(regionPool, base, sizeof(J9SRP), J9ROM_SRP, slotName);
276
if (NULL != region) {
277
region->pointsToUTF8 = TRUE;
278
}
279
break;
280
case J9ROM_UTF8_NOSRP:
281
addUTF8Region(state, romClass, (J9UTF8 *)slotPtr, slotName);
282
break;
283
case J9ROM_NAS:
284
addNASRegion(state, romClass, (J9SRP *)slotPtr, slotName);
285
addRegion(regionPool, base, sizeof(J9SRP), J9ROM_SRP, slotName);
286
break;
287
case J9ROM_AOT:
288
addRegion(regionPool, base, sizeof(J9SRP), J9ROM_SRP, slotName);
289
break;
290
case J9ROM_INTERMEDIATECLASSDATA:
291
addRegion(regionPool, base, romClass->intermediateClassDataLength, type, slotName);
292
}
293
}
294
295
static void
296
addSectionCallback(J9ROMClass *romClass, void *address, UDATA length, const char *name, void *userData)
297
{
298
J9ROMClassGatherLayoutInfoState *state = userData;
299
J9Pool *regionPool = state->regionsPool;
300
UDATA base, end;
301
302
if (0 != length) {
303
base = (UDATA)address - (UDATA)romClass;
304
end = base + length;
305
306
addRegion(regionPool, base, length, J9ROM_SECTION_START, name);
307
addRegion(regionPool, end, length, J9ROM_SECTION_END, name);
308
}
309
}
310
311
static int
312
compareRegions(const void *r1, const void *r2)
313
{
314
J9ROMClassRegion *region1 = *(J9ROMClassRegion **) r1;
315
J9ROMClassRegion *region2 = *(J9ROMClassRegion **) r2;
316
int delta = (int)(region1->offset - region2->offset);
317
318
if (0 != delta) {
319
return delta;
320
}
321
322
if (J9ROM_SECTION_START == region1->type) {
323
if (J9ROM_SECTION_START == region2->type) {
324
/* start of longest section first, if equal length, region with longer name goes first
325
* e.g., fields over field */
326
if (region2->length == region1->length) {
327
return (int)(strlen(region2->name)-strlen(region1->name));
328
}
329
return (int)(region2->length - region1->length);
330
} else if (J9ROM_SECTION_END == region2->type) {
331
/* previous section ends before next section starts */
332
return 1;
333
}
334
} else if (J9ROM_SECTION_END == region1->type) {
335
if (J9ROM_SECTION_END == region2->type) {
336
/* end of longest section last if equal length, region with longer name goes last
337
* e.g., fields after field */
338
if (region2->length == region1->length) {
339
return (int)(strlen(region1->name)-strlen(region2->name));
340
}
341
return (int)(region1->length - region2->length);
342
} else if (J9ROM_SECTION_START == region2->type) {
343
/* previous section ends before next section starts */
344
return -1;
345
}
346
}
347
348
return (int)(region2->type - region1->type);
349
}
350
351
static BOOLEAN
352
gatherROMClassLayoutInfo(J9PortLibrary *portLib, J9ROMClass *romClass,
353
J9ROMClassValidateRangeCallback validateRangeCallback, J9ROMClassGatherLayoutInfoState *state)
354
{
355
pool_state walkState;
356
UDATA i;
357
358
PORT_ACCESS_FROM_PORT(portLib);
359
360
memset(state, 0, sizeof(J9ROMClassGatherLayoutInfoState));
361
362
state->validateRangeCallback = validateRangeCallback;
363
state->regionsPool = pool_new(sizeof(J9ROMClassRegion), 64, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(PORTLIB));
364
365
if (NULL == state->regionsPool) {
366
j9tty_printf(PORTLIB, "Error: Could not create J9Pool.\n");
367
return FALSE;
368
}
369
370
allSlotsInROMClassDo(romClass, addSlotCallback, addSectionCallback, state->validateRangeCallback, state);
371
372
/* Add section for UTF8s. */
373
if (NULL != state->lastUTF8) {
374
J9UTF8 *utf8;
375
UDATA utf8Length;
376
UDATA sectionLength;
377
378
utf8 = state->lastUTF8;
379
utf8Length = getUTF8Length(utf8);
380
381
sectionLength = (UDATA)utf8 + utf8Length - (UDATA)state->firstUTF8;
382
addSectionCallback(romClass, state->firstUTF8, sectionLength, "UTF8s", state);
383
}
384
385
state->numRegions = pool_numElements(state->regionsPool);
386
if (0 == state->numRegions) {
387
j9tty_printf(PORTLIB, "Error: Failed to walk ROM class slots.\n");
388
pool_kill(state->regionsPool);
389
return FALSE;
390
}
391
392
state->sortedRegions = j9mem_allocate_memory(state->numRegions * sizeof(J9ROMClassRegion *), J9MEM_CATEGORY_CLASSES);
393
if (NULL == state->sortedRegions) {
394
j9tty_printf(PORTLIB, "Error: Could not create sortedSections array.\n");
395
pool_kill(state->regionsPool);
396
return FALSE;
397
}
398
399
state->sortedRegions[0] = pool_startDo(state->regionsPool, &walkState);
400
for (i = 1; i < state->numRegions; i++) {
401
state->sortedRegions[i] = pool_nextDo(&walkState);
402
}
403
qsort(state->sortedRegions, state->numRegions, sizeof(J9ROMClassRegion *), compareRegions);
404
405
return TRUE;
406
}
407
408
static void cleanupGatherROMClassLayoutInfoState(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state)
409
{
410
PORT_ACCESS_FROM_PORT(portLib);
411
412
j9mem_free_memory(state->sortedRegions);
413
pool_kill(state->regionsPool);
414
}
415
416
static BOOLEAN
417
isSameRegion(J9ROMClassRegion *region1, J9ROMClassRegion *region2)
418
{
419
BOOLEAN sameRegion =
420
(region1->type == region2->type) &&
421
(region1->offset == region2->offset) &&
422
(region1->length == region2->length);
423
424
/* Compare section names to not discard nested sections of same size. */
425
if (sameRegion && ((J9ROM_SECTION_START == region1->type) || (J9ROM_SECTION_END == region1->type))) {
426
sameRegion = !strcmp(region1->name, region2->name);
427
}
428
429
return sameRegion;
430
}
431
432
static void
433
printRegionLine(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state,
434
J9ROMClass *romClass, J9ROMClassRegion *region, UDATA base)
435
{
436
char valueString[256];
437
char detailString[256];
438
439
PORT_ACCESS_FROM_PORT(portLib);
440
441
getRegionValueString(portLib, romClass, region, valueString, sizeof(valueString));
442
getRegionDetailString(portLib, state, romClass, region, detailString, sizeof(detailString), base);
443
444
j9tty_printf(PORTLIB, "0x%p-0x%p [ %12s %-28s ]%s\n", base + region->offset,
445
base + region->offset + region->length, valueString, region->name, detailString);
446
}
447
448
static void
449
getRegionValueString(J9PortLibrary *portLib, J9ROMClass *romClass, J9ROMClassRegion *region, char *str, size_t strSize)
450
{
451
void *fieldPtr;
452
453
PORT_ACCESS_FROM_PORT(portLib);
454
455
fieldPtr = (void *)((UDATA)romClass + region->offset);
456
457
switch (region->type) {
458
case J9ROM_U8:
459
j9str_printf(PORTLIB, str, strSize, "%12u", *(U_8 *)fieldPtr);
460
return;
461
case J9ROM_U16:
462
j9str_printf(PORTLIB, str, strSize, "%12u", *(U_16 *)fieldPtr);
463
return;
464
case J9ROM_U32:
465
j9str_printf(PORTLIB, str, strSize, "%12u", *(U_32 *)fieldPtr);
466
return;
467
case J9ROM_U64:
468
j9str_printf(PORTLIB, str, strSize, "%12llu", *(U_64 *)fieldPtr);
469
return;
470
case J9ROM_UTF8:
471
j9str_printf(PORTLIB, str, strSize, "(UTF-8)");
472
return;
473
case J9ROM_SRP:
474
j9str_printf(PORTLIB, str, strSize, "0x%08x", *(J9SRP *)fieldPtr);
475
return;
476
case J9ROM_WSRP:
477
j9str_printf(PORTLIB, str, strSize, "0x%08x", *(J9WSRP *)fieldPtr);
478
return;
479
case J9ROM_SECTION_END:
480
j9str_printf(PORTLIB, str, strSize, "(SECTION)");
481
return;
482
case J9ROM_INTERMEDIATECLASSDATA:
483
j9str_printf(PORTLIB, str, strSize, "");
484
return;
485
}
486
487
j9str_printf(PORTLIB, str, strSize, "<error>");
488
}
489
490
static void
491
getRegionDetailString(J9PortLibrary *portLib, J9ROMClassGatherLayoutInfoState *state,
492
J9ROMClass *romClass, J9ROMClassRegion *region, char *str, size_t strSize, UDATA base)
493
{
494
void *fieldPtr;
495
496
PORT_ACCESS_FROM_PORT(portLib);
497
498
fieldPtr = (void *)((UDATA)romClass + region->offset);
499
500
*str = '\0';
501
if (J9ROM_UTF8 == region->type) {
502
J9UTF8 *utf8 = fieldPtr;
503
504
if (NULL != utf8) {
505
str[0] = ' ';
506
escapeUTF8(PORTLIB, utf8, str + 1, strSize - 1);
507
}
508
} else if (J9ROM_SRP == region->type) {
509
BOOLEAN printedUTF8 = FALSE;
510
511
if (region->pointsToUTF8) {
512
J9UTF8 *utf8 = SRP_PTR_GET((J9SRP*)fieldPtr, J9UTF8*);
513
514
if (NULL != utf8) {
515
BOOLEAN rangeValid = TRUE;
516
517
if (NULL != state->validateRangeCallback) {
518
rangeValid = state->validateRangeCallback(romClass, utf8, sizeof(J9UTF8), NULL);
519
if (rangeValid) {
520
rangeValid = state->validateRangeCallback(romClass, utf8, getUTF8Length(utf8), NULL);
521
}
522
}
523
524
if (rangeValid) {
525
UDATA length = j9str_printf(PORTLIB, str, strSize, " -> ");
526
527
escapeUTF8(PORTLIB, utf8, str + length, strSize - length);
528
printedUTF8 = TRUE;
529
}
530
}
531
}
532
533
if (FALSE == printedUTF8) {
534
U_8 *addr = SRP_PTR_GET((J9SRP*)fieldPtr, U_8*);
535
536
if (NULL != addr) {
537
j9str_printf(PORTLIB, str, strSize, " -> 0x%p%s", (UDATA)addr - (UDATA)romClass,
538
((UDATA)addr - (UDATA)romClass) > romClass->romSize ? " (external)" : "");
539
}
540
}
541
} else if (J9ROM_INTERMEDIATECLASSDATA == region->type) {
542
j9str_printf(PORTLIB, str, strSize, " %5d bytes !j9x 0x%p,0x%p", region->length, base + region->offset, region->length);
543
}
544
545
if (J9ROM_SECTION_END == region->type) {
546
j9str_printf(PORTLIB, str, strSize, " %5d bytes", region->length);
547
}
548
}
549
550
static void
551
reportSuspectedPadding(J9PortLibrary *portLib, J9ROMClass *romClass, J9ROMClassGatherLayoutInfoState *state, UDATA lastOffset, UDATA offset, UDATA base)
552
{
553
IDATA i = 0;
554
IDATA nbytes = 0;
555
U_8 *romBase = (U_8 *)romClass;
556
BOOLEAN rangeValid = TRUE;
557
558
PORT_ACCESS_FROM_PORT(portLib);
559
nbytes = offset - lastOffset;
560
if (nbytes < 0) {
561
nbytes = 0;
562
} else if (nbytes > 6) {
563
nbytes = 6;
564
}
565
j9tty_printf(PORTLIB, "0x%p-0x%p [ %*s", base + lastOffset, base + offset, 12 - (2 * nbytes), "");
566
567
if (NULL != state->validateRangeCallback) {
568
rangeValid = state->validateRangeCallback(romClass, romBase + lastOffset, nbytes, NULL);
569
}
570
if (rangeValid) {
571
for (i = 0; i < nbytes; i++) {
572
j9tty_printf(PORTLIB, "%02x", romBase[i + lastOffset]);
573
}
574
}
575
576
j9tty_printf(PORTLIB, " %-28s ] %5d bytes\n", "padding", offset - lastOffset);
577
}
578
579
void
580
j9bcutil_linearDumpROMClass(J9PortLibrary *portLib, J9ROMClass *romClass, void *baseAddress, UDATA nestingThreshold, J9ROMClassValidateRangeCallback validateRangeCallback)
581
{
582
J9ROMClassGatherLayoutInfoState state;
583
UDATA i, lastOffset, totalMissing, nesting, base;
584
char buf[256];
585
BOOLEAN success;
586
587
PORT_ACCESS_FROM_PORT(portLib);
588
589
success = gatherROMClassLayoutInfo(portLib, romClass, validateRangeCallback, &state);
590
if (FALSE == success) {
591
return;
592
}
593
594
lastOffset = 0;
595
totalMissing = 0;
596
nesting = 1;
597
base = (UDATA)baseAddress;
598
599
for (i = 0; i < state.numRegions; i++) {
600
J9ROMClassRegion *region = state.sortedRegions[i];
601
602
/* Skip duplicates (e.g. if there were two SRPs to the same thing). */
603
if ((i > 0) && isSameRegion(region, state.sortedRegions[i - 1])) {
604
continue;
605
}
606
607
if (J9ROM_SECTION_START == region->type) {
608
if (region->offset != lastOffset) {
609
reportSuspectedPadding(portLib, romClass, &state, lastOffset, region->offset, base);
610
totalMissing += region->offset - lastOffset;
611
lastOffset = region->offset;
612
}
613
if (nesting < nestingThreshold) {
614
j9str_printf(PORTLIB, buf, sizeof(buf), "Section Start: %s (%d bytes)", region->name, region->length);
615
j9tty_printf(PORTLIB, "=== %-59s ===\n", buf);
616
}
617
nesting++;
618
} else if (J9ROM_SECTION_END == region->type) {
619
nesting--;
620
if (nesting < nestingThreshold) {
621
if (lastOffset != region->offset) {
622
if (nesting <= nestingThreshold) {
623
reportSuspectedPadding(portLib, romClass, &state, lastOffset, region->offset, base);
624
}
625
}
626
j9str_printf(PORTLIB, buf, sizeof(buf), "Section End: %s", region->name);
627
j9tty_printf(PORTLIB, "=== %-59s ===\n", buf);
628
} else if (nesting == nestingThreshold) {
629
printRegionLine(portLib, &state, romClass, region, base - region->length);
630
}
631
if (lastOffset != region->offset) {
632
/* found some padding
633
* TODO: add an ensure '0' function to make sure that padding is in fact 0
634
* */
635
lastOffset = region->offset;
636
}
637
} else {
638
/* Do not print regions or padding if they are nested under the nestingThreshold */
639
if (nesting <= nestingThreshold) {
640
if (region->offset != lastOffset) {
641
reportSuspectedPadding(portLib, romClass, &state, lastOffset, region->offset, base);
642
totalMissing += region->offset - lastOffset;
643
}
644
printRegionLine(portLib, &state, romClass, region, base);
645
}
646
lastOffset = region->offset + region->length;
647
}
648
}
649
650
if (romClass->romSize != lastOffset) {
651
reportSuspectedPadding(portLib, romClass, &state, lastOffset, romClass->romSize, base);
652
totalMissing += romClass->romSize - lastOffset;
653
}
654
655
if (0 == totalMissing) {
656
j9tty_printf(PORTLIB, "\nAll bytes were accounted for.\n");
657
} else {
658
j9tty_printf(PORTLIB, "\nNOTE: %d bytes were not accounted for.\n", totalMissing);
659
}
660
661
cleanupGatherROMClassLayoutInfoState(portLib, &state);
662
}
663
664
static J9ROMClassQueryComponent*
665
parseROMQuery(J9Pool *allocator, const char *query)
666
{
667
UDATA componentIndex = 0;
668
J9ROMClassQueryComponent *head;
669
J9ROMClassQueryComponent *component;
670
671
head = pool_newElement(allocator);
672
if (NULL == head) {
673
return NULL;
674
}
675
component = head;
676
component->componentIndex = -1;
677
678
do {
679
if ('/' != *query) {
680
return NULL;
681
}
682
query++;
683
684
component->next = pool_newElement(allocator);
685
component->next->prev = component;
686
component = component->next;
687
component->componentIndex = componentIndex++;
688
689
if (!isalnum(*query)) {
690
return NULL;
691
}
692
693
component->name = query;
694
do {
695
query++;
696
component->nameLength++;
697
} while (isalnum(*query));
698
699
if ('[' == *query) {
700
query++;
701
if (!isdigit(*query)) {
702
return NULL;
703
}
704
705
component->arrayIndex = atoi(query);
706
do {
707
query++;
708
} while (isdigit(*query));
709
710
if (']' != *query) {
711
return NULL;
712
}
713
query++;
714
}
715
} while ('\0' != *query);
716
717
return head;
718
}
719
720
static BOOLEAN
721
regionNameMatchesComponent(J9ROMClassRegion *region, J9ROMClassQueryComponent *component)
722
{
723
return (0 == strncmp(region->name, component->name, component->nameLength)) &&
724
('\0' == region->name[component->nameLength]);
725
}
726
727
void
728
j9bcutil_queryROMClass(J9PortLibrary *portLib, J9ROMClass *romClass, void *baseAddress, const char **queries, UDATA numQueries, J9ROMClassValidateRangeCallback validateRangeCallback)
729
{
730
J9ROMClassGatherLayoutInfoState state;
731
J9Pool *queryComponentPool;
732
UDATA base, queryIndex;
733
734
PORT_ACCESS_FROM_PORT(portLib);
735
736
queryComponentPool = pool_new(sizeof(J9ROMClassQueryComponent), 64, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(PORTLIB));
737
if (NULL == queryComponentPool) {
738
j9tty_printf(PORTLIB, "Error: Could not create queryComponentPool J9Pool.\n");
739
return;
740
}
741
742
if (FALSE == gatherROMClassLayoutInfo(portLib, romClass, validateRangeCallback, &state)) {
743
return;
744
}
745
746
base = (UDATA)baseAddress;
747
748
for (queryIndex = 0; queryIndex < numQueries; queryIndex++) {
749
UDATA i, nesting, currentArrayIndex;
750
BOOLEAN queryMatched;
751
J9ROMClassQueryComponent *componentsHead;
752
J9ROMClassQueryComponent *componentToMatch;
753
754
pool_clear(queryComponentPool);
755
componentsHead = parseROMQuery(queryComponentPool, queries[queryIndex]);
756
if (NULL == componentsHead) {
757
j9tty_printf(PORTLIB, "Syntax error in query '%s'\n", queries[queryIndex]);
758
continue;
759
}
760
761
queryMatched = FALSE;
762
currentArrayIndex = -1;
763
nesting = 0;
764
componentToMatch = componentsHead->next;
765
766
for (i = 0; i < state.numRegions; i++) {
767
J9ROMClassRegion *region = state.sortedRegions[i];
768
769
/* Skip duplicates (e.g. if there were two SRPs to the same thing). */
770
if ((i > 0) && isSameRegion(region, state.sortedRegions[i - 1])) {
771
continue;
772
}
773
774
/* Are we matching? */
775
if (NULL != componentToMatch) {
776
/* Does the nesting level correspond to what we're looking for? */
777
if (nesting == componentToMatch->componentIndex) {
778
if (J9ROM_SECTION_END != region->type) {
779
/* Either a section start, or a field - check if it matches the next component. */
780
if (regionNameMatchesComponent(region, componentToMatch)) {
781
currentArrayIndex++;
782
/* It's a match if the currentArrayIndex equals the arrayIndex of the component. */
783
if (currentArrayIndex == componentToMatch->arrayIndex) {
784
componentToMatch = componentToMatch->next;
785
if (NULL == componentToMatch) {
786
/* Done matching. Reset nesting for printing stage. */
787
nesting = 0;
788
} else {
789
/* Reset currentArrayIndex for matching the next query component. */
790
currentArrayIndex = -1;
791
}
792
}
793
}
794
} else if (regionNameMatchesComponent(region, componentToMatch->prev)) {
795
/* This is the end of the section that matched the previous component. Query matched nothing. */
796
break;
797
}
798
}
799
800
if (NULL != componentToMatch) {
801
if (J9ROM_SECTION_START == region->type) {
802
nesting++;
803
} else if (J9ROM_SECTION_END == region->type) {
804
nesting--;
805
}
806
}
807
}
808
809
/* Are we printing? */
810
if (NULL == componentToMatch) {
811
char buf[256];
812
813
if (J9ROM_SECTION_START == region->type) {
814
j9str_printf(PORTLIB, buf, sizeof(buf), "Section Start: %s (%d bytes)", region->name, region->length);
815
j9tty_printf(PORTLIB, "=== %-59s ===\n", buf);
816
nesting++;
817
} else if (J9ROM_SECTION_END == region->type) {
818
nesting--;
819
j9str_printf(PORTLIB, buf, sizeof(buf), "Section End: %s", region->name);
820
j9tty_printf(PORTLIB, "=== %-59s ===\n", buf);
821
if (0 == nesting) {
822
queryMatched = TRUE;
823
break;
824
}
825
} else {
826
printRegionLine(portLib, &state, romClass, region, base);
827
if (0 == nesting) {
828
queryMatched = TRUE;
829
break;
830
}
831
}
832
}
833
}
834
835
if (FALSE == queryMatched) {
836
j9tty_printf(PORTLIB, "Warning: Query '%s' matched nothing!\n", queries[queryIndex]);
837
}
838
}
839
840
pool_kill(queryComponentPool);
841
cleanupGatherROMClassLayoutInfoState(portLib, &state);
842
}
843
844
void
845
j9bcutil_queryROMClassCommaSeparated(J9PortLibrary *portLib, J9ROMClass *romClass, void *baseAddress, const char *commaSeparatedQueries, J9ROMClassValidateRangeCallback validateRangeCallback)
846
{
847
char **queries;
848
UDATA i, numQueries;
849
char *string;
850
UDATA stringLength;
851
852
PORT_ACCESS_FROM_PORT(portLib);
853
854
stringLength = strlen(commaSeparatedQueries);
855
string = j9mem_allocate_memory(stringLength + 1, J9MEM_CATEGORY_CLASSES);
856
if (NULL == string) {
857
j9tty_printf(PORTLIB, "Insufficient memory to complete operation\n");
858
return;
859
}
860
861
numQueries = 1;
862
for (i = 0; i <= stringLength; i++) {
863
string[i] = commaSeparatedQueries[i];
864
if (',' == string[i]) {
865
numQueries++;
866
}
867
}
868
869
queries = j9mem_allocate_memory(sizeof(char *) * numQueries, J9MEM_CATEGORY_CLASSES);
870
if (NULL == queries) {
871
j9mem_free_memory(string);
872
j9tty_printf(PORTLIB, "Insufficient memory to complete operation\n");
873
return;
874
}
875
876
queries[0] = string;
877
numQueries = 1;
878
879
for (i = 0; i < stringLength; i++) {
880
if (',' == string[i]) {
881
string[i] = '\0';
882
queries[numQueries++] = &string[i] + 1;
883
}
884
}
885
886
j9bcutil_queryROMClass(portLib, romClass, baseAddress, (const char **)queries, numQueries, validateRangeCallback);
887
888
j9mem_free_memory(queries);
889
j9mem_free_memory(string);
890
}
891
892
static void
893
printIndentation(J9PortLibrary *portLib, UDATA n)
894
{
895
UDATA i;
896
PORT_ACCESS_FROM_PORT(portLib);
897
898
for (i = 0; i < n; i++) {
899
j9tty_printf(PORTLIB, "\t");
900
}
901
}
902
903
static void
904
getRegionValueStringXML(J9PortLibrary *portLib, J9ROMClass *romClass, J9ROMClassRegion *region, char *str, size_t strSize)
905
{
906
void *fieldPtr;
907
908
PORT_ACCESS_FROM_PORT(portLib);
909
910
fieldPtr = (void *)((UDATA)romClass + region->offset);
911
912
switch (region->type) {
913
case J9ROM_U8:
914
j9str_printf(PORTLIB, str, strSize, "%u", *(U_8 *)fieldPtr);
915
return;
916
case J9ROM_U16:
917
j9str_printf(PORTLIB, str, strSize, "%u", *(U_16 *)fieldPtr);
918
return;
919
case J9ROM_U32:
920
j9str_printf(PORTLIB, str, strSize, "%u", *(U_32 *)fieldPtr);
921
return;
922
case J9ROM_U64:
923
j9str_printf(PORTLIB, str, strSize, "%llu", *(U_64 *)fieldPtr);
924
return;
925
case J9ROM_UTF8: {
926
J9UTF8 *utf8 = fieldPtr;
927
escapeUTF8(PORTLIB, utf8, str, strSize);
928
return;
929
}
930
case J9ROM_SRP:
931
j9str_printf(PORTLIB, str, strSize, "0x%08x", *(J9SRP *)fieldPtr);
932
return;
933
case J9ROM_WSRP:
934
j9str_printf(PORTLIB, str, strSize, "0x%08x", *(J9WSRP *)fieldPtr);
935
return;
936
}
937
938
j9str_printf(PORTLIB, str, strSize, "error>");
939
}
940
941
void
942
j9bcutil_linearDumpROMClassXML(J9PortLibrary *portLib, J9ROMClass *romClass, J9ROMClassValidateRangeCallback validateRangeCallback)
943
{
944
J9ROMClassGatherLayoutInfoState state;
945
UDATA i, nesting;
946
BOOLEAN success;
947
948
PORT_ACCESS_FROM_PORT(portLib);
949
950
success = gatherROMClassLayoutInfo(portLib, romClass, validateRangeCallback, &state);
951
if (FALSE == success) {
952
return;
953
}
954
955
j9tty_printf(PORTLIB, "<J9ROMClass>\n\n");
956
nesting = 1;
957
958
for (i = 0; i < state.numRegions; i++) {
959
J9ROMClassRegion *region = state.sortedRegions[i];
960
961
/* Skip duplicates (e.g. if there were two SRPs to the same thing). */
962
if ((i > 0) && isSameRegion(region, state.sortedRegions[i - 1])) {
963
continue;
964
}
965
966
if (J9ROM_SECTION_START == region->type) {
967
printIndentation(portLib, nesting);
968
j9tty_printf(PORTLIB, "<section name=\"%s\">\n", region->name);
969
nesting++;
970
} else if (J9ROM_SECTION_END == region->type) {
971
nesting--;
972
printIndentation(portLib, nesting);
973
j9tty_printf(PORTLIB, "</section>\n");
974
} else {
975
const char *typeName;
976
char value[256];
977
978
typeName = getTypeName(region->type);
979
getRegionValueStringXML(portLib, romClass, region, value, sizeof(value));
980
981
printIndentation(portLib, nesting);
982
j9tty_printf(PORTLIB, "<%s name=\"%s\">%s</%s>\n", typeName, region->name, value, typeName);
983
}
984
}
985
j9tty_printf(PORTLIB, "</J9ROMClass>\n");
986
987
cleanupGatherROMClassLayoutInfoState(portLib, &state);
988
}
989
990