Skip to content

Commit c8ad6bb

Browse files
Integrate gdbdebughelpers tests into gate tests
Update tests to work with graal-enterprise Add gdbdebughelperstest with variations to enterprise debuginfotests Abort test if GDB version is below 14, or the Python API could not be used Pass heap base register as CGlobalData to gdb-debughelpers
1 parent bb028ca commit c8ad6bb

File tree

5 files changed

+35
-43
lines changed

5 files changed

+35
-43
lines changed

substratevm/debug/gdbpy/gdb-debughelpers.py

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class SVMUtil:
103103
compression_shift = try_or_else(lambda: int(gdb.parse_and_eval('(int)__svm_compression_shift')), 0, gdb.error)
104104
reserved_bits_mask = try_or_else(lambda: int(gdb.parse_and_eval('(int)__svm_reserved_bits_mask')), 0, gdb.error)
105105
object_alignment = try_or_else(lambda: int(gdb.parse_and_eval('(int)__svm_object_alignment')), 0, gdb.error)
106+
heap_base_regnum = try_or_else(lambda: int(gdb.parse_and_eval('(int)__svm_heap_base_regnum')), 0, gdb.error)
106107

107108
string_type = gdb.lookup_type("java.lang.String")
108109
enum_type = gdb.lookup_type("java.lang.Enum")
@@ -124,39 +125,13 @@ class SVMUtil:
124125
deopt_stub_adr = 0
125126

126127
@classmethod
127-
def get_architecture(cls) -> str:
128+
def get_heap_base(cls) -> gdb.Value:
128129
try:
129-
arch_name = gdb.selected_frame().architecture().name()
130+
return gdb.selected_frame().read_register(cls.heap_base_regnum)
130131
except gdb.error:
131132
# no frame available
132-
arch_name = ""
133-
134-
if "x86-64" in arch_name:
135-
return "amd64"
136-
elif "aarch64" in arch_name:
137-
return "arm64"
138-
else:
139-
return arch_name
140-
141-
@classmethod
142-
def get_isolate_thread(cls) -> gdb.Value:
143-
arch = cls.get_architecture()
144-
if arch == "amd64":
145-
return gdb.selected_frame().read_register('r15')
146-
elif arch == "arm64":
147-
return gdb.selected_frame().read_register('r28')
148-
else:
149133
return cls.null
150134

151-
@classmethod
152-
def get_heap_base(cls) -> gdb.Value:
153-
arch = cls.get_architecture()
154-
if arch == "amd64":
155-
return gdb.selected_frame().read_register('r14')
156-
elif arch == "arm64":
157-
return gdb.selected_frame().read_register('r29')
158-
return cls.null
159-
160135
@classmethod
161136
def is_null(cls, obj: gdb.Value) -> bool:
162137
return adr(obj) == 0 or (cls.use_heap_base and adr(obj) == int(cls.get_heap_base()))
@@ -211,7 +186,7 @@ def get_compressed_oop(cls, obj: gdb.Value) -> int:
211186
compressed_oop -= int(SVMUtil.get_heap_base())
212187
assert compression_shift >= 0
213188
compressed_oop = compressed_oop >> compression_shift
214-
if is_hub:
189+
if is_hub and num_reserved_bits != 0:
215190
assert compression_shift >= 0
216191
compressed_oop = compressed_oop << compression_shift
217192
assert num_alignment_bits >= 0

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,18 +1028,17 @@ def build_debug_test(variant_name, image_name, extra_args):
10281028
def _gdbdebughelperstest(native_image, path, with_isolates_only, args):
10291029

10301030
# ====== check gdb version ======
1031-
# gdb-debughelperstest and this tests are designed for gdb 14 and higher with the python API enabled
1032-
# if we encounter a version lower than 14, we skip this tests
1033-
# TODO: remove when gdb 14 is available
1031+
# gdb-debughelperstests are designed for GDB 14 and higher with the GDB Python API enabled
1032+
# abort if we encounter a version lower than 14 or the GDB Python API is not available
10341033
gdb_version = mx.run([
10351034
os.environ.get('GDB_BIN', 'gdb'), '--nx', '-q',
1036-
'-ex', 'py gdb.execute("quit " + gdb.VERSION.split(".")[0])', # try to get gdb version via python
1037-
'-ex', 'quit 0' # fallback gdb exit
1035+
'-ex', 'py gdb.execute("quit " + gdb.VERSION.split(".")[0])', # try to get GDB version via Python API
1036+
'-ex', 'quit 0' # fallback GDB exit
10381037
]
10391038
, nonZeroIsFatal=False)
10401039
if gdb_version < 14:
1041-
mx.warn(f"Skipping gdb-debughelpers tests (Requires gdb version 14, found gdb version {gdb_version}).")
1042-
return
1040+
mx.abort('gdb-debughelpers test requires at least GDB version 14 with the GDB Python API enabled, ' +
1041+
('GDB Python API is not available.' if gdb_version == 0 else f'found GDB version {gdb_version}.'))
10431042
# ===============================
10441043

10451044
test_proj = mx.dependency('com.oracle.svm.test')
@@ -1108,6 +1107,9 @@ def run_debug_test(image_name: str, testfile: str, source_path: str, with_isolat
11081107
'-H:DebugInfoSourceSearchPath=' + source_path,
11091108
]) + extra_args
11101109

1110+
if '--shared' in extra_args:
1111+
build_args = [arg for arg in build_args if arg not in ['--libc=musl', '--static']]
1112+
11111113
if not with_isolates:
11121114
build_args += svm_experimental_options(['-H:-SpawnIsolates'])
11131115

@@ -1695,7 +1697,7 @@ def gdbdebughelperstest(args, config=None):
16951697
builds and tests gdb-debughelpers.py with multiple native images with debuginfo
16961698
"""
16971699
parser = ArgumentParser(prog='mx gdbdebughelperstest')
1698-
all_args = ['--output-path', '--with-isolates-only', '--build-only', '--test-only']
1700+
all_args = ['--output-path', '--with-isolates-only']
16991701
masked_args = [_mask(arg, all_args) for arg in args]
17001702
parser.add_argument(all_args[0], metavar='<output-path>', nargs=1, help='Path of the generated image', default=[join(svmbuild_dir(), "gdbdebughelperstest")])
17011703
parser.add_argument(all_args[1], action='store_true', help='Only build and test the native image with isolates')

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoFeature.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.function.Function;
3131
import java.util.function.Supplier;
3232

33+
import com.oracle.svm.core.ReservedRegisters;
3334
import org.graalvm.nativeimage.ImageSingletons;
3435
import org.graalvm.nativeimage.Platform;
3536
import org.graalvm.word.PointerBase;
@@ -121,10 +122,12 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
121122
CGlobalData<PointerBase> useHeapBase = CGlobalDataFactory.createWord(WordFactory.unsigned(compressEncoding.hasBase() ? 1 : 0), "__svm_use_heap_base");
122123
CGlobalData<PointerBase> reservedBitsMask = CGlobalDataFactory.createWord(WordFactory.unsigned(Heap.getHeap().getObjectHeader().getReservedBitsMask()), "__svm_reserved_bits_mask");
123124
CGlobalData<PointerBase> objectAlignment = CGlobalDataFactory.createWord(WordFactory.unsigned(ConfigurationValues.getObjectLayout().getAlignment()), "__svm_object_alignment");
125+
CGlobalData<PointerBase> heapBaseRegnum = CGlobalDataFactory.createWord(WordFactory.unsigned(ReservedRegisters.singleton().getHeapBaseRegister().number), "__svm_heap_base_regnum");
124126
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(compressionShift);
125127
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(useHeapBase);
126128
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(reservedBitsMask);
127129
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(objectAlignment);
130+
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(heapBaseRegnum);
128131
}
129132

130133
@Override

substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/helper/test_class_loader.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,21 @@ def tearDown(self):
4747
def test_instanceMethod_named_classloader(self):
4848
gdb_set_breakpoint("com.oracle.svm.test.missing.classes.TestClass::instanceMethod")
4949
gdb_continue() # named classloader is called first in test code
50-
self.assertRegex(gdb_output("this"), rf'testClassLoader_{hex_rexp.pattern}::com\.oracle\.svm\.test\.missing\.classes\.TestClass = {{instanceField = null}}')
50+
exec_string = gdb_output("this")
51+
self.assertTrue(exec_string.startswith("testClassLoader_"), f"GDB output: '{exec_string}'") # check for correct class loader
52+
self.assertIn("::com.oracle.svm.test.missing.classes.TestClass = {", exec_string) # check if TestClass has a namespace
53+
self.assertIn("instanceField = null", exec_string)
5154
gdb_output("$other=(('java.lang.Object' *)this)")
5255
self.assertIn("null", gdb_advanced_print("$other.instanceField")) # force a typecast
5356

5457
def test_instanceMethod_unnamed_classloader(self):
5558
gdb_set_breakpoint("com.oracle.svm.test.missing.classes.TestClass::instanceMethod")
5659
gdb_continue() # skip named classloader
5760
gdb_continue() # unnamed classloader is called second in test code
58-
self.assertRegex(gdb_output("this"), rf'URLClassLoader_{hex_rexp.pattern}::com\.oracle\.svm\.test\.missing\.classes\.TestClass = {{instanceField = null}}')
61+
exec_string = gdb_output("this")
62+
self.assertTrue(exec_string.startswith("URLClassLoader_"), f"GDB output: '{exec_string}'") # check for correct class loader
63+
self.assertIn("::com.oracle.svm.test.missing.classes.TestClass = {", exec_string) # check if TestClass has a namespace
64+
self.assertIn("instanceField = null", exec_string)
5965
gdb_output("$other=(('java.lang.Object' *)this)")
6066
self.assertIn("null", gdb_advanced_print("$other.instanceField")) # force a typecast
6167

substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/helper/test_settings.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,11 +185,17 @@ def test_svm_print_field_limit(self):
185185
gdb_set_breakpoint("com.oracle.svm.test.debug.helper.PrettyPrinterTest::testObject")
186186
gdb_run()
187187
gdb_set_param('svm-print-field-limit', '1')
188-
self.assertIn('f7 = "test string"', gdb_output('object'))
189-
self.assertIn('f8 = ...', gdb_output('object'))
188+
exec_string_1 = gdb_output('object')
189+
self.assertTrue(exec_string_1.startswith('com.oracle.svm.test.debug.helper.PrettyPrinterTest$ExampleClass = {'))
190+
self.assertEqual(exec_string_1.count('='), 3) # 3 '=' signs, one each for object, first field, cut off field
191+
self.assertTrue(exec_string_1.endswith('= ...}'))
190192
gdb_set_param('svm-print-field-limit', 'unlimited')
191-
self.assertIn('f7 = "test string"', gdb_output('object'))
192-
self.assertIn('f8 = Monday(0)', gdb_output('object'))
193+
exec_string = gdb_output('object')
194+
# check if at least 2 member fields are printed
195+
self.assertIn('f7 = "test string"', exec_string)
196+
self.assertIn('f8 = Monday(0)', exec_string)
197+
self.assertNotIn('= ...', exec_string)
198+
self.assertNotEqual(exec_string, exec_string_1)
193199

194200
def test_svm_print_depth_limit(self):
195201
gdb_set_breakpoint("com.oracle.svm.test.debug.helper.PrettyPrinterTest::testObject")

0 commit comments

Comments
 (0)