Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/bcutil.c
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include "j9.h"
27
#include "j2sever.h"
28
#include "jimagereader.h"
29
#include "jvminit.h"
30
#include "bcutil_internal.h"
31
#include "SCAbstractAPI.h"
32
#include "j9protos.h"
33
#ifdef J9VM_OPT_ZIP_SUPPORT
34
#include "vmi.h"
35
#endif
36
37
#define _UTE_STATIC_
38
39
#include "ut_j9bcu.h"
40
41
#if defined(WIN32) || defined(WIN64)
42
#define strdup _strdup
43
#endif
44
45
#define THIS_DLL_NAME J9_DYNLOAD_DLL_NAME
46
47
static IDATA initializeTranslationBuffers (J9PortLibrary * portLib, J9TranslationBufferSet * translationBuffers);
48
49
/*
50
Free memory allocated to dynamic loader buffers.
51
Answer zero on success */
52
53
IDATA
54
j9bcutil_freeTranslationBuffers(J9PortLibrary * portLib, J9TranslationBufferSet * translationBuffers)
55
{
56
PORT_ACCESS_FROM_PORT(portLib);
57
Trc_BCU_freeTranslationBuffers_Entry(translationBuffers);
58
59
j9mem_free_memory(translationBuffers->classFileError);
60
translationBuffers->classFileError = NULL;
61
j9mem_free_memory(translationBuffers->sunClassFileBuffer);
62
translationBuffers->sunClassFileBuffer = NULL;
63
j9mem_free_memory(translationBuffers->searchFilenameBuffer);
64
translationBuffers->searchFilenameBuffer = NULL;
65
if (NULL != translationBuffers->dynamicLoadStats) {
66
j9mem_free_memory(translationBuffers->dynamicLoadStats->name);
67
translationBuffers->dynamicLoadStats->name = NULL;
68
j9mem_free_memory(translationBuffers->dynamicLoadStats);
69
translationBuffers->dynamicLoadStats = NULL;
70
}
71
72
Trc_BCU_freeTranslationBuffers_Exit();
73
return BCT_ERR_NO_ERROR;
74
}
75
76
77
/*
78
Allocate memory for dynamic loader buffers.
79
Answer zero on success */
80
81
J9TranslationBufferSet *
82
j9bcutil_allocTranslationBuffers(J9PortLibrary *portLib)
83
{
84
J9TranslationBufferSet *translationBuffers;
85
PORT_ACCESS_FROM_PORT( portLib );
86
87
Trc_BCU_allocTranslationBuffers_Entry(0);
88
89
translationBuffers = (J9TranslationBufferSet*)j9mem_allocate_memory((UDATA) sizeof(J9TranslationBufferSet), J9MEM_CATEGORY_CLASSES);
90
if (NULL == translationBuffers) {
91
Trc_BCU_allocTranslationBuffers_Exit(NULL);
92
return NULL;
93
}
94
95
if (BCT_ERR_NO_ERROR != initializeTranslationBuffers( portLib, translationBuffers)) {
96
j9bcutil_freeAllTranslationBuffers(portLib, translationBuffers);
97
translationBuffers = NULL;
98
}
99
100
Trc_BCU_allocTranslationBuffers_Exit(translationBuffers);
101
102
return translationBuffers;
103
}
104
105
/*
106
Free memory allocated to dynamic loader buffers.
107
Answer zero on success */
108
109
IDATA
110
j9bcutil_freeAllTranslationBuffers( J9PortLibrary *portLib, J9TranslationBufferSet *translationBuffers )
111
{
112
PORT_ACCESS_FROM_PORT( portLib );
113
j9bcutil_freeTranslationBuffers( portLib, translationBuffers );
114
j9mem_free_memory( translationBuffers );
115
return BCT_ERR_NO_ERROR;
116
}
117
118
IDATA
119
bcutil_J9VMDllMain(J9JavaVM* vm, IDATA stage, void* reserved)
120
{
121
IDATA returnVal = J9VMDLLMAIN_OK;
122
I_32 rc = J9JIMAGE_NO_ERROR;
123
J9VMDllLoadInfo* loadInfo;
124
J9JImageIntf *jimageIntf = NULL;
125
J9TranslationBufferSet* translationBuffers;
126
127
PORT_ACCESS_FROM_JAVAVM(vm);
128
VMI_ACCESS_FROM_JAVAVM((JavaVM*)vm);
129
130
#define BUFFERS_ALLOC_STAGE BYTECODE_TABLE_SET /* defined separately to ensure dependencies below */
131
132
switch(stage) {
133
134
/* Note that verbose support should have already been initialized in an earlier stage */
135
case BUFFERS_ALLOC_STAGE :
136
loadInfo = FIND_DLL_TABLE_ENTRY( THIS_DLL_NAME );
137
if (J2SE_VERSION(vm) >= J2SE_V11) {
138
rc = initJImageIntf(&jimageIntf, vm, PORTLIB);
139
if (J9JIMAGE_NO_ERROR != rc) {
140
loadInfo->fatalErrorStr = "failed to initialize JImage interface";
141
returnVal = J9VMDLLMAIN_FAILED;
142
break;
143
}
144
}
145
translationBuffers = j9bcutil_allocTranslationBuffers(vm->portLibrary);
146
if (translationBuffers == NULL) {
147
loadInfo->fatalErrorStr = "j9bcutil_allocTranslationBuffers failed";
148
returnVal = J9VMDLLMAIN_FAILED;
149
break;
150
}
151
#ifdef J9VM_OPT_ZIP_SUPPORT
152
translationBuffers->closeZipFileFunction = (I_32 (*)(J9VMInterface* vmi, struct VMIZipFile* zipFile)) ((*VMI)->GetZipFunctions(VMI)->zip_closeZipFile);
153
#endif
154
155
#ifdef J9VM_INTERP_VERBOSE
156
if(vm->verboseLevel & VERBOSE_DYNLOAD) {
157
vm->verboseStruct->hookDynamicLoadReporting(translationBuffers);
158
}
159
#endif
160
vm->jimageIntf = jimageIntf;
161
vm->dynamicLoadBuffers = translationBuffers;
162
vm->mapMemoryBufferSize = MAP_MEMORY_DEFAULT + MAP_MEMORY_RESULTS_BUFFER_SIZE;
163
vm->mapMemoryResultsBuffer = j9mem_allocate_memory(vm->mapMemoryBufferSize, J9MEM_CATEGORY_CLASSES);
164
165
if (omrthread_monitor_init_with_name(&vm->mapMemoryBufferMutex, 0, "global mapMemoryBuffer mutex")
166
|| (vm->mapMemoryResultsBuffer == NULL)
167
) {
168
loadInfo->fatalErrorStr = "initial global mapMemoryBuffer or mapMemoryBufferMutex allocation failed";
169
returnVal = J9VMDLLMAIN_FAILED;
170
}
171
vm->mapMemoryBuffer = vm->mapMemoryResultsBuffer + MAP_MEMORY_RESULTS_BUFFER_SIZE;
172
break;
173
174
case AGENTS_STARTED :
175
break;
176
177
case JCL_INITIALIZED :
178
break;
179
180
case LIBRARIES_ONUNLOAD :
181
loadInfo = FIND_DLL_TABLE_ENTRY( THIS_DLL_NAME );
182
if (IS_STAGE_COMPLETED(loadInfo->completedBits, BUFFERS_ALLOC_STAGE) && vm->dynamicLoadBuffers) {
183
shutdownROMClassBuilder(vm);
184
j9bcutil_freeAllTranslationBuffers(vm->portLibrary, vm->dynamicLoadBuffers);
185
vm->dynamicLoadBuffers = 0;
186
}
187
188
j9mem_free_memory(vm->mapMemoryResultsBuffer);
189
if (vm->mapMemoryBufferMutex) {
190
omrthread_monitor_destroy(vm->mapMemoryBufferMutex);
191
}
192
193
if (vm->jimageIntf) {
194
closeJImageIntf(vm->jimageIntf);
195
vm->jimageIntf = NULL;
196
}
197
198
break;
199
}
200
return returnVal;
201
}
202
203
/*
204
Formerly j9bcutil_copyAndCompressUTF8 in jbmapsub
205
206
Walks the UTF-8 encoded buffer specified by source and length (in bytes) and
207
checks for well formed UTF-8 bytes well making the output canonical.
208
(Canonical means a Unicode character is encoded in the fewest UTF-8 bytes possible)
209
The bytes are written as read and if the read data is not canonical, back up and fix.
210
211
As converted from builder.
212
213
UTF-8 encodings:
214
1-7F -> 0xxxxxxx
215
0, 80-7FF -> 110xxxxx 10xxxxxx - note a zero byte is illegal in Java UTF-8's
216
800-FFFF -> 1110xxxx 10xxxxxx 10xxxxxx
217
218
Surrogate pairs
219
U+D800..U+DBFF followed by one of U+DC00..U+DFFF
220
-> 11101101 1010xxxx 10xxxxxx
221
11101101 1011xxxx 10xxxxxx
222
This function ignores surrogates and treats them as two separate three byte
223
encodings. This is valid.
224
225
The bit CFR_FOUND_CHARS_IN_EXTENDED_MUE_FORM is set in mueAsciiStatus if a
226
non-null UTF character is extended using modified UTF-8 (MUE)format,
227
similar to the null character. For classfile versions 48 and up, the JVM is
228
supposed to reject MUE characters.
229
The bit CFR_FOUND_SEPARATOR_IN_MUE_FORM is set in mueAsciiStatus if the
230
character '/' was found in MUE form, which is specifically
231
disallowed in class names even for classfile version 47 and lower.
232
If mueAsciiStatus is left NULL it is not used.
233
234
Returns compressed length or -1.
235
*/
236
237
I_32
238
j9bcutil_verifyCanonisizeAndCopyUTF8 (U_8 *dest, U_8 *source, U_32 length, U_8 *mueAsciiStatus)
239
{
240
U_8 *originalDest = dest;
241
U_8 *originalSource = source;
242
U_8 *sourceEnd = source + length;
243
UDATA firstByte, nextByte, outWord, charLength, compression = 0;
244
I_32 result = -1;
245
U_8 mueStatus = 0;
246
247
Trc_BCU_verifyCanonisizeAndCopyUTF8_Entry(dest, source, length);
248
249
/* Assumes success */
250
memcpy (dest, source, length);
251
252
while (source != sourceEnd) {
253
254
/* Handle multibyte */
255
if (((UDATA) ((*source++) - 1)) < 0x7F) {
256
continue;
257
}
258
259
firstByte = *(source - 1);
260
if (firstByte == 0) {
261
Trc_BCU_verifyCanonisizeAndCopyUTF8_FailedFirstByteZero();
262
goto fail;
263
}
264
265
/* if multi-byte then first byte must be 11xxxxxx and more to come */
266
if (((firstByte & 0x40) == 0) || (source == sourceEnd)) {
267
Trc_BCU_verifyCanonisizeAndCopyUTF8_FailedFirstByteFormat(firstByte);
268
goto fail;
269
}
270
271
charLength = 2;
272
273
nextByte = *source++;
274
if ((nextByte & 0xC0) != 0x80) {
275
Trc_BCU_verifyCanonisizeAndCopyUTF8_FailedSecondByteFormat(nextByte);
276
goto fail;
277
}
278
279
/* Assemble first two bytes */
280
/* 0x1F mask is okay for 3-byte codes as legal ones have a 0 bit at 0x10 */
281
outWord = ((firstByte & 0x1F) << 6) | (nextByte & 0x3F);
282
283
if ((firstByte & 0x20) != 0) {
284
/* three bytes */
285
if (((firstByte & 0x10) != 0) || (source == sourceEnd)) {
286
Trc_BCU_verifyCanonisizeAndCopyUTF8_FailedFirstOfThreeByteFormat(firstByte);
287
goto fail;
288
}
289
290
charLength = 3;
291
292
nextByte = *source++;
293
if ((nextByte & 0xC0) != 0x80) {
294
Trc_BCU_verifyCanonisizeAndCopyUTF8_FailedThirdByteFormat(nextByte);
295
goto fail;
296
}
297
298
/* Add the third byte */
299
outWord = (outWord << 6) | (nextByte & 0x3F);
300
}
301
302
/* Overwrite the multibyte UTF8 character only if shorter */
303
if ((outWord != 0) && (outWord < 0x80)) {
304
/* character '/' handled specially in class name utf8 */
305
if ((UDATA)'/' == outWord) {
306
mueStatus |= CFR_FOUND_SEPARATOR_IN_MUE_FORM;
307
}
308
/* One byte must be shorter in here */
309
dest = originalDest + (source - originalSource - charLength - compression);
310
*dest++ = (U_8) outWord;
311
compression += charLength - 1;
312
memcpy (dest, source, (UDATA) (sourceEnd - source));
313
314
} else if ((outWord < 0x800) && (charLength == 3)) {
315
dest = originalDest + (source - originalSource - charLength - compression);
316
*dest++ = (U_8) ((outWord >> 6) | 0xC0);
317
*dest++ = (U_8) ((outWord & 0x3F) | 0x80);
318
compression++;
319
memcpy (dest, source, (UDATA) (sourceEnd - source));
320
}
321
}
322
323
if (compression > 0) {
324
mueStatus |= CFR_FOUND_CHARS_IN_EXTENDED_MUE_FORM;
325
}
326
327
result = (I_32) (length - compression);
328
329
if (NULL != mueAsciiStatus) {
330
*mueAsciiStatus = mueStatus;
331
}
332
333
fail:
334
Trc_BCU_verifyCanonisizeAndCopyUTF8_Exit(result);
335
336
return result;
337
}
338
339
/*
340
Allocate memory for dynamic loader buffers.
341
Answer zero on success */
342
343
static IDATA
344
initializeTranslationBuffers(J9PortLibrary * portLib, J9TranslationBufferSet * translationBuffers)
345
{
346
PORT_ACCESS_FROM_PORT(portLib);
347
348
memset(translationBuffers, 0, sizeof(J9TranslationBufferSet));
349
350
351
translationBuffers->findLocallyDefinedClassFunction = findLocallyDefinedClass;
352
translationBuffers->internalDefineClassFunction = internalDefineClass;
353
354
translationBuffers->dynamicLoadStats =
355
(J9DynamicLoadStats *) j9mem_allocate_memory((UDATA) sizeof(struct J9DynamicLoadStats), J9MEM_CATEGORY_CLASSES);
356
if (translationBuffers->dynamicLoadStats == NULL) {
357
return BCT_ERR_OUT_OF_MEMORY;
358
}
359
memset(translationBuffers->dynamicLoadStats, 0, sizeof(struct J9DynamicLoadStats));
360
translationBuffers->dynamicLoadStats->nameBufferLength = 1024;
361
translationBuffers->dynamicLoadStats->name =
362
j9mem_allocate_memory(translationBuffers->dynamicLoadStats->nameBufferLength, J9MEM_CATEGORY_CLASSES);
363
if (translationBuffers->dynamicLoadStats->name == NULL) {
364
return BCT_ERR_OUT_OF_MEMORY;
365
}
366
367
translationBuffers->relocatorDLLHandle = 0;
368
369
translationBuffers->internalLoadROMClassFunction = internalLoadROMClass;
370
translationBuffers->transformROMClassFunction = j9bcutil_transformROMClass;
371
372
#if defined(J9VM_OPT_INVARIANT_INTERNING)
373
/* invariant interning support */
374
translationBuffers->flags |= BCU_ENABLE_INVARIANT_INTERNING;
375
#endif
376
377
return BCT_ERR_NO_ERROR;
378
}
379
380