mirror of
https://github.com/clearlinux/graphene.git
synced 2026-04-28 11:13:41 +00:00
[Pal] Clean up GDB configuration
- Extract parts that are common for all hosts - Remove some outdated/unnecessary options, we should now be closer to default configuration - Disable libthread_db loading (does not work and crashes GDB 9.2) - Disable pagination when loading debug maps
This commit is contained in:
committed by
Michał Kowalczyk
parent
c59a1438d5
commit
09c6307631
@@ -3,6 +3,9 @@
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Paweł Marczewski <pawel@invisiblethingslab.com>
|
||||
|
||||
# Debug map handling, so that GDB sees all ELF binaries loaded by Graphene. Connects with
|
||||
# debug_map.c (in PAL) using a breakpoint on debug_map_update_debugger() function.
|
||||
|
||||
import os
|
||||
import shlex
|
||||
|
||||
@@ -128,7 +131,14 @@ class UpdateDebugMaps(gdb.Command):
|
||||
cmd += ' '.join('-s {} 0x{:x}'.format(shlex.quote(name), addr)
|
||||
for name, addr in sections
|
||||
if name != '.text')
|
||||
gdb.execute(cmd)
|
||||
try:
|
||||
# Temporarily disable pagination, because 'add-symbol-file` produces a lot of
|
||||
# noise.
|
||||
gdb.execute('push-pagination off')
|
||||
|
||||
gdb.execute(cmd)
|
||||
finally:
|
||||
gdb.execute('pop-pagination')
|
||||
|
||||
progspace.debug_maps = new
|
||||
|
||||
|
||||
31
Pal/gdb_integration/graphene.gdb
Normal file
31
Pal/gdb_integration/graphene.gdb
Normal file
@@ -0,0 +1,31 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
# Paweł Marczewski <pawel@invisiblethingslab.com>
|
||||
|
||||
# Graphene GDB configuration (common for all hosts).
|
||||
|
||||
# Tell Graphene to behave more gdb-friendly.
|
||||
set env IN_GDB=1
|
||||
|
||||
# Used internally by Graphene, generates a lot of noise if we don't silence it.
|
||||
handle SIGCONT pass noprint nostop
|
||||
|
||||
# Disable loading inferior-specific libthread_db library. This does not work with our patched
|
||||
# libpthread, and prevents newer GDB versions (9.2+) from working when a program uses libpthread.
|
||||
set auto-load libthread-db off
|
||||
set libthread-db-search-path ""
|
||||
|
||||
# Reenable address space layout randomization (ASLR). Graphene's features often take memory layout
|
||||
# into account, so running with ASLR enabled is more realistic and allows us to catch issues sooner.
|
||||
set disable-randomization off
|
||||
|
||||
# Make GDB follow both sides of the fork - GDB (at least version 8.1) crashes on Graphene running
|
||||
# some applications otherwise (e.g. exit_group regression test).
|
||||
set detach-on-fork off
|
||||
|
||||
# Resume all processes by default. This is to negate consequences of 'set detach-on-fork off': by
|
||||
# default, it keeps running only one side of the fork. This is usually not what we want, and it's
|
||||
# particularly annoying in Graphene, because checkpoint data is sent between processes just after
|
||||
# forking.
|
||||
set schedule-multiple on
|
||||
53
Pal/gdb_integration/pagination_gdb.py
Normal file
53
Pal/gdb_integration/pagination_gdb.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later */
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
# Paweł Marczewski <pawel@invisiblethingslab.com>
|
||||
|
||||
# Commands for temporarily changing pagination state. Used by other Graphene GDB scripts in
|
||||
# situation where we produce a lot of noise and we don't want to repeatedly prompt user for
|
||||
# continuation.
|
||||
|
||||
import gdb # pylint: disable=import-error
|
||||
|
||||
_g_paginations = []
|
||||
|
||||
|
||||
class PushPagination(gdb.Command):
|
||||
"""Temporarily change pagination and save the old state"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("push-pagination", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, _from_tty):
|
||||
self.dont_repeat()
|
||||
|
||||
pagination_str = gdb.execute('show pagination', to_string=True).strip()
|
||||
assert pagination_str in ('State of pagination is on.', 'State of pagination is off.')
|
||||
pagination = pagination_str.endswith('on.')
|
||||
_g_paginations.append(pagination)
|
||||
|
||||
assert arg in ('on', 'off')
|
||||
gdb.execute('set pagination ' + arg)
|
||||
|
||||
|
||||
class PopPagination(gdb.Command):
|
||||
"""Recover pagination state saved by PushPagination"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("pop-pagination", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, _from_tty):
|
||||
self.dont_repeat()
|
||||
|
||||
assert arg == ''
|
||||
pagination = _g_paginations.pop()
|
||||
gdb.execute('set pagination ' + ('on' if pagination else 'off'))
|
||||
|
||||
|
||||
def main():
|
||||
PushPagination()
|
||||
PopPagination()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
1
Pal/src/host/Linux-SGX/gdb_integration/common
Symbolic link
1
Pal/src/host/Linux-SGX/gdb_integration/common
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../gdb_integration/
|
||||
@@ -1 +0,0 @@
|
||||
../../../../gdb_integration/debug_map_gdb.py
|
||||
@@ -1,47 +1,28 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later */
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
# Paweł Marczewski <pawel@invisiblethingslab.com>
|
||||
|
||||
|
||||
# GDB Python "API" [1] is so wonderful that what we need [2] is not possible to be implemented using
|
||||
# it, so we have to fall back to raw GDB scripting. But raw GDB scripting is also broken, so we need
|
||||
# to supply things like `push-pagination` command from Python.
|
||||
#
|
||||
# [1] It mostly consists of `gdb.execute()`, there isn't even gdb.continue() API, you need to call
|
||||
# `gdb.execute('continue')`.
|
||||
# [2] One of the things we want is to silently pass SIGILLs caused by CPUID and RDTSC to the
|
||||
# application, but without silencing SIGILLs caused by other reasons. This is impossible to
|
||||
# implement from GDB Python "API", neither using event handlers nor even executing raw commands
|
||||
# with gdb.execute() - it doesn't support multiline commands, and gdb.execute('commands') blocks
|
||||
# for input on the *user terminal*, not giving the script a chance to provide more lines.
|
||||
|
||||
# Graphene GDB configuration (Linux-SGX specific).
|
||||
|
||||
# Prevent the preloaded sgx_gdb.so from being preloaded to the debuggee.
|
||||
set env LD_PRELOAD=
|
||||
|
||||
# Tell Graphene to behave more gdb-friendly.
|
||||
set env IN_GDB=1
|
||||
|
||||
# Used internally by Graphene, generates a lot of noise if we don't silence it.
|
||||
handle SIGCONT pass noprint nostop
|
||||
|
||||
# TODO: This block of commands was copied from an older Graphene integration script where they
|
||||
# didn't have any comments with rationale why they are needed. We should revise and comment them.
|
||||
handle SIGKILL pass print stop
|
||||
set disable-randomization off
|
||||
set detach-on-fork off
|
||||
set schedule-multiple on
|
||||
set follow-exec-mode same
|
||||
set follow-fork-mode child
|
||||
# Disable displaced stepping. Displaced stepping means GDB executes an out-of-line copy of an
|
||||
# instruction, instead of the original instruction at breakpoint location. This does not work when
|
||||
# the instruction in question is located in SGX enclave memory, and should be executed in enclave.
|
||||
set displaced-stepping off
|
||||
|
||||
# CPUID/RDTSC SIGILL skipping. See [2] above.
|
||||
# CPUID/RDTSC SIGILL skipping. We want to silently pass SIGILLs caused by CPUID and RDTSC
|
||||
# instructions to the application, but without silencing SIGILLs caused by other reasons.
|
||||
|
||||
# (This seems impossible to implement in Python, either by using event handlers or even executing
|
||||
# raw commands with gdb.execute(). gdb.execute() doesn't support multiline commands, and instead
|
||||
# blocks for input on the *user terminal*, not giving the script a chance to provide more lines.)
|
||||
|
||||
catch signal SIGILL
|
||||
|
||||
# break only on CPUID (0fa2) and RDTSC (0f31)
|
||||
condition $bpnum *(uint16_t*)$rip == 0xa20f || *(uint16_t*)$rip == 0x310f
|
||||
|
||||
commands
|
||||
silent
|
||||
|
||||
|
||||
@@ -7,53 +7,16 @@ import os
|
||||
|
||||
import gdb # pylint: disable=import-error
|
||||
|
||||
_g_paginations = []
|
||||
|
||||
|
||||
class PushPagination(gdb.Command):
|
||||
"""Temporarily changing pagination and saving the old state.
|
||||
|
||||
Supplements gdb interface with functionality it's missing and seems to not be possible to
|
||||
implement from a gdb script. This command is used by graphene_sgx.gdb script.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("push-pagination", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, _from_tty):
|
||||
self.dont_repeat()
|
||||
|
||||
pagination_str = gdb.execute('show pagination', to_string=True).strip()
|
||||
assert pagination_str in ('State of pagination is on.', 'State of pagination is off.')
|
||||
pagination = pagination_str.endswith('on.')
|
||||
_g_paginations.append(pagination)
|
||||
|
||||
assert arg in ('on', 'off')
|
||||
gdb.execute('set pagination ' + arg)
|
||||
|
||||
|
||||
class PopPagination(gdb.Command):
|
||||
"""Recover pagination state saved by PushPagination"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__("pop-pagination", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, _from_tty):
|
||||
self.dont_repeat()
|
||||
|
||||
assert arg == ''
|
||||
pagination = _g_paginations.pop()
|
||||
gdb.execute('set pagination ' + ('on' if pagination else 'off'))
|
||||
|
||||
def main():
|
||||
PushPagination()
|
||||
PopPagination()
|
||||
|
||||
# Some of the things we want to do can't be done using gdb Python API, we need to fall back to a
|
||||
# standard gdb script.
|
||||
gdb_script = os.path.dirname(__file__) + "/graphene_sgx.gdb"
|
||||
print("[%s] Loading %s..." % (os.path.basename(__file__), gdb_script))
|
||||
gdb.execute("source " + gdb_script)
|
||||
for filename in [
|
||||
'common/pagination_gdb.py',
|
||||
'common/debug_map_gdb.py',
|
||||
'common/graphene.gdb',
|
||||
'graphene_sgx.gdb',
|
||||
]:
|
||||
print("[%s] Loading %s..." % (os.path.basename(__file__), filename))
|
||||
path = os.path.join(os.path.dirname(__file__), filename)
|
||||
gdb.execute("source " + path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
1
Pal/src/host/Linux/gdb_integration/common
Symbolic link
1
Pal/src/host/Linux/gdb_integration/common
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../gdb_integration/
|
||||
@@ -1 +0,0 @@
|
||||
../../../../gdb_integration/debug_map_gdb.py
|
||||
@@ -1,38 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later */
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
|
||||
# Tell Graphene to behave more gdb-friendly.
|
||||
set env IN_GDB=1
|
||||
|
||||
# Used internally by Graphene, generates a lot of noise if we don't silence it.
|
||||
handle SIGCONT pass noprint nostop
|
||||
|
||||
# TODO: This block of commands was copied from an older Graphene integration script where they
|
||||
# didn't have any comments with rationale why they are needed. We should revise and comment them.
|
||||
set auto-load off
|
||||
handle SIGKILL pass print stop
|
||||
set disable-randomization off
|
||||
set detach-on-fork off
|
||||
set schedule-multiple on
|
||||
set follow-fork-mode child
|
||||
|
||||
break pal_start
|
||||
command
|
||||
silent
|
||||
set scheduler-locking off
|
||||
continue
|
||||
end
|
||||
|
||||
break thread_start
|
||||
command
|
||||
silent
|
||||
continue
|
||||
end
|
||||
|
||||
catch vfork
|
||||
command
|
||||
silent
|
||||
set scheduler-locking on
|
||||
continue
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later */
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
|
||||
import os
|
||||
import gdb # pylint: disable=import-error
|
||||
|
||||
def main():
|
||||
gdb_script = os.path.dirname(__file__) + "/graphene.gdb"
|
||||
print("[%s] Loading %s..." % (os.path.basename(__file__), gdb_script))
|
||||
gdb.execute("source " + gdb_script)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
20
Pal/src/host/Linux/gdb_integration/graphene_linux_gdb.py
Normal file
20
Pal/src/host/Linux/gdb_integration/graphene_linux_gdb.py
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later */
|
||||
# Copyright (C) 2020 Intel Corporation
|
||||
# Michał Kowalczyk <mkow@invisiblethingslab.com>
|
||||
|
||||
import os
|
||||
import gdb # pylint: disable=import-error
|
||||
|
||||
def main():
|
||||
for filename in [
|
||||
'common/pagination_gdb.py',
|
||||
'common/debug_map_gdb.py',
|
||||
'common/graphene.gdb',
|
||||
]:
|
||||
print("[%s] Loading %s..." % (os.path.basename(__file__), filename))
|
||||
path = os.path.join(os.path.dirname(__file__), filename)
|
||||
gdb.execute("source " + path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -6,9 +6,10 @@ if direct
|
||||
install_dir: join_paths(pkglibexecdir, 'linux'))
|
||||
install_subdir('../Pal/src/host/Linux/gdb_integration',
|
||||
install_dir: join_paths(pkglibexecdir, 'linux'),
|
||||
exclude_files: ['debug_map_gdb.py'])
|
||||
exclude_directories: ['common'])
|
||||
install_subdir('../Pal/gdb_integration',
|
||||
install_dir: join_paths(pkglibexecdir, 'linux'))
|
||||
install_dir: join_paths(pkglibexecdir, 'linux/gdb_integration/common'),
|
||||
strip_directory: true)
|
||||
|
||||
hostpalpath_linux = join_paths(prefix, pkglibexecdir, 'linux')
|
||||
conf_graphene = configuration_data()
|
||||
@@ -33,9 +34,10 @@ if sgx
|
||||
install_dir: join_paths(pkglibexecdir, 'linux-sgx'))
|
||||
install_subdir('../Pal/src/host/Linux-SGX/gdb_integration',
|
||||
install_dir: join_paths(pkglibexecdir, 'linux-sgx'),
|
||||
exclude_files: ['debug_map_gdb.py'])
|
||||
exclude_directories: ['common'])
|
||||
install_subdir('../Pal/gdb_integration',
|
||||
install_dir: join_paths(pkglibexecdir, 'linux-sgx'))
|
||||
install_dir: join_paths(pkglibexecdir, 'linux-sgx/gdb_integration/common'),
|
||||
strip_directory: true)
|
||||
|
||||
hostpalpath_linux_sgx = join_paths(prefix, pkglibexecdir, 'linux-sgx')
|
||||
conf_graphene_sgx = configuration_data()
|
||||
|
||||
@@ -77,12 +77,10 @@ if [ "$GDB" == "1" ]; then
|
||||
PREFIX+=("-i=mi")
|
||||
fi
|
||||
if [ 0"$SGX" -gt 0 ]; then
|
||||
PREFIX+=("-x" "$HOST_PAL_PATH/gdb_integration/debug_map_gdb.py")
|
||||
PREFIX+=("-x" "$HOST_PAL_PATH/gdb_integration/graphene_sgx_gdb.py")
|
||||
ENVS+=("LD_PRELOAD=$HOST_PAL_PATH/gdb_integration/sgx_gdb.so:$LD_PRELOAD")
|
||||
else
|
||||
PREFIX+=("-x" "$HOST_PAL_PATH/gdb_integration/debug_map_gdb.py")
|
||||
PREFIX+=("-x" "$HOST_PAL_PATH/gdb_integration/graphene_gdb.py")
|
||||
PREFIX+=("-x" "$HOST_PAL_PATH/gdb_integration/graphene_linux_gdb.py")
|
||||
fi
|
||||
if [ "$GDB_SCRIPT" != "" ]; then
|
||||
# Run a script in batch mode, and without TTY (so that it can be piped, redirected etc.)
|
||||
|
||||
@@ -40,13 +40,12 @@ class RegressionTestCase(unittest.TestCase):
|
||||
# See also pal_loader.
|
||||
prefix = ['gdb', '-q']
|
||||
env = os.environ.copy()
|
||||
prefix += ['-x', os.path.join(host_pal_path, 'gdb_integration/debug_map_gdb.py')]
|
||||
if HAS_SGX:
|
||||
prefix += ['-x', os.path.join(host_pal_path, 'gdb_integration/graphene_sgx_gdb.py')]
|
||||
sgx_gdb = os.path.join(host_pal_path, 'gdb_integration/sgx_gdb.so')
|
||||
env['LD_PRELOAD'] = sgx_gdb + ':' + env.get('LD_PRELOAD', '')
|
||||
else:
|
||||
prefix += ['-x', os.path.join(host_pal_path, 'gdb_integration/graphene_gdb.py')]
|
||||
prefix += ['-x', os.path.join(host_pal_path, 'gdb_integration/graphene_linux_gdb.py')]
|
||||
|
||||
# Override TTY, as apparently os.setpgrp() confuses GDB and causes it to hang.
|
||||
prefix += ['-x', gdb_script, '-batch', '-tty=/dev/null']
|
||||
|
||||
Reference in New Issue
Block a user