Skip to content

Commit 13c0369

Browse files
committed
8242181: [Linux] Show source information when printing native stack traces in hs_err files
Reviewed-by: erikj, tschatzl, stuefe, ihse
1 parent fe0544f commit 13c0369

18 files changed

+2740
-95
lines changed

make/RunTests.gmk

+2
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,8 @@ define SetupRunJtregTestBody
785785
# symbol lookup in hserr files
786786
ifeq ($$(call isTargetOs, windows), true)
787787
$1_JTREG_BASIC_OPTIONS += -e:_NT_SYMBOL_PATH
788+
else ifeq ($$(call isTargetOs, linux), true)
789+
$1_JTREG_BASIC_OPTIONS += -e:_JVM_DWARF_PATH=$$(SYMBOLS_IMAGE_DIR)
788790
endif
789791

790792
$1_JTREG_BASIC_OPTIONS += \

make/autoconf/flags-cflags.m4

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ AC_DEFUN([FLAGS_SETUP_DEBUG_SYMBOLS],
113113
)
114114
fi
115115
116-
CFLAGS_DEBUG_SYMBOLS="-g"
116+
CFLAGS_DEBUG_SYMBOLS="-g -gdwarf-4"
117117
ASFLAGS_DEBUG_SYMBOLS="-g"
118118
elif test "x$TOOLCHAIN_TYPE" = xclang; then
119119
if test "x$ALLOW_ABSOLUTE_PATHS_IN_OUTPUT" = "xfalse"; then

make/conf/jib-profiles.js

+3-13
Original file line numberDiff line numberDiff line change
@@ -943,15 +943,16 @@ var getJibProfilesProfiles = function (input, common, data) {
943943
target_cpu: input.build_cpu,
944944
dependencies: [
945945
"jtreg", "gnumake", "boot_jdk", "devkit", "jib", "jcov", testedProfileJdk,
946-
testedProfileTest
946+
testedProfileTest, testedProfile + ".jdk_symbols",
947947
],
948948
src: "src.conf",
949949
make_args: testOnlyMake,
950950
environment: {
951951
"BOOT_JDK": common.boot_jdk_home,
952952
"JT_HOME": input.get("jtreg", "home_path"),
953953
"JDK_IMAGE_DIR": input.get(testedProfileJdk, "home_path"),
954-
"TEST_IMAGE_DIR": input.get(testedProfileTest, "home_path")
954+
"TEST_IMAGE_DIR": input.get(testedProfileTest, "home_path"),
955+
"SYMBOLS_IMAGE_DIR": input.get(testedProfile + ".jdk_symbols", "home_path")
955956
},
956957
labels: "test"
957958
}
@@ -991,17 +992,6 @@ var getJibProfilesProfiles = function (input, common, data) {
991992
profiles["run-test"] = concatObjects(profiles["run-test"], macosxRunTestExtra);
992993
profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"], macosxRunTestExtra);
993994
}
994-
// On windows we want the debug symbols available at test time
995-
if (input.build_os == "windows") {
996-
windowsRunTestPrebuiltExtra = {
997-
dependencies: [ testedProfile + ".jdk_symbols" ],
998-
environment: {
999-
"SYMBOLS_IMAGE_DIR": input.get(testedProfile + ".jdk_symbols", "home_path"),
1000-
}
1001-
};
1002-
profiles["run-test-prebuilt"] = concatObjects(profiles["run-test-prebuilt"],
1003-
windowsRunTestPrebuiltExtra);
1004-
}
1005995

1006996
// The profile run-test-prebuilt defines src.conf as the src bundle. When
1007997
// running in Mach 5, this reduces the time it takes to populate the

src/hotspot/os/windows/decoder_windows.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@ bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const voi
3535
return SymbolEngine::decode(addr, buf, buflen, offset, true);
3636
}
3737

38-
bool Decoder::get_source_info(address pc, char* buf, size_t buflen, int* line) {
38+
bool Decoder::get_source_info(address pc, char* buf, size_t buflen, int* line, bool is_pc_after_call) {
3939
return SymbolEngine::get_source_info(pc, buf, buflen, line);
4040
}
4141

src/hotspot/share/runtime/globals.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,10 @@ const int ObjectAlignmentInBytes = 8;
511511
"error log in case of a crash.") \
512512
range(0, (uint64_t)max_jlong/1000) \
513513
\
514+
develop(intx, TraceDwarfLevel, 0, \
515+
"Debug levels for the dwarf parser") \
516+
range(0, 4) \
517+
\
514518
product(bool, SuppressFatalErrorMessage, false, \
515519
"Report NO fatal error message (avoid deadlock)") \
516520
\

src/hotspot/share/utilities/decoder.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2017, 2020 SAP SE. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -113,8 +113,13 @@ bool Decoder::demangle(const char* symbol, char* buf, int buflen) {
113113
void Decoder::print_state_on(outputStream* st) {
114114
}
115115

116-
bool Decoder::get_source_info(address pc, char* buf, size_t buflen, int* line) {
117-
return false;
116+
bool Decoder::get_source_info(address pc, char* filename, size_t filename_len, int* line, bool is_pc_after_call) {
117+
if (VMError::is_error_reported_in_current_thread()) {
118+
return get_error_handler_instance()->get_source_info(pc, filename, filename_len, line, is_pc_after_call);
119+
} else {
120+
MutexLocker locker(shared_decoder_lock(), Mutex::_no_safepoint_check_flag);
121+
return get_shared_instance()->get_source_info(pc, filename, filename_len, line, is_pc_after_call);
122+
}
118123
}
119124

120125
#endif // !_WINDOWS

src/hotspot/share/utilities/decoder.hpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ class AbstractDecoder : public CHeapObj<mtInternal> {
6363
// demangle a C++ symbol
6464
virtual bool demangle(const char* symbol, char* buf, int buflen) = 0;
6565

66+
// Get filename and line number information.
67+
virtual bool get_source_info(address pc, char* filename, size_t filename_len, int* line, bool is_pc_after_call) {
68+
return false;
69+
}
70+
6671
virtual decoder_status status() const {
6772
return _decoder_status;
6873
}
@@ -109,9 +114,11 @@ class Decoder : AllStatic {
109114
static bool demangle(const char* symbol, char* buf, int buflen);
110115

111116
// Attempts to retrieve source file name and line number associated with a pc.
112-
// If buf != NULL, points to a buffer of size buflen which will receive the
117+
// If filename != NULL, points to a buffer of size filename_len which will receive the
113118
// file name. File name will be silently truncated if output buffer is too small.
114-
static bool get_source_info(address pc, char* buf, size_t buflen, int* line);
119+
// If is_pc_after_call is true, then pc is treated as pointing to the next instruction
120+
// after a call. The source information for the call instruction is fetched in that case.
121+
static bool get_source_info(address pc, char* filename, size_t filename_len, int* line, bool is_pc_after_call = false);
115122

116123
static void print_state_on(outputStream* st);
117124

src/hotspot/share/utilities/decoder_elf.cpp

+42-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,8 @@
2626

2727
#if !defined(_WINDOWS) && !defined(__APPLE__)
2828
#include "decoder_elf.hpp"
29-
#include "memory/allocation.inline.hpp"
29+
#include "logging/log.hpp"
30+
#include "runtime/os.hpp"
3031

3132
ElfDecoder::~ElfDecoder() {
3233
if (_opened_elf_files != NULL) {
@@ -53,6 +54,45 @@ bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const
5354
return true;
5455
}
5556

57+
bool ElfDecoder::get_source_info(address pc, char* filename, size_t filename_len, int* line, bool is_pc_after_call) {
58+
assert(filename != nullptr && filename_len > 0 && line != nullptr, "Argument error");
59+
filename[0] = '\0';
60+
*line = -1;
61+
62+
char filepath[JVM_MAXPATHLEN];
63+
filepath[JVM_MAXPATHLEN - 1] = '\0';
64+
int offset_in_library = -1;
65+
if (!os::dll_address_to_library_name(pc, filepath, sizeof(filepath), &offset_in_library)) {
66+
// Method not found. offset_in_library should not overflow.
67+
DWARF_LOG_ERROR("Did not find library for address " INTPTR_FORMAT, p2i(pc))
68+
return false;
69+
}
70+
71+
if (filepath[JVM_MAXPATHLEN - 1] != '\0') {
72+
DWARF_LOG_ERROR("File path is too large to fit into buffer of size %d", JVM_MAXPATHLEN);
73+
return false;
74+
}
75+
76+
const uint32_t unsigned_offset_in_library = (uint32_t)offset_in_library;
77+
78+
ElfFile* file = get_elf_file(filepath);
79+
if (file == NULL) {
80+
return false;
81+
}
82+
DWARF_LOG_INFO("##### Find filename and line number for offset " PTR32_FORMAT " in library %s #####",
83+
unsigned_offset_in_library, filepath);
84+
85+
if (!file->get_source_info(unsigned_offset_in_library, filename, filename_len, line, is_pc_after_call)) {
86+
return false;
87+
}
88+
89+
DWARF_LOG_SUMMARY("pc: " INTPTR_FORMAT ", offset: " PTR32_FORMAT ", filename: %s, line: %u",
90+
p2i(pc), offset_in_library, filename, *line);
91+
DWARF_LOG_INFO("") // To structure the debug output better.
92+
return true;
93+
}
94+
95+
5696
ElfFile* ElfDecoder::get_elf_file(const char* filepath) {
5797
ElfFile* file;
5898

src/hotspot/share/utilities/decoder_elf.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,7 @@ class ElfDecoder : public AbstractDecoder {
4545
ShouldNotReachHere();
4646
return false;
4747
}
48+
bool get_source_info(address pc, char* buf, size_t buflen, int* line, bool is_pc_after_call);
4849

4950
private:
5051
ElfFile* get_elf_file(const char* filepath);

0 commit comments

Comments
 (0)