1 /*
  2  * Copyright (c) 2002, 2023, 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 "code/nmethod.hpp"
 27 #include "memory/allocation.hpp"
 28 #include "memory/allocation.inline.hpp"
 29 #include "memory/resourceArea.hpp"
 30 #include "oops/methodData.hpp"
 31 #include "oops/method.inline.hpp"
 32 #include "oops/oop.inline.hpp"
 33 #include "runtime/deoptimization.hpp"
 34 #include "runtime/handles.inline.hpp"
 35 #include "runtime/vmOperations.hpp"
 36 #include "runtime/vmThread.hpp"
 37 #include "utilities/vmError.hpp"
 38 #include "utilities/xmlstream.hpp"
 39 
 40 // Do not assert this condition if there's already another error reported.
 41 #define assert_if_no_error(cond, msg) \
 42   vmassert((cond) || VMError::is_error_reported(), msg)
 43 
 44 void xmlStream::initialize(outputStream* out) {
 45   _out = out;
 46   _last_flush = 0;
 47   _markup_state = BODY;
 48   _text_init._outer_xmlStream = this;
 49   _text = &_text_init;
 50 
 51 #ifdef ASSERT
 52   _element_depth = 0;
 53   int   init_len = 100;
 54   char* init_buf = NEW_C_HEAP_ARRAY(char, init_len, mtInternal);
 55   _element_close_stack_low  = init_buf;
 56   _element_close_stack_high = init_buf + init_len;
 57   _element_close_stack_ptr  = init_buf + init_len - 1;
 58   _element_close_stack_ptr[0] = '\0';
 59 #endif
 60 
 61   // Make sure each log uses the same base for time stamps.
 62   if (is_open()) {
 63     _out->time_stamp().update_to(1);
 64   }
 65 }
 66 
 67 #ifdef ASSERT
 68 xmlStream::~xmlStream() {
 69   FREE_C_HEAP_ARRAY(char, _element_close_stack_low);
 70 }
 71 #endif
 72 
 73 // Pass the given chars directly to _out.
 74 void xmlStream::write(const char* s, size_t len) {
 75   if (!is_open())  return;
 76 
 77   out()->write(s, len);
 78   update_position(s, len);
 79 }
 80 
 81 
 82 // Pass the given chars directly to _out, except that
 83 // we watch for special "<&>" chars.
 84 // This is suitable for either attribute text or for body text.
 85 // We don't fool with "<![CDATA[" quotes, just single-character entities.
 86 // This makes it easier for dumb tools to parse the output.
 87 void xmlStream::write_text(const char* s, size_t len) {
 88   if (!is_open())  return;
 89 
 90   size_t written = 0;
 91   // All normally printed material goes inside XML quotes.
 92   // This leaves the output free to include markup also.
 93   // Scan the string looking for inadvertent "<&>" chars
 94   for (size_t i = 0; i < len; i++) {
 95     char ch = s[i];
 96     // Escape special chars.
 97     const char* esc = nullptr;
 98     switch (ch) {
 99       // These are important only in attrs, but we do them always:
100     case '\'': esc = "&apos;"; break;
101     case '"':  esc = "&quot;"; break;
102     case '<':  esc = "&lt;";   break;
103     case '&':  esc = "&amp;";  break;
104       // This is a freebie.
105     case '>':  esc = "&gt;";   break;
106     }
107     if (esc != nullptr) {
108       if (written < i) {
109         out()->write(&s[written], i - written);
110         written = i;
111       }
112       out()->print_raw(esc);
113       written++;
114     }
115   }
116 
117   // Print the clean remainder.  Usually, it is all of s.
118   if (written < len) {
119     out()->write(&s[written], len - written);
120   }
121 }
122 
123 // ------------------------------------------------------------------
124 // Outputs XML text, with special characters quoted.
125 void xmlStream::text(const char* format, ...) {
126   va_list ap;
127   va_start(ap, format);
128   va_text(format, ap);
129   va_end(ap);
130 }
131 
132 #define BUFLEN 2*K   /* max size of output of individual print methods */
133 
134 // ------------------------------------------------------------------
135 void xmlStream::va_tag(bool push, const char* format, va_list ap) {
136   assert_if_no_error(!inside_attrs(), "cannot print tag inside attrs");
137   char buffer[BUFLEN];
138   size_t len;
139   const char* kind = do_vsnprintf(buffer, BUFLEN, format, ap, false, len);
140   see_tag(kind, push);
141   print_raw("<");
142   write(kind, len);
143   _markup_state = (push ? HEAD : ELEM);
144 }
145 
146 #ifdef ASSERT
147 /// Debugging goo to make sure element tags nest properly.
148 
149 // ------------------------------------------------------------------
150 void xmlStream::see_tag(const char* tag, bool push) {
151   assert_if_no_error(!inside_attrs(), "cannot start new element inside attrs");
152   if (!push)  return;
153 
154   // tag goes up until either null or space:
155   const char* tag_end = strchr(tag, ' ');
156   size_t tag_len = (tag_end == nullptr) ? strlen(tag) : tag_end - tag;
157   assert(tag_len > 0, "tag must not be empty");
158   // push the tag onto the stack, pulling down the pointer
159   char* old_ptr  = _element_close_stack_ptr;
160   char* old_low  = _element_close_stack_low;
161   char* push_ptr = old_ptr - (tag_len+1);
162   if (push_ptr < old_low) {
163     int old_len = pointer_delta_as_int(_element_close_stack_high, old_ptr);
164     int new_len = old_len * 2;
165     if (new_len < 100)  new_len = 100;
166     char* new_low  = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
167     char* new_high = new_low + new_len;
168     char* new_ptr  = new_high - old_len;
169     memcpy(new_ptr, old_ptr, old_len);
170     _element_close_stack_high = new_high;
171     _element_close_stack_low  = new_low;
172     _element_close_stack_ptr  = new_ptr;
173     FREE_C_HEAP_ARRAY(char, old_low);
174     push_ptr = new_ptr - (tag_len+1);
175   }
176   assert(push_ptr >= _element_close_stack_low, "in range");
177   memcpy(push_ptr, tag, tag_len);
178   push_ptr[tag_len] = 0;
179   _element_close_stack_ptr = push_ptr;
180   _element_depth += 1;
181 }
182 
183 // ------------------------------------------------------------------
184 void xmlStream::pop_tag(const char* tag) {
185   assert_if_no_error(!inside_attrs(), "cannot close element inside attrs");
186   assert(_element_depth > 0, "must be in an element to close");
187   assert(*tag != 0, "tag must not be empty");
188   char* cur_tag = _element_close_stack_ptr;
189   bool  bad_tag = false;
190   while (*cur_tag != 0 && strcmp(cur_tag, tag) != 0) {
191     this->print_cr("</%s> <!-- missing closing tag -->", cur_tag);
192     _element_close_stack_ptr = (cur_tag += strlen(cur_tag) + 1);
193     _element_depth -= 1;
194     bad_tag = true;
195   }
196   if (*cur_tag == 0) {
197     bad_tag = true;
198   } else {
199     // Pop the stack, by skipping over the tag and its null.
200     _element_close_stack_ptr = cur_tag + strlen(cur_tag) + 1;
201     _element_depth -= 1;
202   }
203   if (bad_tag && !VMThread::should_terminate() && !VM_Exit::vm_exited() &&
204       !VMError::is_error_reported())
205   {
206     assert(false, "bad tag in log");
207   }
208 }
209 #endif
210 
211 
212 // ------------------------------------------------------------------
213 // First word in formatted string is element kind, and any subsequent
214 // words must be XML attributes.  Outputs "<kind .../>".
215 void xmlStream::elem(const char* format, ...) {
216   va_list ap;
217   va_start(ap, format);
218   va_elem(format, ap);
219   va_end(ap);
220 }
221 
222 // ------------------------------------------------------------------
223 void xmlStream::va_elem(const char* format, va_list ap) {
224   va_begin_elem(format, ap);
225   end_elem();
226 }
227 
228 
229 // ------------------------------------------------------------------
230 // First word in formatted string is element kind, and any subsequent
231 // words must be XML attributes.  Outputs "<kind ...", not including "/>".
232 void xmlStream::begin_elem(const char* format, ...) {
233   va_list ap;
234   va_start(ap, format);
235   va_tag(false, format, ap);
236   va_end(ap);
237 }
238 
239 // ------------------------------------------------------------------
240 void xmlStream::va_begin_elem(const char* format, va_list ap) {
241   va_tag(false, format, ap);
242 }
243 
244 // ------------------------------------------------------------------
245 // Outputs "/>".
246 void xmlStream::end_elem() {
247   assert(_markup_state == ELEM, "misplaced end_elem");
248   print_raw("/>\n");
249   _markup_state = BODY;
250 }
251 
252 // ------------------------------------------------------------------
253 // Outputs formatted text, followed by "/>".
254 void xmlStream::end_elem(const char* format, ...) {
255   va_list ap;
256   va_start(ap, format);
257   out()->vprint(format, ap);
258   va_end(ap);
259   end_elem();
260 }
261 
262 
263 // ------------------------------------------------------------------
264 // First word in formatted string is element kind, and any subsequent
265 // words must be XML attributes.  Outputs "<kind ...>".
266 void xmlStream::head(const char* format, ...) {
267   va_list ap;
268   va_start(ap, format);
269   va_head(format, ap);
270   va_end(ap);
271 }
272 
273 // ------------------------------------------------------------------
274 void xmlStream::va_head(const char* format, va_list ap) {
275   va_begin_head(format, ap);
276   end_head();
277 }
278 
279 // ------------------------------------------------------------------
280 // First word in formatted string is element kind, and any subsequent
281 // words must be XML attributes.  Outputs "<kind ...", not including ">".
282 void xmlStream::begin_head(const char* format, ...) {
283   va_list ap;
284   va_start(ap, format);
285   va_tag(true, format, ap);
286   va_end(ap);
287 }
288 
289 // ------------------------------------------------------------------
290 void xmlStream::va_begin_head(const char* format, va_list ap) {
291   va_tag(true, format, ap);
292 }
293 
294 // ------------------------------------------------------------------
295 // Outputs ">".
296 void xmlStream::end_head() {
297   assert(_markup_state == HEAD, "misplaced end_head");
298   print_raw(">\n");
299   _markup_state = BODY;
300 }
301 
302 
303 // ------------------------------------------------------------------
304 // Outputs formatted text, followed by ">".
305 void xmlStream::end_head(const char* format, ...) {
306   va_list ap;
307   va_start(ap, format);
308   out()->vprint(format, ap);
309   va_end(ap);
310   end_head();
311 }
312 
313 
314 // ------------------------------------------------------------------
315 // Outputs "</kind>".
316 void xmlStream::tail(const char* kind) {
317   pop_tag(kind);
318   print_raw("</");
319   print_raw(kind);
320   print_raw(">\n");
321 }
322 
323 // ------------------------------------------------------------------
324 // Outputs "<kind_done ... stamp='D.DD'/> </kind>".
325 void xmlStream::done(const char* format, ...) {
326   va_list ap;
327   va_start(ap, format);
328   va_done(format, ap);
329   va_end(ap);
330 }
331 
332 // ------------------------------------------------------------------
333 // Outputs "<kind_done stamp='D.DD'/> </kind>".
334 // Because done_raw() doesn't need to format strings, it's simpler than
335 // done(), and can be called safely by fatal error handler.
336 void xmlStream::done_raw(const char* kind) {
337   print_raw("<");
338   print_raw(kind);
339   print_raw("_done stamp='");
340   out()->stamp();
341   print_raw_cr("'/>");
342   print_raw("</");
343   print_raw(kind);
344   print_raw_cr(">");
345 }
346 
347 // If you remove the PRAGMA, this fails to compile with clang-503.0.40.
348 PRAGMA_DIAG_PUSH
349 PRAGMA_FORMAT_NONLITERAL_IGNORED
350 // ------------------------------------------------------------------
351 void xmlStream::va_done(const char* format, va_list ap) {
352   char buffer[200];
353   size_t format_len = strlen(format);
354   guarantee(format_len + 10 < sizeof(buffer), "bigger format buffer");
355   const char* kind = format;
356   const char* kind_end = strchr(kind, ' ');
357   size_t kind_len;
358   if (kind_end != nullptr) {
359     kind_len = kind_end - kind;
360     int n = os::snprintf(buffer, sizeof(buffer), "%.*s_done%s", (int)kind_len, kind, kind + kind_len);
361     assert((size_t)n < sizeof(buffer), "Unexpected number of characters in string");
362   } else {
363     kind_len = format_len;
364     int n = os::snprintf(buffer, sizeof(buffer), "%s_done", kind);
365     assert((size_t)n < sizeof(buffer), "Unexpected number of characters in string");
366   }
367   // Output the trailing event with the timestamp.
368   va_begin_elem(buffer, ap);
369   stamp();
370   end_elem();
371   // Output the tail-tag of the enclosing element.
372   buffer[kind_len] = 0;
373   tail(buffer);
374 }
375 PRAGMA_DIAG_POP
376 
377 // Output a timestamp attribute.
378 void xmlStream::stamp() {
379   assert_if_no_error(inside_attrs(), "stamp must be an attribute");
380   print_raw(" stamp='");
381   out()->stamp();
382   print_raw("'");
383 }
384 
385 
386 // ------------------------------------------------------------------
387 // Output a method attribute, in the form " method='pkg/cls name sig'".
388 // This is used only when there is no ciMethod available.
389 void xmlStream::method(Method* method) {
390   assert_if_no_error(inside_attrs(), "printing attributes");
391   if (method == nullptr)  return;
392   print_raw(" method='");
393   method_text(method);
394   print("' bytes='%d'", method->code_size());
395   print(" count='%d'", method->invocation_count());
396   int bec = method->backedge_count();
397   if (bec != 0)  print(" backedge_count='%d'", bec);
398   print(" iicount='%d'", method->interpreter_invocation_count());
399   int throwouts = method->interpreter_throwout_count();
400   if (throwouts != 0)  print(" throwouts='%d'", throwouts);
401   MethodData* mdo = method->method_data();
402   if (mdo != nullptr) {
403     uint cnt;
404     cnt = mdo->decompile_count();
405     if (cnt != 0)  print(" decompiles='%d'", cnt);
406     for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
407       cnt = mdo->trap_count(reason);
408       if (cnt != 0)  print(" %s_traps='%d'", Deoptimization::trap_reason_name(reason), cnt);
409     }
410     cnt = mdo->overflow_trap_count();
411     if (cnt != 0)  print(" overflow_traps='%d'", cnt);
412     cnt = mdo->overflow_recompile_count();
413     if (cnt != 0)  print(" overflow_recompiles='%d'", cnt);
414   }
415 }
416 
417 void xmlStream::method_text(Method* method) {
418   ResourceMark rm;
419   assert_if_no_error(inside_attrs(), "printing attributes");
420   if (method == nullptr)  return;
421   text()->print("%s", method->method_holder()->external_name());
422   print_raw(" ");  // " " is easier for tools to parse than "::"
423   method->name()->print_symbol_on(text());
424   print_raw(" ");  // separator
425   method->signature()->print_symbol_on(text());
426 }
427 
428 
429 // ------------------------------------------------------------------
430 // Output a klass attribute, in the form " klass='pkg/cls'".
431 // This is used only when there is no ciKlass available.
432 void xmlStream::klass(Klass* klass) {
433   assert_if_no_error(inside_attrs(), "printing attributes");
434   if (klass == nullptr) return;
435   print_raw(" klass='");
436   klass_text(klass);
437   print_raw("'");
438 }
439 
440 void xmlStream::klass_text(Klass* klass) {
441   assert_if_no_error(inside_attrs(), "printing attributes");
442   if (klass == nullptr) return;
443   //klass->print_short_name(log->out());
444   klass->name()->print_symbol_on(out());
445 }
446 
447 void xmlStream::name(const Symbol* name) {
448   assert_if_no_error(inside_attrs(), "printing attributes");
449   if (name == nullptr)  return;
450   print_raw(" name='");
451   name_text(name);
452   print_raw("'");
453 }
454 
455 void xmlStream::name_text(const Symbol* name) {
456   assert_if_no_error(inside_attrs(), "printing attributes");
457   if (name == nullptr)  return;
458   //name->print_short_name(text());
459   name->print_symbol_on(text());
460 }
461 
462 void xmlStream::object(const char* attr, Handle x) {
463   assert_if_no_error(inside_attrs(), "printing attributes");
464   if (x == nullptr)  return;
465   print_raw(" ");
466   print_raw(attr);
467   print_raw("='");
468   object_text(x);
469   print_raw("'");
470 }
471 
472 void xmlStream::object_text(Handle x) {
473   assert_if_no_error(inside_attrs(), "printing attributes");
474   if (x == nullptr)  return;
475   x->print_value_on(text());
476 }
477 
478 
479 void xmlStream::object(const char* attr, Metadata* x) {
480   assert_if_no_error(inside_attrs(), "printing attributes");
481   if (x == nullptr)  return;
482   print_raw(" ");
483   print_raw(attr);
484   print_raw("='");
485   object_text(x);
486   print_raw("'");
487 }
488 
489 void xmlStream::object_text(Metadata* x) {
490   assert_if_no_error(inside_attrs(), "printing attributes");
491   if (x == nullptr)  return;
492   //x->print_value_on(text());
493   if (x->is_method())
494     method_text((Method*)x);
495   else if (x->is_klass())
496     klass_text((Klass*)x);
497   else
498     ShouldNotReachHere(); // Add impl if this is reached.
499 }
500 
501 
502 void xmlStream::flush() {
503   out()->flush();
504   _last_flush = count();
505 }
506 
507 void xmlTextStream::flush() {
508   if (_outer_xmlStream == nullptr)  return;
509   _outer_xmlStream->flush();
510 }
511 
512 void xmlTextStream::write(const char* str, size_t len) {
513   if (_outer_xmlStream == nullptr)  return;
514   _outer_xmlStream->write_text(str, len);
515   update_position(str, len);
516 }