Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/ddr/j9ddr.c
5991 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2017 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
#include "j9protos.h"
25
#include "j9port.h"
26
27
#include "j9ddr.h"
28
#include "ddrtable.h"
29
30
extern U_8 sizeofBool(void);
31
32
typedef struct {
33
U_32 x1 : 1;
34
U_32 x2 : 15;
35
U_32 x3 : 6;
36
U_32 x4 : 10;
37
38
U_32 x5 : 7;
39
U_32 x6 : 9;
40
U_32 x7 : 4;
41
U_32 x8 : 12;
42
} bitField;
43
44
#define DEBUG
45
46
#define J9DDR_CORE_FILE_DATA_VERSION 1
47
48
typedef struct {
49
U_32 version;
50
U_8 sizeofBool;
51
U_8 sizeofUDATA;
52
U_8 bitfieldFormat;
53
U_8 unused;
54
U_32 structDataSize;
55
U_32 stringDataSize;
56
U_32 structureCount;
57
} J9DDRCoreFileData;
58
59
typedef struct {
60
OMRPortLibrary * portLibrary;
61
J9DDRCoreFileData * coreFileData;
62
const J9DDRStructDefinition ** structTables;
63
UDATA totalSize;
64
J9HashTable * stringTable;
65
void * cursor;
66
char * filename;
67
} J9DDRTranslationData;
68
69
typedef struct {
70
const char * cString;
71
U_32 offset;
72
} J9DDRStringTableEntry;
73
74
typedef struct {
75
U_32 nameOffset;
76
U_32 superOffset;
77
U_32 structSize;
78
U_32 fieldCount;
79
U_32 constantCount;
80
} J9DDRCoreFileStruct;
81
82
typedef struct {
83
U_32 nameOffset;
84
U_32 typeOffset;
85
U_32 offset;
86
} J9DDRCoreFileField;
87
88
typedef struct {
89
U_32 nameOffset;
90
U_32 value[2];
91
} J9DDRCoreFileConstant;
92
93
static jint initializeBitfieldEncoding PROTOTYPE((J9DDRTranslationData * data));
94
static jint processDDRStructTableList PROTOTYPE((J9DDRTranslationData * data));
95
static jint writeDataFile PROTOTYPE((J9DDRTranslationData * data));
96
static jint processDDRStructTable PROTOTYPE((J9DDRTranslationData * data, const J9DDRStructDefinition * ddrStruct));
97
static U_32 stringTableOffset PROTOTYPE((J9DDRTranslationData * data, const char * cString));
98
static void copyStringTable PROTOTYPE((J9DDRTranslationData * data));
99
static jint processDDRField PROTOTYPE((J9DDRTranslationData * data, const J9DDRFieldDeclaration * ddrField, U_32 * size));
100
static UDATA stringTableHash PROTOTYPE((void *key, void *userData));
101
static UDATA stringTableEquals PROTOTYPE((void *leftKey, void *rightKey, void *userData));
102
static jint processDDRConstant PROTOTYPE((J9DDRTranslationData * data, const J9DDRConstantDeclaration * ddrConstant, U_32 * size));
103
static jint createDDRCoreData PROTOTYPE((J9DDRTranslationData * data));
104
105
/* Try to initialize the NLS catalog; otherwise use defaults */
106
static void
107
ddr_setNLSCatalog(OMRPortLibrary * portLib, char **argv)
108
{
109
char *exename = NULL;
110
111
OMRPORT_ACCESS_FROM_OMRPORT(portLib);
112
113
/* Look for java.home in the executable's directory */
114
if ( omrsysinfo_get_executable_name( argv[0], &exename ) == 0 ) {
115
116
/* find the last separator and add the "java" string */
117
omrnls_set_catalog( (const char**)&exename, 1, "java", "properties" );
118
}
119
/* Do /not/ delete executable name string; system-owned. */
120
}
121
122
123
static jint
124
createDDRCoreData(J9DDRTranslationData * data)
125
{
126
OMRPORT_ACCESS_FROM_OMRPORT(data->portLibrary);
127
J9HashTable * stringTable = NULL;
128
jint rc = JNI_OK;
129
J9DDRCoreFileData pass1Header;
130
J9DDRCoreFileData * coreFileData;
131
132
omrtty_printf("Encoding struct data\n");
133
134
/* Create an empty string table */
135
136
stringTable = hashTableNew(OMRPORTLIB, J9_GET_CALLSITE(), 0, sizeof(J9DDRStringTableEntry), 0, 0, OMRMEM_CATEGORY_VM, stringTableHash, stringTableEquals, NULL, NULL);
137
if (stringTable == NULL) {
138
omrtty_printf("ERROR: Unable to allocate string hash table\n");
139
rc = JNI_ENOMEM;
140
goto done;
141
}
142
143
/* Run the conversion once without writing to compute the size */
144
145
data->stringTable = stringTable;
146
data->coreFileData = &pass1Header;
147
memset(&pass1Header, 0, sizeof(pass1Header));
148
rc = processDDRStructTableList(data);
149
if (rc != JNI_OK) {
150
omrtty_printf("ERROR: Pass 1 encoding failed\n");
151
data->coreFileData = NULL;
152
rc = JNI_ENOMEM;
153
goto done;
154
}
155
156
/* Allocate memory for the header, struct data and string table and copy in the header */
157
158
data->totalSize = sizeof(pass1Header) + pass1Header.structDataSize + pass1Header.stringDataSize;
159
coreFileData = omrmem_allocate_memory(data->totalSize, OMRMEM_CATEGORY_VM);
160
if (coreFileData == NULL) {
161
omrtty_printf("ERROR: Unable to allocate temp space of size %d for encoded data\n", data->totalSize);
162
rc = JNI_ENOMEM;
163
goto done;
164
}
165
data->coreFileData = coreFileData;
166
*coreFileData = pass1Header;
167
168
/* Run the conversion again, writing the struct data to the allocated memory */
169
170
memset(coreFileData, 0, data->totalSize);
171
coreFileData->stringDataSize = pass1Header.stringDataSize;
172
data->cursor = coreFileData + 1;
173
rc = processDDRStructTableList(data);
174
if (rc != JNI_OK) {
175
omrtty_printf("ERROR: Pass 2 encoding failed\n");
176
rc = JNI_ERR;
177
goto done;
178
}
179
180
/* Sanity check to make sure the second pass computations match the first pass */
181
182
if (memcmp(&pass1Header, coreFileData, sizeof(pass1Header)) != 0) {
183
omrtty_printf("ERROR: Pass 2 header does not match pass 1\n");
184
rc = JNI_EINVAL;
185
goto done;
186
}
187
if ((((U_8 *)(coreFileData +1)) + coreFileData->structDataSize) != data->cursor) {
188
omrtty_printf("ERROR: Pass 2 data size does not match pass 1\n");
189
rc = JNI_EINVAL;
190
goto done;
191
}
192
193
/* Write the string table after the struct data */
194
195
copyStringTable(data);
196
197
/* Sanity check to make sure the second pass computations match the first pass */
198
199
if ((((U_8 *)(coreFileData +1)) + coreFileData->structDataSize + coreFileData->stringDataSize) != data->cursor) {
200
omrtty_printf("ERROR: Pass 2 string table size does not match pass 1\n");
201
rc = JNI_EINVAL;
202
goto done;
203
}
204
205
/* Fill in compile-time constants */
206
207
coreFileData->version = J9DDR_CORE_FILE_DATA_VERSION;
208
coreFileData->sizeofBool = sizeofBool();
209
coreFileData->sizeofUDATA = sizeof(UDATA);
210
rc = initializeBitfieldEncoding(data);
211
212
done:
213
if (stringTable != NULL) {
214
hashTableFree(stringTable);
215
}
216
217
return rc;
218
}
219
220
static jint
221
processDDRStructTableList(J9DDRTranslationData * data)
222
{
223
const J9DDRStructDefinition ** list = data->structTables;
224
225
/* Process each struct table in the list */
226
while(NULL != *list) {
227
jint rc = processDDRStructTable(data, *list++);
228
229
if (rc != JNI_OK) {
230
return rc;
231
}
232
}
233
234
/* Round the string data size up to U_32 to maintain alignment of anything which comes after it */
235
236
data->coreFileData->stringDataSize = (data->coreFileData->stringDataSize + 3) & ~(U_32)3;
237
238
return JNI_OK;
239
}
240
241
242
static void
243
copyStringTable(J9DDRTranslationData * data)
244
{
245
U_8 * stringData = data->cursor;
246
J9HashTableState state;
247
J9DDRStringTableEntry * entry;
248
249
/* Iterate the table and copy each string to its already-assigned offset */
250
251
entry = hashTableStartDo(data->stringTable, &state);
252
while (entry != NULL) {
253
J9UTF8 * utf = (J9UTF8 *)(stringData + entry->offset);
254
const char * cString = entry->cString;
255
size_t len = strlen(cString);
256
257
J9UTF8_SET_LENGTH(utf, (U_16)len);
258
memcpy(J9UTF8_DATA(utf), cString, len);
259
260
entry = hashTableNextDo(&state);
261
}
262
263
/* Update cursor (stringDataSize is U_32 aligned already) */
264
265
data->cursor = stringData + data->coreFileData->stringDataSize;
266
}
267
268
static UDATA
269
stringTableHash(void *key, void *userData)
270
{
271
const char *s = ((J9DDRStringTableEntry *)key)->cString;
272
size_t length = strlen(s);
273
UDATA hash = 0;
274
U_8 * data = (U_8 *) s;
275
const U_8 * end = data + length;
276
277
while (data < end) {
278
U_16 c;
279
280
data += decodeUTF8Char(data, &c);
281
hash = (hash << 5) - hash + c;
282
}
283
return hash;
284
}
285
static UDATA
286
stringTableEquals(void *leftKey, void *rightKey, void *userData)
287
{
288
const char *left_s = ((J9DDRStringTableEntry *)leftKey)->cString;
289
const char *right_s = ((J9DDRStringTableEntry *)rightKey)->cString;
290
291
return (left_s == right_s) || (0 == strcmp(left_s, right_s));
292
}
293
static U_32
294
stringTableOffset(J9DDRTranslationData * data, const char * cString)
295
{
296
J9DDRStringTableEntry exemplar;
297
J9DDRStringTableEntry * entry;
298
299
exemplar.cString = cString;
300
exemplar.offset = U_32_MAX;
301
302
/* Add will return an existing entry if one matches, NULL on allocation failure, or the new node */
303
304
entry = hashTableAdd(data->stringTable, &exemplar);
305
306
/* NULL means the string was new, but memory allocation failed */
307
308
if (entry == NULL) {
309
OMRPORT_ACCESS_FROM_OMRPORT(data->portLibrary);
310
omrtty_printf("ERROR: Unable to allocate memory for string table entry: %s", cString);
311
return U_32_MAX;
312
}
313
314
/* If the offset is U_32_MAX, this indicates that a new entry was added */
315
316
if (entry->offset == U_32_MAX) {
317
entry->offset = data->coreFileData->stringDataSize;
318
319
/* Reserve space for the U_16 size, the string data, and the padding byte, if necessary */
320
321
data->coreFileData->stringDataSize += (U_32)((sizeof(U_16) + strlen(cString) + 1) & ~(size_t)1);
322
}
323
324
return entry->offset;
325
}
326
static jint
327
processDDRStructTable(J9DDRTranslationData * data, const J9DDRStructDefinition * ddrStruct)
328
{
329
/* Process each struct definition in the array (table is terminated with an all-zero entry */
330
331
while (ddrStruct->name != NULL) {
332
J9DDRCoreFileStruct * coreFileStruct = data->cursor;
333
const J9DDRFieldDeclaration * ddrField;
334
const J9DDRConstantDeclaration * ddrConstant;
335
U_32 nameOffset;
336
U_32 superOffset;
337
U_32 fieldCount = 0;
338
U_32 constantCount = 0;
339
jint rc;
340
341
if (data->cursor != NULL) {
342
data->cursor = coreFileStruct + 1;
343
}
344
data->coreFileData->structDataSize += sizeof(J9DDRCoreFileStruct);
345
346
/* Process fields */
347
348
ddrField = ddrStruct->fields;
349
if (ddrField != NULL) {
350
while (ddrField->name != NULL) {
351
rc = processDDRField(data, ddrField, &(data->coreFileData->structDataSize));
352
if (rc != JNI_OK) {
353
return rc;
354
}
355
++fieldCount;
356
++ddrField;
357
}
358
}
359
360
/* Process constants */
361
362
ddrConstant = ddrStruct->constants;
363
if (ddrConstant != NULL) {
364
while (ddrConstant->name != NULL) {
365
rc = processDDRConstant(data, ddrConstant, &(data->coreFileData->structDataSize));
366
if (rc != JNI_OK) {
367
return rc;
368
}
369
++constantCount;
370
++ddrConstant;
371
}
372
}
373
374
/* Create the strings */
375
376
nameOffset = stringTableOffset(data, ddrStruct->name);
377
if (nameOffset == U_32_MAX) {
378
return JNI_ENOMEM;
379
}
380
if (ddrStruct->superName == NULL) {
381
superOffset = U_32_MAX;
382
} else {
383
superOffset = stringTableOffset(data, ddrStruct->superName);
384
if (superOffset == U_32_MAX) {
385
return JNI_ENOMEM;
386
}
387
}
388
389
/* Fill in the header */
390
391
if (data->cursor != NULL) {
392
coreFileStruct->nameOffset = nameOffset;
393
coreFileStruct->superOffset = superOffset;
394
coreFileStruct->structSize = ddrStruct->size;
395
coreFileStruct->fieldCount = fieldCount;
396
coreFileStruct->constantCount = constantCount;
397
}
398
399
data->coreFileData->structureCount += 1;
400
++ddrStruct;
401
}
402
403
return JNI_OK;
404
}
405
406
static jint
407
processDDRField(J9DDRTranslationData * data, const J9DDRFieldDeclaration * ddrField, U_32 * size)
408
{
409
U_32 nameOffset;
410
U_32 typeOffset;
411
412
/* Create the strings */
413
414
nameOffset = stringTableOffset(data, ddrField->name);
415
if (nameOffset == U_32_MAX) {
416
return JNI_ENOMEM;
417
}
418
typeOffset = stringTableOffset(data, ddrField->type);
419
if (typeOffset == U_32_MAX) {
420
return JNI_ENOMEM;
421
}
422
423
/* Fill in the struct */
424
425
if (data->cursor != NULL) {
426
J9DDRCoreFileField * coreFileField = data->cursor;
427
428
coreFileField->nameOffset = nameOffset;
429
coreFileField->typeOffset = typeOffset;
430
coreFileField->offset = ddrField->offset;
431
432
data->cursor = coreFileField + 1;
433
}
434
435
/* Update required size */
436
437
*size += sizeof(J9DDRCoreFileField);
438
439
return JNI_OK;
440
}
441
442
static jint
443
processDDRConstant(J9DDRTranslationData * data, const J9DDRConstantDeclaration * ddrConstant, U_32 * size)
444
{
445
U_32 nameOffset;
446
447
/* Create the strings */
448
449
nameOffset = stringTableOffset(data, ddrConstant->name);
450
if (nameOffset == U_32_MAX) {
451
return JNI_ENOMEM;
452
}
453
454
/* Fill in the struct */
455
456
if (data->cursor != NULL) {
457
J9DDRCoreFileConstant * coreFileConstant = data->cursor;
458
459
memcpy(coreFileConstant->value, &ddrConstant->value, sizeof(U_64));
460
coreFileConstant->nameOffset = nameOffset;
461
462
data->cursor = coreFileConstant + 1;
463
}
464
465
/* Update required size */
466
467
*size += sizeof(J9DDRCoreFileConstant);
468
469
return JNI_OK;
470
}
471
472
UDATA
473
ddrSignalProtectedMain(struct OMRPortLibrary *portLibrary, void *arg)
474
{
475
J9DDRCmdlineOptions *startupOptions = arg;
476
int argc = startupOptions->argc;
477
char **argv = startupOptions->argv;
478
char **envp = startupOptions->envp;
479
OMRPORT_ACCESS_FROM_OMRPORT(startupOptions->portLibrary);
480
J9DDRTranslationData data;
481
UDATA rc = JNI_OK;
482
483
memset(&data, 0, sizeof(data));
484
data.portLibrary = OMRPORTLIB;
485
data.filename = J9DDR_DAT_FILE;
486
487
ddr_setNLSCatalog(OMRPORTLIB, argv);
488
489
/* Initialize the thread library -- Zip code now uses monitors. */
490
omrthread_attach_ex(NULL, J9THREAD_ATTR_DEFAULT);
491
492
data.structTables = initializeDDRComponents(data.portLibrary);
493
if (NULL == data.structTables) {
494
rc = JNI_ENOMEM;
495
goto done;
496
}
497
498
rc = createDDRCoreData(&data);
499
if (rc != JNI_OK) {
500
goto done;
501
}
502
503
rc = writeDataFile(&data);
504
if (rc != JNI_OK) {
505
goto done;
506
}
507
508
omrtty_printf("Completed with no errors\n");
509
510
done:
511
omrmem_free_memory(data.coreFileData);
512
omrmem_free_memory((void*) data.structTables);
513
return (UDATA) rc;
514
}
515
516
static jint
517
writeDataFile(J9DDRTranslationData * data)
518
{
519
OMRPORT_ACCESS_FROM_OMRPORT(data->portLibrary);
520
IDATA fd;
521
IDATA length = data->totalSize;
522
523
omrtty_printf("Creating output file %s of size %i\n", data->filename, length);
524
fd = omrfile_open(data->filename, EsOpenWrite | EsOpenCreate | EsOpenTruncate, 0666);
525
if (fd == -1) {
526
omrtty_printf("ERROR: Failed to open output file\n");
527
return JNI_ERR;
528
}
529
530
if (omrfile_write(fd, data->coreFileData, length) != length) {
531
omrtty_printf("ERROR: Failed to write to output file\n");
532
omrfile_close(fd);
533
return JNI_ERR;
534
}
535
536
if (omrfile_close(fd) != 0) {
537
omrtty_printf("ERROR: Failed to close output file\n");
538
return JNI_ERR;
539
}
540
541
return JNI_OK;
542
}
543
544
545
546
static jint
547
initializeBitfieldEncoding(J9DDRTranslationData * data)
548
{
549
bitField bf;
550
jint rc = JNI_OK;
551
U_32 slot0;
552
U_32 slot1;
553
554
memset(&bf, 0, sizeof(bf));
555
556
bf.x1 = 1; /* 1 */
557
bf.x2 = 31768; /* 111110000011000 */
558
bf.x3 = 3; /* 000011 */
559
bf.x4 = 777; /* 1100001001 */
560
561
bf.x5 = 43; /* 0101011 */
562
bf.x6 = 298; /* 100101010 */
563
bf.x7 = 12; /* 1100 */
564
bf.x8 = 1654; /* 011001110110 */
565
566
slot0 = ((U_32*)&bf)[0];
567
slot1 = ((U_32*)&bf)[1];
568
if ((slot0 ==0xC243F831) && (slot1 == 0x676C952B)) {
569
data->coreFileData->bitfieldFormat = 1;
570
} else if ((slot0 ==0xFC180F09) && (slot1 == 0x572AC676)) {
571
data->coreFileData->bitfieldFormat = 2;
572
} else {
573
OMRPORT_ACCESS_FROM_OMRPORT(data->portLibrary);
574
575
omrtty_printf("ERROR: Unable to determine bitfield format from %08X %08X\n", slot0, slot1);
576
rc = JNI_ERR;
577
}
578
579
return rc;
580
}
581
582
583