From b9e65f982fe6ae69d3912f32465a688d67c1c765 Mon Sep 17 00:00:00 2001
From: Matthias Baesken <mbaesken@openjdk.org>
Date: Fri, 30 Aug 2024 06:47:49 +0000
Subject: [PATCH] 8337662: Improve os::print_hex_dump for printing Instructions
 sections

Reviewed-by: stuefe, lucy
---
 src/hotspot/share/runtime/os.cpp       | 13 +++++++---
 src/hotspot/share/runtime/os.hpp       |  6 ++---
 test/hotspot/gtest/runtime/test_os.cpp | 34 ++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 6cb57e9dcb6..a8f3bc5c1d5 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -1016,11 +1016,14 @@ static void print_hex_location(outputStream* st, const_address p, int unitsize,
 }
 
 void os::print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize,
-                        bool print_ascii, int bytes_per_line, const_address logical_start) {
+                        bool print_ascii, int bytes_per_line, const_address logical_start, const_address highlight_address) {
   constexpr int max_bytes_per_line = 64;
   assert(unitsize == 1 || unitsize == 2 || unitsize == 4 || unitsize == 8, "just checking");
   assert(bytes_per_line > 0 && bytes_per_line <= max_bytes_per_line &&
          is_power_of_2(bytes_per_line), "invalid bytes_per_line");
+  assert(highlight_address == nullptr || (highlight_address >= start && highlight_address < end),
+         "address %p to highlight not in range %p - %p", highlight_address, start, end);
+
 
   start = align_down(start, unitsize);
   logical_start = align_down(logical_start, unitsize);
@@ -1037,7 +1040,11 @@ void os::print_hex_dump(outputStream* st, const_address start, const_address end
   // Print out the addresses as if we were starting from logical_start.
   while (p < end) {
     if (cols == 0) {
-      st->print(PTR_FORMAT ":   ", p2i(logical_p));
+      // highlight start of line if address of interest is located in the line
+      const bool should_highlight = (highlight_address >= p && highlight_address < p + bytes_per_line);
+      const char* const prefix =
+        (highlight_address != nullptr) ? (should_highlight ? "=>" : "  ") : "";
+      st->print("%s" PTR_FORMAT ":   ", prefix, p2i(logical_p));
     }
     print_hex_location(st, p, unitsize, ascii_form);
     p += unitsize;
@@ -1082,7 +1089,7 @@ void os::print_tos(outputStream* st, address sp) {
 
 void os::print_instructions(outputStream* st, address pc, int unitsize) {
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", p2i(pc));
-  print_hex_dump(st, pc - 256, pc + 256, unitsize, /* print_ascii=*/false);
+  print_hex_dump(st, pc - 256, pc + 256, unitsize, /* print_ascii=*/false, pc);
 }
 
 void os::print_environment_variables(outputStream* st, const char** env_list) {
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index 63ea1721667..1d81612c033 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -857,9 +857,9 @@ class os: AllStatic {
   static frame      current_frame();
 
   static void print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, bool print_ascii,
-                             int bytes_per_line, const_address logical_start);
-  static void print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, bool print_ascii = true) {
-    print_hex_dump(st, start, end, unitsize, print_ascii, /*bytes_per_line=*/16, /*logical_start=*/start);
+                             int bytes_per_line, const_address logical_start, const_address highlight_address = nullptr);
+  static void print_hex_dump(outputStream* st, const_address start, const_address end, int unitsize, bool print_ascii = true, const_address highlight_address = nullptr) {
+    print_hex_dump(st, start, end, unitsize, print_ascii, /*bytes_per_line=*/16, /*logical_start=*/start, highlight_address);
   }
 
   // returns a string to describe the exception/signal;
diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp
index 4d3e6ba7f52..78e5212ab37 100644
--- a/test/hotspot/gtest/runtime/test_os.cpp
+++ b/test/hotspot/gtest/runtime/test_os.cpp
@@ -178,6 +178,16 @@ static void do_test_print_hex_dump(const_address from, const_address to, int uni
   EXPECT_STREQ(buf, expected);
 }
 
+// version with a highlighted pc location
+static void do_test_print_hex_dump_highlighted(const_address from, const_address to, int unitsize, int bytes_per_line,
+                                   const_address logical_start, const char* expected, const_address highlight) {
+  char buf[2048];
+  buf[0] = '\0';
+  stringStream ss(buf, sizeof(buf));
+  os::print_hex_dump(&ss, from, to, unitsize, /* print_ascii=*/true, bytes_per_line, logical_start, highlight);
+  EXPECT_STREQ(buf, expected);
+}
+
 TEST_VM(os, test_print_hex_dump) {
 
 #ifdef _LP64
@@ -197,6 +207,24 @@ TEST_VM(os, test_print_hex_dump) {
               ADDRESS2 ":   ff ff e0 dc 23 00 6a 64 6b 2f 69 6e 74 65 72 6e 61 6c 2f 6c 6f 61 64 65 72 2f 4e 61 74 69 76 65   " ASCII_1 "\n" \
               ADDRESS3 ":   4c 69 62 72 61 72 69 65 73 00 00 00 00 00 00 00                                                   " ASCII_2 "\n"
 
+#define PAT_HL_1A "=>" ADDRESS1 ":   ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??\n" \
+              "  " ADDRESS2 ":   ff ff e0 dc 23 00 6a 64 6b 2f 69 6e 74 65 72 6e 61 6c 2f 6c 6f 61 64 65 72 2f 4e 61 74 69 76 65   " ASCII_1 "\n" \
+              "  " ADDRESS3 ":   4c 69 62 72 61 72 69 65 73 00 00 00 00 00 00 00                                                   " ASCII_2 "\n"
+
+#define PAT_HL_1B "  " ADDRESS1 ":   ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??\n" \
+              "=>" ADDRESS2 ":   ff ff e0 dc 23 00 6a 64 6b 2f 69 6e 74 65 72 6e 61 6c 2f 6c 6f 61 64 65 72 2f 4e 61 74 69 76 65   " ASCII_1 "\n" \
+              "  " ADDRESS3 ":   4c 69 62 72 61 72 69 65 73 00 00 00 00 00 00 00                                                   " ASCII_2 "\n"
+
+#ifdef VM_LITTLE_ENDIAN
+#define PAT_HL_1C "  " ADDRESS1 ":   ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ????\n" \
+              "=>" ADDRESS2 ":   ffff dce0 0023 646a 2f6b 6e69 6574 6e72 6c61 6c2f 616f 6564 2f72 614e 6974 6576   " ASCII_1 "\n" \
+              "  " ADDRESS3 ":   694c 7262 7261 6569 0073 0000 0000 0000                                           " ASCII_2 "\n"
+#else
+#define PAT_HL_1C "  " ADDRESS1 ":   ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ????\n" \
+              "=>" ADDRESS2 ":   ffff e0dc 2300 6a64 6b2f 696e 7465 726e 616c 2f6c 6f61 6465 722f 4e61 7469 7665   " ASCII_1 "\n" \
+              "  " ADDRESS3 ":   4c69 6272 6172 6965 7300 0000 0000 0000                                           " ASCII_2 "\n"
+#endif
+
 #ifdef VM_LITTLE_ENDIAN
 #define PAT_2 ADDRESS1 ":   ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ???? ????\n" \
               ADDRESS2 ":   ffff dce0 0023 646a 2f6b 6e69 6574 6e72 6c61 6c2f 616f 6564 2f72 614e 6974 6576   " ASCII_1 "\n" \
@@ -252,6 +280,12 @@ TEST_VM(os, test_print_hex_dump) {
   do_test_print_hex_dump(from + 1, to, 4, 32, logical_start, PAT_4);
   do_test_print_hex_dump(from + 1, to, 8, 32, logical_start, PAT_8);
 
+  // print with highlighted address
+  do_test_print_hex_dump_highlighted(from, to, 1, 32, logical_start, PAT_HL_1A, from+5);
+  do_test_print_hex_dump_highlighted(from, to, 1, 32, logical_start, PAT_HL_1B, from+32);
+  do_test_print_hex_dump_highlighted(from, to, 1, 32, logical_start, PAT_HL_1B, from+60);
+  do_test_print_hex_dump_highlighted(from, to, 2, 32, logical_start, PAT_HL_1C, from+60);
+
   os::release_memory(two_pages, ps * 2);
 }
 #endif // not AIX