Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
53ce7f4
Use NativeLibraries to idenitfy foreign word and pointer types
adinn Mar 17, 2023
249ad5c
Log details of foreign types
adinn Apr 27, 2023
9773483
Initial modelling + DWARF for foreign types minus struct layouts
adinn May 12, 2023
070969c
Correct mangled names to omit P tag for foreign type arg or return value
adinn May 15, 2023
9f122ef
Model foreign structs and indirect pointers
adinn May 17, 2023
cd7c38e
Style fixes
adinn May 17, 2023
73eca71
More style fixes
adinn May 17, 2023
92877d9
More style fixes and cleanups
adinn May 17, 2023
9314e7b
Fix logic typo caught in stooke review
adinn May 18, 2023
5d887dd
Fix typo after fzakkak review
adinn May 22, 2023
abdf60e
Ensure foreign struct layouts inherit 'super' fields
adinn May 24, 2023
39996ab
Support embedded values in foreign structs including arrays
adinn May 25, 2023
46d83cd
Rework for chaeubl review
adinn May 25, 2023
30e8c27
Allow for larger offsets in header/structs
adinn May 25, 2023
a0cb35a
Generate correct array byte_size only where appropriate
adinn May 26, 2023
1810873
Test foreign debug info
adinn May 26, 2023
f716a86
Avoid python style issues for gdb script
adinn May 26, 2023
8a5890f
Fix python style issue
adinn May 30, 2023
ac34fb0
More style fixes
adinn May 30, 2023
2206da0
Make debuginfotest use one native image and fix C inlude lookup
adinn May 30, 2023
5f5f556
Remove file added by accident
adinn May 31, 2023
185a162
Disable CInterfaceDebugTestDirectives when not running debug test
adinn May 31, 2023
89816d9
Fix problem typing embedded pointer fields
adinn Jun 5, 2023
991fd7a
Update and document assert condition for layout index
adinn Jun 7, 2023
d97d8be
Respond to review feedback
adinn Jun 12, 2023
df5aa4d
Fix logging issues
olpaw Jun 12, 2023
532b0fa
Style fix
olpaw Jun 12, 2023
2746870
Find all known targets of pointer types
adinn Jun 14, 2023
5857278
Ensure debuginfotest_arch is set for all gdb test-runs
olpaw Jun 15, 2023
a48884a
Aarch64 maps CCharPointer to uint8_t
olpaw Jun 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions substratevm/mx.substratevm/gdb_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2023, 2023, Red Hat Inc. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# ----------------------------------------------------------------------------------------------------
# pylint: skip-file
#
# python utility code for use by the gdb scripts that test native debug info

import gdb
import re
import sys
import os

# set various gdb operating modes to desired setting

def configure_gdb():
# disable prompting to continue output
execute("set pagination off")
# enable pretty printing of structures
execute("set print pretty on")
# enable demangling of symbols in assembly code listings
execute("set print asm-demangle on")
# disable printing of address symbols
execute("set print symbol off")
# ensure file listings show only the current line
execute("set listsize 1")


# execute a gdb command and return the resulting output as a string

def execute(command):
print('(gdb) %s'%(command))
try:
return gdb.execute(command, to_string=True)
except gdb.error as e:
print(e)
sys.exit(1)

# a variety of useful regular expression patterns

address_pattern = '0x[0-9a-f]+'
hex_digits_pattern = '[0-9a-f]+'
spaces_pattern = '[ \t]+'
maybe_spaces_pattern = '[ \t]*'
digits_pattern = '[0-9]+'
line_number_prefix_pattern = digits_pattern + ':' + spaces_pattern
package_pattern = '[a-z/]+'
package_file_pattern = '[a-zA-Z0-9_/]+\\.java'
varname_pattern = '[a-zA-Z0-9_]+'
wildcard_pattern = '.*'
no_arg_values_pattern = "\(\)"
arg_values_pattern = "\(([a-zA-Z0-9$_]+=[a-zA-Z0-9$_<> ]+)(, [a-zA-Z0-9$_]+=[a-zA-Z0-9$_<> ]+)*\)"
no_param_types_pattern = "\(\)"
param_types_pattern = "\(([a-zA-Z0-9[.*$_\]]+)(, [a-zA-Z0-9[.*$_\]]+)*\)"

# A helper class which checks that a sequence of lines of output
# from a gdb command matches a sequence of per-line regular
# expressions

class Checker:
# Create a checker to check gdb command output text.
# name - string to help identify the check if we have a failure.
# regexps - a list of regular expressions which must match.
# successive lines of checked
def __init__(self, name, regexps):
self.name = name
if not isinstance(regexps, list):
regexps = [regexps]
self.rexps = [re.compile(r) for r in regexps if r is not None]

# Check that successive lines of a gdb command's output text
# match the corresponding regexp patterns provided when this
# Checker was created.
# text - the full output of a gdb comand run by calling
# gdb.execute and passing to_string = True.
# Exits with status 1 if there are less lines in the text
# than regexp patterns or if any line fails to match the
# corresponding pattern otherwise prints the text and returns
# the set of matches.
def check(self, text, skip_fails=True):
lines = text.splitlines()
rexps = self.rexps
num_lines = len(lines)
num_rexps = len(rexps)
line_idx = 0
matches = []
for i in range(0, (num_rexps)):
rexp = rexps[i]
match = None
while line_idx < num_lines and match is None:
line = lines[line_idx]
match = rexp.match(line)
if match is None:
if not skip_fails:
print('Checker %s: match %d failed at line %d %s\n'%(self.name, i, line_idx, line))
print(self)
print(text)
sys.exit(1)
else:
matches.append(match)
line_idx += 1
if len(matches) < num_rexps:
print('Checker %s: insufficient matching lines %d for regular expressions %d'%(self.name, len(matches), num_rexps))
print(self)
print(text)
sys.exit(1)
print(text)
return matches

# Format a Checker as a string
def __str__(self):
rexps = self.rexps
result = 'Checker %s '%(self.name)
result += '{\n'
for rexp in rexps:
result += ' %s\n'%(rexp)
result += '}\n'
return result

def match_gdb_version():
# obtain the gdb version
# n.b. we can only test printing in gdb 10.1 upwards
exec_string=execute("show version")
checker = Checker('show version',
r"GNU gdb %s (%s)\.(%s)%s"%(wildcard_pattern, digits_pattern, digits_pattern, wildcard_pattern))
matches = checker.check(exec_string, skip_fails=False)
return matches[0]

def check_print_data(major, minor):
# printing does not always work on gdb 10.x or earlier
can_print_data = major > 10
if os.environ.get('GDB_CAN_PRINT', '') == 'True':
can_print_data = True
return can_print_data
55 changes: 33 additions & 22 deletions substratevm/mx.substratevm/mx_substratevm.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,9 @@ def _debuginfotest(native_image, path, build_only, with_isolates_only, args):
mx.log("sourcepath=%s"%sourcepath)
sourcecache = join(path, 'sources')
mx.log("sourcecache=%s"%sourcecache)

# the header file for foreign types resides at the root of the
# com.oracle.svm.test source tree
cincludepath = sourcepath
javaProperties = {}
for dist in suite.dists:
if isinstance(dist, mx.ClasspathDependency):
Expand All @@ -807,23 +809,26 @@ def _debuginfotest(native_image, path, build_only, with_isolates_only, args):
for key, value in javaProperties.items():
args.append("-D" + key + "=" + value)


native_image_args = ["--native-image-info",
'-H:+VerifyNamingConventions',
'-cp', classpath('com.oracle.svm.test'),
'-Dgraal.LogFile=graal.log',
'-g',
'-H:+SourceLevelDebug',
'-H:DebugInfoSourceSearchPath=' + sourcepath,
# We do not want to step into class initializer, so initialize everything at build time.
'--initialize-at-build-time=hello',
'hello.Hello'] + args

def build_debug_test(variant_name, extra_args):
# set property controlling inclusion of foreign struct header
args.append("-DbuildDebugInfoTestExample=true")

native_image_args = [
'--native-compiler-options=-I' + cincludepath,
'-H:CLibraryPath=' + sourcepath,
'--native-image-info',
'-H:+VerifyNamingConventions',
'-cp', classpath('com.oracle.svm.test'),
'-Dgraal.LogFile=graal.log',
'-g',
'-H:+SourceLevelDebug',
'-H:DebugInfoSourceSearchPath=' + sourcepath,
] + args

def build_debug_test(variant_name, image_name, extra_args):
per_build_path = join(path, variant_name)
mkpath(per_build_path)
build_args = native_image_args + extra_args + [
'-o', join(per_build_path, 'hello_image')
'-o', join(per_build_path, image_name)
]
mx.log('native_image {}'.format(build_args))
return native_image(build_args)
Expand All @@ -832,20 +837,26 @@ def build_debug_test(variant_name, extra_args):
if '--libc=musl' in args:
os.environ.update({'debuginfotest_musl' : 'yes'})

gdb_utils_py = join(suite.dir, 'mx.substratevm', 'gdb_utils.py')
testhello_py = join(suite.dir, 'mx.substratevm', 'testhello.py')

hello_binary = build_debug_test('isolates_on', ['-H:+SpawnIsolates'])
testhello_args = [
# We do not want to step into class initializer, so initialize everything at build time.
'--initialize-at-build-time=hello',
'hello.Hello'
]
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest_arch' : mx.get_arch()})
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest_isolates' : 'yes'})
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=True"', '-x', testhello_py, hello_binary])

if not with_isolates_only:
hello_binary = build_debug_test('isolates_off', ['-H:-SpawnIsolates'])
hello_binary = build_debug_test('isolates_off', 'hello_image', testhello_args + ['-H:-SpawnIsolates'])
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest_isolates' : 'no'})
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=False"', '-x', testhello_py, hello_binary])
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=False"', '-x', gdb_utils_py, '-x', testhello_py, hello_binary])

hello_binary = build_debug_test('isolates_on', 'hello_image', testhello_args + ['-H:+SpawnIsolates'])
if mx.get_os() == 'linux' and not build_only:
os.environ.update({'debuginfotest_isolates' : 'yes'})
mx.run([os.environ.get('GDB_BIN', 'gdb'), '-ex', 'python "ISOLATES=True"', '-x', gdb_utils_py, '-x', testhello_py, hello_binary])

def _javac_image(native_image, path, args=None):
args = [] if args is None else args
Expand Down
Loading