Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcverify/bcverify.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 <string.h>
24
25
#include "bcvcfr.h"
26
#include "bcverify.h"
27
#include "j9bcvnls.h"
28
29
#include "cfreader.h"
30
#include "bcnames.h"
31
#include "pcstack.h"
32
#include "j9cp.h"
33
#include "j9protos.h"
34
#include "j9consts.h"
35
#include "omrthread.h"
36
#include "jvminit.h"
37
#include "vrfyconvert.h"
38
#include "bcverify_internal.h"
39
#include "vrfytbl.h"
40
#include "vmhook_internal.h"
41
#include "SCQueryFunctions.h"
42
43
#define _UTE_STATIC_
44
#include "ut_j9bcverify.h"
45
46
#include "bcverify.h"
47
48
/* Define for debug
49
#define DEBUG_BCV
50
*/
51
52
#define BYTECODE_MAP_DEFAULT_SIZE (2 * 1024)
53
#define STACK_MAPS_DEFAULT_SIZE (2 * 1024)
54
#define LIVE_STACK_DEFAULT_SIZE 256
55
#define ROOT_QUEUE_DEFAULT_SIZE 256
56
#define CLASSNAMELIST_DEFAULT_SIZE (128 * sizeof(UDATA *)) /* 128 pointers */
57
#define CLASSNAMESEGMENT_DEFAULT_SIZE 1024 /* 1k bytes - minimum of 8 bytes per classNameList entry */
58
59
#define BCV_INTERNAL_DEFAULT_SIZE (32*1024)
60
61
#define THIS_DLL_NAME J9_VERIFY_DLL_NAME
62
#define OPT_XVERIFY "-Xverify"
63
#define OPT_XVERIFY_COLON "-Xverify:"
64
#define OPT_ALL "all"
65
#define OPT_OPT "opt"
66
#define OPT_NO_OPT "noopt"
67
#define OPT_NO_FALLBACK "nofallback"
68
#define OPT_IGNORE_STACK_MAPS "ignorestackmaps"
69
#define OPT_EXCLUDEATTRIBUTE_EQUAL "excludeattribute="
70
#define OPT_BOOTCLASSPATH_STATIC "bootclasspathstatic"
71
#define OPT_DO_PROTECTED_ACCESS_CHECK "doProtectedAccessCheck"
72
73
static IDATA buildBranchMap (J9BytecodeVerificationData * verifyData);
74
static IDATA decompressStackMaps (J9BytecodeVerificationData * verifyData, IDATA localsCount, U_8 * stackMapData);
75
static VMINLINE IDATA parseLocals (J9BytecodeVerificationData * verifyData, U_8** stackMapData, J9BranchTargetStack * liveStack, IDATA localDelta, IDATA localsCount, IDATA maxLocals);
76
static VMINLINE IDATA parseStack (J9BytecodeVerificationData * verifyData, U_8** stackMapData, J9BranchTargetStack * liveStack, UDATA stackCount, UDATA maxStack);
77
static UDATA parseElement (J9BytecodeVerificationData * verifyData, U_8 ** stackMapData);
78
static VMINLINE void copyStack (J9BranchTargetStack *source, J9BranchTargetStack *destination);
79
static IDATA mergeObjectTypes (J9BytecodeVerificationData *verifyData, UDATA sourceType, UDATA * targetTypePointer);
80
static IDATA mergeStacks (J9BytecodeVerificationData * verifyData, UDATA target);
81
static J9UTF8 * mergeClasses(J9BytecodeVerificationData *verifyData, U_8* firstClass, UDATA firstLength, U_8* secondClass, UDATA secondLength, IDATA *reasonCode);
82
static void bcvHookClassesUnload (J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
83
static void printMethod (J9BytecodeVerificationData * verifyData);
84
static IDATA simulateStack (J9BytecodeVerificationData * verifyData);
85
86
static IDATA parseOptions (J9JavaVM *vm, char *optionValues, char **errorString);
87
static IDATA setVerifyState ( J9JavaVM *vm, char *option, char **errorString );
88
89
90
/**
91
* Walk the J9-format stack maps and set the uninitialized_this flag appropriately
92
* for each map. It is set to TRUE for the map, if the map's stack contains an
93
* uninitialized_this object.
94
* NOTE: This is only necessary for <init> methods.
95
*/
96
static void
97
setInitializedThisStatus(J9BytecodeVerificationData *verifyData)
98
{
99
J9BranchTargetStack * currentStack = NULL;
100
IDATA nextMapIndex = 0;
101
102
while (nextMapIndex < verifyData->stackMapsCount) {
103
currentStack = BCV_INDEX_STACK (nextMapIndex);
104
nextMapIndex++;
105
106
/* Ensure we're not a stack map for dead code */
107
if (currentStack->stackBaseIndex != -1) {
108
BOOLEAN flag_uninitialized = FALSE;
109
IDATA i = 0;
110
for (; i < currentStack->stackTopIndex; i++) {
111
if ((currentStack->stackElements[i] & BCV_SPECIAL_INIT) == BCV_SPECIAL_INIT) {
112
flag_uninitialized = TRUE;
113
break;
114
}
115
}
116
currentStack->uninitializedThis = flag_uninitialized;
117
}
118
}
119
}
120
121
122
123
/*
124
API
125
@verifyData - internal data structure
126
@firstClass - U_8 pointer to class name
127
@firstLength - UDATA length of class name
128
@secondClass - U_8 pointer to class name
129
@secondLength - UDATA length of class name
130
131
Answer the first common class shared by the two classes.
132
If one of the classes is a parent of the other, answer that class.
133
Return NULL on error.
134
sets reasonCode to BCV_FAIL on verification error
135
sets reasonCode to BCV_ERR_INSUFFICIENT_MEMORY on OOM
136
sets reasonCode to BCV_ERR_INTERNAL_ERROR otherwise
137
*/
138
#define SUPERCLASS(clazz) ((clazz)->superclasses[ J9CLASS_DEPTH(clazz) - 1 ])
139
static J9UTF8 *
140
mergeClasses(J9BytecodeVerificationData *verifyData, U_8* firstClass, UDATA firstLength, U_8* secondClass, UDATA secondLength, IDATA *reasonCode)
141
{
142
J9Class *sourceRAM, *targetRAM;
143
UDATA sourceDepth, targetDepth;
144
145
/* Go get the ROM class for the source and target. Check if it returns null immediately to prevent
146
* having to load the second class in an error case */
147
sourceRAM = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, firstClass, firstLength, reasonCode);
148
if (NULL == sourceRAM) {
149
return NULL;
150
}
151
152
targetRAM = j9rtv_verifierGetRAMClass( verifyData, verifyData->classLoader, secondClass, secondLength, reasonCode );
153
if (NULL == targetRAM) {
154
return NULL;
155
}
156
sourceRAM = J9_CURRENT_CLASS(sourceRAM);
157
sourceDepth = J9CLASS_DEPTH(sourceRAM);
158
targetDepth = J9CLASS_DEPTH(targetRAM);
159
160
/* walk up the chain until sourceROM == targetROM */
161
while( sourceRAM != targetRAM ) {
162
if( sourceDepth >= targetDepth ) {
163
sourceRAM = SUPERCLASS(sourceRAM);
164
if ( sourceRAM ) {
165
sourceDepth = J9CLASS_DEPTH(sourceRAM);
166
}
167
}
168
if (sourceRAM == targetRAM )
169
break;
170
if( sourceDepth <= targetDepth ) {
171
targetRAM = SUPERCLASS(targetRAM);
172
if ( targetRAM ) {
173
targetDepth = J9CLASS_DEPTH(targetRAM);
174
}
175
}
176
if( (sourceRAM == NULL) || (targetRAM == NULL) ) {
177
*reasonCode = BCV_FAIL;
178
return NULL;
179
}
180
}
181
182
/* good, both sourceROM and targetROM are the same class -- this is the new target class */
183
return( J9ROMCLASS_CLASSNAME( targetRAM->romClass ) );
184
}
185
#undef SUPERCLASS
186
187
188
/*
189
Determine the number of branch targets in this method.
190
191
Returns
192
count of unique branch targets and exception handler starts.
193
BCV_ERR_INTERNAL_ERROR for any unexpected error
194
*/
195
196
static IDATA
197
buildBranchMap (J9BytecodeVerificationData * verifyData)
198
{
199
J9ROMMethod *romMethod = verifyData->romMethod;
200
U_32 *bytecodeMap = verifyData->bytecodeMap;
201
U_8 *bcStart;
202
U_8 *bcIndex;
203
U_8 *bcEnd;
204
UDATA npairs, temp;
205
IDATA pc, start, high, low, pcs;
206
I_16 shortBranch;
207
I_32 longBranch;
208
UDATA bc, size;
209
UDATA count = 0;
210
211
bcStart = J9_BYTECODE_START_FROM_ROM_METHOD(romMethod);
212
bcIndex = bcStart;
213
bcEnd = bcStart + J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
214
215
while (bcIndex < bcEnd) {
216
bc = *bcIndex;
217
size = J9JavaInstructionSizeAndBranchActionTable[bc];
218
if (size == 0) {
219
verifyData->errorPC = bcIndex - bcStart;
220
Trc_BCV_buildBranchMap_UnknownInstruction(verifyData->vmStruct,
221
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
222
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
223
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
224
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
225
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
226
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
227
bc, verifyData->errorPC, verifyData->errorPC);
228
return BCV_ERR_INTERNAL_ERROR;
229
}
230
231
switch (size >> 4) {
232
233
case 5: /* switches */
234
start = bcIndex - bcStart;
235
pc = (start + 4) & ~3;
236
bcIndex = bcStart + pc;
237
longBranch = (I_32) PARAM_32(bcIndex, 0);
238
bcIndex += 4;
239
if (bytecodeMap[start + longBranch] == 0) {
240
bytecodeMap[start + longBranch] = BRANCH_TARGET;
241
count++;
242
}
243
low = (I_32) PARAM_32(bcIndex, 0);
244
bcIndex += 4;
245
low = (I_32) low;
246
if (bc == JBtableswitch) {
247
high = (I_32) PARAM_32(bcIndex, 0);
248
bcIndex += 4;
249
high = (I_32) high;
250
npairs = (UDATA) (high - low + 1);
251
pcs = 0;
252
} else {
253
npairs = (UDATA) low;
254
pcs = 4;
255
}
256
257
for (temp = 0; temp < npairs; temp++) {
258
bcIndex += pcs;
259
longBranch = (I_32) PARAM_32(bcIndex, 0);
260
bcIndex += 4;
261
if (bytecodeMap[start + longBranch] == 0) {
262
bytecodeMap[start + longBranch] = BRANCH_TARGET;
263
count++;
264
}
265
}
266
continue;
267
268
case 2: /* gotos */
269
if (bc == JBgotow) {
270
start = bcIndex - bcStart;
271
longBranch = (I_32) PARAM_32(bcIndex, 1);
272
if (bytecodeMap[start + longBranch] == 0) {
273
bytecodeMap[start + longBranch] = BRANCH_TARGET;
274
count++;
275
}
276
break;
277
} /* fall through for JBgoto */
278
279
case 1: /* ifs */
280
shortBranch = (I_16) PARAM_16(bcIndex, 1);
281
start = bcIndex - bcStart;
282
if (bytecodeMap[start + shortBranch] == 0) {
283
bytecodeMap[start + shortBranch] = BRANCH_TARGET;
284
count++;
285
}
286
break;
287
288
}
289
bcIndex += size & 7;
290
}
291
292
/* need to walk exceptions as well, since they are branch targets */
293
if (romMethod->modifiers & J9AccMethodHasExceptionInfo) {
294
J9ExceptionInfo * exceptionData = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
295
J9ExceptionHandler *handler;
296
297
if (exceptionData->catchCount) {
298
handler = J9EXCEPTIONINFO_HANDLERS(exceptionData);
299
for (temp=0; temp < (U_32) exceptionData->catchCount; temp++) {
300
pc = (IDATA) handler->startPC;
301
pcs = (IDATA) handler->handlerPC;
302
/* Avoid re-walking a handler that handles itself */
303
if (pc != pcs) {
304
bytecodeMap[pc] |= BRANCH_EXCEPTION_START;
305
}
306
if ((bytecodeMap[pcs] & BRANCH_TARGET) == 0) {
307
bytecodeMap[pcs] |= BRANCH_TARGET;
308
count++;
309
}
310
handler++;
311
}
312
}
313
}
314
Trc_BCV_buildBranchMap_branchCount(verifyData->vmStruct,
315
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
316
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
317
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
318
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
319
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
320
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
321
count);
322
323
return count;
324
}
325
326
327
328
/*
329
Convert the StackMap Attribute maps to internal uncompressed stackmaps.
330
331
Returns
332
BCV_SUCCESS on success,
333
BCV_FAIL on verification error
334
*/
335
static IDATA
336
decompressStackMaps (J9BytecodeVerificationData * verifyData, IDATA localsCount, U_8 * stackMapData)
337
{
338
J9ROMMethod *romMethod = verifyData->romMethod;
339
UDATA maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);
340
IDATA maxLocals = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod);
341
UDATA length = (UDATA) J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
342
UDATA i;
343
IDATA rc = BCV_SUCCESS;
344
J9BranchTargetStack *liveStack = (J9BranchTargetStack *)verifyData->liveStack;
345
J9BranchTargetStack *branchTargetStack = BCV_FIRST_STACK();
346
U_8 mapType;
347
UDATA mapPC = -1;
348
UDATA temp;
349
UDATA start = 0; /* Used in BUILD_VERIFY_ERROR */
350
UDATA mapIndex = 0;
351
UDATA errorModule = J9NLS_BCV_ERR_NO_ERROR__MODULE; /* default to BCV NLS catalog */
352
353
Trc_BCV_decompressStackMaps_Entry(verifyData->vmStruct, localsCount);
354
/* localsCount records the current locals depth as all stack maps (except full frame) are relative to the previous frame */
355
for (i = 0; i < (UDATA) verifyData->stackMapsCount; i++) {
356
IDATA localDelta = 0;
357
UDATA stackCount = 0;
358
359
NEXT_U8(mapType, stackMapData);
360
mapPC++;
361
362
if (mapType < CFR_STACKMAP_SAME_LOCALS_1_STACK) {
363
/* Same frame 0-63 */
364
mapPC += (UDATA) mapType;
365
/* done */
366
367
} else if (mapType < CFR_STACKMAP_SAME_LOCALS_1_STACK_END) {
368
/* Same with one stack entry frame 64-127 */
369
mapPC += (UDATA) ((UDATA) mapType - CFR_STACKMAP_SAME_LOCALS_1_STACK);
370
stackCount = 1;
371
372
} else {
373
mapPC += NEXT_U16(temp, stackMapData);
374
375
if (mapType == CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED) {
376
/* Same with one stack entry extended address frame 247 */
377
stackCount = 1;
378
379
} else if (mapType < CFR_STACKMAP_FULL) {
380
/* Chop 3-1 locals frame 248-250 */
381
/* Same with extended address frame 251 */
382
/* Append 1-3 locals frame 252-254 */
383
localDelta = ((IDATA) mapType) - CFR_STACKMAP_SAME_EXTENDED;
384
385
} else if (mapType == CFR_STACKMAP_FULL) {
386
/* Full frame 255 */
387
localDelta = NEXT_U16(temp, stackMapData);
388
localsCount = 0;
389
}
390
}
391
392
localsCount = parseLocals (verifyData, &stackMapData, liveStack, localDelta, localsCount, maxLocals);
393
if (localsCount < 0) {
394
BUILD_VERIFY_ERROR (errorModule, J9NLS_BCV_ERR_INCONSISTENT_STACK__ID);
395
/* Jazz 82615: Set the pc value of the current stackmap frame to show up in the error message frame work */
396
liveStack->pc = mapPC;
397
verifyData->errorPC = mapPC;
398
399
Trc_BCV_decompressStackMaps_LocalsArrayOverFlowUnderFlow(verifyData->vmStruct,
400
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
401
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
402
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
403
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
404
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
405
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
406
i, mapPC);
407
rc = BCV_FAIL;
408
break;
409
}
410
411
if (mapType == CFR_STACKMAP_FULL) {
412
stackCount = NEXT_U16(temp, stackMapData);
413
}
414
415
if (BCV_SUCCESS != parseStack (verifyData, &stackMapData, liveStack, stackCount, maxStack)) {
416
BUILD_VERIFY_ERROR (errorModule, J9NLS_BCV_ERR_INCONSISTENT_STACK__ID);
417
/* Jazz 82615: Set the pc value of the current stackmap frame to show up in the error message frame work */
418
liveStack->pc = mapPC;
419
verifyData->errorPC = mapPC;
420
421
Trc_BCV_decompressStackMaps_StackArrayOverFlow(verifyData->vmStruct,
422
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
423
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
424
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
425
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
426
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
427
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
428
i, mapPC);
429
rc = BCV_FAIL;
430
break;
431
}
432
433
if (mapPC >= length) {
434
/* should never get here - caught in staticverify.c checkStackMap */
435
BUILD_VERIFY_ERROR (errorModule, J9NLS_BCV_ERR_INCONSISTENT_STACK__ID);
436
Trc_BCV_decompressStackMaps_MapOutOfRange(verifyData->vmStruct,
437
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
438
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
439
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
440
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
441
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
442
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
443
i, mapPC, length);
444
rc = BCV_FAIL;
445
break;
446
}
447
448
(verifyData->bytecodeMap)[mapPC] |= (mapIndex << BRANCH_INDEX_SHIFT) | BRANCH_TARGET;
449
mapIndex++;
450
451
copyStack (liveStack, branchTargetStack);
452
branchTargetStack->pc = mapPC;
453
/* Point to the next stack */
454
branchTargetStack = BCV_NEXT_STACK (branchTargetStack);
455
}
456
457
Trc_BCV_decompressStackMaps_Exit(verifyData->vmStruct, rc);
458
return rc;
459
}
460
461
462
463
/* Specifically returns BCV_ERR_INTERNAL_ERROR for failure */
464
465
static IDATA
466
parseLocals (J9BytecodeVerificationData * verifyData, U_8** stackMapData, J9BranchTargetStack * liveStack, IDATA localDelta, IDATA localsCount, IDATA maxLocals)
467
{
468
UDATA i;
469
UDATA stackEntry;
470
UDATA unusedLocals;
471
472
if (localDelta < 0) {
473
/* Clear the chopped elements */
474
for (;localDelta; localDelta++) {
475
localsCount--;
476
if (localsCount < 0) {
477
goto _underflow;
478
}
479
liveStack->stackElements[localsCount] = BCV_BASE_TYPE_TOP;
480
481
/* Check long/double type as long as there still remains local variables
482
* in the stackmap frame.
483
*/
484
if (localsCount > 0) {
485
/* Possibly remove a double or long (counts as 1 local, but two slots).
486
* A double or a long is pushed as <top, double|long>
487
*/
488
stackEntry = liveStack->stackElements[localsCount - 1];
489
if ((BCV_BASE_TYPE_DOUBLE == stackEntry) || (BCV_BASE_TYPE_LONG == stackEntry)) {
490
localsCount--;
491
if (localsCount < 0) {
492
goto _underflow;
493
}
494
liveStack->stackElements[localsCount] = BCV_BASE_TYPE_TOP;
495
}
496
}
497
}
498
499
} else {
500
for (;localDelta; localDelta--) {
501
stackEntry = parseElement (verifyData, stackMapData);
502
if (localsCount >= maxLocals) {
503
/* Overflow */
504
goto _overflow;
505
}
506
liveStack->stackElements[localsCount++] = stackEntry;
507
if ((BCV_BASE_TYPE_DOUBLE == stackEntry) || (BCV_BASE_TYPE_LONG == stackEntry)) {
508
if (localsCount >= maxLocals) {
509
/* Overflow */
510
goto _overflow;
511
}
512
liveStack->stackElements[localsCount++] = BCV_BASE_TYPE_TOP;
513
}
514
}
515
516
/* Clear the remaining locals */
517
unusedLocals = liveStack->stackBaseIndex - localsCount;
518
for (i = localsCount; i < (unusedLocals + localsCount); i++) {
519
liveStack->stackElements[i] = BCV_BASE_TYPE_TOP;
520
}
521
}
522
523
return localsCount;
524
525
_underflow:
526
/* Jazz 82615: Set the error code in the case of underflow on 'locals' in the current stackmap frame */
527
verifyData->errorDetailCode = BCV_ERR_STACKMAP_FRAME_LOCALS_UNDERFLOW;
528
529
Trc_BCV_parseLocals_LocalsArrayUnderFlow(verifyData->vmStruct,
530
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
531
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
532
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
533
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
534
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
535
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
536
return BCV_ERR_INTERNAL_ERROR;
537
538
_overflow:
539
/* Jazz 82615: Set the error code, the location of the last local variable allowed on 'locals'
540
* and the maximum local size in the case of overflow on 'locals' in the currrent stackmap frame.
541
*/
542
verifyData->errorDetailCode = BCV_ERR_STACKMAP_FRAME_LOCALS_OVERFLOW;
543
verifyData->errorCurrentFramePosition = (maxLocals > 0) ? (U_32)(maxLocals - 1) : 0;
544
verifyData->errorTempData = (UDATA)maxLocals;
545
546
Trc_BCV_parseLocals_LocalsArrayOverFlow(verifyData->vmStruct,
547
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
548
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
549
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
550
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
551
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
552
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
553
return BCV_ERR_INTERNAL_ERROR;
554
}
555
556
557
/*
558
* returns BCV_SUCCESS on success
559
* returns BCV_ERR_INTERNAL_ERROR on failure
560
*/
561
562
static IDATA
563
parseStack (J9BytecodeVerificationData * verifyData, U_8** stackMapData, J9BranchTargetStack * liveStack, UDATA stackCount, UDATA maxStack)
564
{
565
UDATA stackEntry;
566
UDATA* stackTop = RELOAD_STACKBASE(liveStack); /* Clears the stack */
567
UDATA* stackBase = stackTop;
568
569
for (;stackCount; stackCount--) {
570
stackEntry = parseElement (verifyData, stackMapData);
571
if ((UDATA) (stackTop - stackBase) >= maxStack) {
572
/* Jazz 82615: Set the error code and the location of wrong data type on 'stack' (only keep the maximum size for stack) */
573
verifyData->errorDetailCode = BCV_ERR_STACKMAP_FRAME_STACK_OVERFLOW;
574
verifyData->errorCurrentFramePosition = (U_32)(stackBase - liveStack->stackElements);
575
if (maxStack > 0) {
576
verifyData->errorCurrentFramePosition += (U_32)(maxStack - 1);
577
}
578
verifyData->errorTempData = maxStack;
579
return BCV_ERR_INTERNAL_ERROR;
580
}
581
PUSH(stackEntry);
582
if ((stackEntry == BCV_BASE_TYPE_DOUBLE) || (stackEntry == BCV_BASE_TYPE_LONG)) {
583
if ((UDATA) (stackTop - stackBase) >= maxStack) {
584
/* Jazz 82615: Set the error code and the location of wrong data type on 'stack' (only keep the maximum size for stack) */
585
verifyData->errorDetailCode = BCV_ERR_STACKMAP_FRAME_STACK_OVERFLOW;
586
verifyData->errorCurrentFramePosition = (U_32)(stackBase - liveStack->stackElements);
587
if (maxStack > 0) {
588
verifyData->errorCurrentFramePosition += (U_32)(maxStack - 1);
589
}
590
verifyData->errorTempData = maxStack;
591
return BCV_ERR_INTERNAL_ERROR;
592
}
593
PUSH(BCV_BASE_TYPE_TOP);
594
}
595
}
596
597
SAVE_STACKTOP(liveStack, stackTop);
598
return BCV_SUCCESS;
599
}
600
601
602
/*
603
* returns stackEntry
604
* No error path in this function
605
*/
606
607
static UDATA
608
parseElement (J9BytecodeVerificationData * verifyData, U_8** stackMapData)
609
{
610
J9ROMClass * romClass = verifyData->romClass;
611
U_8 entryType;
612
U_8 *mapData = *stackMapData;
613
U_16 cpIndex;
614
UDATA stackEntry;
615
616
NEXT_U8(entryType, mapData);
617
618
if (entryType < CFR_STACKMAP_TYPE_INIT_OBJECT) {
619
/* return primitive type */
620
stackEntry = verificationTokenDecode[entryType];
621
622
} else if (entryType == CFR_STACKMAP_TYPE_INIT_OBJECT) {
623
J9ROMMethod *romMethod = verifyData->romMethod;
624
J9UTF8* className = J9ROMCLASS_CLASSNAME(romClass);
625
stackEntry = convertClassNameToStackMapType(verifyData, J9UTF8_DATA(className), J9UTF8_LENGTH(className), BCV_SPECIAL_INIT, 0);
626
627
} else if (entryType == CFR_STACKMAP_TYPE_OBJECT) {
628
J9UTF8 *utf8string;
629
J9ROMConstantPoolItem *constantPool = J9_ROM_CP_FROM_ROM_CLASS(romClass);
630
631
NEXT_U16(cpIndex, mapData);
632
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) (&constantPool[cpIndex]));
633
pushClassType(verifyData, utf8string, &stackEntry);
634
635
} else if (entryType == CFR_STACKMAP_TYPE_NEW_OBJECT) {
636
NEXT_U16(cpIndex, mapData);
637
stackEntry = BCV_SPECIAL_NEW | (((UDATA) cpIndex) << BCV_CLASS_INDEX_SHIFT);
638
639
} else {
640
/* Primitive arrays */
641
U_16 arity;
642
643
stackEntry = (UDATA) verificationTokenDecode[entryType];
644
NEXT_U16(arity, mapData);
645
stackEntry |= (((UDATA) arity) << BCV_ARITY_SHIFT);
646
}
647
648
*stackMapData = mapData;
649
return stackEntry;
650
}
651
652
653
654
static void
655
copyStack (J9BranchTargetStack *source, J9BranchTargetStack *destination)
656
{
657
UDATA pc = destination->pc;
658
659
memcpy((UDATA *) destination, (UDATA *) source, (source->stackTopIndex + BCV_TARGET_STACK_HEADER_UDATA_SIZE) * sizeof(UDATA));
660
661
destination->pc = pc;
662
}
663
664
665
/* returns
666
* BCV_SUCCESS : no merge necessary
667
* BCV_FAIL : cause a rewalk
668
* BCV_ERR_INSUFFICIENT_MEMORY : OOM - no rewalk
669
*/
670
static IDATA
671
mergeObjectTypes (J9BytecodeVerificationData *verifyData, UDATA sourceType, UDATA * targetTypePointer)
672
{
673
J9ROMClass * romClass = verifyData->romClass;
674
UDATA targetType = *targetTypePointer;
675
UDATA sourceIndex, targetIndex;
676
J9UTF8 *name;
677
UDATA classArity, targetArity, classIndex;
678
IDATA rc = BCV_SUCCESS;
679
U_8 *sourceName, *targetName;
680
UDATA sourceLength, targetLength;
681
U_32 *offset;
682
IDATA reasonCode = 0;
683
684
/* assume that sourceType and targetType are not equal */
685
686
/* if target is more general than source, then its fine */
687
rc = isClassCompatible( verifyData, sourceType, targetType, &reasonCode ) ;
688
689
if (TRUE == rc) {
690
return BCV_SUCCESS; /* no merge required */
691
} else { /* FALSE == rc */
692
/* VM error, no need to continue, return appropriate rc */
693
if (BCV_ERR_INTERNAL_ERROR == reasonCode) {
694
*targetTypePointer = (U_32)BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT;
695
Trc_BCV_mergeObjectTypes_UnableToLoadClass(verifyData->vmStruct,
696
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
697
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
698
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
699
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
700
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
701
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
702
sourceType, targetType);
703
return (IDATA) BCV_FAIL;
704
} else if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
705
Trc_BCV_mergeObjectTypes_MergeClasses_OutOfMemoryException(verifyData->vmStruct,
706
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
707
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
708
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
709
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
710
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
711
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
712
return BCV_ERR_INSUFFICIENT_MEMORY;
713
}
714
}
715
716
/* Types were not compatible, thus target is not equal or more general than source */
717
718
/* NULL always loses to objects */
719
if (targetType == BCV_BASE_TYPE_NULL) {
720
Trc_BCV_mergeObjectTypes_NullTargetOverwritten(verifyData->vmStruct,
721
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
722
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
723
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
724
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
725
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
726
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
727
sourceType);
728
*targetTypePointer = sourceType;
729
/* cause a re-walk */
730
return (IDATA) BCV_FAIL;
731
}
732
733
/* if the source or target are base type arrays, decay them to object arrays of arity n-1 (or just Object) */
734
/* Base arrays already have an implicit arity of 1, so just keep the arity for object */
735
if (sourceType & BCV_TAG_BASE_ARRAY_OR_NULL) {
736
Trc_BCV_mergeObjectTypes_DecaySourceArray(verifyData->vmStruct,
737
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
738
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
739
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
740
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
741
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
742
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
743
sourceType);
744
sourceType = (sourceType & BCV_ARITY_MASK) | ((U_32)BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT);
745
}
746
747
if (targetType & BCV_TAG_BASE_ARRAY_OR_NULL) {
748
Trc_BCV_mergeObjectTypes_DecayTargetArray(verifyData->vmStruct,
749
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
750
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
751
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
752
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
753
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
754
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
755
targetType);
756
targetType = (targetType & BCV_ARITY_MASK) | ((U_32)BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT);
757
}
758
759
classArity = sourceType & BCV_ARITY_MASK;
760
targetArity = targetType & BCV_ARITY_MASK;
761
762
if (classArity == targetArity) {
763
/* Find the common parent class if the same arity */
764
765
sourceIndex = (sourceType & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT;
766
targetIndex = (targetType & BCV_CLASS_INDEX_MASK) >> BCV_CLASS_INDEX_SHIFT;
767
768
offset = (U_32 *) verifyData->classNameList[sourceIndex];
769
sourceLength = (UDATA) J9UTF8_LENGTH(offset + 1);
770
771
if (offset[0] == 0) {
772
sourceName = J9UTF8_DATA(offset + 1);
773
774
} else {
775
sourceName = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);
776
}
777
778
offset = (U_32 *) verifyData->classNameList[targetIndex];
779
targetLength = (UDATA) J9UTF8_LENGTH(offset + 1);
780
781
if (offset[0] == 0) {
782
targetName = J9UTF8_DATA(offset + 1);
783
784
} else {
785
targetName = (U_8 *) ((UDATA) offset[0] + (UDATA) romClass);
786
}
787
788
name = mergeClasses(verifyData, sourceName, sourceLength, targetName, targetLength, &reasonCode);
789
790
if (NULL == name) {
791
if (BCV_ERR_INSUFFICIENT_MEMORY == reasonCode) {
792
Trc_BCV_mergeObjectTypes_MergeClasses_OutOfMemoryException(verifyData->vmStruct,
793
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
794
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
795
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
796
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
797
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
798
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)));
799
return BCV_ERR_INSUFFICIENT_MEMORY;
800
} else {
801
Trc_BCV_mergeObjectTypes_MergeClassesFail(verifyData->vmStruct,
802
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
803
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
804
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
805
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
806
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
807
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
808
sourceLength, sourceName, targetLength, targetName);
809
*targetTypePointer = sourceType;
810
/* cause a re-walk */
811
return (IDATA) BCV_FAIL;
812
}
813
}
814
815
classIndex = findClassName( verifyData, J9UTF8_DATA(name), J9UTF8_LENGTH(name) );
816
Trc_BCV_mergeObjectTypes_MergeClassesSucceed(verifyData->vmStruct,
817
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
818
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
819
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
820
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
821
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
822
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
823
sourceLength, sourceName, targetLength, targetName, J9UTF8_LENGTH(name), J9UTF8_DATA(name), classIndex);
824
825
} else {
826
827
/* Different arity means common parent class is the minimum arity of class Object */
828
classIndex = BCV_JAVA_LANG_OBJECT_INDEX;
829
830
Trc_BCV_mergeObjectTypes_MergeClassesMinimumArity(verifyData->vmStruct,
831
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
832
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
833
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
834
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
835
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
836
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
837
classArity, targetArity);
838
/* Find minimum common arity of arrays */
839
if( targetArity < classArity ) {
840
classArity = targetArity;
841
}
842
}
843
844
/* slam new type into targetTypePointer */
845
*targetTypePointer = classArity | ( classIndex << BCV_CLASS_INDEX_SHIFT );
846
Trc_BCV_mergeObjectTypes_MergedClass(verifyData->vmStruct,
847
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
848
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
849
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
850
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
851
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
852
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
853
*targetTypePointer);
854
/* cause a re-walk */
855
return (IDATA) BCV_FAIL;
856
}
857
858
/*
859
* returns BCV_SUCCESS on success
860
* returns BCV_FAIL on failure
861
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM */
862
static IDATA
863
mergeStacks (J9BytecodeVerificationData * verifyData, UDATA target)
864
{
865
J9ROMClass *romClass = verifyData->romClass;
866
J9ROMMethod *romMethod = verifyData->romMethod;
867
UDATA maxIndex = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod);
868
U_32 *bytecodeMap = verifyData->bytecodeMap;
869
UDATA i = 0;
870
UDATA stackIndex = bytecodeMap[target] >> BRANCH_INDEX_SHIFT;
871
IDATA rewalk = FALSE;
872
IDATA rc = BCV_SUCCESS;
873
UDATA *targetStackPtr = NULL;
874
UDATA *targetStackTop = NULL;
875
UDATA *sourceStackPtr = NULL;
876
UDATA *sourceStackTop = NULL;
877
UDATA *sourceStackTemps = NULL;
878
J9BranchTargetStack *liveStack = (J9BranchTargetStack *) verifyData->liveStack;
879
J9BranchTargetStack *targetStack = BCV_INDEX_STACK(stackIndex);
880
881
Trc_BCV_mergeStacks_Entry(verifyData->vmStruct,
882
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
883
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
884
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
885
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
886
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
887
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
888
target, target);
889
890
if (targetStack->stackBaseIndex == -1) {
891
892
/* Target location does not have a stack, so give the target our current stack */
893
copyStack(liveStack, targetStack);
894
verifyData->unwalkedQueue[verifyData->unwalkedQueueTail++] = target;
895
verifyData->unwalkedQueueTail %= (verifyData->rootQueueSize / sizeof(UDATA));
896
bytecodeMap[target] |= BRANCH_ON_UNWALKED_QUEUE;
897
Trc_BCV_mergeStacks_CopyStack(verifyData->vmStruct,
898
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
899
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
900
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
901
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
902
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
903
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
904
stackIndex, target, target);
905
goto _finished;
906
907
} else {
908
/* These variables are reused across loop iterations */
909
UDATA mergePC = (UDATA) -1;
910
U_32 resultArrayBase = 0;
911
912
/* Check stack size equality */
913
if (targetStack->stackTopIndex != liveStack->stackTopIndex) {
914
rc = BCV_FAIL;
915
Trc_BCV_mergeStacks_DepthMismatch(verifyData->vmStruct,
916
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
917
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
918
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
919
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
920
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
921
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
922
stackIndex, target, target,
923
liveStack->stackTopIndex, targetStack->stackTopIndex);
924
goto _finished;
925
}
926
927
/* Now we have to merge stacks */
928
targetStackPtr = targetStack->stackElements;
929
targetStackTop = RELOAD_STACKTOP(targetStack);
930
sourceStackPtr = liveStack->stackElements;
931
sourceStackTop = RELOAD_STACKTOP(liveStack);
932
933
/* remember where the temps end */
934
sourceStackTemps = RELOAD_STACKBASE(liveStack);
935
936
Trc_BCV_mergeStacks_MergeStacks(verifyData->vmStruct,
937
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
938
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
939
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
940
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
941
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
942
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
943
stackIndex, target, target);
944
945
while (sourceStackPtr != sourceStackTop) {
946
947
/* Merge if the source and target slots are not identical */
948
if (*sourceStackPtr != *targetStackPtr) {
949
UDATA sourceItem = *sourceStackPtr;
950
UDATA targetItem = *targetStackPtr;
951
952
/* Merge in the locals */
953
if (sourceStackPtr < sourceStackTemps ) {
954
955
/* Merge when either the source or target not an object */
956
if ((sourceItem | targetItem) & (BCV_BASE_OR_SPECIAL)) {
957
958
/* Mismatch results in undefined local - rewalk if modified stack
959
* Note: BCV_SPECIAL_INIT must be reserved to flag the uninitialized_this object
960
* existing in the stackmap frame when invoking setInitializedThisStatus() after
961
* the stackmaps are successfully built.
962
*/
963
if (((UDATA)(BCV_BASE_TYPE_TOP) != targetItem)
964
&& (0 == (targetItem & BCV_SPECIAL_INIT))
965
) {
966
*targetStackPtr = (UDATA) (BCV_BASE_TYPE_TOP);
967
rewalk = TRUE;
968
}
969
970
/* Merge two objects */
971
} else {
972
973
/* extra checks here to avoid calling local mapper unnecessarily */
974
/* Null source or java/lang/Object targets always work trivially */
975
if ((*sourceStackPtr != BCV_BASE_TYPE_NULL) && (*targetStackPtr != (BCV_JAVA_LANG_OBJECT_INDEX << BCV_CLASS_INDEX_SHIFT))) {
976
977
/* Null target always causes a re-walk - source is never null here */
978
if (*targetStackPtr == BCV_BASE_TYPE_NULL) {
979
*targetStackPtr = *sourceStackPtr;
980
rewalk = TRUE;
981
} else {
982
/* Use local mapper to check merge necessity in locals */
983
if ((verifyData->verificationFlags & J9_VERIFY_OPTIMIZE) && (maxIndex <= 32)) {
984
/* Only handle 32 locals or less */
985
UDATA index = (UDATA) (sourceStackPtr - liveStack->stackElements);
986
987
/* Reuse map in this merge if needed for multiple merges at same map */
988
if (mergePC == ((UDATA) -1)) {
989
mergePC = target;
990
if (j9localmap_LocalBitsForPC(verifyData->portLib, romClass, romMethod, mergePC, &resultArrayBase, NULL, NULL, NULL) != 0) {
991
/* local map error - force a full merge */
992
resultArrayBase = (U_32) -1;
993
}
994
}
995
996
if (resultArrayBase & (1 << index)) {
997
UDATA origSource = *sourceStackPtr;
998
UDATA origTarget = *targetStackPtr;
999
IDATA tempRC = mergeObjectTypes(verifyData, *sourceStackPtr, targetStackPtr);
1000
1001
/* Merge the objects - the result is live */
1002
if (BCV_FAIL == tempRC) {
1003
rewalk = TRUE;
1004
} else if (BCV_ERR_INSUFFICIENT_MEMORY == tempRC) {
1005
rc = BCV_ERR_INSUFFICIENT_MEMORY;
1006
goto _finished;
1007
}
1008
1009
Trc_BCV_mergeStacks_OptMergeRequired(verifyData->vmStruct,
1010
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1011
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1012
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
1013
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
1014
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1015
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1016
origSource, origTarget, *targetStackPtr);
1017
1018
} else {
1019
Trc_BCV_mergeStacks_OptMergeNotRequired(verifyData->vmStruct,
1020
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1021
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1022
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
1023
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
1024
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1025
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1026
*sourceStackPtr, *targetStackPtr);
1027
/* Tag undefined - local variable is dead */
1028
*targetStackPtr = (UDATA) (BCV_BASE_TYPE_TOP);
1029
rewalk = TRUE;
1030
}
1031
1032
} else {
1033
IDATA tempRC = mergeObjectTypes(verifyData, *sourceStackPtr, targetStackPtr);
1034
if (BCV_FAIL == tempRC) {
1035
rewalk = TRUE;
1036
} else if (BCV_ERR_INSUFFICIENT_MEMORY == tempRC) {
1037
rc = BCV_ERR_INSUFFICIENT_MEMORY;
1038
goto _finished;
1039
}
1040
}
1041
}
1042
}
1043
}
1044
1045
/* Merge is on the stack */
1046
} else {
1047
1048
if (!((sourceItem | targetItem) & BCV_BASE_OR_SPECIAL)) {
1049
/* Merge two objects */
1050
IDATA tempRC = mergeObjectTypes(verifyData, *sourceStackPtr, targetStackPtr);
1051
if (BCV_FAIL == tempRC) {
1052
rewalk = TRUE;
1053
} else if (BCV_ERR_INSUFFICIENT_MEMORY == tempRC) {
1054
rc = BCV_ERR_INSUFFICIENT_MEMORY;
1055
goto _finished;
1056
}
1057
}
1058
}
1059
}
1060
sourceStackPtr++;
1061
targetStackPtr++;
1062
}
1063
}
1064
1065
/* add to the root set if we changed the target stack */
1066
if (rewalk) {
1067
if (!(bytecodeMap[target] & BRANCH_ON_REWALK_QUEUE)) {
1068
Trc_BCV_mergeStacks_QueueForRewalk(verifyData->vmStruct,
1069
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1070
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1071
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
1072
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
1073
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1074
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1075
target, target);
1076
verifyData->rewalkQueue[verifyData->rewalkQueueTail++] = target;
1077
verifyData->rewalkQueueTail %= (verifyData->rootQueueSize / sizeof(UDATA));
1078
bytecodeMap[target] |= BRANCH_ON_REWALK_QUEUE;
1079
bytecodeMap[target] &= ~BRANCH_ON_UNWALKED_QUEUE;
1080
}
1081
}
1082
1083
_finished:
1084
1085
Trc_BCV_mergeStacks_Exit(verifyData->vmStruct,
1086
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1087
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1088
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(verifyData->romMethod)),
1089
J9UTF8_DATA(J9ROMMETHOD_NAME(verifyData->romMethod)),
1090
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1091
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(verifyData->romMethod)),
1092
rc);
1093
1094
return rc;
1095
}
1096
1097
1098
1099
1100
1101
#ifdef DEBUG_BCV
1102
static void
1103
printMethod (J9BytecodeVerificationData * verifyData)
1104
{
1105
J9ROMClass *romClass = verifyData->romCLass;
1106
J9ROMMethod *method = verifyData->romMethod;
1107
U_8* string;
1108
#if 0
1109
J9CfrAttributeExceptions* exceptions;
1110
#endif
1111
IDATA arity, i, j;
1112
1113
string = J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass));
1114
printf("<");
1115
for( i=0; i< J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)); i++ )
1116
{
1117
printf( "%c", (string[i] == '/')?'.':string[i]);
1118
}
1119
printf(">");
1120
1121
if( strncmp( string, "java/util/Arrays", i ) == 0 ) {
1122
printf("stop");
1123
}
1124
1125
/* Return type. */
1126
string = J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(method));
1127
i = 0;
1128
while(string[i++] != ')');
1129
arity = 0;
1130
while(string[i] == '[') arity++, i++;
1131
switch(string[i])
1132
{
1133
case 'B':
1134
printf( "byte");
1135
break;
1136
1137
case 'C':
1138
printf( "char");
1139
break;
1140
1141
case 'D':
1142
printf( "double");
1143
break;
1144
1145
case 'F':
1146
printf( "float");
1147
break;
1148
1149
case 'I':
1150
printf( "int");
1151
break;
1152
1153
case 'J':
1154
printf( "long");
1155
break;
1156
1157
case 'L':
1158
i++;
1159
while(string[i] != ';')
1160
{
1161
printf( "%c", (string[i] == '/')?'.':string[i]);
1162
i++;
1163
}
1164
break;
1165
1166
case 'S':
1167
printf( "short");
1168
break;
1169
1170
case 'V':
1171
printf( "void");
1172
break;
1173
1174
case 'Z':
1175
printf( "boolean");
1176
break;
1177
}
1178
for(i = 0; i < arity; i++)
1179
printf( "[]");
1180
1181
printf( " %.*s(", J9UTF8_LENGTH(J9ROMMETHOD_NAME(method)), J9UTF8_DATA(J9ROMMETHOD_NAME(method)));
1182
1183
for(i = 1; string[i] != ')'; i++)
1184
{
1185
arity = 0;
1186
while(string[i] == '[') arity++, i++;
1187
switch(string[i])
1188
{
1189
case 'B':
1190
printf( "byte");
1191
break;
1192
1193
case 'C':
1194
printf( "char");
1195
break;
1196
1197
case 'D':
1198
printf( "double");
1199
break;
1200
1201
case 'F':
1202
printf( "float");
1203
break;
1204
1205
case 'I':
1206
printf( "int");
1207
break;
1208
1209
case 'J':
1210
printf( "long");
1211
break;
1212
1213
case 'L':
1214
i++;
1215
while(string[i] != ';')
1216
{
1217
printf( "%c", (string[i] == '/')?'.':string[i]);
1218
i++;
1219
}
1220
break;
1221
1222
case 'S':
1223
printf( "short");
1224
break;
1225
1226
case 'V':
1227
printf( "void");
1228
break;
1229
1230
case 'Z':
1231
printf( "boolean");
1232
break;
1233
}
1234
for(j = 0; j < arity; j++)
1235
printf( "[]");
1236
1237
if(string[i + 1] != ')')
1238
printf( ", ");
1239
}
1240
1241
printf( ")");
1242
#if 0 /* need to fix this code to work with J9ROMMethods.. */
1243
for(i = 0; i < method->attributesCount; i++)
1244
{
1245
if(method->attributes[i]->tag == CFR_ATTRIBUTE_Exceptions)
1246
{
1247
exceptions = (J9CfrAttributeExceptions*)method->attributes[i];
1248
1249
printf( " throws ");
1250
for(j = 0; j < exceptions->numberOfExceptions - 1; j++)
1251
{
1252
if(exceptions->exceptionIndexTable[j] != 0)
1253
{
1254
index = classfile->constantPool[exceptions->exceptionIndexTable[j]].slot1;
1255
string = classfile->constantPool[index].bytes;
1256
while(*string)
1257
{
1258
printf( "%c", (*string == '/')?'.':*string);
1259
string++;
1260
}
1261
printf( ", ");
1262
}
1263
}
1264
index = classfile->constantPool[exceptions->exceptionIndexTable[j]].slot1;
1265
string = classfile->constantPool[index].bytes;
1266
while(*string)
1267
{
1268
printf( "%c", (*string == '/')?'.':*string);
1269
string++;
1270
}
1271
1272
i = method->attributesCount;
1273
}
1274
}
1275
#endif
1276
printf( ";\n");
1277
return;
1278
}
1279
1280
1281
#endif
1282
1283
/*
1284
* return BCV_SUCCESS on success
1285
* returns BCV_ERR_INTERNAL_ERROR on any errors
1286
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
1287
1288
*/
1289
1290
static IDATA
1291
simulateStack (J9BytecodeVerificationData * verifyData)
1292
{
1293
1294
#define CHECK_END \
1295
if(pc > length) { \
1296
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID; \
1297
verboseErrorCode = BCV_ERR_UNEXPECTED_EOF; \
1298
goto _verifyError; \
1299
}
1300
1301
J9ROMClass * romClass = verifyData->romClass;
1302
J9ROMMethod * romMethod = verifyData->romMethod;
1303
J9BranchTargetStack * liveStack = (J9BranchTargetStack *) verifyData->liveStack;
1304
U_32 * bytecodeMap = verifyData->bytecodeMap;
1305
IDATA start = 0;
1306
UDATA pc = 0;
1307
UDATA length, index, target;
1308
J9ROMConstantPoolItem *constantPool;
1309
J9ROMConstantPoolItem *info;
1310
J9UTF8 *utf8string;
1311
U_8 *code;
1312
U_8 *bcIndex;
1313
UDATA bc = 0;
1314
UDATA popCount, type1, type2, action;
1315
UDATA type, temp1, temp2, temp3, maxStack;
1316
UDATA justLoadedStack = FALSE;
1317
UDATA *stackBase;
1318
UDATA *stackTop;
1319
UDATA *temps;
1320
UDATA stackIndex;
1321
UDATA wideIndex = FALSE;
1322
UDATA *ptr;
1323
IDATA i1, i2;
1324
UDATA classIndex;
1325
UDATA errorModule = J9NLS_BCV_ERR_NO_ERROR__MODULE; /* default to BCV NLS catalog */
1326
U_16 errorType;
1327
I_16 offset16;
1328
I_32 offset32;
1329
J9BranchTargetStack * branch;
1330
UDATA checkIfInsideException = romMethod->modifiers & J9AccMethodHasExceptionInfo;
1331
UDATA tempStoreChange;
1332
J9ExceptionInfo *exceptionData = J9_EXCEPTION_DATA_FROM_ROM_METHOD(romMethod);
1333
J9ExceptionHandler *handler;
1334
UDATA exception;
1335
J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);
1336
UDATA* originalStackTop;
1337
UDATA originalStackZeroEntry;
1338
/* Jazz 104084: Initialize verification error codes by default */
1339
IDATA verboseErrorCode = 0;
1340
UDATA errorTargetType = (UDATA)-1;
1341
UDATA errorStackIndex = (UDATA)-1;
1342
UDATA errorTempData = (UDATA)-1;
1343
1344
Trc_BCV_simulateStack_Entry(verifyData->vmStruct);
1345
1346
#ifdef DEBUG_BCV
1347
printMethod(verifyData);
1348
#endif
1349
1350
verifyData->unwalkedQueueHead = 0;
1351
verifyData->unwalkedQueueTail = 0;
1352
verifyData->rewalkQueueHead = 0;
1353
verifyData->rewalkQueueTail = 0;
1354
1355
code = J9_BYTECODE_START_FROM_ROM_METHOD(romMethod);
1356
length = (UDATA) J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod);
1357
maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);
1358
1359
/* Jazz 105041: Initialize the 1st data slot on 'stack' with 'top' (placeholdler)
1360
* to avoid storing garbage data type in the error message buffer
1361
* when stack underflow occurs.
1362
*/
1363
liveStack->stackElements[liveStack->stackBaseIndex] = BCV_BASE_TYPE_TOP;
1364
1365
RELOAD_LIVESTACK;
1366
1367
bcIndex = code;
1368
1369
constantPool = J9_ROM_CP_FROM_ROM_CLASS(romClass);
1370
1371
while (pc < length) {
1372
if ((UDATA) (stackTop - stackBase) > maxStack) {
1373
errorType = J9NLS_BCV_ERR_STACK_OVERFLOW__ID;
1374
verboseErrorCode = BCV_ERR_STACK_OVERFLOW;
1375
SAVE_STACKTOP(liveStack, stackTop);
1376
goto _verifyError;
1377
}
1378
1379
/* If exception start PC, or possible branch to inside an exception range, */
1380
/* copy the existing stack shape into the exception stack */
1381
if ((bytecodeMap[pc] & BRANCH_EXCEPTION_START) || (justLoadedStack && checkIfInsideException)) {
1382
handler = J9EXCEPTIONINFO_HANDLERS(exceptionData);
1383
SAVE_STACKTOP(liveStack, stackTop);
1384
1385
/* Save the current liveStack element zero */
1386
/* Reset the stack pointer to push the exception on the empty stack */
1387
originalStackTop = stackTop;
1388
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
1389
1390
for (exception = 0; exception < (UDATA) exceptionData->catchCount; exception++) {
1391
1392
/* find the matching branch target, and copy/merge the stack with the exception object */
1393
if ((pc >= handler->startPC) && (pc < handler->endPC)) {
1394
#ifdef DEBUG_BCV
1395
printf("exception startPC: %d\n", handler->startPC);
1396
#endif
1397
stackIndex = bytecodeMap[handler->handlerPC] >> BRANCH_INDEX_SHIFT;
1398
branch = BCV_INDEX_STACK (stackIndex);
1399
1400
/* "push" the exception object */
1401
classIndex = BCV_JAVA_LANG_THROWABLE_INDEX;
1402
if (handler->exceptionClassIndex) {
1403
/* look up the class in the constant pool */
1404
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)(&constantPool [handler->exceptionClassIndex]));
1405
classIndex = findClassName(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string));
1406
}
1407
1408
/* Empty the stack */
1409
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
1410
PUSH(classIndex << BCV_CLASS_INDEX_SHIFT);
1411
SAVE_STACKTOP(liveStack, stackTop);
1412
1413
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, handler->handlerPC)) {
1414
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1415
goto _outOfMemoryError;
1416
}
1417
}
1418
handler++;
1419
}
1420
1421
/* Restore liveStack */
1422
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
1423
stackTop = originalStackTop;
1424
}
1425
1426
start = (IDATA) pc;
1427
1428
/* Merge all branchTargets encountered */
1429
if (bytecodeMap[pc] & BRANCH_TARGET) {
1430
/* Don't try to merge a stack we just loaded */
1431
if (!justLoadedStack) {
1432
SAVE_STACKTOP(liveStack, stackTop);
1433
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, start)) {
1434
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1435
goto _outOfMemoryError;
1436
}
1437
goto _checkFinished;
1438
}
1439
}
1440
justLoadedStack = FALSE;
1441
1442
bcIndex = code + pc;
1443
bc = *bcIndex;
1444
#ifdef DEBUG_BCV
1445
#if 1 /* for really verbose logging */
1446
printf("pc: %d bc: %d\n", pc, bc);
1447
#endif
1448
#endif
1449
pc += (J9JavaInstructionSizeAndBranchActionTable[bc] & 7);
1450
CHECK_END;
1451
1452
popCount = JavaStackActionTable[bc] & 0x07;
1453
if ((stackTop - popCount) < stackBase) {
1454
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
1455
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
1456
/* Given that the actual data type involved has not yet been located through pop operation
1457
* when stack underflow occurs, it needs to step back by 1 slot to the actual data type
1458
* to be manipulated by the opcode.
1459
*/
1460
errorStackIndex = (U_32)(stackTop - liveStack->stackElements - 1);
1461
/* Always set to the location of the 1st data type on 'stack' to show up if stackTop <= stackBase */
1462
if (stackTop <= stackBase) {
1463
errorStackIndex = (U_32)(stackBase - liveStack->stackElements);
1464
}
1465
goto _verifyError;
1466
}
1467
1468
type1 = (UDATA) J9JavaBytecodeVerificationTable[bc];
1469
action = type1 >> 8;
1470
type2 = (type1 >> 4) & 0xF;
1471
type1 = (UDATA) decodeTable[type1 & 0xF];
1472
type2 = (UDATA) decodeTable[type2];
1473
1474
switch (action) {
1475
case RTV_NOP:
1476
case RTV_INCREMENT:
1477
break;
1478
1479
case RTV_WIDE_LOAD_TEMP_PUSH:
1480
if (type1 == BCV_GENERIC_OBJECT) {
1481
/* Only set for wide Objects - primitives don't read temps */
1482
wideIndex = TRUE;
1483
} /* Fall through case !!! */
1484
1485
case RTV_LOAD_TEMP_PUSH:
1486
if (type1 == BCV_GENERIC_OBJECT) {
1487
/* aload family */
1488
index = type2 & 0x7;
1489
if (type2 == 0) {
1490
index = PARAM_8(bcIndex, 1);
1491
if (wideIndex) {
1492
index = PARAM_16(bcIndex, 1);
1493
wideIndex = FALSE;
1494
}
1495
}
1496
type1 = temps[index];
1497
PUSH(type1);
1498
break;
1499
} /* Fall through case !!! */
1500
1501
case RTV_PUSH_CONSTANT:
1502
1503
_pushConstant:
1504
PUSH(type1);
1505
if (type1 & BCV_WIDE_TYPE_MASK) {
1506
PUSH(BCV_BASE_TYPE_TOP);
1507
}
1508
break;
1509
1510
case RTV_PUSH_CONSTANT_POOL_ITEM:
1511
switch (bc) {
1512
case JBldc:
1513
case JBldcw:
1514
if (bc == JBldc) {
1515
index = PARAM_8(bcIndex, 1);
1516
} else {
1517
index = PARAM_16(bcIndex, 1);
1518
}
1519
stackTop = pushLdcType(verifyData, romClass, index, stackTop);
1520
break;
1521
1522
/* Change lookup table to generate constant of correct type */
1523
case JBldc2lw:
1524
PUSH_LONG_CONSTANT;
1525
break;
1526
1527
case JBldc2dw:
1528
PUSH_DOUBLE_CONSTANT;
1529
break;
1530
}
1531
break;
1532
1533
case RTV_ARRAY_FETCH_PUSH:
1534
DROP(1);
1535
type = POP;
1536
if (type != BCV_BASE_TYPE_NULL) {
1537
if (bc == JBaaload) {
1538
type1 = type - 0x01000000; /* reduce types arity by one */
1539
PUSH(type1);
1540
break;
1541
}
1542
}
1543
goto _pushConstant;
1544
break;
1545
1546
case RTV_WIDE_POP_STORE_TEMP:
1547
wideIndex = TRUE; /* Fall through case !!! */
1548
1549
case RTV_POP_STORE_TEMP:
1550
index = type2 & 0x7;
1551
if (type2 == 0) {
1552
index = PARAM_8(bcIndex, 1);
1553
if (wideIndex) {
1554
index = PARAM_16(bcIndex, 1);
1555
wideIndex = FALSE;
1556
}
1557
}
1558
1559
tempStoreChange = FALSE;
1560
1561
if (type1 == BCV_GENERIC_OBJECT) {
1562
/* astore family */
1563
type = POP;
1564
tempStoreChange = (type != temps[index]);
1565
STORE_TEMP(index, type);
1566
} else {
1567
DROP(popCount);
1568
/* because of pre-index local clearing - the order here matters */
1569
if (type1 & BCV_WIDE_TYPE_MASK) {
1570
tempStoreChange = (temps[index + 1] != BCV_BASE_TYPE_TOP);
1571
STORE_TEMP((index + 1), BCV_BASE_TYPE_TOP);
1572
}
1573
tempStoreChange |= (type1 != temps[index]);
1574
STORE_TEMP(index, type1);
1575
}
1576
1577
if (checkIfInsideException && tempStoreChange) {
1578
/* For all exception handlers covering this instruction */
1579
handler = J9EXCEPTIONINFO_HANDLERS(exceptionData);
1580
SAVE_STACKTOP(liveStack, stackTop);
1581
1582
/* Save the current liveStack element zero */
1583
/* Reset the stack pointer to push the exception on the empty stack */
1584
originalStackTop = stackTop;
1585
originalStackZeroEntry = liveStack->stackElements[liveStack->stackBaseIndex];
1586
1587
for (exception = 0; exception < (UDATA) exceptionData->catchCount; exception++) {
1588
1589
/* Find all matching exception ranges and copy/merge the stack with the exception object */
1590
if (((UDATA) start >= handler->startPC) && ((UDATA) start < handler->endPC)) {
1591
#ifdef DEBUG_BCV
1592
printf("exception map change at startPC: %d\n", handler->startPC);
1593
#endif
1594
stackIndex = bytecodeMap[handler->handlerPC] >> BRANCH_INDEX_SHIFT;
1595
branch = BCV_INDEX_STACK (stackIndex);
1596
1597
/* "push" the exception object */
1598
classIndex = BCV_JAVA_LANG_THROWABLE_INDEX;
1599
if (handler->exceptionClassIndex) {
1600
/* look up the class in the constant pool */
1601
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) (&constantPool [handler->exceptionClassIndex]));
1602
classIndex = findClassName(verifyData, J9UTF8_DATA(utf8string), J9UTF8_LENGTH(utf8string));
1603
}
1604
1605
/* Empty the stack */
1606
stackTop = &(liveStack->stackElements[liveStack->stackBaseIndex]);
1607
PUSH(classIndex << BCV_CLASS_INDEX_SHIFT);
1608
SAVE_STACKTOP(liveStack, stackTop);
1609
1610
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, branch->pc)) {
1611
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1612
goto _outOfMemoryError;
1613
}
1614
}
1615
handler++;
1616
}
1617
1618
/* Restore liveStack */
1619
liveStack->stackElements[liveStack->stackBaseIndex] = originalStackZeroEntry;
1620
stackTop = originalStackTop;
1621
}
1622
break;
1623
1624
case RTV_POP_X_PUSH_X:
1625
popCount = 0;
1626
if (type2) {
1627
/* shift family */
1628
popCount = 1;
1629
} /* fall through */
1630
1631
case RTV_ARRAY_STORE:
1632
DROP(popCount);
1633
break;
1634
1635
case RTV_POP_X_PUSH_Y:
1636
/* Cause push of output type */
1637
type1 = type2; /* fall through */
1638
1639
case RTV_POP_2_PUSH:
1640
DROP(popCount);
1641
goto _pushConstant;
1642
break;
1643
1644
case RTV_BRANCH:
1645
popCount = type2 & 0x07;
1646
stackTop -= popCount;
1647
1648
if (bc == JBgotow) {
1649
offset32 = (I_32) PARAM_32(bcIndex, 1);
1650
target = start + offset32;
1651
} else {
1652
offset16 = (I_16) PARAM_16(bcIndex, 1);
1653
target = start + offset16;
1654
}
1655
1656
SAVE_STACKTOP(liveStack, stackTop);
1657
/* Merge our stack to the target */
1658
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, target)) {
1659
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1660
goto _outOfMemoryError;
1661
}
1662
1663
/* Unconditional branch (goto family) */
1664
if (popCount == 0) {
1665
goto _checkFinished;
1666
}
1667
break;
1668
1669
case RTV_RETURN:
1670
goto _checkFinished;
1671
break;
1672
1673
case RTV_STATIC_FIELD_ACCESS:
1674
index = PARAM_16(bcIndex, 1);
1675
info = &constantPool[index];
1676
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) info))));
1677
1678
if (bc >= JBgetfield) {
1679
/* field bytecode receiver */
1680
DROP(1);
1681
}
1682
1683
if (bc & 1) {
1684
/* JBputfield/JBpustatic - odd bc's */
1685
DROP(1);
1686
if ((*J9UTF8_DATA(utf8string) == 'D') || (*J9UTF8_DATA(utf8string) == 'J')) {
1687
DROP(1);
1688
}
1689
1690
} else {
1691
/* JBgetfield/JBgetstatic - even bc's */
1692
stackTop = pushFieldType(verifyData, utf8string, stackTop);
1693
}
1694
break;
1695
1696
case RTV_SEND:
1697
if (bc == JBinvokeinterface2) {
1698
/* Set to point to JBinvokeinterface */
1699
bcIndex += 2;
1700
}
1701
index = PARAM_16(bcIndex, 1);
1702
if (JBinvokestaticsplit == bc) {
1703
index = *(U_16 *)(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(romClass) + index);
1704
} else if (JBinvokespecialsplit == bc) {
1705
index = *(U_16 *)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(romClass) + index);
1706
}
1707
if (bc == JBinvokedynamic) {
1708
/* TODO invokedynamic should allow for a 3 byte index. Adjust 'index' to include the other byte */
1709
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(SRP_PTR_GET(callSiteData + index, J9ROMNameAndSignature*))));
1710
} else {
1711
info = &constantPool[index];
1712
utf8string = ((J9UTF8 *) (J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info))));
1713
}
1714
stackTop -= getSendSlotsFromSignature(J9UTF8_DATA(utf8string));
1715
1716
if ((JBinvokestatic != bc)
1717
&& (JBinvokedynamic != bc)
1718
&& (JBinvokestaticsplit != bc)
1719
) {
1720
if ((JBinvokespecial == bc)
1721
|| (JBinvokespecialsplit == bc)
1722
) {
1723
1724
type = POP;
1725
if (J9UTF8_DATA(J9ROMNAMEANDSIGNATURE_NAME(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) info)))[0] == '<') {
1726
1727
/* This is <init>, verify that this is a NEW or INIT object */
1728
if (type & BCV_SPECIAL) {
1729
temp1 = getSpecialType(verifyData, type, code);
1730
/* This invoke special will make all copies of this "type" on the stack a real
1731
object, find all copies of this object and initialize them */
1732
ptr = temps; /* assumption that stack follows temps */
1733
/* we don't strictly need to walk temps here, the pending stack would be enough */
1734
while (ptr != stackTop) {
1735
if (*ptr == type) {
1736
*ptr = temp1;
1737
}
1738
ptr++;
1739
}
1740
type = temp1;
1741
break;
1742
}
1743
}
1744
} else { /* virtual or interface */
1745
DROP(1);
1746
}
1747
}
1748
1749
stackTop = pushReturnType(verifyData, utf8string, stackTop);
1750
break;
1751
1752
case RTV_PUSH_NEW:
1753
switch (bc) {
1754
case JBnew:
1755
case JBnewdup:
1756
/* put a uninitialized object of the correct type on the stack */
1757
PUSH(BCV_SPECIAL_NEW | (start << BCV_CLASS_INDEX_SHIFT));
1758
break;
1759
1760
case JBnewarray:
1761
index = PARAM_8(bcIndex, 1);
1762
type = (UDATA) newArrayParamConversion[index];
1763
DROP(1); /* pop the size of the array */
1764
PUSH(type); /* arity of one implicit */
1765
break;
1766
1767
case JBanewarray:
1768
index = PARAM_16(bcIndex, 1);
1769
DROP(1); /* pop the size of the array */
1770
info = &constantPool[index];
1771
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1772
1773
stackTop = pushClassType(verifyData, utf8string, stackTop);
1774
/* arity is one greater than signature */
1775
type = POP;
1776
PUSH(( (UDATA)1 << BCV_ARITY_SHIFT) + type);
1777
break;
1778
1779
case JBmultianewarray:
1780
/* points to cp entry for class of object to create */
1781
index = PARAM_16(bcIndex, 1);
1782
i1 = PARAM_8(bcIndex, 3);
1783
DROP(i1);
1784
if (stackTop < stackBase) {
1785
errorType = J9NLS_BCV_ERR_STACK_UNDERFLOW__ID;
1786
verboseErrorCode = BCV_ERR_STACK_UNDERFLOW;
1787
/* Always set to the location of the 1st data type on 'stack' to show up if stackTop <= stackBase */
1788
errorStackIndex = (U_32)(stackBase - liveStack->stackElements);
1789
goto _verifyError;
1790
}
1791
1792
info = &constantPool[index];
1793
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1794
1795
stackTop = pushClassType(verifyData, utf8string, stackTop);
1796
break;
1797
}
1798
break;
1799
1800
case RTV_MISC:
1801
switch (bc) {
1802
case JBathrow:
1803
goto _checkFinished;
1804
break;
1805
1806
case JBarraylength:
1807
case JBinstanceof:
1808
DROP(1);
1809
PUSH_INTEGER_CONSTANT;
1810
break;
1811
1812
case JBtableswitch:
1813
case JBlookupswitch:
1814
DROP(1);
1815
index = (UDATA) ((4 - (pc & 3)) & 3); /* consume padding */
1816
pc += index;
1817
bcIndex += index;
1818
pc += 8;
1819
CHECK_END;
1820
offset32 = (I_32) PARAM_32(bcIndex, 1);
1821
bcIndex += 4;
1822
target = offset32 + start;
1823
SAVE_STACKTOP(liveStack, stackTop);
1824
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, target)) {
1825
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1826
goto _outOfMemoryError;
1827
}
1828
1829
if (bc == JBtableswitch) {
1830
i1 = (I_32) PARAM_32(bcIndex, 1);
1831
bcIndex += 4;
1832
pc += 4;
1833
i2 = (I_32) PARAM_32(bcIndex, 1);
1834
bcIndex += 4;
1835
1836
pc += ((I_32)i2 - (I_32)i1 + 1) * 4;
1837
CHECK_END;
1838
1839
/* Add the table switch destinations in reverse order to more closely mimic the order that people
1840
(ie: the TCKs) expect you to load classes */
1841
bcIndex += (((I_32)i2 - (I_32)i1) * 4); /* point at the last table switch entry */
1842
1843
/* Count the entries */
1844
i2 = (I_32)i2 - (I_32)i1 + 1;
1845
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
1846
offset32 = (I_32) PARAM_32(bcIndex, 1);
1847
bcIndex -= 4; /* back up to point at the previous table switch entry */
1848
target = offset32 + start;
1849
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, target)) {
1850
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1851
goto _outOfMemoryError;
1852
}
1853
}
1854
} else {
1855
i2 = (I_32) PARAM_32(bcIndex, 1);
1856
bcIndex += 4;
1857
1858
pc += (I_32)i2 * 8;
1859
CHECK_END;
1860
for (i1 = 0; (I_32)i1 < (I_32)i2; i1++) {
1861
bcIndex += 4;
1862
offset32 = (I_32) PARAM_32(bcIndex, 1);
1863
bcIndex += 4;
1864
target = offset32 + start;
1865
if (BCV_ERR_INSUFFICIENT_MEMORY == mergeStacks (verifyData, target)) {
1866
errorType = J9NLS_BCV_ERR_VERIFY_OUT_OF_MEMORY__ID;
1867
goto _outOfMemoryError;
1868
}
1869
}
1870
}
1871
goto _checkFinished;
1872
break;
1873
1874
case JBmonitorenter:
1875
case JBmonitorexit:
1876
DROP(1);
1877
break;
1878
1879
case JBcheckcast:
1880
index = PARAM_16(bcIndex, 1);
1881
DROP(1);
1882
info = &constantPool[index];
1883
utf8string = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) info);
1884
stackTop = pushClassType(verifyData, utf8string, stackTop);
1885
break;
1886
}
1887
break;
1888
1889
case RTV_POP_2_PUSH_INT:
1890
DROP(popCount);
1891
PUSH_INTEGER_CONSTANT;
1892
break;
1893
1894
case RTV_BYTECODE_POP:
1895
case RTV_BYTECODE_POP2:
1896
DROP(popCount);
1897
break;
1898
1899
case RTV_BYTECODE_DUP:
1900
type = POP;
1901
PUSH(type);
1902
PUSH(type);
1903
break;
1904
1905
case RTV_BYTECODE_DUPX1:
1906
type = POP;
1907
temp1 = POP;
1908
PUSH(type);
1909
PUSH(temp1);
1910
PUSH(type);
1911
break;
1912
1913
case RTV_BYTECODE_DUPX2:
1914
type = POP;
1915
temp1 = POP;
1916
temp2 = POP;
1917
PUSH(type);
1918
PUSH(temp2);
1919
PUSH(temp1);
1920
PUSH(type);
1921
break;
1922
1923
case RTV_BYTECODE_DUP2:
1924
temp1 = POP;
1925
temp2 = POP;
1926
PUSH(temp2);
1927
PUSH(temp1);
1928
PUSH(temp2);
1929
PUSH(temp1);
1930
break;
1931
1932
case RTV_BYTECODE_DUP2X1:
1933
type = POP;
1934
temp1 = POP;
1935
temp2 = POP;
1936
PUSH(temp1);
1937
PUSH(type);
1938
PUSH(temp2);
1939
PUSH(temp1);
1940
PUSH(type);
1941
break;
1942
1943
case RTV_BYTECODE_DUP2X2:
1944
type = POP;
1945
temp1 = POP;
1946
temp2 = POP;
1947
temp3 = POP;
1948
PUSH(temp1);
1949
PUSH(type);
1950
PUSH(temp3);
1951
PUSH(temp2);
1952
PUSH(temp1);
1953
PUSH(type);
1954
break;
1955
1956
case RTV_BYTECODE_SWAP:
1957
type = POP;
1958
temp1 = POP;
1959
PUSH(type);
1960
PUSH(temp1);
1961
break;
1962
1963
case RTV_UNIMPLEMENTED:
1964
errorType = J9NLS_BCV_ERR_BC_UNKNOWN__ID;
1965
/* Jazz 104084: Set the error code in the case of unrecognized opcode. */
1966
verboseErrorCode = BCV_ERR_BAD_BYTECODE;
1967
goto _verifyError;
1968
break;
1969
}
1970
continue;
1971
1972
_checkFinished:
1973
1974
if (verifyData->unwalkedQueueHead != verifyData->unwalkedQueueTail) {
1975
pc = verifyData->unwalkedQueue[verifyData->unwalkedQueueHead++];
1976
verifyData->unwalkedQueueHead %= (verifyData->rootQueueSize / sizeof(UDATA));
1977
if ((bytecodeMap[pc] & BRANCH_ON_UNWALKED_QUEUE) == 0) {
1978
goto _checkFinished;
1979
}
1980
bytecodeMap[pc] &= ~BRANCH_ON_UNWALKED_QUEUE;
1981
bcIndex = code + pc;
1982
stackIndex = bytecodeMap[pc] >> BRANCH_INDEX_SHIFT;
1983
branch = BCV_INDEX_STACK (stackIndex);
1984
copyStack(branch, liveStack);
1985
RELOAD_LIVESTACK;
1986
justLoadedStack = TRUE;
1987
Trc_BCV_simulateStack_NewWalkFrom(verifyData->vmStruct,
1988
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1989
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
1990
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
1991
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
1992
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
1993
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
1994
start, start, pc, pc);
1995
} else if (verifyData->rewalkQueueHead != verifyData->rewalkQueueTail) {
1996
pc = verifyData->rewalkQueue[verifyData->rewalkQueueHead++];
1997
verifyData->rewalkQueueHead %= (verifyData->rootQueueSize / sizeof(UDATA));
1998
if ((bytecodeMap[pc] & BRANCH_ON_REWALK_QUEUE) == 0) {
1999
goto _checkFinished;
2000
}
2001
bytecodeMap[pc] &= ~BRANCH_ON_REWALK_QUEUE;
2002
bcIndex = code + pc;
2003
stackIndex = bytecodeMap[pc] >> BRANCH_INDEX_SHIFT;
2004
branch = BCV_INDEX_STACK (stackIndex);
2005
copyStack(branch, liveStack);
2006
RELOAD_LIVESTACK;
2007
justLoadedStack = TRUE;
2008
Trc_BCV_simulateStack_RewalkFrom(verifyData->vmStruct,
2009
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2010
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2011
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2012
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2013
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2014
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2015
start, start, pc, pc);
2016
} else {
2017
Trc_BCV_simulateStack_Exit(verifyData->vmStruct);
2018
/* else we are done the rootSet -- return */
2019
return BCV_SUCCESS;
2020
}
2021
}
2022
#undef CHECK_END
2023
2024
errorType = J9NLS_BCV_ERR_UNEXPECTED_EOF__ID; /* should never reach here */
2025
2026
_verifyError:
2027
/* Jazz 104084: Store the verification error data here when error occurs */
2028
storeVerifyErrorData(verifyData, (I_16)verboseErrorCode, (U_32)errorStackIndex, errorTargetType, errorTempData, start);
2029
2030
BUILD_VERIFY_ERROR(errorModule, errorType);
2031
Trc_BCV_simulateStack_verifyError(verifyData->vmStruct,
2032
verifyData->errorPC,
2033
verifyData->errorCode);
2034
Trc_BCV_simulateStack_verifyErrorBytecode(verifyData->vmStruct,
2035
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2036
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2037
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2038
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2039
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2040
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2041
verifyData->errorCode, verifyData->errorPC, verifyData->errorPC, bc);
2042
Trc_BCV_simulateStack_Exit(verifyData->vmStruct);
2043
2044
return BCV_ERR_INTERNAL_ERROR;
2045
2046
_outOfMemoryError:
2047
BUILD_VERIFY_ERROR(errorModule, errorType);
2048
Trc_BCV_simulateStack_verifyError(verifyData->vmStruct,
2049
verifyData->errorPC,
2050
verifyData->errorCode);
2051
2052
Trc_BCV_simulateStack_verifyErrorBytecode_OutOfMemoryException(verifyData->vmStruct,
2053
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2054
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2055
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2056
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2057
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2058
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2059
verifyData->errorCode, verifyData->errorPC, verifyData->errorPC, bc);
2060
Trc_BCV_simulateStack_Exit(verifyData->vmStruct);
2061
2062
return BCV_ERR_INSUFFICIENT_MEMORY;
2063
2064
}
2065
2066
/*
2067
* return BCV_SUCCESS on success
2068
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
2069
*/
2070
2071
IDATA
2072
allocateVerifyBuffers (J9PortLibrary * portLib, J9BytecodeVerificationData *verifyData)
2073
{
2074
Trc_BCV_allocateVerifyBuffers_Event1(verifyData->vmStruct);
2075
2076
verifyData->classNameList = 0;
2077
verifyData->classNameListEnd = 0;
2078
verifyData->classNameSegment = 0;
2079
verifyData->classNameSegmentFree = 0;
2080
verifyData->classNameSegmentEnd = 0;
2081
verifyData->bytecodeMap = 0;
2082
verifyData->stackMaps = 0;
2083
verifyData->liveStack = 0;
2084
verifyData->unwalkedQueue = 0;
2085
verifyData->rewalkQueue = 0;
2086
2087
verifyData->classNameList = (J9UTF8 **) bcvalloc (verifyData, (UDATA) CLASSNAMELIST_DEFAULT_SIZE);
2088
verifyData->classNameListEnd = (J9UTF8 **)((UDATA)verifyData->classNameList + CLASSNAMELIST_DEFAULT_SIZE);
2089
2090
verifyData->classNameSegment = bcvalloc (verifyData, (UDATA) CLASSNAMESEGMENT_DEFAULT_SIZE);
2091
verifyData->classNameSegmentEnd = verifyData->classNameSegment + CLASSNAMESEGMENT_DEFAULT_SIZE;
2092
verifyData->classNameSegmentFree = verifyData->classNameSegment;
2093
2094
verifyData->bytecodeMap = bcvalloc (verifyData, (UDATA) BYTECODE_MAP_DEFAULT_SIZE);
2095
verifyData->bytecodeMapSize = BYTECODE_MAP_DEFAULT_SIZE;
2096
2097
verifyData->stackMaps = bcvalloc (verifyData, (UDATA) STACK_MAPS_DEFAULT_SIZE);
2098
verifyData->stackMapsSize = STACK_MAPS_DEFAULT_SIZE;
2099
verifyData->stackMapsCount = 0;
2100
2101
verifyData->unwalkedQueue = bcvalloc (verifyData, (UDATA) ROOT_QUEUE_DEFAULT_SIZE);
2102
verifyData->unwalkedQueueHead = 0;
2103
verifyData->unwalkedQueueTail = 0;
2104
verifyData->rewalkQueue = bcvalloc (verifyData, (UDATA) ROOT_QUEUE_DEFAULT_SIZE);
2105
verifyData->rewalkQueueHead = 0;
2106
verifyData->rewalkQueueTail = 0;
2107
verifyData->rootQueueSize = ROOT_QUEUE_DEFAULT_SIZE;
2108
2109
verifyData->liveStack = bcvalloc (verifyData, (UDATA) LIVE_STACK_DEFAULT_SIZE);
2110
verifyData->liveStackSize = LIVE_STACK_DEFAULT_SIZE;
2111
verifyData->stackSize = 0;
2112
2113
RESET_VERIFY_ERROR(verifyData);
2114
2115
verifyData->portLib = portLib;
2116
2117
if (!(verifyData->classNameList && verifyData->classNameSegment && verifyData->bytecodeMap
2118
&& verifyData->stackMaps && verifyData->unwalkedQueue && verifyData->rewalkQueue && verifyData->liveStack)) {
2119
freeVerifyBuffers (portLib, verifyData);
2120
Trc_BCV_allocateVerifyBuffers_allocFailure(verifyData->vmStruct);
2121
return BCV_ERR_INSUFFICIENT_MEMORY;
2122
}
2123
/* Now we know the allocates were successful, initialize the required data */
2124
verifyData->classNameList[0] = NULL;
2125
return BCV_SUCCESS;
2126
}
2127
2128
2129
/*
2130
BCV interface to j9mem_allocate_memory.
2131
@return pointer to allocated memory, or 0 if allocation fails.
2132
@note Does not deallocate the internal buffer
2133
*/
2134
2135
void*
2136
bcvalloc (J9BytecodeVerificationData * verifyData, UDATA byteCount)
2137
{
2138
UDATA *returnVal = 0;
2139
J9BCVAlloc *temp1, *temp2;
2140
2141
PORT_ACCESS_FROM_PORT(verifyData->portLib);
2142
2143
/* Round to UDATA multiple */
2144
byteCount = (UDATA) ((byteCount + (sizeof(UDATA) - 1)) & ~(sizeof(UDATA) - 1));
2145
/* Allow room for the linking header */
2146
byteCount += sizeof(UDATA);
2147
2148
if (verifyData->internalBufferStart == 0) {
2149
verifyData->internalBufferStart = j9mem_allocate_memory(BCV_INTERNAL_DEFAULT_SIZE, J9MEM_CATEGORY_CLASSES);
2150
if (verifyData->internalBufferStart == 0) {
2151
return 0;
2152
}
2153
verifyData->internalBufferEnd = (UDATA *) ((UDATA)verifyData->internalBufferStart + BCV_INTERNAL_DEFAULT_SIZE);
2154
verifyData->currentAlloc = verifyData->internalBufferStart;
2155
*verifyData->currentAlloc = (UDATA) verifyData->currentAlloc;
2156
}
2157
2158
temp1 = (J9BCVAlloc *) verifyData->currentAlloc;
2159
temp2 = (J9BCVAlloc *) ((UDATA) temp1 + byteCount);
2160
2161
if ((UDATA *) temp2 >= verifyData->internalBufferEnd) {
2162
returnVal = j9mem_allocate_memory(byteCount, J9MEM_CATEGORY_CLASSES);
2163
Trc_BCV_bcvalloc_ExternalAlloc(verifyData->vmStruct,
2164
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2165
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2166
byteCount, returnVal);
2167
if (returnVal == 0) {
2168
return 0;
2169
}
2170
} else {
2171
/* tag the back pointer as the block following this pointer is in use */
2172
temp1->prev = (J9BCVAlloc *) ((UDATA) temp1->prev | 1);
2173
temp2->prev = temp1;
2174
verifyData->currentAlloc = (UDATA *) temp2;
2175
returnVal = temp1->data;
2176
}
2177
return returnVal;
2178
}
2179
2180
2181
2182
/*
2183
BCV interface to j9mem_allocate_memory.
2184
*/
2185
2186
void
2187
bcvfree (J9BytecodeVerificationData * verifyData, void* address)
2188
{
2189
J9BCVAlloc *temp1, *temp2;
2190
2191
PORT_ACCESS_FROM_PORT(verifyData->portLib);
2192
2193
if (((UDATA *) address >= verifyData->internalBufferEnd) || ((UDATA *) address < verifyData->internalBufferStart)) {
2194
Trc_BCV_bcvalloc_ExternalFreeAddress(verifyData->vmStruct, address);
2195
j9mem_free_memory(address);
2196
return;
2197
}
2198
2199
temp1 = (J9BCVAlloc *) ((UDATA *) address - 1);
2200
/* flag block following the pointer as free */
2201
temp1->prev = (J9BCVAlloc *) ((UDATA) temp1->prev & ~1);
2202
temp2 = (J9BCVAlloc *) verifyData->currentAlloc;
2203
2204
while (temp1 == temp2->prev) {
2205
/* Release most recent alloc and any preceding contiguous already freed allocs */
2206
temp2 = temp2->prev;
2207
temp1 = temp2->prev;
2208
if ((UDATA) temp1->prev & 1) {
2209
/* stop if an in-use block is found */
2210
verifyData->currentAlloc = (UDATA *) temp2;
2211
break;
2212
}
2213
if (temp1 == temp2) {
2214
/* all blocks unused - release the buffer */
2215
j9mem_free_memory(verifyData->internalBufferStart);
2216
verifyData->internalBufferStart = 0; /* Set the internal buffer start to zero so it will be re-allocated next time */
2217
verifyData->internalBufferEnd = 0;
2218
break;
2219
}
2220
}
2221
}
2222
2223
2224
void
2225
freeVerifyBuffers (J9PortLibrary * portLib, J9BytecodeVerificationData *verifyData)
2226
{
2227
Trc_BCV_freeVerifyBuffers_Event1(verifyData->vmStruct);
2228
2229
if (verifyData->classNameList ) {
2230
bcvfree (verifyData, verifyData->classNameList);
2231
}
2232
2233
if (verifyData->classNameSegment ) {
2234
bcvfree (verifyData, verifyData->classNameSegment);
2235
}
2236
2237
if (verifyData->bytecodeMap ) {
2238
bcvfree (verifyData, verifyData->bytecodeMap);
2239
}
2240
2241
if (verifyData->stackMaps ) {
2242
bcvfree (verifyData, verifyData->stackMaps);
2243
}
2244
2245
if (verifyData->unwalkedQueue ) {
2246
bcvfree (verifyData, verifyData->unwalkedQueue);
2247
}
2248
2249
if (verifyData->rewalkQueue ) {
2250
bcvfree (verifyData, verifyData->rewalkQueue);
2251
}
2252
2253
if (verifyData->liveStack ) {
2254
bcvfree (verifyData, verifyData->liveStack);
2255
}
2256
2257
verifyData->classNameList = 0;
2258
verifyData->classNameListEnd = 0;
2259
verifyData->classNameSegment = 0;
2260
verifyData->classNameSegmentFree = 0;
2261
verifyData->classNameSegmentEnd = 0;
2262
verifyData->bytecodeMap = 0;
2263
verifyData->stackMaps = 0;
2264
verifyData->liveStack = 0;
2265
verifyData->unwalkedQueue = 0;
2266
verifyData->rewalkQueue = 0;
2267
}
2268
2269
2270
2271
void
2272
j9bcv_freeVerificationData (J9PortLibrary * portLib, J9BytecodeVerificationData * verifyData)
2273
{
2274
PORT_ACCESS_FROM_PORT(portLib);
2275
if (verifyData) {
2276
#ifdef J9VM_THR_PREEMPTIVE
2277
JavaVM* jniVM = (JavaVM*)verifyData->javaVM;
2278
J9ThreadEnv* threadEnv;
2279
(*jniVM)->GetEnv(jniVM, (void**)&threadEnv, J9THREAD_VERSION_1_1);
2280
2281
threadEnv->monitor_destroy( verifyData->verifierMutex );
2282
#endif
2283
freeVerifyBuffers( PORTLIB, verifyData );
2284
j9mem_free_memory( verifyData->excludeAttribute );
2285
j9mem_free_memory( verifyData );
2286
}
2287
}
2288
2289
/*
2290
* returns J9BytecodeVerificationData* on success
2291
* returns NULL on OOM
2292
*/
2293
J9BytecodeVerificationData *
2294
j9bcv_initializeVerificationData(J9JavaVM* javaVM)
2295
{
2296
J9BytecodeVerificationData * verifyData;
2297
PORT_ACCESS_FROM_JAVAVM(javaVM);
2298
JavaVM* jniVM = (JavaVM*)javaVM;
2299
J9ThreadEnv* threadEnv;
2300
2301
(*jniVM)->GetEnv(jniVM, (void**)&threadEnv, J9THREAD_VERSION_1_1);
2302
2303
verifyData = j9mem_allocate_memory((UDATA) sizeof(*verifyData), J9MEM_CATEGORY_CLASSES);
2304
if( !verifyData ) {
2305
goto error_no_memory;
2306
}
2307
2308
/* blank the vmStruct field */
2309
verifyData->vmStruct = NULL;
2310
verifyData->javaVM = javaVM;
2311
2312
#ifdef J9VM_THR_PREEMPTIVE
2313
threadEnv->monitor_init_with_name(&verifyData->verifierMutex, 0, "BCVD verifier");
2314
if (!verifyData->verifierMutex) {
2315
goto error_no_memory;
2316
}
2317
#endif
2318
2319
verifyData->verifyBytecodesFunction = j9bcv_verifyBytecodes;
2320
verifyData->checkClassLoadingConstraintForNameFunction = j9bcv_checkClassLoadingConstraintForName;
2321
verifyData->internalBufferStart = 0;
2322
verifyData->internalBufferEnd = 0;
2323
verifyData->portLib = PORTLIB;
2324
verifyData->ignoreStackMaps = 0;
2325
verifyData->excludeAttribute = NULL;
2326
verifyData->redefinedClassesCount = 0;
2327
2328
if (BCV_ERR_INSUFFICIENT_MEMORY == allocateVerifyBuffers (PORTLIB, verifyData)) {
2329
goto error_no_memory;
2330
}
2331
2332
/* default verification options */
2333
verifyData->verificationFlags = J9_VERIFY_SKIP_BOOTSTRAP_CLASSES | J9_VERIFY_OPTIMIZE;
2334
2335
return verifyData;
2336
2337
error_no_memory:
2338
if (verifyData) {
2339
#ifdef J9VM_THR_PREEMPTIVE
2340
threadEnv->monitor_destroy (verifyData->verifierMutex);
2341
#endif
2342
j9mem_free_memory(verifyData);
2343
}
2344
return NULL;
2345
}
2346
2347
2348
2349
#define ALLOC_BUFFER(name, needed) \
2350
if (needed > name##Size) { \
2351
bcvfree(verifyData, name); \
2352
name = bcvalloc(verifyData, needed); \
2353
if (NULL == name) { \
2354
name##Size = 0; \
2355
result = BCV_ERR_INSUFFICIENT_MEMORY; \
2356
break; \
2357
} \
2358
name##Size = needed; \
2359
}
2360
2361
/*
2362
* Sequence the 2 verification passes - flow based type inference stack map generation
2363
* and linear stack map verification
2364
*
2365
* returns BCV_SUCCESS on success
2366
* returns BCV_ERR_INSUFFICIENT_MEMORY on OOM
2367
*/
2368
2369
IDATA
2370
j9bcv_verifyBytecodes (J9PortLibrary * portLib, J9Class * clazz, J9ROMClass * romClass,
2371
J9BytecodeVerificationData * verifyData)
2372
{
2373
UDATA i, j;
2374
J9ROMMethod *romMethod;
2375
UDATA argCount;
2376
UDATA length;
2377
UDATA mapLength;
2378
BOOLEAN hasStackMaps = (J9ROMCLASS_HAS_VERIFY_DATA(romClass) != 0);
2379
UDATA oldState;
2380
IDATA result = 0;
2381
UDATA rootQueueSize;
2382
U_32 *bytecodeMap;
2383
UDATA start = 0;
2384
J9BranchTargetStack *liveStack;
2385
U_8 *stackMapData;
2386
UDATA stackMapsSize;
2387
UDATA *stackTop;
2388
BOOLEAN classVersionRequiresStackmaps = romClass->majorVersion >= CFR_MAJOR_VERSION_REQUIRING_STACKMAPS;
2389
BOOLEAN newFormat = (classVersionRequiresStackmaps || hasStackMaps);
2390
BOOLEAN verboseVerification = (J9_VERIFY_VERBOSE_VERIFICATION == (verifyData->verificationFlags & J9_VERIFY_VERBOSE_VERIFICATION));
2391
2392
PORT_ACCESS_FROM_PORT(portLib);
2393
2394
Trc_BCV_j9bcv_verifyBytecodes_Entry(verifyData->vmStruct,
2395
(UDATA) J9UTF8_LENGTH((J9ROMCLASS_CLASSNAME(romClass))),
2396
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)));
2397
2398
/* save current and set vmState */
2399
oldState = verifyData->vmStruct->omrVMThread->vmState;
2400
verifyData->vmStruct->omrVMThread->vmState = J9VMSTATE_BCVERIFY;
2401
2402
verifyData->romClass = romClass;
2403
verifyData->errorPC = 0;
2404
2405
verifyData->romClassInSharedClasses = j9shr_Query_IsAddressInCache(verifyData->javaVM, romClass, romClass->romSize);
2406
2407
/* List is used for the whole class */
2408
initializeClassNameList(verifyData);
2409
2410
2411
romMethod = (J9ROMMethod *) J9ROMCLASS_ROMMETHODS(romClass);
2412
2413
if (verboseVerification) {
2414
ALWAYS_TRIGGER_J9HOOK_VM_CLASS_VERIFICATION_START(verifyData->javaVM->hookInterface, verifyData, newFormat);
2415
}
2416
2417
/* For each method in the class */
2418
for (i = 0; i < (UDATA) romClass->romMethodCount; i++) {
2419
2420
UDATA createStackMaps;
2421
2422
verifyData->ignoreStackMaps = (verifyData->verificationFlags & J9_VERIFY_IGNORE_STACK_MAPS) != 0;
2423
verifyData->createdStackMap = FALSE;
2424
verifyData->romMethod = romMethod;
2425
2426
Trc_BCV_j9bcv_verifyBytecodes_VerifyMethod(verifyData->vmStruct,
2427
(UDATA) J9UTF8_LENGTH((J9ROMCLASS_CLASSNAME(romClass))),
2428
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)),
2429
(UDATA) J9UTF8_LENGTH((J9ROMMETHOD_NAME(romMethod))),
2430
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2431
(UDATA) J9UTF8_LENGTH((J9ROMMETHOD_SIGNATURE(romMethod))),
2432
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)),
2433
romMethod->modifiers);
2434
2435
/* If native or abstract method, do nothing */
2436
if (!((romMethod->modifiers & J9AccNative) || (romMethod->modifiers & J9AccAbstract))) {
2437
BOOLEAN isInitMethod = FALSE;
2438
2439
/* BCV_TARGET_STACK_HEADER_UDATA_SIZE for pc/stackBase/stackEnd in J9BranchTargetStack and
2440
* BCV_STACK_OVERFLOW_BUFFER_UDATA_SIZE for late overflow detection of longs/doubles
2441
*/
2442
verifyData->stackSize = (J9_MAX_STACK_FROM_ROM_METHOD(romMethod)
2443
+ J9_ARG_COUNT_FROM_ROM_METHOD(romMethod)
2444
+ J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod)
2445
+ BCV_TARGET_STACK_HEADER_UDATA_SIZE
2446
+ BCV_STACK_OVERFLOW_BUFFER_UDATA_SIZE) * sizeof(UDATA);
2447
2448
ALLOC_BUFFER(verifyData->liveStack, verifyData->stackSize);
2449
2450
length = (UDATA) (J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod));
2451
mapLength = length * sizeof(U_32);
2452
2453
ALLOC_BUFFER(verifyData->bytecodeMap, mapLength);
2454
bytecodeMap = verifyData->bytecodeMap;
2455
2456
_fallBack:
2457
memset(bytecodeMap, 0, mapLength);
2458
2459
createStackMaps = !classVersionRequiresStackmaps && (verifyData->ignoreStackMaps || !hasStackMaps);
2460
2461
if (createStackMaps) {
2462
verifyData->stackMapsCount = buildBranchMap(verifyData);
2463
2464
if (verifyData->stackMapsCount == (UDATA)BCV_ERR_INTERNAL_ERROR) {
2465
BUILD_VERIFY_ERROR(J9NLS_BCV_ERR_BYTECODES_INVALID__MODULE, J9NLS_BCV_ERR_BYTECODES_INVALID__ID);
2466
result = BCV_ERR_INTERNAL_ERROR;
2467
break;
2468
}
2469
} else {
2470
2471
U_32 *stackMapMethod = getStackMapInfoForROMMethod(romMethod);
2472
2473
verifyData->stackMapsCount = 0;
2474
stackMapData = 0;
2475
2476
/*Access the stored stack map data for this method, get pointer and map count */
2477
if (stackMapMethod) {
2478
stackMapData = (U_8 *)(stackMapMethod + 1);
2479
NEXT_U16(verifyData->stackMapsCount, stackMapData);
2480
}
2481
}
2482
2483
stackMapsSize = (verifyData->stackSize) * (verifyData->stackMapsCount);
2484
2485
ALLOC_BUFFER(verifyData->stackMaps, stackMapsSize);
2486
2487
if (createStackMaps && verifyData->stackMapsCount) {
2488
UDATA mapIndex = 0;
2489
/* Non-empty internal stackMap created */
2490
verifyData->createdStackMap = TRUE;
2491
2492
liveStack = BCV_FIRST_STACK ();
2493
/* Initialize stackMaps */
2494
for (j = 0; j < length; j++) {
2495
if ((bytecodeMap)[j] & BRANCH_TARGET) {
2496
liveStack->pc = j; /* offset of the branch target */
2497
liveStack->stackBaseIndex = -1;
2498
liveStack->stackTopIndex = -1;
2499
liveStack = BCV_NEXT_STACK (liveStack);
2500
(bytecodeMap)[j] |= (mapIndex << BRANCH_INDEX_SHIFT);
2501
mapIndex++;
2502
}
2503
}
2504
2505
rootQueueSize = (verifyData->stackMapsCount + 1) * sizeof(UDATA);
2506
2507
if (rootQueueSize > verifyData->rootQueueSize) {
2508
bcvfree(verifyData, verifyData->unwalkedQueue);
2509
verifyData->unwalkedQueue = bcvalloc(verifyData, rootQueueSize);
2510
bcvfree(verifyData, verifyData->rewalkQueue);
2511
verifyData->rewalkQueue = bcvalloc(verifyData, rootQueueSize);
2512
verifyData->rootQueueSize = rootQueueSize;
2513
if (!(verifyData->unwalkedQueue && verifyData->rewalkQueue)) {
2514
result = BCV_ERR_INSUFFICIENT_MEMORY;
2515
break;
2516
}
2517
}
2518
}
2519
2520
liveStack = (J9BranchTargetStack *) verifyData->liveStack;
2521
stackTop = &(liveStack->stackElements[0]);
2522
2523
isInitMethod = buildStackFromMethodSignature(verifyData, &stackTop, &argCount);
2524
2525
SAVE_STACKTOP(liveStack, stackTop);
2526
liveStack->stackBaseIndex = liveStack->stackTopIndex;
2527
2528
result = 0;
2529
if (verifyData->stackMapsCount) {
2530
if (createStackMaps) {
2531
result = simulateStack (verifyData);
2532
} else {
2533
result = decompressStackMaps (verifyData, argCount, stackMapData);
2534
}
2535
}
2536
2537
if (BCV_ERR_INSUFFICIENT_MEMORY == result) {
2538
goto _done;
2539
}
2540
2541
/* If stack maps created */
2542
/* Only perform second verification pass with a valid J9Class */
2543
if ((result == BCV_SUCCESS) && clazz) {
2544
if (isInitMethod) {
2545
/* CMVC 199785: Jazz103 45899: Only run this when the stack has been built correctly */
2546
setInitializedThisStatus(verifyData);
2547
}
2548
2549
if (newFormat && verboseVerification) {
2550
ALWAYS_TRIGGER_J9HOOK_VM_METHOD_VERIFICATION_START(verifyData->javaVM->hookInterface, verifyData);
2551
}
2552
2553
result = j9rtv_verifyBytecodes (verifyData);
2554
2555
if (BCV_ERR_INSUFFICIENT_MEMORY == result) {
2556
goto _done;
2557
}
2558
2559
if (newFormat && verboseVerification) {
2560
BOOLEAN willFailOver = FALSE;
2561
/*
2562
* If verification failed and will fail over to older verifier, we only output stack map frame details
2563
* if the frame count is bigger than 0.
2564
*/
2565
if ((BCV_SUCCESS != result)
2566
&& !classVersionRequiresStackmaps
2567
&& !createStackMaps
2568
&& (J9_VERIFY_NO_FALLBACK != (verifyData->verificationFlags & J9_VERIFY_NO_FALLBACK))) {
2569
willFailOver = TRUE;
2570
}
2571
2572
if (!willFailOver || (verifyData->stackMapsCount > 0)) {
2573
ALWAYS_TRIGGER_J9HOOK_VM_STACKMAPFRAME_VERIFICATION(verifyData->javaVM->hookInterface, verifyData);
2574
}
2575
}
2576
}
2577
/* If verify error */
2578
if (result) {
2579
/* Check verification fallback criteria */
2580
if (classVersionRequiresStackmaps || createStackMaps || (verifyData->verificationFlags & J9_VERIFY_NO_FALLBACK)) {
2581
/* no retry */
2582
result = BCV_ERR_INTERNAL_ERROR;
2583
break;
2584
} else {
2585
/* reset verification failure */
2586
RESET_VERIFY_ERROR(verifyData);
2587
verifyData->errorPC = (UDATA) 0;
2588
verifyData->errorModule = 0;
2589
verifyData->errorCode = 0;
2590
2591
Trc_BCV_j9bcv_verifyBytecodes_ReverifyMethod(verifyData->vmStruct,
2592
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(romClass)),
2593
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(romClass)),
2594
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2595
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2596
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2597
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
2598
2599
/* retry with ignoreStackMaps enabled */
2600
verifyData->ignoreStackMaps = TRUE;
2601
2602
if (verboseVerification) {
2603
newFormat = FALSE;
2604
ALWAYS_TRIGGER_J9HOOK_VM_CLASS_VERIFICATION_FALLBACK(verifyData->javaVM->hookInterface, verifyData, newFormat);
2605
}
2606
2607
goto _fallBack;
2608
}
2609
}
2610
}
2611
2612
romMethod = J9_NEXT_ROM_METHOD(romMethod);
2613
}
2614
2615
_done:
2616
verifyData->vmStruct->omrVMThread->vmState = oldState;
2617
if (result == BCV_ERR_INSUFFICIENT_MEMORY) {
2618
Trc_BCV_j9bcv_verifyBytecodes_OutOfMemory(verifyData->vmStruct,
2619
(UDATA) J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2620
J9UTF8_DATA(J9ROMCLASS_CLASSNAME(verifyData->romClass)),
2621
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_NAME(romMethod)),
2622
J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)),
2623
(UDATA) J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(romMethod)),
2624
J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod)));
2625
}
2626
2627
if (verboseVerification) {
2628
ALWAYS_TRIGGER_J9HOOK_VM_CLASS_VERIFICATION_END(verifyData->javaVM->hookInterface, verifyData, newFormat);
2629
}
2630
2631
Trc_BCV_j9bcv_verifyBytecodes_Exit(verifyData->vmStruct, result);
2632
2633
return result;
2634
}
2635
#undef ALLOC_BUFFER
2636
2637
2638
/*
2639
* returns J9VMDLLMAIN_OK on success
2640
* returns J9VMDLLMAIN_FAILED on error
2641
*/
2642
IDATA
2643
j9bcv_J9VMDllMain (J9JavaVM* vm, IDATA stage, void* reserved)
2644
{
2645
J9BytecodeVerificationData* verifyData = NULL;
2646
char optionValuesBuffer[128]; /* Needs to be big enough to hold -Xverify option values */
2647
char* optionValuesBufferPtr = optionValuesBuffer;
2648
J9VMDllLoadInfo* loadInfo = NULL;
2649
IDATA xVerifyIndex = -1;
2650
IDATA xVerifyColonIndex = -1;
2651
IDATA verboseVerificationIndex = -1;
2652
IDATA noVerboseVerificationIndex = -1;
2653
IDATA verifyErrorDetailsIndex = -1;
2654
IDATA noVerifyErrorDetailsIndex = -1;
2655
IDATA classRelationshipVerifierIndex = -1;
2656
IDATA noClassRelationshipVerifierIndex = -1;
2657
IDATA returnVal = J9VMDLLMAIN_OK;
2658
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2659
J9HookInterface ** vmHooks = vm->internalVMFunctions->getVMHookInterface(vm);
2660
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
2661
2662
PORT_ACCESS_FROM_JAVAVM(vm);
2663
2664
switch(stage) {
2665
2666
case ALL_VM_ARGS_CONSUMED :
2667
FIND_AND_CONSUME_ARG( OPTIONAL_LIST_MATCH, OPT_XVERIFY, NULL);
2668
break;
2669
2670
case BYTECODE_TABLE_SET :
2671
loadInfo = FIND_DLL_TABLE_ENTRY( THIS_DLL_NAME );
2672
verifyData = j9bcv_initializeVerificationData(vm);
2673
if( !verifyData ) {
2674
loadInfo->fatalErrorStr = "j9bcv_initializeVerificationData failed";
2675
returnVal = J9VMDLLMAIN_FAILED;
2676
break;
2677
}
2678
2679
vm->bytecodeVerificationData = verifyData;
2680
vm->runtimeFlags |= J9_RUNTIME_VERIFY;
2681
2682
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2683
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, bcvHookClassesUnload, OMR_GET_CALLSITE(), vm)) {
2684
returnVal = J9VMDLLMAIN_FAILED;
2685
break;
2686
}
2687
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
2688
2689
/* Parse the -Xverify and -Xverify:<opt> commandline options.
2690
* Rules:
2691
* 1. -Xverify skips any previous -Xverify:<opt> arguments. -Xverify is the default state.
2692
* 2. Any -Xverify:<opt> prior to -Xverify is ignored.
2693
* 3. All -Xverify:<opt> after the -Xverify are processed in left-to-right order.
2694
* 4. -Xverify:<opt>,<opt> etc is also valid.
2695
* 5. -Xverify: is an error.
2696
* 6. -Xverify:<opt> processing occurs in the parseOptions function.
2697
*
2698
* This parsing is a duplicate of the parsing in the function VMInitStages of jvminit.c
2699
*/
2700
xVerifyIndex = FIND_ARG_IN_VMARGS( EXACT_MATCH, OPT_XVERIFY, NULL);
2701
xVerifyColonIndex = FIND_ARG_IN_VMARGS_FORWARD( STARTSWITH_MATCH, OPT_XVERIFY_COLON, NULL);
2702
while (xVerifyColonIndex >= 0) {
2703
/* Ignore -Xverify:<opt>'s prior to the last -Xverify */
2704
if (xVerifyColonIndex > xVerifyIndex) {
2705
/* Deal with possible -Xverify:<opt>,<opt> case */
2706
GET_OPTION_VALUES( xVerifyColonIndex, ':', ',', &optionValuesBufferPtr, 128 );
2707
2708
if(*optionValuesBuffer) {
2709
if (!parseOptions(vm, optionValuesBuffer, &loadInfo->fatalErrorStr)) {
2710
returnVal = J9VMDLLMAIN_FAILED;
2711
}
2712
} else {
2713
loadInfo->fatalErrorStr = "No options specified for -Xverify:<opt>";
2714
returnVal = J9VMDLLMAIN_FAILED;
2715
}
2716
}
2717
/* Advance to next argument */
2718
xVerifyColonIndex = FIND_NEXT_ARG_IN_VMARGS_FORWARD(STARTSWITH_MATCH, OPT_XVERIFY_COLON, NULL, xVerifyColonIndex);
2719
}
2720
2721
verboseVerificationIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXVERBOSEVERIFICATION, NULL);
2722
noVerboseVerificationIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXNOVERBOSEVERIFICATION, NULL);
2723
if (verboseVerificationIndex > noVerboseVerificationIndex) {
2724
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_VERBOSE_VERIFICATION;
2725
}
2726
2727
verifyErrorDetailsIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXVERIFYERRORDETAILS, NULL);
2728
noVerifyErrorDetailsIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXNOVERIFYERRORDETAILS, NULL);
2729
if (verifyErrorDetailsIndex >= noVerifyErrorDetailsIndex) {
2730
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_ERROR_DETAILS;
2731
}
2732
2733
/* Set runtime flag for -XX:+ClassRelationshipVerifier */
2734
classRelationshipVerifierIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXCLASSRELATIONSHIPVERIFIER, NULL);
2735
noClassRelationshipVerifierIndex = FIND_AND_CONSUME_ARG(EXACT_MATCH, VMOPT_XXNOCLASSRELATIONSHIPVERIFIER, NULL);
2736
if (classRelationshipVerifierIndex > noClassRelationshipVerifierIndex) {
2737
if (J9_ARE_ANY_BITS_SET(vm->runtimeFlags, J9_RUNTIME_XFUTURE)) {
2738
loadInfo->fatalErrorStr = "-XX:+ClassRelationshipVerifier cannot be used if -Xfuture or if -Xverify:all is enabled";
2739
returnVal = J9VMDLLMAIN_FAILED;
2740
} else {
2741
vm->extendedRuntimeFlags2 |= J9_EXTENDED_RUNTIME2_ENABLE_CLASS_RELATIONSHIP_VERIFIER;
2742
}
2743
}
2744
2745
break;
2746
2747
case LIBRARIES_ONUNLOAD :
2748
if (vm->bytecodeVerificationData) {
2749
j9bcv_freeVerificationData(PORTLIB, vm->bytecodeVerificationData);
2750
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2751
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, bcvHookClassesUnload, vm);
2752
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
2753
}
2754
break;
2755
}
2756
return returnVal;
2757
}
2758
2759
2760
static IDATA
2761
setVerifyState(J9JavaVM *vm, char *option, char **errorString)
2762
{
2763
PORT_ACCESS_FROM_JAVAVM(vm);
2764
2765
if (0 == strcmp(option, OPT_ALL)) {
2766
/* JDK7 - CMVC 151154: Sun launcher converts -Xfuture to -Xverify:all */
2767
vm->runtimeFlags |= J9_RUNTIME_XFUTURE;
2768
vm->bytecodeVerificationData->verificationFlags &= ~J9_VERIFY_SKIP_BOOTSTRAP_CLASSES;
2769
} else if (0 == strcmp(option, OPT_OPT)) {
2770
/* on by default - will override a "noopt" before it */
2771
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_OPTIMIZE;
2772
} else if (0 == strcmp(option, OPT_NO_OPT)) {
2773
vm->bytecodeVerificationData->verificationFlags &= ~J9_VERIFY_OPTIMIZE;
2774
} else if (0 == strcmp(option, OPT_NO_FALLBACK)) {
2775
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_NO_FALLBACK;
2776
} else if (0 == strcmp(option, OPT_IGNORE_STACK_MAPS)) {
2777
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_IGNORE_STACK_MAPS;
2778
} else if (0 == strncmp(option, OPT_EXCLUDEATTRIBUTE_EQUAL, sizeof(OPT_EXCLUDEATTRIBUTE_EQUAL) - 1)) {
2779
if (0 != option[sizeof(OPT_EXCLUDEATTRIBUTE_EQUAL)]) {
2780
UDATA length;
2781
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_EXCLUDE_ATTRIBUTE;
2782
/* Save the parameter string, NULL terminated and the length excluding the NULL */
2783
length = strlen(option) - sizeof(OPT_EXCLUDEATTRIBUTE_EQUAL) + 1;
2784
vm->bytecodeVerificationData->excludeAttribute = j9mem_allocate_memory(length + 1, J9MEM_CATEGORY_CLASSES);
2785
if (NULL == vm->bytecodeVerificationData->excludeAttribute) {
2786
if (errorString) {
2787
*errorString = "Out of memory processing -Xverify:<opt>";
2788
}
2789
return FALSE;
2790
}
2791
memcpy(vm->bytecodeVerificationData->excludeAttribute, &(option[sizeof(OPT_EXCLUDEATTRIBUTE_EQUAL) - 1]), length + 1);
2792
}
2793
} else if (0 == strcmp(option, OPT_BOOTCLASSPATH_STATIC)) {
2794
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_BOOTCLASSPATH_STATIC;
2795
} else if (0 == strcmp(option, OPT_DO_PROTECTED_ACCESS_CHECK)) {
2796
vm->bytecodeVerificationData->verificationFlags |= J9_VERIFY_DO_PROTECTED_ACCESS_CHECK;
2797
} else {
2798
if (errorString) {
2799
*errorString = "Unrecognised option(s) for -Xverify:<opt>";
2800
}
2801
return FALSE;
2802
}
2803
return TRUE;
2804
}
2805
2806
2807
2808
static IDATA
2809
parseOptions(J9JavaVM *vm, char *optionValues, char **errorString)
2810
{
2811
char *optionValue = optionValues; /* Values are separated by single NULL characters. */
2812
2813
/* call setVerifyState on each individual option */
2814
while (*optionValue) {
2815
if( !setVerifyState( vm, optionValue, errorString ) ) {
2816
return FALSE;
2817
}
2818
optionValue = optionValue + strlen(optionValue) + 1; /* Step past null separator to next element */
2819
}
2820
return TRUE;
2821
}
2822
2823
2824
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2825
/**
2826
* Unlink any constraints related to dying classloaders
2827
*/
2828
static void
2829
bcvHookClassesUnload(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
2830
{
2831
J9JavaVM *javaVM = userData;
2832
2833
if (0 != (javaVM->runtimeFlags & J9_RUNTIME_VERIFY)) {
2834
unlinkClassLoadingConstraints(javaVM);
2835
}
2836
}
2837
#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */
2838
2839
2840
2841