Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/services/diagnosticArgument.cpp
41144 views
1
/*
2
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "jvm.h"
27
#include "memory/allocation.inline.hpp"
28
#include "memory/resourceArea.hpp"
29
#include "runtime/thread.hpp"
30
#include "services/diagnosticArgument.hpp"
31
32
StringArrayArgument::StringArrayArgument() {
33
_array = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<char *>(32, mtServiceability);
34
assert(_array != NULL, "Sanity check");
35
}
36
37
StringArrayArgument::~StringArrayArgument() {
38
for (int i=0; i<_array->length(); i++) {
39
FREE_C_HEAP_ARRAY(char, _array->at(i));
40
}
41
delete _array;
42
}
43
44
void StringArrayArgument::add(const char* str, size_t len) {
45
if (str != NULL) {
46
char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
47
strncpy(ptr, str, len);
48
ptr[len] = 0;
49
_array->append(ptr);
50
}
51
}
52
53
void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
54
/* NOTE:Some argument types doesn't require a value,
55
* for instance boolean arguments: "enableFeatureX". is
56
* equivalent to "enableFeatureX=true". In these cases,
57
* str will be null. This is perfectly valid.
58
* All argument types must perform null checks on str.
59
*/
60
61
if (is_set() && !allow_multiple()) {
62
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
63
"Duplicates in diagnostic command arguments\n");
64
}
65
parse_value(str, len, CHECK);
66
set_is_set(true);
67
}
68
69
void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) const {
70
jio_snprintf(buf, len, INT64_FORMAT, l);
71
}
72
73
void GenDCmdArgument::to_string(bool b, char* buf, size_t len) const {
74
jio_snprintf(buf, len, b ? "true" : "false");
75
}
76
77
void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) const {
78
jio_snprintf(buf, len, INT64_FORMAT, n._nanotime);
79
}
80
81
void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) const {
82
jio_snprintf(buf, len, INT64_FORMAT, m._size);
83
}
84
85
void GenDCmdArgument::to_string(char* c, char* buf, size_t len) const {
86
jio_snprintf(buf, len, "%s", (c != NULL) ? c : "");
87
}
88
89
void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) const {
90
int length = f->array()->length();
91
size_t written = 0;
92
buf[0] = 0;
93
for (int i = 0; i < length; i++) {
94
char* next_str = f->array()->at(i);
95
size_t next_size = strlen(next_str);
96
//Check if there's room left to write next element
97
if (written + next_size > len) {
98
return;
99
}
100
//Actually write element
101
strcat(buf, next_str);
102
written += next_size;
103
//Check if there's room left for the comma
104
if (i < length-1 && len - written > 0) {
105
strcat(buf, ",");
106
}
107
}
108
}
109
110
template <> void DCmdArgument<jlong>::parse_value(const char* str,
111
size_t len, TRAPS) {
112
int scanned = -1;
113
if (str == NULL
114
|| sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1
115
|| (size_t)scanned != len)
116
{
117
ResourceMark rm;
118
119
char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
120
strncpy(buf, str, len);
121
buf[len] = '\0';
122
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
123
"Integer parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf);
124
}
125
}
126
127
template <> void DCmdArgument<jlong>::init_value(TRAPS) {
128
if (has_default()) {
129
this->parse_value(_default_string, strlen(_default_string), THREAD);
130
if (HAS_PENDING_EXCEPTION) {
131
fatal("Default string must be parseable");
132
}
133
} else {
134
set_value(0);
135
}
136
}
137
138
template <> void DCmdArgument<jlong>::destroy_value() { }
139
140
template <> void DCmdArgument<bool>::parse_value(const char* str,
141
size_t len, TRAPS) {
142
// len is the length of the current token starting at str
143
if (len == 0) {
144
set_value(true);
145
} else {
146
if (len == strlen("true") && strncasecmp(str, "true", len) == 0) {
147
set_value(true);
148
} else if (len == strlen("false") && strncasecmp(str, "false", len) == 0) {
149
set_value(false);
150
} else {
151
ResourceMark rm;
152
153
char* buf = NEW_RESOURCE_ARRAY(char, len + 1);
154
155
PRAGMA_DIAG_PUSH
156
PRAGMA_STRINGOP_TRUNCATION_IGNORED
157
// This code can incorrectly cause a "stringop-truncation" warning with gcc
158
strncpy(buf, str, len);
159
PRAGMA_DIAG_POP
160
161
buf[len] = '\0';
162
Exceptions::fthrow(THREAD_AND_LOCATION, vmSymbols::java_lang_IllegalArgumentException(),
163
"Boolean parsing error in command argument '%s'. Could not parse: %s.\n", _name, buf);
164
}
165
}
166
}
167
168
template <> void DCmdArgument<bool>::init_value(TRAPS) {
169
if (has_default()) {
170
this->parse_value(_default_string, strlen(_default_string), THREAD);
171
if (HAS_PENDING_EXCEPTION) {
172
fatal("Default string must be parsable");
173
}
174
} else {
175
set_value(false);
176
}
177
}
178
179
template <> void DCmdArgument<bool>::destroy_value() { }
180
181
template <> void DCmdArgument<char*>::parse_value(const char* str,
182
size_t len, TRAPS) {
183
if (str == NULL) {
184
_value = NULL;
185
} else {
186
_value = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
187
int n = os::snprintf(_value, len + 1, "%.*s", (int)len, str);
188
assert((size_t)n <= len, "Unexpected number of characters in string");
189
}
190
}
191
192
template <> void DCmdArgument<char*>::init_value(TRAPS) {
193
if (has_default() && _default_string != NULL) {
194
this->parse_value(_default_string, strlen(_default_string), THREAD);
195
if (HAS_PENDING_EXCEPTION) {
196
fatal("Default string must be parsable");
197
}
198
} else {
199
set_value(NULL);
200
}
201
}
202
203
template <> void DCmdArgument<char*>::destroy_value() {
204
FREE_C_HEAP_ARRAY(char, _value);
205
set_value(NULL);
206
}
207
208
template <> void DCmdArgument<NanoTimeArgument>::parse_value(const char* str,
209
size_t len, TRAPS) {
210
if (str == NULL) {
211
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
212
"Integer parsing error nanotime value: syntax error, value is null\n");
213
}
214
215
int argc = sscanf(str, JLONG_FORMAT, &_value._time);
216
if (argc != 1) {
217
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
218
"Integer parsing error nanotime value: syntax error\n");
219
}
220
size_t idx = 0;
221
while(idx < len && isdigit(str[idx])) {
222
idx++;
223
}
224
if (idx == len) {
225
// only accept missing unit if the value is 0
226
if (_value._time != 0) {
227
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
228
"Integer parsing error nanotime value: unit required\n");
229
} else {
230
_value._nanotime = 0;
231
strcpy(_value._unit, "ns");
232
return;
233
}
234
} else if(len - idx > 2) {
235
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
236
"Integer parsing error nanotime value: illegal unit\n");
237
} else {
238
strncpy(_value._unit, &str[idx], len - idx);
239
/*Write an extra null termination. This is safe because _value._unit
240
* is declared as char[3], and length is checked to be not larger than
241
* two above. Also, this is necessary, since length might be 1, and the
242
* default value already in the string is ns, which is two chars.
243
*/
244
_value._unit[len-idx] = '\0';
245
}
246
247
if (strcmp(_value._unit, "ns") == 0) {
248
_value._nanotime = _value._time;
249
} else if (strcmp(_value._unit, "us") == 0) {
250
_value._nanotime = _value._time * 1000;
251
} else if (strcmp(_value._unit, "ms") == 0) {
252
_value._nanotime = _value._time * 1000 * 1000;
253
} else if (strcmp(_value._unit, "s") == 0) {
254
_value._nanotime = _value._time * 1000 * 1000 * 1000;
255
} else if (strcmp(_value._unit, "m") == 0) {
256
_value._nanotime = _value._time * 60 * 1000 * 1000 * 1000;
257
} else if (strcmp(_value._unit, "h") == 0) {
258
_value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000;
259
} else if (strcmp(_value._unit, "d") == 0) {
260
_value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000;
261
} else {
262
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
263
"Integer parsing error nanotime value: illegal unit\n");
264
}
265
}
266
267
template <> void DCmdArgument<NanoTimeArgument>::init_value(TRAPS) {
268
if (has_default()) {
269
this->parse_value(_default_string, strlen(_default_string), THREAD);
270
if (HAS_PENDING_EXCEPTION) {
271
fatal("Default string must be parsable");
272
}
273
} else {
274
_value._time = 0;
275
_value._nanotime = 0;
276
strcpy(_value._unit, "ns");
277
}
278
}
279
280
template <> void DCmdArgument<NanoTimeArgument>::destroy_value() { }
281
282
// WARNING StringArrayArgument can only be used as an option, it cannot be
283
// used as an argument with the DCmdParser
284
285
template <> void DCmdArgument<StringArrayArgument*>::parse_value(const char* str,
286
size_t len, TRAPS) {
287
_value->add(str,len);
288
}
289
290
template <> void DCmdArgument<StringArrayArgument*>::init_value(TRAPS) {
291
_value = new StringArrayArgument();
292
_allow_multiple = true;
293
if (has_default()) {
294
fatal("StringArrayArgument cannot have default value");
295
}
296
}
297
298
template <> void DCmdArgument<StringArrayArgument*>::destroy_value() {
299
if (_value != NULL) {
300
delete _value;
301
set_value(NULL);
302
}
303
}
304
305
template <> void DCmdArgument<MemorySizeArgument>::parse_value(const char* str,
306
size_t len, TRAPS) {
307
if (str == NULL) {
308
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
309
"Parsing error memory size value: syntax error, value is null\n");
310
}
311
if (*str == '-') {
312
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
313
"Parsing error memory size value: negative values not allowed\n");
314
}
315
int res = sscanf(str, UINT64_FORMAT "%c", &_value._val, &_value._multiplier);
316
if (res == 2) {
317
switch (_value._multiplier) {
318
case 'k': case 'K':
319
_value._size = _value._val * 1024;
320
break;
321
case 'm': case 'M':
322
_value._size = _value._val * 1024 * 1024;
323
break;
324
case 'g': case 'G':
325
_value._size = _value._val * 1024 * 1024 * 1024;
326
break;
327
default:
328
_value._size = _value._val;
329
_value._multiplier = ' ';
330
//default case should be to break with no error, since user
331
//can write size in bytes, or might have a delimiter and next arg
332
break;
333
}
334
} else if (res == 1) {
335
_value._size = _value._val;
336
} else {
337
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
338
"Parsing error memory size value: invalid value\n");
339
}
340
}
341
342
template <> void DCmdArgument<MemorySizeArgument>::init_value(TRAPS) {
343
if (has_default()) {
344
this->parse_value(_default_string, strlen(_default_string), THREAD);
345
if (HAS_PENDING_EXCEPTION) {
346
fatal("Default string must be parsable");
347
}
348
} else {
349
_value._size = 0;
350
_value._val = 0;
351
_value._multiplier = ' ';
352
}
353
}
354
355
template <> void DCmdArgument<MemorySizeArgument>::destroy_value() { }
356
357