Skip to content

Commit 4d9fe29

Browse files
committed
[GR-46599] Integrate foreign debuginfo types PR #6625.
PullRequest: graal/14799
2 parents fb1ed2d + a48884a commit 4d9fe29

File tree

22 files changed

+2028
-323
lines changed

22 files changed

+2028
-323
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2023, 2023, Red Hat Inc. 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+
# pylint: skip-file
25+
#
26+
# python utility code for use by the gdb scripts that test native debug info
27+
28+
import gdb
29+
import re
30+
import sys
31+
import os
32+
33+
# set various gdb operating modes to desired setting
34+
35+
def configure_gdb():
36+
# disable prompting to continue output
37+
execute("set pagination off")
38+
# enable pretty printing of structures
39+
execute("set print pretty on")
40+
# enable demangling of symbols in assembly code listings
41+
execute("set print asm-demangle on")
42+
# disable printing of address symbols
43+
execute("set print symbol off")
44+
# ensure file listings show only the current line
45+
execute("set listsize 1")
46+
47+
48+
# execute a gdb command and return the resulting output as a string
49+
50+
def execute(command):
51+
print('(gdb) %s'%(command))
52+
try:
53+
return gdb.execute(command, to_string=True)
54+
except gdb.error as e:
55+
print(e)
56+
sys.exit(1)
57+
58+
# a variety of useful regular expression patterns
59+
60+
address_pattern = '0x[0-9a-f]+'
61+
hex_digits_pattern = '[0-9a-f]+'
62+
spaces_pattern = '[ \t]+'
63+
maybe_spaces_pattern = '[ \t]*'
64+
digits_pattern = '[0-9]+'
65+
line_number_prefix_pattern = digits_pattern + ':' + spaces_pattern
66+
package_pattern = '[a-z/]+'
67+
package_file_pattern = '[a-zA-Z0-9_/]+\\.java'
68+
varname_pattern = '[a-zA-Z0-9_]+'
69+
wildcard_pattern = '.*'
70+
no_arg_values_pattern = "\(\)"
71+
arg_values_pattern = "\(([a-zA-Z0-9$_]+=[a-zA-Z0-9$_<> ]+)(, [a-zA-Z0-9$_]+=[a-zA-Z0-9$_<> ]+)*\)"
72+
no_param_types_pattern = "\(\)"
73+
param_types_pattern = "\(([a-zA-Z0-9[.*$_\]]+)(, [a-zA-Z0-9[.*$_\]]+)*\)"
74+
75+
# A helper class which checks that a sequence of lines of output
76+
# from a gdb command matches a sequence of per-line regular
77+
# expressions
78+
79+
class Checker:
80+
# Create a checker to check gdb command output text.
81+
# name - string to help identify the check if we have a failure.
82+
# regexps - a list of regular expressions which must match.
83+
# successive lines of checked
84+
def __init__(self, name, regexps):
85+
self.name = name
86+
if not isinstance(regexps, list):
87+
regexps = [regexps]
88+
self.rexps = [re.compile(r) for r in regexps if r is not None]
89+
90+
# Check that successive lines of a gdb command's output text
91+
# match the corresponding regexp patterns provided when this
92+
# Checker was created.
93+
# text - the full output of a gdb comand run by calling
94+
# gdb.execute and passing to_string = True.
95+
# Exits with status 1 if there are less lines in the text
96+
# than regexp patterns or if any line fails to match the
97+
# corresponding pattern otherwise prints the text and returns
98+
# the set of matches.
99+
def check(self, text, skip_fails=True):
100+
lines = text.splitlines()
101+
rexps = self.rexps
102+
num_lines = len(lines)
103+
num_rexps = len(rexps)
104+
line_idx = 0
105+
matches = []
106+
for i in range(0, (num_rexps)):
107+
rexp = rexps[i]
108+
match = None
109+
while line_idx < num_lines and match is None:
110+
line = lines[line_idx]
111+
match = rexp.match(line)
112+
if match is None:
113+
if not skip_fails:
114+
print('Checker %s: match %d failed at line %d %s\n'%(self.name, i, line_idx, line))
115+
print(self)
116+
print(text)
117+
sys.exit(1)
118+
else:
119+
matches.append(match)
120+
line_idx += 1
121+
if len(matches) < num_rexps:
122+
print('Checker %s: insufficient matching lines %d for regular expressions %d'%(self.name, len(matches), num_rexps))
123+
print(self)
124+
print(text)
125+
sys.exit(1)
126+
print(text)
127+
return matches
128+
129+
# Format a Checker as a string
130+
def __str__(self):
131+
rexps = self.rexps
132+
result = 'Checker %s '%(self.name)
133+
result += '{\n'
134+
for rexp in rexps:
135+
result += ' %s\n'%(rexp)
136+
result += '}\n'
137+
return result
138+
139+
def match_gdb_version():
140+
# obtain the gdb version
141+
# n.b. we can only test printing in gdb 10.1 upwards
142+
exec_string=execute("show version")
143+
checker = Checker('show version',
144+
r"GNU gdb %s (%s)\.(%s)%s"%(wildcard_pattern, digits_pattern, digits_pattern, wildcard_pattern))
145+
matches = checker.check(exec_string, skip_fails=False)
146+
return matches[0]
147+
148+
def check_print_data(major, minor):
149+
# printing does not always work on gdb 10.x or earlier
150+
can_print_data = major > 10
151+
if os.environ.get('GDB_CAN_PRINT', '') == 'True':
152+
can_print_data = True
153+
return can_print_data

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,9 @@ def _debuginfotest(native_image, path, build_only, with_isolates_only, args):
796796
mx.log("sourcepath=%s"%sourcepath)
797797
sourcecache = join(path, 'sources')
798798
mx.log("sourcecache=%s"%sourcecache)
799-
799+
# the header file for foreign types resides at the root of the
800+
# com.oracle.svm.test source tree
801+
cincludepath = sourcepath
800802
javaProperties = {}
801803
for dist in suite.dists:
802804
if isinstance(dist, mx.ClasspathDependency):
@@ -807,23 +809,26 @@ def _debuginfotest(native_image, path, build_only, with_isolates_only, args):
807809
for key, value in javaProperties.items():
808810
args.append("-D" + key + "=" + value)
809811

810-
811-
native_image_args = ["--native-image-info",
812-
'-H:+VerifyNamingConventions',
813-
'-cp', classpath('com.oracle.svm.test'),
814-
'-Dgraal.LogFile=graal.log',
815-
'-g',
816-
'-H:+SourceLevelDebug',
817-
'-H:DebugInfoSourceSearchPath=' + sourcepath,
818-
# We do not want to step into class initializer, so initialize everything at build time.
819-
'--initialize-at-build-time=hello',
820-
'hello.Hello'] + args
821-
822-
def build_debug_test(variant_name, extra_args):
812+
# set property controlling inclusion of foreign struct header
813+
args.append("-DbuildDebugInfoTestExample=true")
814+
815+
native_image_args = [
816+
'--native-compiler-options=-I' + cincludepath,
817+
'-H:CLibraryPath=' + sourcepath,
818+
'--native-image-info',
819+
'-H:+VerifyNamingConventions',
820+
'-cp', classpath('com.oracle.svm.test'),
821+
'-Dgraal.LogFile=graal.log',
822+
'-g',
823+
'-H:+SourceLevelDebug',
824+
'-H:DebugInfoSourceSearchPath=' + sourcepath,
825+
] + args
826+
827+
def build_debug_test(variant_name, image_name, extra_args):
823828
per_build_path = join(path, variant_name)
824829
mkpath(per_build_path)
825830
build_args = native_image_args + extra_args + [
826-
'-o', join(per_build_path, 'hello_image')
831+
'-o', join(per_build_path, image_name)
827832
]
828833
mx.log('native_image {}'.format(build_args))
829834
return native_image(build_args)
@@ -832,20 +837,26 @@ def build_debug_test(variant_name, extra_args):
832837
if '--libc=musl' in args:
833838
os.environ.update({'debuginfotest_musl' : 'yes'})
834839

840+
gdb_utils_py = join(suite.dir, 'mx.substratevm', 'gdb_utils.py')
835841
testhello_py = join(suite.dir, 'mx.substratevm', 'testhello.py')
836-
837-
hello_binary = build_debug_test('isolates_on', ['-H:+SpawnIsolates'])
842+
testhello_args = [
843+
# We do not want to step into class initializer, so initialize everything at build time.
844+
'--initialize-at-build-time=hello',
845+
'hello.Hello'
846+
]
838847
if mx.get_os() == 'linux' and not build_only:
839848
os.environ.update({'debuginfotest_arch' : mx.get_arch()})
840-
if mx.get_os() == 'linux' and not build_only:
841-
os.environ.update({'debuginfotest_isolates' : 'yes'})
842-
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=True"', '-x', testhello_py, hello_binary])
843849

844850
if not with_isolates_only:
845-
hello_binary = build_debug_test('isolates_off', ['-H:-SpawnIsolates'])
851+
hello_binary = build_debug_test('isolates_off', 'hello_image', testhello_args + ['-H:-SpawnIsolates'])
846852
if mx.get_os() == 'linux' and not build_only:
847853
os.environ.update({'debuginfotest_isolates' : 'no'})
848-
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=False"', '-x', testhello_py, hello_binary])
854+
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=False"', '-x', gdb_utils_py, '-x', testhello_py, hello_binary])
855+
856+
hello_binary = build_debug_test('isolates_on', 'hello_image', testhello_args + ['-H:+SpawnIsolates'])
857+
if mx.get_os() == 'linux' and not build_only:
858+
os.environ.update({'debuginfotest_isolates' : 'yes'})
859+
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=True"', '-x', gdb_utils_py, '-x', testhello_py, hello_binary])
849860

850861
def _javac_image(native_image, path, args=None):
851862
args = [] if args is None else args

0 commit comments

Comments
 (0)