From 8b264f8823b205d1664fb673a056d1f0c3633433 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Fri, 15 May 2020 15:13:02 -0700 Subject: [PATCH 1/8] Update copyright headers to Facebook and add missing headers drgn was originally my side project, but for awhile now it's also been my work project. Update the copyright headers to reflect this, and add a copyright header to various files that were missing it. --- README.rst | 2 +- _drgn.pyi | 2 +- docs/exts/drgndoc/docstrings.py | 2 +- docs/exts/drgndoc/ext.py | 2 +- docs/exts/drgndoc/format.py | 2 +- docs/exts/drgndoc/namespace.py | 2 +- docs/exts/drgndoc/parse.py | 2 +- docs/exts/drgndoc/util.py | 2 +- docs/exts/drgndoc/visitor.py | 2 +- drgn/__init__.py | 2 +- drgn/__main__.py | 2 +- drgn/helpers/__init__.py | 2 +- drgn/helpers/linux/__init__.py | 2 +- drgn/helpers/linux/block.py | 2 +- drgn/helpers/linux/bpf.py | 1 + drgn/helpers/linux/cgroup.py | 1 + drgn/helpers/linux/cpumask.py | 2 +- drgn/helpers/linux/device.py | 2 +- drgn/helpers/linux/fs.py | 2 +- drgn/helpers/linux/idr.py | 2 +- drgn/helpers/linux/kconfig.py | 1 + drgn/helpers/linux/kernfs.py | 1 + drgn/helpers/linux/list.py | 2 +- drgn/helpers/linux/list_nulls.py | 1 + drgn/helpers/linux/mm.py | 2 +- drgn/helpers/linux/net.py | 1 + drgn/helpers/linux/percpu.py | 2 +- drgn/helpers/linux/pid.py | 2 +- drgn/helpers/linux/radixtree.py | 2 +- drgn/helpers/linux/rbtree.py | 2 +- drgn/helpers/linux/sched.py | 2 +- drgn/helpers/linux/tcp.py | 1 + drgn/helpers/linux/user.py | 2 +- drgn/internal/__init__.py | 2 +- drgn/internal/cli.py | 2 +- drgn/internal/rlcompleter.py | 2 +- examples/linux/cgroup.py | 3 +++ examples/linux/fs_inodes.py | 3 +++ examples/linux/lsmod.py | 3 +++ examples/linux/ps.py | 3 +++ examples/linux/tcp_sock.py | 3 +++ libdrgn/Makefile.am | 3 +++ libdrgn/arch_x86_64.c.in | 2 +- libdrgn/binary_search_tree.h | 2 +- libdrgn/build-aux/gen_arch.awk | 2 +- libdrgn/build-aux/gen_constants.py | 2 +- libdrgn/build-aux/gen_drgn_h.awk | 2 +- libdrgn/build-aux/parse_arch.awk | 2 +- libdrgn/cityhash.h | 2 +- libdrgn/configure.ac | 3 +++ libdrgn/drgn.h.in | 2 +- libdrgn/dwarf_index.c | 2 +- libdrgn/dwarf_index.h | 2 +- libdrgn/dwarf_info_cache.c | 2 +- libdrgn/dwarf_info_cache.h | 2 +- libdrgn/error.c | 2 +- libdrgn/error.h | 2 +- libdrgn/hash_table.c | 3 +++ libdrgn/hash_table.h | 2 +- libdrgn/helpers.h | 2 +- libdrgn/include/Makefile.am | 3 +++ libdrgn/internal.c | 2 +- libdrgn/internal.h | 2 +- libdrgn/language.c | 2 +- libdrgn/language.h | 2 +- libdrgn/language_c.c | 2 +- libdrgn/lexer.c | 2 +- libdrgn/lexer.h | 2 +- libdrgn/linux_kernel.c | 2 +- libdrgn/linux_kernel.h | 2 +- libdrgn/linux_kernel_helpers.c | 2 +- libdrgn/memory_reader.c | 2 +- libdrgn/memory_reader.h | 2 +- libdrgn/object.c | 2 +- libdrgn/object.h | 2 +- libdrgn/object_index.c | 2 +- libdrgn/object_index.h | 2 +- libdrgn/path.c | 2 +- libdrgn/platform.c | 2 +- libdrgn/platform.h | 2 +- libdrgn/program.c | 2 +- libdrgn/program.h | 2 +- libdrgn/python/drgnpy.h | 2 +- libdrgn/python/error.c | 2 +- libdrgn/python/helpers.c | 2 +- libdrgn/python/language.c | 2 +- libdrgn/python/module.c | 2 +- libdrgn/python/object.c | 2 +- libdrgn/python/platform.c | 2 +- libdrgn/python/program.c | 2 +- libdrgn/python/stack_trace.c | 2 +- libdrgn/python/symbol.c | 2 +- libdrgn/python/test.c | 2 +- libdrgn/python/type.c | 2 +- libdrgn/python/util.c | 2 +- libdrgn/read.h | 2 +- libdrgn/serialize.c | 2 +- libdrgn/serialize.h | 2 +- libdrgn/siphash.h | 2 +- libdrgn/splay_tree.c | 2 +- libdrgn/stack_trace.c | 2 +- libdrgn/string_builder.c | 2 +- libdrgn/string_builder.h | 2 +- libdrgn/symbol.c | 2 +- libdrgn/symbol.h | 2 +- libdrgn/type.c | 3 +++ libdrgn/type.h | 2 +- libdrgn/type_index.c | 2 +- libdrgn/type_index.h | 2 +- libdrgn/util.h | 2 +- libdrgn/vector.c | 2 +- libdrgn/vector.h | 2 +- scripts/generate_dwarf_constants.py | 2 ++ scripts/generate_primitive_type_spellings.py | 2 ++ scripts/test_cityhash.c | 3 +++ scripts/test_siphash.c | 3 +++ scripts/update-elfutils.sh | 2 ++ setup.py | 2 ++ tests/__init__.py | 3 +++ tests/dwarfwriter.py | 3 +++ tests/elf.py | 3 +++ tests/elfwriter.py | 3 +++ tests/helpers/linux/__init__.py | 3 +++ tests/helpers/linux/test_block.py | 3 +++ tests/helpers/linux/test_cgroup.py | 3 +++ tests/helpers/linux/test_fs.py | 3 +++ tests/helpers/linux/test_kconfig.py | 3 +++ tests/helpers/linux/test_kernfs.py | 3 +++ tests/helpers/linux/test_mm.py | 3 +++ tests/helpers/linux/test_net.py | 3 +++ tests/helpers/linux/test_pid.py | 3 +++ tests/helpers/linux/test_sched.py | 3 +++ tests/helpers/linux/test_stack_trace.py | 3 +++ tests/helpers/linux/test_tcp.py | 3 +++ tests/helpers/linux/test_user.py | 3 +++ tests/helpers/linux/test_uts.py | 3 +++ tests/libdrgn.py | 3 +++ tests/test_docs.py | 3 +++ tests/test_dwarf.py | 3 +++ tests/test_language_c.py | 3 +++ tests/test_lexer.py | 3 +++ tests/test_object.py | 3 +++ tests/test_path.py | 3 +++ tests/test_platform.py | 3 +++ tests/test_program.py | 3 +++ tests/test_python.py | 3 +++ tests/test_serialize.py | 3 +++ tests/test_type.py | 3 +++ tests/test_util.py | 3 +++ tools/bpf_inspect.py | 3 +-- util.py | 2 +- vmtest/manage.py | 2 +- vmtest/onoatimehack.c | 2 +- vmtest/resolver.py | 2 +- vmtest/vm.py | 2 +- 155 files changed, 245 insertions(+), 102 deletions(-) diff --git a/README.rst b/README.rst index 3f6d8edc3..6fc8d8330 100644 --- a/README.rst +++ b/README.rst @@ -125,7 +125,7 @@ License .. start-license -Copyright 2018-2020 Omar Sandoval +Copyright (c) Facebook, Inc. and its affiliates. drgn is licensed under the `GPLv3 `_ or later. diff --git a/_drgn.pyi b/_drgn.pyi index 0e1c69aa3..94f33106f 100644 --- a/_drgn.pyi +++ b/_drgn.pyi @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/docs/exts/drgndoc/docstrings.py b/docs/exts/drgndoc/docstrings.py index ef2b2012e..a5a6d7270 100644 --- a/docs/exts/drgndoc/docstrings.py +++ b/docs/exts/drgndoc/docstrings.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import argparse diff --git a/docs/exts/drgndoc/ext.py b/docs/exts/drgndoc/ext.py index a19ef8f52..5d6779f75 100644 --- a/docs/exts/drgndoc/ext.py +++ b/docs/exts/drgndoc/ext.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/docs/exts/drgndoc/format.py b/docs/exts/drgndoc/format.py index fb7e6fa2d..efa162887 100644 --- a/docs/exts/drgndoc/format.py +++ b/docs/exts/drgndoc/format.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import ast diff --git a/docs/exts/drgndoc/namespace.py b/docs/exts/drgndoc/namespace.py index af2d04e7f..cf2602853 100644 --- a/docs/exts/drgndoc/namespace.py +++ b/docs/exts/drgndoc/namespace.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import itertools diff --git a/docs/exts/drgndoc/parse.py b/docs/exts/drgndoc/parse.py index 72436919f..4b272cfbc 100644 --- a/docs/exts/drgndoc/parse.py +++ b/docs/exts/drgndoc/parse.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import ast diff --git a/docs/exts/drgndoc/util.py b/docs/exts/drgndoc/util.py index 5fef80818..7c0f2b8e3 100644 --- a/docs/exts/drgndoc/util.py +++ b/docs/exts/drgndoc/util.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ from typing import Optional diff --git a/docs/exts/drgndoc/visitor.py b/docs/exts/drgndoc/visitor.py index d2c0cb3ec..e8a5085b4 100644 --- a/docs/exts/drgndoc/visitor.py +++ b/docs/exts/drgndoc/visitor.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import ast diff --git a/drgn/__init__.py b/drgn/__init__.py index 7bf30ba2e..69f87611d 100644 --- a/drgn/__init__.py +++ b/drgn/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/__main__.py b/drgn/__main__.py index f9e207a93..f8898c636 100644 --- a/drgn/__main__.py +++ b/drgn/__main__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/__init__.py b/drgn/helpers/__init__.py index 3321a868f..e60a5683a 100644 --- a/drgn/helpers/__init__.py +++ b/drgn/helpers/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/__init__.py b/drgn/helpers/linux/__init__.py index d8715ce93..cbdd6ee7a 100644 --- a/drgn/helpers/linux/__init__.py +++ b/drgn/helpers/linux/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/block.py b/drgn/helpers/linux/block.py index 1dbee7156..061c8af1c 100644 --- a/drgn/helpers/linux/block.py +++ b/drgn/helpers/linux/block.py @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/bpf.py b/drgn/helpers/linux/bpf.py index 1d9bd1357..291c28cba 100644 --- a/drgn/helpers/linux/bpf.py +++ b/drgn/helpers/linux/bpf.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/cgroup.py b/drgn/helpers/linux/cgroup.py index 6c3d37d06..c492136e0 100644 --- a/drgn/helpers/linux/cgroup.py +++ b/drgn/helpers/linux/cgroup.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/cpumask.py b/drgn/helpers/linux/cpumask.py index d4a003e6b..4d9a55508 100644 --- a/drgn/helpers/linux/cpumask.py +++ b/drgn/helpers/linux/cpumask.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/device.py b/drgn/helpers/linux/device.py index e6bfd14cf..f339ec2d6 100644 --- a/drgn/helpers/linux/device.py +++ b/drgn/helpers/linux/device.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/fs.py b/drgn/helpers/linux/fs.py index dd9741ed5..5d30a7205 100644 --- a/drgn/helpers/linux/fs.py +++ b/drgn/helpers/linux/fs.py @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/idr.py b/drgn/helpers/linux/idr.py index 3cdcd4f76..76bd521c5 100644 --- a/drgn/helpers/linux/idr.py +++ b/drgn/helpers/linux/idr.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/kconfig.py b/drgn/helpers/linux/kconfig.py index 406152297..5baf58b27 100644 --- a/drgn/helpers/linux/kconfig.py +++ b/drgn/helpers/linux/kconfig.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/kernfs.py b/drgn/helpers/linux/kernfs.py index ce795b200..33c68d4a1 100644 --- a/drgn/helpers/linux/kernfs.py +++ b/drgn/helpers/linux/kernfs.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/list.py b/drgn/helpers/linux/list.py index 3c0012678..d29e06f66 100644 --- a/drgn/helpers/linux/list.py +++ b/drgn/helpers/linux/list.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/list_nulls.py b/drgn/helpers/linux/list_nulls.py index 39fa4400e..51a490762 100644 --- a/drgn/helpers/linux/list_nulls.py +++ b/drgn/helpers/linux/list_nulls.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/mm.py b/drgn/helpers/linux/mm.py index 78f64fc65..38d5ed712 100644 --- a/drgn/helpers/linux/mm.py +++ b/drgn/helpers/linux/mm.py @@ -1,4 +1,4 @@ -# Copyright 2018-2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/net.py b/drgn/helpers/linux/net.py index fb01f5a4f..4a8e406e4 100644 --- a/drgn/helpers/linux/net.py +++ b/drgn/helpers/linux/net.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/percpu.py b/drgn/helpers/linux/percpu.py index 896f595a0..1b97d7b3e 100644 --- a/drgn/helpers/linux/percpu.py +++ b/drgn/helpers/linux/percpu.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/pid.py b/drgn/helpers/linux/pid.py index d9c98967b..1ff744f19 100644 --- a/drgn/helpers/linux/pid.py +++ b/drgn/helpers/linux/pid.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/radixtree.py b/drgn/helpers/linux/radixtree.py index 78ef42555..2796c6bbc 100644 --- a/drgn/helpers/linux/radixtree.py +++ b/drgn/helpers/linux/radixtree.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/rbtree.py b/drgn/helpers/linux/rbtree.py index a70555f72..ee33e468b 100644 --- a/drgn/helpers/linux/rbtree.py +++ b/drgn/helpers/linux/rbtree.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/sched.py b/drgn/helpers/linux/sched.py index d746c3a6b..85fdd74e9 100644 --- a/drgn/helpers/linux/sched.py +++ b/drgn/helpers/linux/sched.py @@ -1,4 +1,4 @@ -# Copyright 2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/tcp.py b/drgn/helpers/linux/tcp.py index f1f82e438..63c32ced2 100644 --- a/drgn/helpers/linux/tcp.py +++ b/drgn/helpers/linux/tcp.py @@ -1,3 +1,4 @@ +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/helpers/linux/user.py b/drgn/helpers/linux/user.py index a91555979..d6edfc57e 100644 --- a/drgn/helpers/linux/user.py +++ b/drgn/helpers/linux/user.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/internal/__init__.py b/drgn/internal/__init__.py index 2f38da76c..300b85ebc 100644 --- a/drgn/internal/__init__.py +++ b/drgn/internal/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """ diff --git a/drgn/internal/cli.py b/drgn/internal/cli.py index 3c8fd9d07..de6dd93c3 100644 --- a/drgn/internal/cli.py +++ b/drgn/internal/cli.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """drgn command line interface""" diff --git a/drgn/internal/rlcompleter.py b/drgn/internal/rlcompleter.py index a117ad92e..0684276c2 100644 --- a/drgn/internal/rlcompleter.py +++ b/drgn/internal/rlcompleter.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ """Improved readline completer""" diff --git a/examples/linux/cgroup.py b/examples/linux/cgroup.py index 6859f2a81..3d85bb1d1 100755 --- a/examples/linux/cgroup.py +++ b/examples/linux/cgroup.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + """List the paths of all descendants of a cgroup v2""" import os diff --git a/examples/linux/fs_inodes.py b/examples/linux/fs_inodes.py index fb25a8333..081c6854b 100755 --- a/examples/linux/fs_inodes.py +++ b/examples/linux/fs_inodes.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + """List the paths of all inodes cached in a given filesystem""" from drgn.helpers.linux.fs import for_each_mount, inode_path diff --git a/examples/linux/lsmod.py b/examples/linux/lsmod.py index 3036ab5f5..b7fef922a 100755 --- a/examples/linux/lsmod.py +++ b/examples/linux/lsmod.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + """An implementation of lsmod(8) using drgn""" from drgn.helpers.linux.list import list_for_each_entry diff --git a/examples/linux/ps.py b/examples/linux/ps.py index e5644426d..45adfc7c8 100755 --- a/examples/linux/ps.py +++ b/examples/linux/ps.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + """A simplified implementation of ps(1) using drgn""" from drgn.helpers.linux.pid import for_each_task diff --git a/examples/linux/tcp_sock.py b/examples/linux/tcp_sock.py index 76220c25c..438146908 100755 --- a/examples/linux/tcp_sock.py +++ b/examples/linux/tcp_sock.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + """List all TCP sockets and their cgroup v2 paths""" import ipaddress diff --git a/libdrgn/Makefile.am b/libdrgn/Makefile.am index 0a86f2e28..74a0128ad 100644 --- a/libdrgn/Makefile.am +++ b/libdrgn/Makefile.am @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + ACLOCAL_AMFLAGS = -I m4 SUBDIRS = elfutils include diff --git a/libdrgn/arch_x86_64.c.in b/libdrgn/arch_x86_64.c.in index e0a41ddd1..3ad15b7eb 100644 --- a/libdrgn/arch_x86_64.c.in +++ b/libdrgn/arch_x86_64.c.in @@ -1,5 +1,5 @@ %{ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/binary_search_tree.h b/libdrgn/binary_search_tree.h index 09f261295..0fa378435 100644 --- a/libdrgn/binary_search_tree.h +++ b/libdrgn/binary_search_tree.h @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/build-aux/gen_arch.awk b/libdrgn/build-aux/gen_arch.awk index fcae8f91b..b808c5225 100644 --- a/libdrgn/build-aux/gen_arch.awk +++ b/libdrgn/build-aux/gen_arch.awk @@ -1,4 +1,4 @@ -# Copyright 2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ # This script generates "arch_foo.c" from "arch_foo.c.in". It uses diff --git a/libdrgn/build-aux/gen_constants.py b/libdrgn/build-aux/gen_constants.py index ba5b6b6bd..354ae78f5 100644 --- a/libdrgn/build-aux/gen_constants.py +++ b/libdrgn/build-aux/gen_constants.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import os.path diff --git a/libdrgn/build-aux/gen_drgn_h.awk b/libdrgn/build-aux/gen_drgn_h.awk index 3aa1d41ce..e06690b15 100644 --- a/libdrgn/build-aux/gen_drgn_h.awk +++ b/libdrgn/build-aux/gen_drgn_h.awk @@ -1,4 +1,4 @@ -# Copyright 2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ # This script generates "drgn.h" from "drgn.h.in" and all of the diff --git a/libdrgn/build-aux/parse_arch.awk b/libdrgn/build-aux/parse_arch.awk index 0148fbac8..d23d40a8b 100644 --- a/libdrgn/build-aux/parse_arch.awk +++ b/libdrgn/build-aux/parse_arch.awk @@ -1,4 +1,4 @@ -# Copyright 2019 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ # This script parses the architecture support files in drgn (arch_foo.c.in). diff --git a/libdrgn/cityhash.h b/libdrgn/cityhash.h index c2bb4fb3b..95b2dbf67 100644 --- a/libdrgn/cityhash.h +++ b/libdrgn/cityhash.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_CITYHASH_H diff --git a/libdrgn/configure.ac b/libdrgn/configure.ac index b4ed56c10..e13ea2242 100644 --- a/libdrgn/configure.ac +++ b/libdrgn/configure.ac @@ -1,3 +1,6 @@ +dnl Copyright (c) Facebook, Inc. and its affiliates. +dnl SPDX-License-Identifier: GPL-3.0+ + AC_INIT([drgn], [0.0.4], [https://github.com/osandov/drgn/issues],, [https://github.com/osandov/drgn]) diff --git a/libdrgn/drgn.h.in b/libdrgn/drgn.h.in index da0596139..cc435c46a 100644 --- a/libdrgn/drgn.h.in +++ b/libdrgn/drgn.h.in @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/dwarf_index.c b/libdrgn/dwarf_index.c index 9b0ba5502..92d8798a7 100644 --- a/libdrgn/dwarf_index.c +++ b/libdrgn/dwarf_index.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/dwarf_index.h b/libdrgn/dwarf_index.h index 86e6bdc10..da7a4f9f2 100644 --- a/libdrgn/dwarf_index.h +++ b/libdrgn/dwarf_index.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/dwarf_info_cache.c b/libdrgn/dwarf_info_cache.c index 1a97a3ef1..2292fe5bf 100644 --- a/libdrgn/dwarf_info_cache.c +++ b/libdrgn/dwarf_info_cache.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/dwarf_info_cache.h b/libdrgn/dwarf_info_cache.h index 5b70a92b3..2d8a871c3 100644 --- a/libdrgn/dwarf_info_cache.h +++ b/libdrgn/dwarf_info_cache.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/error.c b/libdrgn/error.c index 08ff1b708..bba0e5432 100644 --- a/libdrgn/error.c +++ b/libdrgn/error.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/error.h b/libdrgn/error.h index de998eb92..fe44b6665 100644 --- a/libdrgn/error.h +++ b/libdrgn/error.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/hash_table.c b/libdrgn/hash_table.c index cc062d46e..1a73c21c3 100644 --- a/libdrgn/hash_table.c +++ b/libdrgn/hash_table.c @@ -1,3 +1,6 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// SPDX-License-Identifier: GPL-3.0+ + #include "hash_table.h" const uint8_t hash_table_empty_chunk_header[16] __attribute__((aligned(16))); diff --git a/libdrgn/hash_table.h b/libdrgn/hash_table.h index 61eb96f79..32652af7f 100644 --- a/libdrgn/hash_table.h +++ b/libdrgn/hash_table.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/helpers.h b/libdrgn/helpers.h index e32882d80..e287d19e4 100644 --- a/libdrgn/helpers.h +++ b/libdrgn/helpers.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/include/Makefile.am b/libdrgn/include/Makefile.am index 56d1e0e60..2afd29229 100644 --- a/libdrgn/include/Makefile.am +++ b/libdrgn/include/Makefile.am @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + # "Install" the elfutils headers to the build directory. BUILT_SOURCES = dwarf.h \ diff --git a/libdrgn/internal.c b/libdrgn/internal.c index 859b28b00..4c2e42aac 100644 --- a/libdrgn/internal.c +++ b/libdrgn/internal.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/internal.h b/libdrgn/internal.h index b16ed2ef4..84fc814d2 100644 --- a/libdrgn/internal.h +++ b/libdrgn/internal.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/language.c b/libdrgn/language.c index ee71aa26f..e6219cd2d 100644 --- a/libdrgn/language.c +++ b/libdrgn/language.c @@ -1,4 +1,4 @@ -// Copyright 2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "internal.h" diff --git a/libdrgn/language.h b/libdrgn/language.h index c63fdb771..9d129dcc1 100644 --- a/libdrgn/language.h +++ b/libdrgn/language.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/language_c.c b/libdrgn/language_c.c index 8d2c49ac9..b74910c8d 100644 --- a/libdrgn/language_c.c +++ b/libdrgn/language_c.c @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/lexer.c b/libdrgn/lexer.c index 1b43b4f87..426f72098 100644 --- a/libdrgn/lexer.c +++ b/libdrgn/lexer.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "internal.h" diff --git a/libdrgn/lexer.h b/libdrgn/lexer.h index cb098e469..62511e8a8 100644 --- a/libdrgn/lexer.h +++ b/libdrgn/lexer.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/linux_kernel.c b/libdrgn/linux_kernel.c index 4f7801894..8499bd031 100644 --- a/libdrgn/linux_kernel.c +++ b/libdrgn/linux_kernel.c @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/linux_kernel.h b/libdrgn/linux_kernel.h index 6bb3b5751..f765fbe7c 100644 --- a/libdrgn/linux_kernel.h +++ b/libdrgn/linux_kernel.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_LINUX_KERNEL_H diff --git a/libdrgn/linux_kernel_helpers.c b/libdrgn/linux_kernel_helpers.c index 2365d88cf..dedaed776 100644 --- a/libdrgn/linux_kernel_helpers.c +++ b/libdrgn/linux_kernel_helpers.c @@ -1,4 +1,4 @@ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/memory_reader.c b/libdrgn/memory_reader.c index b368fb8e7..48682c3ce 100644 --- a/libdrgn/memory_reader.c +++ b/libdrgn/memory_reader.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/memory_reader.h b/libdrgn/memory_reader.h index f8cca1fb1..f6d94a332 100644 --- a/libdrgn/memory_reader.h +++ b/libdrgn/memory_reader.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/object.c b/libdrgn/object.c index 330f96ae9..5361dedee 100644 --- a/libdrgn/object.c +++ b/libdrgn/object.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/object.h b/libdrgn/object.h index 5b80b5fcf..ca9b3c580 100644 --- a/libdrgn/object.h +++ b/libdrgn/object.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/object_index.c b/libdrgn/object_index.c index 46cebf123..68f069b0c 100644 --- a/libdrgn/object_index.c +++ b/libdrgn/object_index.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/object_index.h b/libdrgn/object_index.h index 5e54bf5d3..fcd384795 100644 --- a/libdrgn/object_index.h +++ b/libdrgn/object_index.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/path.c b/libdrgn/path.c index aa78cd3fa..6aa5ed690 100644 --- a/libdrgn/path.c +++ b/libdrgn/path.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/platform.c b/libdrgn/platform.c index edaed554f..a2ba6df37 100644 --- a/libdrgn/platform.c +++ b/libdrgn/platform.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/platform.h b/libdrgn/platform.h index bc7f7d206..f0f885722 100644 --- a/libdrgn/platform.h +++ b/libdrgn/platform.h @@ -1,4 +1,4 @@ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_PLATFORM_H diff --git a/libdrgn/program.c b/libdrgn/program.c index b8a23b902..968b49610 100644 --- a/libdrgn/program.c +++ b/libdrgn/program.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/program.h b/libdrgn/program.h index ac1602dbb..58cce0d15 100644 --- a/libdrgn/program.h +++ b/libdrgn/program.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/python/drgnpy.h b/libdrgn/python/drgnpy.h index e916f61cf..96c7d303a 100644 --- a/libdrgn/python/drgnpy.h +++ b/libdrgn/python/drgnpy.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGNPY_H diff --git a/libdrgn/python/error.c b/libdrgn/python/error.c index 8116fd27a..dedb40898 100644 --- a/libdrgn/python/error.c +++ b/libdrgn/python/error.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/helpers.c b/libdrgn/python/helpers.c index 189831bf7..805255066 100644 --- a/libdrgn/python/helpers.c +++ b/libdrgn/python/helpers.c @@ -1,4 +1,4 @@ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/language.c b/libdrgn/python/language.c index d5b9b6e76..b677215a2 100644 --- a/libdrgn/python/language.c +++ b/libdrgn/python/language.c @@ -1,4 +1,4 @@ -// Copyright 2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/module.c b/libdrgn/python/module.c index 981c1aed1..92d5185f4 100644 --- a/libdrgn/python/module.c +++ b/libdrgn/python/module.c @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/object.c b/libdrgn/python/object.c index 99b4b7833..4c4e967cc 100644 --- a/libdrgn/python/object.c +++ b/libdrgn/python/object.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/python/platform.c b/libdrgn/python/platform.c index 281ac1b09..43a7c39da 100644 --- a/libdrgn/python/platform.c +++ b/libdrgn/python/platform.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/program.c b/libdrgn/python/program.c index 5d4ad9b92..bcd0d0959 100644 --- a/libdrgn/python/program.c +++ b/libdrgn/python/program.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/stack_trace.c b/libdrgn/python/stack_trace.c index 21bf3a411..6653311e9 100644 --- a/libdrgn/python/stack_trace.c +++ b/libdrgn/python/stack_trace.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/symbol.c b/libdrgn/python/symbol.c index 77ea47d66..8fc2bfa26 100644 --- a/libdrgn/python/symbol.c +++ b/libdrgn/python/symbol.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/test.c b/libdrgn/python/test.c index 24af51df8..2077a31ed 100644 --- a/libdrgn/python/test.c +++ b/libdrgn/python/test.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /* diff --git a/libdrgn/python/type.c b/libdrgn/python/type.c index 893b64943..649dcfff2 100644 --- a/libdrgn/python/type.c +++ b/libdrgn/python/type.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/python/util.c b/libdrgn/python/util.c index d0dfb2c5c..aa419c4bb 100644 --- a/libdrgn/python/util.c +++ b/libdrgn/python/util.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" diff --git a/libdrgn/read.h b/libdrgn/read.h index 9f0231e93..7b9b16ff5 100644 --- a/libdrgn/read.h +++ b/libdrgn/read.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/serialize.c b/libdrgn/serialize.c index 9b739599a..91cfa0f35 100644 --- a/libdrgn/serialize.c +++ b/libdrgn/serialize.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/serialize.h b/libdrgn/serialize.h index b22434c93..43ed0453f 100644 --- a/libdrgn/serialize.h +++ b/libdrgn/serialize.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/siphash.h b/libdrgn/siphash.h index 997718d3d..fd522d521 100644 --- a/libdrgn/siphash.h +++ b/libdrgn/siphash.h @@ -1,4 +1,4 @@ -// Copyright 2018 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_SIPHASH_H diff --git a/libdrgn/splay_tree.c b/libdrgn/splay_tree.c index f10e0dd7c..7b216fc73 100644 --- a/libdrgn/splay_tree.c +++ b/libdrgn/splay_tree.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "binary_search_tree.h" diff --git a/libdrgn/stack_trace.c b/libdrgn/stack_trace.c index 771009e53..8fe641cb8 100644 --- a/libdrgn/stack_trace.c +++ b/libdrgn/stack_trace.c @@ -1,4 +1,4 @@ -// Copyright 2019-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/string_builder.c b/libdrgn/string_builder.c index a738e8878..1fbf86b3c 100644 --- a/libdrgn/string_builder.c +++ b/libdrgn/string_builder.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/string_builder.h b/libdrgn/string_builder.h index cfdb194db..a517c0686 100644 --- a/libdrgn/string_builder.h +++ b/libdrgn/string_builder.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/symbol.c b/libdrgn/symbol.c index 37d092d4a..369452c21 100644 --- a/libdrgn/symbol.c +++ b/libdrgn/symbol.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/symbol.h b/libdrgn/symbol.h index c57997839..f6cf4ddb5 100644 --- a/libdrgn/symbol.h +++ b/libdrgn/symbol.h @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_SYMBOL_H diff --git a/libdrgn/type.c b/libdrgn/type.c index aa07da60b..f09f0b104 100644 --- a/libdrgn/type.c +++ b/libdrgn/type.c @@ -1,3 +1,6 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// SPDX-License-Identifier: GPL-3.0+ + #include #include "internal.h" diff --git a/libdrgn/type.h b/libdrgn/type.h index 46c451e61..4acae99e2 100644 --- a/libdrgn/type.h +++ b/libdrgn/type.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/type_index.c b/libdrgn/type_index.c index c9f5ce49a..5b5113fef 100644 --- a/libdrgn/type_index.c +++ b/libdrgn/type_index.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include diff --git a/libdrgn/type_index.h b/libdrgn/type_index.h index 8bfc5b813..46425ac2f 100644 --- a/libdrgn/type_index.h +++ b/libdrgn/type_index.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/util.h b/libdrgn/util.h index 7a756d7b9..085999bdd 100644 --- a/libdrgn/util.h +++ b/libdrgn/util.h @@ -1,4 +1,4 @@ -// Copyright 2018-2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/libdrgn/vector.c b/libdrgn/vector.c index 2eefa6696..573a10c0e 100644 --- a/libdrgn/vector.c +++ b/libdrgn/vector.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ #include "vector.h" diff --git a/libdrgn/vector.h b/libdrgn/vector.h index 3261885f9..3e3a96b0a 100644 --- a/libdrgn/vector.h +++ b/libdrgn/vector.h @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /** diff --git a/scripts/generate_dwarf_constants.py b/scripts/generate_dwarf_constants.py index 09dd9c88c..ae62a6300 100755 --- a/scripts/generate_dwarf_constants.py +++ b/scripts/generate_dwarf_constants.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ import keyword import re diff --git a/scripts/generate_primitive_type_spellings.py b/scripts/generate_primitive_type_spellings.py index e755b94f3..03b943dad 100755 --- a/scripts/generate_primitive_type_spellings.py +++ b/scripts/generate_primitive_type_spellings.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ import itertools import sys diff --git a/scripts/test_cityhash.c b/scripts/test_cityhash.c index bd2a79869..3f9d2ebed 100644 --- a/scripts/test_cityhash.c +++ b/scripts/test_cityhash.c @@ -1,3 +1,6 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// SPDX-License-Identifier: GPL-3.0+ + #include #include diff --git a/scripts/test_siphash.c b/scripts/test_siphash.c index f070f0264..f84ac8bdf 100644 --- a/scripts/test_siphash.c +++ b/scripts/test_siphash.c @@ -1,3 +1,6 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// SPDX-License-Identifier: GPL-3.0+ + #include #include #include diff --git a/scripts/update-elfutils.sh b/scripts/update-elfutils.sh index 013f788d6..bc9029055 100755 --- a/scripts/update-elfutils.sh +++ b/scripts/update-elfutils.sh @@ -1,4 +1,6 @@ #!/bin/sh +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ # drgn depends heavily on elfutils. In particular, we need a recent version, # potentially with some patches that may not be released or even merged yet. We diff --git a/setup.py b/setup.py index 143a2466e..2b21b9183 100755 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ import contextlib from distutils import log diff --git a/tests/__init__.py b/tests/__init__.py index 2b2b523c3..96d7366ca 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import functools from typing import Any, NamedTuple, Optional import unittest diff --git a/tests/dwarfwriter.py b/tests/dwarfwriter.py index f87255dac..8073d0ed9 100644 --- a/tests/dwarfwriter.py +++ b/tests/dwarfwriter.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + from collections import namedtuple import os.path diff --git a/tests/elf.py b/tests/elf.py index 26ac9614a..8a99f5ca9 100644 --- a/tests/elf.py +++ b/tests/elf.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import enum diff --git a/tests/elfwriter.py b/tests/elfwriter.py index 56f90b5f9..b96246eb7 100644 --- a/tests/elfwriter.py +++ b/tests/elfwriter.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import struct from typing import Optional, Sequence diff --git a/tests/helpers/linux/__init__.py b/tests/helpers/linux/__init__.py index b0f96f3a4..42abe34d3 100644 --- a/tests/helpers/linux/__init__.py +++ b/tests/helpers/linux/__init__.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import ctypes import errno import os diff --git a/tests/helpers/linux/test_block.py b/tests/helpers/linux/test_block.py index 9666c1163..b77b77b5e 100644 --- a/tests/helpers/linux/test_block.py +++ b/tests/helpers/linux/test_block.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import errno from fcntl import ioctl import os diff --git a/tests/helpers/linux/test_cgroup.py b/tests/helpers/linux/test_cgroup.py index ed4ee5712..686657af1 100644 --- a/tests/helpers/linux/test_cgroup.py +++ b/tests/helpers/linux/test_cgroup.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os diff --git a/tests/helpers/linux/test_fs.py b/tests/helpers/linux/test_fs.py index 4fbad7076..dbcccb394 100644 --- a/tests/helpers/linux/test_fs.py +++ b/tests/helpers/linux/test_fs.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os import os.path import tempfile diff --git a/tests/helpers/linux/test_kconfig.py b/tests/helpers/linux/test_kconfig.py index 2992140bf..83d0d80ac 100644 --- a/tests/helpers/linux/test_kconfig.py +++ b/tests/helpers/linux/test_kconfig.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os.path from drgn.helpers.linux.kconfig import get_kconfig diff --git a/tests/helpers/linux/test_kernfs.py b/tests/helpers/linux/test_kernfs.py index 5c3d63721..4ceaf0178 100644 --- a/tests/helpers/linux/test_kernfs.py +++ b/tests/helpers/linux/test_kernfs.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os from drgn import cast diff --git a/tests/helpers/linux/test_mm.py b/tests/helpers/linux/test_mm.py index 7227915a1..edd8dca89 100644 --- a/tests/helpers/linux/test_mm.py +++ b/tests/helpers/linux/test_mm.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import contextlib import ctypes import mmap diff --git a/tests/helpers/linux/test_net.py b/tests/helpers/linux/test_net.py index b20dc8025..ff909a139 100644 --- a/tests/helpers/linux/test_net.py +++ b/tests/helpers/linux/test_net.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os from drgn import cast diff --git a/tests/helpers/linux/test_pid.py b/tests/helpers/linux/test_pid.py index cbd3e9a8f..7fe870ed5 100644 --- a/tests/helpers/linux/test_pid.py +++ b/tests/helpers/linux/test_pid.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os from drgn.helpers.linux.pid import ( diff --git a/tests/helpers/linux/test_sched.py b/tests/helpers/linux/test_sched.py index edff69439..37f9ac84b 100644 --- a/tests/helpers/linux/test_sched.py +++ b/tests/helpers/linux/test_sched.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os import re import signal diff --git a/tests/helpers/linux/test_stack_trace.py b/tests/helpers/linux/test_stack_trace.py index 88e3e5026..44481e42e 100644 --- a/tests/helpers/linux/test_stack_trace.py +++ b/tests/helpers/linux/test_stack_trace.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os import signal diff --git a/tests/helpers/linux/test_tcp.py b/tests/helpers/linux/test_tcp.py index 5e2877c1c..e8fa2056e 100644 --- a/tests/helpers/linux/test_tcp.py +++ b/tests/helpers/linux/test_tcp.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os import socket diff --git a/tests/helpers/linux/test_user.py b/tests/helpers/linux/test_user.py index 021056b7a..47a9c0555 100644 --- a/tests/helpers/linux/test_user.py +++ b/tests/helpers/linux/test_user.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import functools import os import signal diff --git a/tests/helpers/linux/test_uts.py b/tests/helpers/linux/test_uts.py index adb3804df..033262ef0 100644 --- a/tests/helpers/linux/test_uts.py +++ b/tests/helpers/linux/test_uts.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os import drgn diff --git a/tests/libdrgn.py b/tests/libdrgn.py index 1b6b49df2..8138a945f 100644 --- a/tests/libdrgn.py +++ b/tests/libdrgn.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import ctypes import enum from enum import auto diff --git a/tests/test_docs.py b/tests/test_docs.py index 0cbeeb694..1288cf112 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import pydoc import unittest diff --git a/tests/test_dwarf.py b/tests/test_dwarf.py index acf43610a..27527bdb5 100644 --- a/tests/test_dwarf.py +++ b/tests/test_dwarf.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import os.path import re import tempfile diff --git a/tests/test_language_c.py b/tests/test_language_c.py index 07077bda2..3aee580a3 100644 --- a/tests/test_language_c.py +++ b/tests/test_language_c.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + from functools import reduce import operator import unittest diff --git a/tests/test_lexer.py b/tests/test_lexer.py index ea62914d9..c2ff473b7 100644 --- a/tests/test_lexer.py +++ b/tests/test_lexer.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import unittest from tests.libdrgn import drgn_test_lexer_func, Lexer diff --git a/tests/test_object.py b/tests/test_object.py index 6121cfbb9..0b8b719a3 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import math import operator import struct diff --git a/tests/test_path.py b/tests/test_path.py index 50edb6d55..e3c0a7b9d 100644 --- a/tests/test_path.py +++ b/tests/test_path.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import itertools import os.path import unittest diff --git a/tests/test_platform.py b/tests/test_platform.py index 58b7a87cf..2ddaea11f 100644 --- a/tests/test_platform.py +++ b/tests/test_platform.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import unittest from drgn import Architecture, Platform, PlatformFlags diff --git a/tests/test_program.py b/tests/test_program.py index 090fad079..2399114d3 100644 --- a/tests/test_program.py +++ b/tests/test_program.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import ctypes import itertools import os diff --git a/tests/test_python.py b/tests/test_python.py index d881eda8f..44efd6af1 100644 --- a/tests/test_python.py +++ b/tests/test_python.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import _drgn import drgn import unittest diff --git a/tests/test_serialize.py b/tests/test_serialize.py index 7840237d0..04ae95023 100644 --- a/tests/test_serialize.py +++ b/tests/test_serialize.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import unittest from tests.libdrgn import deserialize_bits, serialize_bits diff --git a/tests/test_type.py b/tests/test_type.py index c7986eaa3..31a389b4a 100644 --- a/tests/test_type.py +++ b/tests/test_type.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + import unittest from drgn import ( diff --git a/tests/test_util.py b/tests/test_util.py index bf5cef82f..a88e4761b 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -1,3 +1,6 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# SPDX-License-Identifier: GPL-3.0+ + from functools import cmp_to_key import unittest diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py index c4ac6c1d0..8fd5f986e 100755 --- a/tools/bpf_inspect.py +++ b/tools/bpf_inspect.py @@ -1,7 +1,6 @@ #!/usr/bin/env drgn +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ -# -# Copyright (c) 2020 Facebook DESCRIPTION = """ drgn script to list BPF programs or maps and their properties diff --git a/util.py b/util.py index 982bd9553..4ac7ab051 100644 --- a/util.py +++ b/util.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ from functools import total_ordering diff --git a/vmtest/manage.py b/vmtest/manage.py index 7b121f14e..10058bba9 100644 --- a/vmtest/manage.py +++ b/vmtest/manage.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import aiohttp diff --git a/vmtest/onoatimehack.c b/vmtest/onoatimehack.c index 3d65f51cf..dd5c4fa82 100644 --- a/vmtest/onoatimehack.c +++ b/vmtest/onoatimehack.c @@ -1,4 +1,4 @@ -// Copyright 2020 - Omar Sandoval +// Copyright (c) Facebook, Inc. and its affiliates. // SPDX-License-Identifier: GPL-3.0+ /* diff --git a/vmtest/resolver.py b/vmtest/resolver.py index bf2f8fa84..ffa862ea7 100644 --- a/vmtest/resolver.py +++ b/vmtest/resolver.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import fnmatch diff --git a/vmtest/vm.py b/vmtest/vm.py index 569457f25..de1d7e690 100644 --- a/vmtest/vm.py +++ b/vmtest/vm.py @@ -1,4 +1,4 @@ -# Copyright 2020 - Omar Sandoval +# Copyright (c) Facebook, Inc. and its affiliates. # SPDX-License-Identifier: GPL-3.0+ import errno From 1cc771605d2ca00ed70943b87ebed1a0a63e159c Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Fri, 15 May 2020 15:19:11 -0700 Subject: [PATCH 2/8] tests: run black on stray change --- tests/test_program.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_program.py b/tests/test_program.py index 2399114d3..52c32f4ef 100644 --- a/tests/test_program.py +++ b/tests/test_program.py @@ -164,8 +164,7 @@ def test_read_unsigned(self): self.assertEqual(prog.read_word(0xA0, True), value) prog = mock_program( - MOCK_32BIT_PLATFORM, - segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0)], + MOCK_32BIT_PLATFORM, segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0)], ) def test_bad_address(self): From ab876f3dbd3c50f56d3c8f79ad3837318ea5c487 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Fri, 15 May 2020 15:32:25 -0700 Subject: [PATCH 3/8] libdrgn/python: allow specifying Object value positionally It's annoying to have to do value= when creating objects, especially in interactive mode. Let's allow passing in the value positionally so that `Object(prog, "int", value=0)` becomes `Object(prog, "int", 0)`. It's clear enough that this is creating an int with value 0. --- _drgn.pyi | 10 +++++----- libdrgn/python/object.c | 2 +- tests/test_object.py | 12 ++++++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/_drgn.pyi b/_drgn.pyi index 94f33106f..2d9de196f 100644 --- a/_drgn.pyi +++ b/_drgn.pyi @@ -611,14 +611,14 @@ class Object: language. For example, adding two objects from a program written in C results in an object with a type and value according to the rules of C: - >>> Object(prog, 'unsigned long', value=2**64 - 1) + Object(prog, 'int', value=1) + >>> Object(prog, 'unsigned long', 2**64 - 1) + Object(prog, 'int', 1) Object(prog, 'unsigned long', value=0) If only one operand to a binary operator is an object, the other operand will be converted to an object according to the language's rules for literals: - >>> Object(prog, 'char', value=0) - 1 + >>> Object(prog, 'char', 0) - 1 Object(prog, 'int', value=-1) The standard :class:`int() `, :class:`float() `, and @@ -640,9 +640,9 @@ class Object: :param prog: The program to create this object in. :param type: The type of the object. If omitted, this is deduced from *value* according to the language's rules for literals. + :param value: The value of this object. See :meth:`value_()`. :param address: The address of this object in the program. Either this or *value* must be given, but not both. - :param value: The value of this object. See :meth:`value_()`. :param byteorder: Byte order of the object. This should be ``'little'`` or ``'big'``. The default is ``None``, which indicates the program byte order. This must be ``None`` for primitive values. @@ -657,9 +657,9 @@ class Object: self, prog: Program, type: Union[str, Type, None] = None, + value: Any = None, *, address: Optional[int] = None, - value: Any = None, byteorder: Optional[str] = None, bit_offset: Optional[int] = None, bit_field_size: Optional[int] = None, @@ -935,7 +935,7 @@ def NULL(prog: Program, type: Union[str, Type]) -> Object: """ Get an object representing ``NULL`` casted to the given type. - This is equivalent to ``Object(prog, type, value=0)``. + This is equivalent to ``Object(prog, type, 0)``. :param prog: The program. :param type: The type. diff --git a/libdrgn/python/object.c b/libdrgn/python/object.c index 4c4e967cc..2b5e9506d 100644 --- a/libdrgn/python/object.c +++ b/libdrgn/python/object.c @@ -412,7 +412,7 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) struct index_arg bit_field_size = { .allow_none = true, .is_none = true }; struct drgn_qualified_type qualified_type; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O$OO&O&O&O&:Object", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OO$O&O&O&O&:Object", keywords, &Program_type, &prog, &type_obj, &value_obj, index_converter, &address, byteorder_converter, diff --git a/tests/test_object.py b/tests/test_object.py index 0b8b719a3..068922416 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -80,6 +80,15 @@ def test_address_xor_value(self): self.prog, "int", ) + self.assertRaisesRegex( + ValueError, + "object cannot have address and value", + Object, + self.prog, + "int", + 0, + address=0, + ) self.assertRaisesRegex( ValueError, "object cannot have address and value", @@ -373,6 +382,9 @@ def test_incomplete(self): class TestValue(ObjectTestCase): + def test_positional(self): + self.assertEqual(Object(self.prog, "int", 1), Object(self.prog, "int", value=1)) + def test_signed(self): obj = Object(self.prog, "int", value=-4) self.assertIs(obj.prog_, self.prog) From 971a2d3687a93bd685d4dabf6613292c653f54cc Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Mon, 18 May 2020 00:03:15 -0700 Subject: [PATCH 4/8] libdrgn/python: make Objects fully immutable The model has always been that drgn Objects are immutable, but for some reason I went through the trouble of allowing __init__() to reinitialize an already initialized Object. Instead, let's fully initialize the Object in __new__() and get rid of __init__(). --- libdrgn/python/object.c | 112 +++++++++++++++++----------------------- tests/test_object.py | 10 ---- 2 files changed, 47 insertions(+), 75 deletions(-) diff --git a/libdrgn/python/object.c b/libdrgn/python/object.c index 2b5e9506d..117c99c61 100644 --- a/libdrgn/python/object.c +++ b/libdrgn/python/object.c @@ -9,32 +9,6 @@ #include "../serialize.h" #include "../type.h" -static DrgnObject *DrgnObject_new(PyTypeObject *subtype, PyObject *args, - PyObject *kwds) -{ - PyObject *arg; - - if (PyTuple_GET_SIZE(args) < 1) { - PyErr_SetString(PyExc_TypeError, - "Object() missing required argument 'prog' (pos 1)"); - return NULL; - } - arg = PyTuple_GET_ITEM(args, 0); - if (!PyObject_TypeCheck(arg, &Program_type)) { - PyErr_SetString(PyExc_TypeError, - "Object() argument 1 must be Program"); - return NULL; - } - return DrgnObject_alloc((Program *)arg); -} - -static void DrgnObject_dealloc(DrgnObject *self) -{ - Py_DECREF(DrgnObject_prog(self)); - drgn_object_deinit(&self->obj); - Py_TYPE(self)->tp_free((PyObject *)self); -} - static int DrgnObject_literal(struct drgn_object *res, PyObject *literal) { struct drgn_error *err; @@ -393,7 +367,8 @@ static int buffer_object_from_value(struct drgn_object *res, return 0; } -static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) +static DrgnObject *DrgnObject_new(PyTypeObject *subtype, PyObject *args, + PyObject *kwds) { static char *keywords[] = { "prog", "type", "value", "address", "byteorder", @@ -411,6 +386,7 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) struct index_arg bit_offset = { .allow_none = true, .is_none = true }; struct index_arg bit_field_size = { .allow_none = true, .is_none = true }; struct drgn_qualified_type qualified_type; + DrgnObject *obj; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OO$O&O&O&O&:Object", keywords, &Program_type, &prog, @@ -419,36 +395,32 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) &byteorder, index_converter, &bit_offset, index_converter, &bit_field_size)) - return -1; - - if (&prog->prog != self->obj.prog) { - PyErr_SetString(PyExc_ValueError, - "cannot change object program"); - return -1; - } + return NULL; - if (Program_type_arg(DrgnObject_prog(self), type_obj, true, - &qualified_type) == -1) - return -1; + if (Program_type_arg(prog, type_obj, true, &qualified_type) == -1) + return NULL; if (!bit_field_size.is_none && bit_field_size.uvalue == 0) { PyErr_SetString(PyExc_ValueError, "bit field size cannot be zero"); - return -1; + return NULL; } + obj = DrgnObject_alloc(prog); + if (!obj) + return NULL; if (!address.is_none && value_obj != Py_None) { PyErr_SetString(PyExc_ValueError, "object cannot have address and value"); - return -1; + goto err; } else if (!address.is_none) { if (!qualified_type.type) { PyErr_SetString(PyExc_ValueError, "reference must have type"); - return -1; + goto err; } - err = drgn_object_set_reference(&self->obj, qualified_type, + err = drgn_object_set_reference(&obj->obj, qualified_type, address.uvalue, bit_offset.uvalue, bit_field_size.uvalue, @@ -459,27 +431,27 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) if (!byteorder.is_none) { PyErr_SetString(PyExc_ValueError, "literal cannot have byteorder"); - return -1; + goto err; } if (!bit_offset.is_none) { PyErr_SetString(PyExc_ValueError, "literal cannot have bit offset"); - return -1; + goto err; } if (!bit_field_size.is_none) { PyErr_SetString(PyExc_ValueError, "literal cannot be bit field"); - return -1; + goto err; } - ret = DrgnObject_literal(&self->obj, value_obj); + ret = DrgnObject_literal(&obj->obj, value_obj); if (ret == -1) { - return -1; + goto err; } else if (ret) { PyErr_Format(PyExc_TypeError, "cannot create %s literal", Py_TYPE(value_obj)->tp_name); - return -1; + goto err; } err = NULL; } else if (value_obj != Py_None) { @@ -490,35 +462,35 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) err = drgn_error_incomplete_type("cannot create object with %s type", qualified_type.type); set_drgn_error(err); - return -1; + goto err; } if (!bit_field_size.is_none && kind != DRGN_OBJECT_SIGNED && kind != DRGN_OBJECT_UNSIGNED) { PyErr_SetString(PyExc_ValueError, "bit field must be integer"); - return -1; + goto err; } if (kind != DRGN_OBJECT_BUFFER) { if (!byteorder.is_none) { PyErr_SetString(PyExc_ValueError, "primitive value cannot have byteorder"); - return -1; + goto err; } if (!bit_offset.is_none) { PyErr_SetString(PyExc_ValueError, "primitive value cannot have bit offset"); - return -1; + goto err; } } switch (kind) { case DRGN_OBJECT_BUFFER: - if (buffer_object_from_value(&self->obj, qualified_type, + if (buffer_object_from_value(&obj->obj, qualified_type, value_obj, bit_offset.uvalue, byteorder.value) == -1) - return -1; + goto err; err = NULL; break; case DRGN_OBJECT_SIGNED: @@ -532,23 +504,23 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) if (!PyNumber_Check(value_obj)) { set_error_type_name("'%s' value must be number", qualified_type); - return -1; + goto err; } long_obj = PyNumber_Long(value_obj); if (!long_obj) - return -1; + goto err; tmp.uvalue = PyLong_AsUnsignedLongLongMask(long_obj); Py_DECREF(long_obj); if (tmp.uvalue == (unsigned long long)-1 && PyErr_Occurred()) - return -1; + goto err; if (kind == DRGN_OBJECT_SIGNED) { - err = drgn_object_set_signed(&self->obj, + err = drgn_object_set_signed(&obj->obj, qualified_type, tmp.svalue, bit_field_size.uvalue); } else { - err = drgn_object_set_unsigned(&self->obj, + err = drgn_object_set_unsigned(&obj->obj, qualified_type, tmp.uvalue, bit_field_size.uvalue); @@ -561,12 +533,12 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) if (!PyNumber_Check(value_obj)) { set_error_type_name("'%s' value must be number", qualified_type); - return -1; + goto err; } fvalue = PyFloat_AsDouble(value_obj); if (fvalue == -1.0 && PyErr_Occurred()) - return -1; - err = drgn_object_set_float(&self->obj, qualified_type, + goto err; + err = drgn_object_set_float(&obj->obj, qualified_type, fvalue); break; } @@ -576,13 +548,24 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) } else { PyErr_SetString(PyExc_ValueError, "object must have either address or value"); - return -1; + goto err; } if (err) { set_drgn_error(err); - return -1; + goto err; } - return 0; + return obj; + +err: + Py_DECREF(obj); + return NULL; +} + +static void DrgnObject_dealloc(DrgnObject *self) +{ + Py_DECREF(DrgnObject_prog(self)); + drgn_object_deinit(&self->obj); + Py_TYPE(self)->tp_free((PyObject *)self); } static PyObject *DrgnObject_value_impl(struct drgn_object *obj); @@ -1743,7 +1726,6 @@ PyTypeObject DrgnObject_type = { .tp_iter = (getiterfunc)DrgnObject_iter, .tp_methods = DrgnObject_methods, .tp_getset = DrgnObject_getset, - .tp_init = (initproc)DrgnObject_init, .tp_new = (newfunc)DrgnObject_new, }; diff --git a/tests/test_object.py b/tests/test_object.py index 068922416..c07dce858 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -42,16 +42,6 @@ class TestInit(ObjectTestCase): - def test_reinit(self): - obj = Object(self.prog, "int", value=1) - self.assertEqual(obj.value_(), 1) - obj.__init__(self.prog, value=2) - self.assertEqual(obj.value_(), 2) - prog = mock_program() - self.assertRaisesRegex( - ValueError, "cannot change object program", obj.__init__, prog, value=3 - ) - def test_type_stays_alive(self): obj = Object(self.prog, int_type("int", 4, True), value=0) self.assertEqual(obj.type_, int_type("int", 4, True)) From 4d8597f0f8f15b9fe68c3f21cd88c1377e1846ff Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Tue, 19 May 2020 17:09:00 -0700 Subject: [PATCH 5/8] libdrgn: add THREAD_SIZE to Linux kernel object finder Despite the naming, this is the kernel stack size. --- libdrgn/linux_kernel.c | 41 +++++++++++++++++++++++++++++++ libdrgn/program.h | 2 ++ tests/helpers/linux/test_sched.py | 16 ++++++++++++ 3 files changed, 59 insertions(+) diff --git a/libdrgn/linux_kernel.c b/libdrgn/linux_kernel.c index 8499bd031..5c97643d0 100644 --- a/libdrgn/linux_kernel.c +++ b/libdrgn/linux_kernel.c @@ -234,6 +234,33 @@ struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, return err; } +static struct drgn_error * +linux_kernel_get_thread_size(struct drgn_program *prog, uint64_t *ret) +{ + struct drgn_error *err; + struct drgn_qualified_type thread_union_type; + struct drgn_member_info stack_member; + + if (!prog->thread_size) { + err = drgn_program_find_type(prog, "union thread_union", NULL, + &thread_union_type); + if (err) + return err; + err = drgn_program_member_info(prog, thread_union_type.type, + "stack", &stack_member); + if (err) + return err; + err = drgn_type_sizeof(stack_member.qualified_type.type, + &prog->thread_size); + if (err) { + prog->thread_size = 0; + return err; + } + } + *ret = prog->thread_size; + return NULL; +} + struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len, const char *filename, enum drgn_find_object_flags flags, @@ -296,6 +323,20 @@ struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len, return drgn_object_set_unsigned(ret, qualified_type, ~(prog->vmcoreinfo.page_size - 1), 0); + } else if (name_len == strlen("THREAD_SIZE") && + memcmp(name, "THREAD_SIZE", name_len) == 0) { + uint64_t thread_size; + + err = linux_kernel_get_thread_size(prog, &thread_size); + if (err) + return err; + err = drgn_type_index_find_primitive(&prog->tindex, + DRGN_C_TYPE_UNSIGNED_LONG, + &qualified_type.type); + if (err) + return err; + return drgn_object_set_unsigned(ret, qualified_type, + thread_size, 0); } else if (name_len == strlen("UTS_RELEASE") && memcmp(name, "UTS_RELEASE", name_len) == 0) { size_t len; diff --git a/libdrgn/program.h b/libdrgn/program.h index 58cce0d15..fad8139de 100644 --- a/libdrgn/program.h +++ b/libdrgn/program.h @@ -74,6 +74,8 @@ struct drgn_program { uint64_t page_offset; /* Cached vmemmap. */ uint64_t vmemmap; + /* Cached THREAD_SIZE. */ + uint64_t thread_size; #ifdef WITH_LIBKDUMPFILE kdump_ctx_t *kdump_ctx; #endif diff --git a/tests/helpers/linux/test_sched.py b/tests/helpers/linux/test_sched.py index 37f9ac84b..548b4c498 100644 --- a/tests/helpers/linux/test_sched.py +++ b/tests/helpers/linux/test_sched.py @@ -15,6 +15,10 @@ ) +def is_power_of_two(n): + return n != 0 and (n & (n - 1)) == 0 + + class TestSched(LinuxHelperTestCase): def test_task_state_to_char(self): task = find_task(self.prog, os.getpid()) @@ -35,3 +39,15 @@ def test_task_state_to_char(self): self.assertEqual(task_state_to_char(task), "Z") os.waitpid(pid, 0) + + def test_thread_size(self): + # As far as I can tell, there's no way to query this value from + # userspace, so at least sanity check that it's a power-of-two multiple + # of the page size and that we can read the entire stack. + thread_size = self.prog["THREAD_SIZE"].value_() + page_size = self.prog["PAGE_SIZE"].value_() + self.assertEqual(thread_size % page_size, 0) + self.assertTrue(is_power_of_two(thread_size // page_size)) + + task = find_task(self.prog, os.getpid()) + self.prog.read(task.stack, thread_size) From 146930aff81dbdc2790339722e0c40e57d23f2bd Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Tue, 19 May 2020 13:28:49 -0700 Subject: [PATCH 6/8] libdrgn: replace arch frame_registers with callbacks We currently unwind from pt_regs and NT_PRSTATUS using an array of register definitions. It's more flexible and more efficient to do this with an architecture-specific callback. For x86-64, this change also makes us depend on the binary layout rather than member names of struct pt_regs, but that shouldn't matter unless people are defining their own, weird struct pt_regs. --- libdrgn/arch_x86_64.c.in | 93 ++++++++++++++++++++++------- libdrgn/platform.h | 20 +++---- libdrgn/stack_trace.c | 126 +++++++-------------------------------- 3 files changed, 99 insertions(+), 140 deletions(-) diff --git a/libdrgn/arch_x86_64.c.in b/libdrgn/arch_x86_64.c.in index 3ad15b7eb..0ba061755 100644 --- a/libdrgn/arch_x86_64.c.in +++ b/libdrgn/arch_x86_64.c.in @@ -107,25 +107,76 @@ bnd2 bnd3 %% -static const struct drgn_frame_register frame_registers_x86_64[] = { - { DRGN_REGISTER_X86_64_rax, 8, 192, "ax", "rax", }, - { DRGN_REGISTER_X86_64_rdx, 8, 208, "dx", "rdx", }, - { DRGN_REGISTER_X86_64_rcx, 8, 200, "cx", "rcx", }, - { DRGN_REGISTER_X86_64_rbx, 8, 152, "bx", "rbx", }, - { DRGN_REGISTER_X86_64_rsi, 8, 216, "si", "rsi", }, - { DRGN_REGISTER_X86_64_rdi, 8, 224, "di", "rdi", }, - { DRGN_REGISTER_X86_64_rbp, 8, 144, "bp", "rbp", }, - { DRGN_REGISTER_X86_64_rsp, 8, 264, "sp", "rsp", }, - { DRGN_REGISTER_X86_64_r8, 8, 184, "r8", }, - { DRGN_REGISTER_X86_64_r9, 8, 176, "r9", }, - { DRGN_REGISTER_X86_64_r10, 8, 168, "r10", }, - { DRGN_REGISTER_X86_64_r11, 8, 160, "r11", }, - { DRGN_REGISTER_X86_64_r12, 8, 136, "r12", }, - { DRGN_REGISTER_X86_64_r13, 8, 128, "r13", }, - { DRGN_REGISTER_X86_64_r14, 8, 120, "r14", }, - { DRGN_REGISTER_X86_64_r15, 8, 112, "r15", }, - { DRGN_REGISTER_X86_64_rip, 8, 240, "ip", "rip", }, -}; +/* + * The in-kernel struct pt_regs, UAPI struct pt_regs, elf_gregset_t, and struct + * user_regs_struct all have the same layout. + */ +static struct drgn_error * +set_initial_registers_from_struct_x86_64(Dwfl_Thread *thread, const void *regs, + size_t size, bool bswap) +{ + Dwarf_Word dwarf_regs[17]; + + if (size < 160) { + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "registers are truncated"); + } + +#define READ_REGISTER(n) ({ \ + uint64_t reg; \ + memcpy(®, (uint64_t *)regs + n, sizeof(reg)); \ + bswap ? bswap_64(reg) : reg; \ +}) + dwarf_regs[0] = READ_REGISTER(10); /* rax */ + dwarf_regs[1] = READ_REGISTER(12); /* rdx */ + dwarf_regs[2] = READ_REGISTER(11); /* rcx */ + dwarf_regs[3] = READ_REGISTER(5); /* rbx */ + dwarf_regs[4] = READ_REGISTER(13); /* rsi */ + dwarf_regs[5] = READ_REGISTER(14); /* rdi */ + dwarf_regs[6] = READ_REGISTER(4); /* rbp */ + dwarf_regs[7] = READ_REGISTER(19); /* rsp */ + dwarf_regs[8] = READ_REGISTER(9); /* r8 */ + dwarf_regs[9] = READ_REGISTER(8); /* r9 */ + dwarf_regs[10] = READ_REGISTER(7); /* r10 */ + dwarf_regs[11] = READ_REGISTER(6); /* r11 */ + dwarf_regs[12] = READ_REGISTER(3); /* r12 */ + dwarf_regs[13] = READ_REGISTER(2); /* r13 */ + dwarf_regs[14] = READ_REGISTER(1); /* r14 */ + dwarf_regs[15] = READ_REGISTER(0); /* r15 */ + dwarf_regs[16] = READ_REGISTER(16); /* rip */ +#undef READ_REGISTER + + if (!dwfl_thread_state_registers(thread, 0, 17, dwarf_regs)) + return drgn_error_libdwfl(); + return NULL; +} + +static struct drgn_error * +pt_regs_set_initial_registers_x86_64(Dwfl_Thread *thread, + const struct drgn_object *obj) +{ + bool bswap = (obj->value.little_endian != + (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)); + return set_initial_registers_from_struct_x86_64(thread, + drgn_object_buffer(obj), + drgn_buffer_object_size(obj), + bswap); +} + +static struct drgn_error * +prstatus_set_initial_registers_x86_64(struct drgn_program *prog, + Dwfl_Thread *thread, const void *prstatus, + size_t size) +{ + if (size < 112) { + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "NT_PRSTATUS is truncated"); + } + return set_initial_registers_from_struct_x86_64(thread, + (char *)prstatus + 112, + size - 112, + drgn_program_bswap(prog)); +} static inline struct drgn_error *read_register(struct drgn_object *reg_obj, struct drgn_object *frame_obj, @@ -485,8 +536,8 @@ const struct drgn_architecture_info arch_info_x86_64 = { ARCHITECTURE_INFO, .default_flags = (DRGN_PLATFORM_IS_64_BIT | DRGN_PLATFORM_IS_LITTLE_ENDIAN), - .frame_registers = frame_registers_x86_64, - .num_frame_registers = ARRAY_SIZE(frame_registers_x86_64), + .pt_regs_set_initial_registers = pt_regs_set_initial_registers_x86_64, + .prstatus_set_initial_registers = prstatus_set_initial_registers_x86_64, .linux_kernel_set_initial_registers = linux_kernel_set_initial_registers_x86_64, .linux_kernel_get_page_offset = linux_kernel_get_page_offset_x86_64, diff --git a/libdrgn/platform.h b/libdrgn/platform.h index f0f885722..8510cc45a 100644 --- a/libdrgn/platform.h +++ b/libdrgn/platform.h @@ -13,17 +13,6 @@ struct drgn_register { enum drgn_register_number number; }; -/* Register in NT_PRSTATUS note or struct pt_regs used for stack unwinding. */ -struct drgn_frame_register { - enum drgn_register_number number; - size_t size; - size_t prstatus_offset; - /* Name used in the kernel. */ - const char *pt_regs_name; - /* Name used for the UAPI, if different from above. */ - const char *pt_regs_name2; -}; - /* Page table iterator. */ struct pgtable_iterator { struct drgn_program *prog; @@ -69,8 +58,13 @@ struct drgn_architecture_info { const struct drgn_register *registers; size_t num_registers; const struct drgn_register *(*register_by_name)(const char *name); - const struct drgn_frame_register *frame_registers; - size_t num_frame_registers; + /* Given pt_regs as a value buffer object. */ + struct drgn_error *(*pt_regs_set_initial_registers)(Dwfl_Thread *, + const struct drgn_object *); + struct drgn_error *(*prstatus_set_initial_registers)(struct drgn_program *, + Dwfl_Thread *, + const void *, + size_t); struct drgn_error *(*linux_kernel_set_initial_registers)(Dwfl_Thread *, const struct drgn_object *); struct drgn_error *(*linux_kernel_get_page_offset)(struct drgn_program *, diff --git a/libdrgn/stack_trace.c b/libdrgn/stack_trace.c index 8fe641cb8..b85f9aa27 100644 --- a/libdrgn/stack_trace.c +++ b/libdrgn/stack_trace.c @@ -241,51 +241,6 @@ drgn_get_stack_trace_obj(struct drgn_object *res, struct drgn_program *prog, ", struct task_struct *" : ""); } -static struct drgn_error * -drgn_pt_regs_set_initial_registers(Dwfl_Thread *thread, - struct drgn_platform *platform, - const struct drgn_object *pt_regs) -{ - struct drgn_error *err; - struct drgn_object obj; - size_t i; - - drgn_object_init(&obj, pt_regs->prog); - - if (!platform->arch->num_frame_registers) { - return drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, - "pt_regs stack unwinding is not supported for %s architecture", - platform->arch->name); - } - - for (i = 0; i < platform->arch->num_frame_registers; i++) { - const struct drgn_frame_register *reg; - union drgn_value value; - Dwarf_Word word; - - reg = &platform->arch->frame_registers[i]; - err = drgn_object_member(&obj, pt_regs, reg->pt_regs_name); - if (err && err->code == DRGN_ERROR_LOOKUP && - reg->pt_regs_name2) { - drgn_error_destroy(err); - err = drgn_object_member(&obj, pt_regs, - reg->pt_regs_name2); - } - if (err) - goto out; - err = drgn_object_read_integer(&obj, &value); - if (err) - goto out; - word = value.uvalue; - if (!dwfl_thread_state_registers(thread, reg->number, 1, &word)) - return drgn_error_libdwfl(); - } - err = NULL; -out: - drgn_object_deinit(&obj); - return err; -} - static struct drgn_error * drgn_get_task_pid(const struct drgn_object *task, uint32_t *ret) { @@ -306,60 +261,6 @@ drgn_get_task_pid(const struct drgn_object *task, uint32_t *ret) return err; } -static struct drgn_error * -drgn_prstatus_set_initial_registers(Dwfl_Thread *thread, - struct drgn_platform *platform, - struct string *prstatus) -{ - bool bswap = (!!(platform->flags & DRGN_PLATFORM_IS_LITTLE_ENDIAN) != - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)); - size_t i; - - if (!platform->arch->num_frame_registers) { - return drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, - "core dump stack unwinding is not supported for %s architecture", - platform->arch->name); - } - - for (i = 0; i < platform->arch->num_frame_registers; i++) { - const struct drgn_frame_register *reg; - const char *p; - Dwarf_Word word; - - reg = &platform->arch->frame_registers[i]; - if (prstatus->len < reg->prstatus_offset + reg->size) { - return drgn_error_create(DRGN_ERROR_OTHER, - "NT_PRSTATUS is truncated"); - } - p = prstatus->str + reg->prstatus_offset; - switch (reg->size) { - case 4: { - uint32_t tmp; - - memcpy(&tmp, p, sizeof(tmp)); - if (bswap) - tmp = bswap_32(tmp); - word = tmp; - break; - } - case 8: { - uint64_t tmp; - - memcpy(&tmp, p, sizeof(tmp)); - if (bswap) - tmp = bswap_64(tmp); - word = tmp; - break; - } - default: - UNREACHABLE(); - } - if (!dwfl_thread_state_registers(thread, reg->number, 1, &word)) - return drgn_error_libdwfl(); - } - return NULL; -} - static bool drgn_thread_set_initial_registers(Dwfl_Thread *thread, void *thread_arg) { @@ -380,10 +281,16 @@ static bool drgn_thread_set_initial_registers(Dwfl_Thread *thread, goto out; if (is_pt_regs) { - assert(obj.kind == DRGN_OBJECT_BUFFER); - err = drgn_pt_regs_set_initial_registers(thread, - &prog->platform, - &obj); + assert(obj.kind == DRGN_OBJECT_BUFFER && + !obj.is_reference); + if (!prog->platform.arch->pt_regs_set_initial_registers) { + err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, + "pt_regs stack unwinding is not supported for %s architecture", + prog->platform.arch->name); + goto out; + } + err = prog->platform.arch->pt_regs_set_initial_registers(thread, + &obj); goto out; } } @@ -408,9 +315,16 @@ static bool drgn_thread_set_initial_registers(Dwfl_Thread *thread, if (err) goto out; if (prstatus.str) { - err = drgn_prstatus_set_initial_registers(thread, - &prog->platform, - &prstatus); + if (!prog->platform.arch->prstatus_set_initial_registers) { + err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, + "core dump stack unwinding is not supported for %s architecture", + prog->platform.arch->name); + goto out; + } + err = prog->platform.arch->prstatus_set_initial_registers(prog, + thread, + prstatus.str, + prstatus.len); goto out; } } From eea5422546004d29f85e4d0b94d62fd7564db15a Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Wed, 20 May 2020 11:30:00 -0700 Subject: [PATCH 7/8] libdrgn: make Linux kernel stack unwinding more robust drgn has a couple of issues unwinding stack traces for kernel core dumps: 1. It can't unwind the stack for the idle task (PID 0), which commonly appears in core dumps. 2. It uses the PID in PRSTATUS, which is racy and can't actually be trusted. The solution for both of these is to look up the PRSTATUS note by CPU instead of PID. For the live kernel, drgn refuses to unwind the stack of tasks in the "R" state. However, the "R" state is running *or runnable*, so in the latter case, we can still unwind the stack. The solution for this is to look at on_cpu for the task instead of the state. --- libdrgn/arch_x86_64.c.in | 44 ++++++++- libdrgn/linux_kernel.c | 4 +- libdrgn/linux_kernel.h | 2 + libdrgn/platform.h | 29 +++++- libdrgn/program.c | 137 ++++++++++++++++++++-------- libdrgn/program.h | 32 ++++++- libdrgn/stack_trace.c | 187 +++++++++++++++++++-------------------- 7 files changed, 293 insertions(+), 142 deletions(-) diff --git a/libdrgn/arch_x86_64.c.in b/libdrgn/arch_x86_64.c.in index 0ba061755..a64a5d15d 100644 --- a/libdrgn/arch_x86_64.c.in +++ b/libdrgn/arch_x86_64.c.in @@ -257,7 +257,9 @@ out: static struct drgn_error * linux_kernel_set_initial_registers_x86_64(Dwfl_Thread *thread, - const struct drgn_object *task_obj) + const struct drgn_object *task_obj, + const void *prstatus, + size_t prstatus_size) { struct drgn_error *err; struct drgn_program *prog = task_obj->prog; @@ -268,8 +270,44 @@ linux_kernel_set_initial_registers_x86_64(Dwfl_Thread *thread, drgn_object_init(&sp_obj, prog); - /* - */ + if (prstatus) { + /* + * If the stack pointer in PRSTATUS is within this task's stack, + * then we can use it. Otherwise, the task either wasn't running + * or was in the middle of context switching. Either way, we + * should use the saved registers instead. + */ + uint64_t thread_size; + uint64_t stack; + + err = linux_kernel_get_thread_size(prog, &thread_size); + if (err) + goto out; + err = drgn_object_member_dereference(&sp_obj, task_obj, + "stack"); + if (err) + goto out; + err = drgn_object_read_unsigned(&sp_obj, &stack); + if (err) + goto out; + + if (prstatus_size < 272) { + err = drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "registers are truncated"); + goto out; + } + memcpy(&sp, (char *)prstatus + 264, sizeof(sp)); + if (drgn_program_bswap(prog)) + sp = bswap_64(sp); + if (sp > stack && sp <= stack + thread_size) { + err = prstatus_set_initial_registers_x86_64(prog, + thread, + prstatus, + prstatus_size); + goto out; + } + } + err = drgn_object_member_dereference(&sp_obj, task_obj, "thread"); if (err) goto out; diff --git a/libdrgn/linux_kernel.c b/libdrgn/linux_kernel.c index 5c97643d0..0c2d0bc22 100644 --- a/libdrgn/linux_kernel.c +++ b/libdrgn/linux_kernel.c @@ -234,8 +234,8 @@ struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, return err; } -static struct drgn_error * -linux_kernel_get_thread_size(struct drgn_program *prog, uint64_t *ret) +struct drgn_error *linux_kernel_get_thread_size(struct drgn_program *prog, + uint64_t *ret) { struct drgn_error *err; struct drgn_qualified_type thread_union_type; diff --git a/libdrgn/linux_kernel.h b/libdrgn/linux_kernel.h index f765fbe7c..c467bf27c 100644 --- a/libdrgn/linux_kernel.h +++ b/libdrgn/linux_kernel.h @@ -24,6 +24,8 @@ struct drgn_error *proc_kallsyms_symbol_addr(const char *name, struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, struct vmcoreinfo *ret); +struct drgn_error *linux_kernel_get_thread_size(struct drgn_program *prog, + uint64_t *ret); struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len, const char *filename, diff --git a/libdrgn/platform.h b/libdrgn/platform.h index 8510cc45a..c97608ec8 100644 --- a/libdrgn/platform.h +++ b/libdrgn/platform.h @@ -65,8 +65,35 @@ struct drgn_architecture_info { Dwfl_Thread *, const void *, size_t); + /* + * Get a task's registers from the task_struct or PRSTATUS note as + * appropriate. + * + * The given PRSTATUS note is for the CPU that the task is assigned to, + * which may or may not be for the given task. This callback must + * determine that (typically by checking whether the stack pointer in + * PRSTATUS lies within the task's stack). + * + * We find the PRSTATUS note by CPU rather than by PID for two reasons: + * + * 1. The PID is populated by the kernel from "current" (the current + * task) via a non-maskable interrupt (NMI). During a context switch, + * the stack pointer and current are not updated atomically, so if + * the NMI arrives in the middle of a context switch, the stack + * pointer may not actually be that of current. Therefore, the stack + * pointer in PRSTATUS may not actually be for the PID in PRSTATUS. + * + * We go through all of this trouble because blindly trusting the PID + * could result in a stack trace for the wrong task, which we want to + * avoid at all costs. + * + * 2. There is an idle task with PID 0 for each CPU, so for an idle task + * we have no choice but to find the note by CPU. + */ struct drgn_error *(*linux_kernel_set_initial_registers)(Dwfl_Thread *, - const struct drgn_object *); + const struct drgn_object *, + const void *prstatus, + size_t prstatus_size); struct drgn_error *(*linux_kernel_get_page_offset)(struct drgn_program *, uint64_t *); struct drgn_error *(*linux_kernel_get_vmemmap)(struct drgn_program *, diff --git a/libdrgn/program.c b/libdrgn/program.c index 968b49610..72fbfe832 100644 --- a/libdrgn/program.c +++ b/libdrgn/program.c @@ -28,6 +28,7 @@ #include "type_index.h" #include "vector.h" +DEFINE_VECTOR_FUNCTIONS(drgn_prstatus_vector) DEFINE_HASH_TABLE_FUNCTIONS(drgn_prstatus_map, hash_pair_int_type, hash_table_scalar_eq) @@ -75,7 +76,6 @@ void drgn_program_init(struct drgn_program *prog, drgn_type_index_init(&prog->tindex); drgn_object_index_init(&prog->oindex); prog->core_fd = -1; - drgn_prstatus_map_init(&prog->prstatus_cache); if (platform) drgn_program_set_platform(prog, platform); } @@ -83,7 +83,12 @@ void drgn_program_init(struct drgn_program *prog, void drgn_program_deinit(struct drgn_program *prog) { free(prog->task_state_chars); - drgn_prstatus_map_deinit(&prog->prstatus_cache); + if (prog->prstatus_cached) { + if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) + drgn_prstatus_vector_deinit(&prog->prstatus_vector); + else + drgn_prstatus_map_deinit(&prog->prstatus_map); + } free(prog->pgtable_it); drgn_object_index_deinit(&prog->oindex); @@ -736,41 +741,64 @@ drgn_program_load_debug_info(struct drgn_program *prog, const char **paths, struct drgn_error *drgn_program_cache_prstatus_entry(struct drgn_program *prog, char *data, size_t size) { - struct drgn_prstatus_map_entry entry; - size_t pr_pid_offset; - uint32_t pr_pid; + if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) { + struct string *entry; - pr_pid_offset = drgn_program_is_64_bit(prog) ? 32 : 24; + entry = drgn_prstatus_vector_append_entry(&prog->prstatus_vector); + if (!entry) + return &drgn_enomem; + entry->str = data; + entry->len = size; + } else { + struct drgn_prstatus_map_entry entry; + size_t pr_pid_offset; + uint32_t pr_pid; - if (size < pr_pid_offset + sizeof(pr_pid)) - return NULL; + pr_pid_offset = drgn_program_is_64_bit(prog) ? 32 : 24; + if (size < pr_pid_offset + sizeof(pr_pid)) + return NULL; - memcpy(&pr_pid, data + pr_pid_offset, sizeof(pr_pid)); - if (drgn_program_bswap(prog)) - pr_pid = bswap_32(pr_pid); - if (!pr_pid) - return NULL; + memcpy(&pr_pid, data + pr_pid_offset, sizeof(pr_pid)); + if (drgn_program_bswap(prog)) + pr_pid = bswap_32(pr_pid); - entry.key = pr_pid; - entry.value.str = data; - entry.value.len = size; - if (drgn_prstatus_map_insert(&prog->prstatus_cache, &entry, - NULL) == -1) { - return &drgn_enomem; + entry.key = pr_pid; + entry.value.str = data; + entry.value.len = size; + if (drgn_prstatus_map_insert(&prog->prstatus_map, &entry, + NULL) == -1) + return &drgn_enomem; } return NULL; } static struct drgn_error *drgn_program_cache_prstatus(struct drgn_program *prog) { + struct drgn_error *err; size_t phnum, i; + if (prog->prstatus_cached) + return NULL; + + if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) + drgn_prstatus_vector_init(&prog->prstatus_vector); + else + drgn_prstatus_map_init(&prog->prstatus_map); + #ifdef WITH_LIBKDUMPFILE - if (prog->kdump_ctx) - return drgn_program_cache_prstatus_kdump(prog); + if (prog->kdump_ctx) { + err = drgn_program_cache_prstatus_kdump(prog); + goto out; + } #endif - if (elf_getphdrnum(prog->core, &phnum) != 0) - return drgn_error_libelf(); + if (!prog->core) { + err = NULL; + goto out; + } + if (elf_getphdrnum(prog->core, &phnum) != 0) { + err = drgn_error_libelf(); + goto out; + } for (i = 0; i < phnum; i++) { GElf_Phdr phdr_mem, *phdr; Elf_Data *data; @@ -779,23 +807,26 @@ static struct drgn_error *drgn_program_cache_prstatus(struct drgn_program *prog) size_t name_offset, desc_offset; phdr = gelf_getphdr(prog->core, i, &phdr_mem); - if (!phdr) - return drgn_error_libelf(); + if (!phdr) { + err = drgn_error_libelf(); + goto out; + } if (phdr->p_type != PT_NOTE) continue; data = elf_getdata_rawchunk(prog->core, phdr->p_offset, phdr->p_filesz, note_header_type(phdr)); - if (!data) - return drgn_error_libelf(); + if (!data) { + err = drgn_error_libelf(); + goto out; + } offset = 0; while (offset < data->d_size && (offset = gelf_getnote(data, offset, &nhdr, &name_offset, &desc_offset))) { const char *name; - struct drgn_error *err; name = (char *)data->d_buf + name_offset; if (strncmp(name, "CORE", nhdr.n_namesz) != 0 || @@ -806,26 +837,56 @@ static struct drgn_error *drgn_program_cache_prstatus(struct drgn_program *prog) (char *)data->d_buf + desc_offset, nhdr.n_descsz); if (err) - return err; + goto out; } } + + err = NULL; +out: + if (err) { + if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) + drgn_prstatus_vector_deinit(&prog->prstatus_vector); + else + drgn_prstatus_map_deinit(&prog->prstatus_map); + } else { + prog->prstatus_cached = true; + } + return err; +} + +struct drgn_error *drgn_program_find_prstatus_by_cpu(struct drgn_program *prog, + uint32_t cpu, + struct string *ret) +{ + struct drgn_error *err; + + assert(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL); + err = drgn_program_cache_prstatus(prog); + if (err) + return err; + + if (cpu < prog->prstatus_vector.size) { + *ret = prog->prstatus_vector.data[cpu]; + } else { + ret->str = NULL; + ret->len = 0; + } return NULL; } -struct drgn_error *drgn_program_find_prstatus(struct drgn_program *prog, - uint32_t tid, struct string *ret) +struct drgn_error *drgn_program_find_prstatus_by_tid(struct drgn_program *prog, + uint32_t tid, + struct string *ret) { struct drgn_error *err; struct drgn_prstatus_map_iterator it; - if (!prog->prstatus_cached) { - err = drgn_program_cache_prstatus(prog); - if (err) - return err; - prog->prstatus_cached = true; - } + assert(!(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL)); + err = drgn_program_cache_prstatus(prog); + if (err) + return err; - it = drgn_prstatus_map_search(&prog->prstatus_cache, &tid); + it = drgn_prstatus_map_search(&prog->prstatus_map, &tid); if (!it.entry) { ret->str = NULL; ret->len = 0; diff --git a/libdrgn/program.h b/libdrgn/program.h index fad8139de..f4db36c6c 100644 --- a/libdrgn/program.h +++ b/libdrgn/program.h @@ -22,6 +22,7 @@ #include "object_index.h" #include "platform.h" #include "type_index.h" +#include "vector.h" /** * @ingroup Internals @@ -53,6 +54,7 @@ struct vmcoreinfo { bool pgtable_l5_enabled; }; +DEFINE_VECTOR_TYPE(drgn_prstatus_vector, struct string) DEFINE_HASH_MAP_TYPE(drgn_prstatus_map, uint32_t, struct string) struct drgn_dwarf_info_cache; @@ -92,7 +94,16 @@ struct drgn_program { */ pid_t pid; struct drgn_dwarf_info_cache *_dicache; - struct drgn_prstatus_map prstatus_cache; + union { + /* + * For the Linux kernel, PRSTATUS notes indexed by CPU. See @ref + * drgn_architecture_info::linux_kernel_set_initial_registers + * for why we don't use the PID map. + */ + struct drgn_prstatus_vector prstatus_vector; + /* For userspace programs, PRSTATUS notes indexed by PID. */ + struct drgn_prstatus_map prstatus_map; + }; /* See @ref drgn_object_stack_trace(). */ struct drgn_error *stack_trace_err; /* See @ref drgn_object_stack_trace_next_thread(). */ @@ -172,16 +183,29 @@ static inline bool drgn_program_is_64_bit(struct drgn_program *prog) struct drgn_error *drgn_program_get_dwfl(struct drgn_program *prog, Dwfl **ret); +/** + * Find the @c NT_PRSTATUS note for the given CPU. + * + * This is only valid for the Linux kernel. + * + * @param[out] ret Returned note data. If not found, ret->str is set to + * @c NULL and ret->len is set to zero. + */ +struct drgn_error *drgn_program_find_prstatus_by_cpu(struct drgn_program *prog, + uint32_t cpu, + struct string *ret); + /** * Find the @c NT_PRSTATUS note for the given thread ID. * - * This assumes that prog->core is not @c NULL. + * This is only valid for userspace programs. * * @param[out] ret Returned note data. If not found, ret->str is set to * @c NULL and ret->len is set to zero. */ -struct drgn_error *drgn_program_find_prstatus(struct drgn_program *prog, - uint32_t tid, struct string *ret); +struct drgn_error *drgn_program_find_prstatus_by_tid(struct drgn_program *prog, + uint32_t tid, + struct string *ret); /** * Cache the @c NT_PRSTATUS note provided by @p data in @p prog. diff --git a/libdrgn/stack_trace.c b/libdrgn/stack_trace.c index b85f9aa27..d3c344df8 100644 --- a/libdrgn/stack_trace.c +++ b/libdrgn/stack_trace.c @@ -241,36 +241,17 @@ drgn_get_stack_trace_obj(struct drgn_object *res, struct drgn_program *prog, ", struct task_struct *" : ""); } -static struct drgn_error * -drgn_get_task_pid(const struct drgn_object *task, uint32_t *ret) -{ - struct drgn_error *err; - struct drgn_object pid; - union drgn_value value; - - drgn_object_init(&pid, task->prog); - err = drgn_object_member_dereference(&pid, task, "pid"); - if (err) - goto out; - err = drgn_object_read_integer(&pid, &value); - if (err) - goto out; - *ret = value.uvalue; -out: - drgn_object_deinit(&pid); - return err; -} - static bool drgn_thread_set_initial_registers(Dwfl_Thread *thread, void *thread_arg) { struct drgn_error *err; struct drgn_program *prog = thread_arg; struct drgn_object obj; - bool truthy; - char state; + struct drgn_object tmp; + struct string prstatus; drgn_object_init(&obj, prog); + drgn_object_init(&tmp, prog); /* First, try pt_regs. */ if (prog->stack_trace_obj) { @@ -293,91 +274,109 @@ static bool drgn_thread_set_initial_registers(Dwfl_Thread *thread, &obj); goto out; } - } + } else if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) { + bool found; - /* Then, try the core dump (and/or kdump if supported). */ -#ifdef WITH_LIBKDUMPFILE - if (prog->core || prog->kdump_ctx) { -#else - if (prog->core) { -#endif - uint32_t tid; - struct string prstatus; - - if (prog->stack_trace_obj) { - err = drgn_get_task_pid(&obj, &tid); - if (err) - goto out; - } else { - tid = prog->stack_trace_tid; - } - err = drgn_program_find_prstatus(prog, tid, &prstatus); + err = drgn_program_find_object(prog, "init_pid_ns", NULL, + DRGN_FIND_OBJECT_ANY, &tmp); if (err) goto out; - if (prstatus.str) { - if (!prog->platform.arch->prstatus_set_initial_registers) { - err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, - "core dump stack unwinding is not supported for %s architecture", - prog->platform.arch->name); - goto out; - } - err = prog->platform.arch->prstatus_set_initial_registers(prog, - thread, - prstatus.str, - prstatus.len); + err = drgn_object_address_of(&tmp, &tmp); + if (err) + goto out; + err = linux_helper_find_task(&obj, &tmp, prog->stack_trace_tid); + if (err) + goto out; + err = drgn_object_bool(&obj, &found); + if (err) + goto out; + if (!found) { + err = drgn_error_create(DRGN_ERROR_LOOKUP, "task not found"); goto out; } } - /* Finally, try the task_struct. */ - if (!(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL)) { - err = drgn_error_create(DRGN_ERROR_LOOKUP, "thread not found"); - goto out; - } - - if (!prog->platform.arch->linux_kernel_set_initial_registers) { - err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, - "Linux kernel stack unwinding is not supported for %s architecture", - prog->platform.arch->name); - goto out; - } - - if (!prog->stack_trace_obj) { - struct drgn_object ns; - - drgn_object_init(&ns, prog); - err = drgn_program_find_object(prog, "init_pid_ns", NULL, - DRGN_FIND_OBJECT_ANY, &ns); - if (!err) - err = drgn_object_address_of(&ns, &ns); - if (!err) { - err = linux_helper_find_task(&obj, &ns, - prog->stack_trace_tid); + if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) { + if (prog->flags & DRGN_PROGRAM_IS_LIVE) { + err = drgn_object_member_dereference(&tmp, &obj, "on_cpu"); + if (!err) { + bool on_cpu; + err = drgn_object_bool(&tmp, &on_cpu); + if (err) + goto out; + if (on_cpu) { + err = drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "cannot unwind stack of running task"); + goto out; + } + } else if (err->code == DRGN_ERROR_LOOKUP) { + /* + * The running kernel is !SMP. Assume that the + * task isn't running (which can only be wrong + * for this thread itself). + */ + drgn_error_destroy(err); + } else { + goto out; + } + prstatus.str = NULL; + prstatus.len = 0; + } else { + union drgn_value value; + uint32_t cpu; + + err = drgn_object_member_dereference(&tmp, &obj, "cpu"); + if (!err) { + err = drgn_object_read_integer(&tmp, &value); + if (err) + goto out; + cpu = value.uvalue; + } else if (err->code == DRGN_ERROR_LOOKUP) { + /* !SMP. Must be CPU 0. */ + drgn_error_destroy(err); + cpu = 0; + } else { + goto out; + } + err = drgn_program_find_prstatus_by_cpu(prog, cpu, + &prstatus); + if (err) + goto out; } - drgn_object_deinit(&ns); + if (!prog->platform.arch->linux_kernel_set_initial_registers) { + err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, + "Linux kernel stack unwinding is not supported for %s architecture", + prog->platform.arch->name); + goto out; + } + err = prog->platform.arch->linux_kernel_set_initial_registers(thread, + &obj, + prstatus.str, + prstatus.len); + } else { + err = drgn_program_find_prstatus_by_tid(prog, + prog->stack_trace_tid, + &prstatus); if (err) goto out; - } - err = drgn_object_bool(&obj, &truthy); - if (err) - goto out; - if (!truthy) { - err = drgn_error_create(DRGN_ERROR_LOOKUP, "task not found"); - goto out; - } - - err = linux_helper_task_state_to_char(&obj, &state); - if (err) - goto out; - if (state == 'R') { - err = drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, - "cannot unwind stack of running task"); - goto out; + if (!prstatus.str) { + err = drgn_error_create(DRGN_ERROR_LOOKUP, "thread not found"); + goto out; + } + if (!prog->platform.arch->prstatus_set_initial_registers) { + err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, + "core dump stack unwinding is not supported for %s architecture", + prog->platform.arch->name); + goto out; + } + err = prog->platform.arch->prstatus_set_initial_registers(prog, + thread, + prstatus.str, + prstatus.len); } - err = prog->platform.arch->linux_kernel_set_initial_registers(thread, - &obj); out: + drgn_object_deinit(&tmp); drgn_object_deinit(&obj); if (err) { drgn_error_destroy(prog->stack_trace_err); From a227d0d50eb429f96fd51884148888fd25f6546a Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Wed, 20 May 2020 13:28:55 -0700 Subject: [PATCH 8/8] Update elfutils and revert activation frame patch After thinking about it some more, I realized that "libdwfl: simplify activation frame logic" breaks the case where during unwinding someone queries isactivation for reasons other than knowing whether to decrement program counter. Revert the patch and refactor "libdwfl: add interface for getting Dwfl_Module and Dwarf_Frame for Dwfl_Frame" to handle it differently. Based on: c95081596 size: Also obey radix printing for bsd format. With the following patches: configure: Add --disable-programs configure: Add --disable-shared libdwfl: add interface for attaching to/detaching from threads libdwfl: export __libdwfl_frame_reg_get as dwfl_frame_register libdwfl: add interface for getting Dwfl_Module and Dwarf_Frame for Dwfl_Frame libdwfl: add interface for evaluating DWARF expressions in a frame --- libdrgn/elfutils/PATCHES | 726 ++++++++------------- libdrgn/elfutils/libcpu/ChangeLog | 4 + libdrgn/elfutils/libcpu/i386_parse.y | 1 + libdrgn/elfutils/libdw/libdw.map | 2 +- libdrgn/elfutils/libdwfl/ChangeLog | 11 + libdrgn/elfutils/libdwfl/core-file.c | 17 +- libdrgn/elfutils/libdwfl/dwfl_frame.c | 3 +- libdrgn/elfutils/libdwfl/dwfl_frame_pc.c | 21 +- libdrgn/elfutils/libdwfl/dwfl_frame_regs.c | 2 + libdrgn/elfutils/libdwfl/find-debuginfo.c | 3 + libdrgn/elfutils/libdwfl/frame_unwind.c | 175 ++--- libdrgn/elfutils/libdwfl/libdwflP.h | 5 +- libdrgn/elfutils/libelf/ChangeLog | 9 + libdrgn/elfutils/libelf/elf_getdata.c | 2 + libdrgn/elfutils/libelf/elf_strptr.c | 2 +- libdrgn/elfutils/src/ChangeLog | 11 + libdrgn/elfutils/src/elflint.c | 9 +- libdrgn/elfutils/src/nm.c | 16 +- libdrgn/elfutils/src/objdump.c | 3 + libdrgn/elfutils/src/size.c | 7 +- libdrgn/elfutils/tests/ChangeLog | 5 + libdrgn/elfutils/tests/elfputzdata.c | 21 +- 22 files changed, 497 insertions(+), 558 deletions(-) diff --git a/libdrgn/elfutils/PATCHES b/libdrgn/elfutils/PATCHES index f7dbbb1ba..551dff7dd 100644 --- a/libdrgn/elfutils/PATCHES +++ b/libdrgn/elfutils/PATCHES @@ -1,4 +1,4 @@ -commit c26c6ddb435d87ceafdd8fb36fa99011119d6e3a +commit eaa481f284524d7f5d14f88dcf6cb62faeae5713 Author: Omar Sandoval Date: Mon Oct 7 01:30:35 2019 -0700 @@ -9,23 +9,23 @@ Date: Mon Oct 7 01:30:35 2019 -0700 pieces are in place, add dwfl_frame_eval_expr to provide this feature. diff --git a/libdw/libdw.map b/libdw/libdw.map -index 5f5946cb1..b4fa63631 100644 +index f4134e318a..25ae8b6e6c 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -377,4 +377,5 @@ ELFUTILS_0.180 { + dwfl_frame_register; dwfl_frame_module; dwfl_frame_dwarf_frame; - dwfl_frame_register; + dwfl_frame_eval_expr; } ELFUTILS_0.177; diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index 3984c65ce..4885caa13 100644 +index bbbd73add4..a6df269763 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c -@@ -814,3 +814,14 @@ out: - return state->frame; +@@ -837,3 +837,14 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); + state->unwound->signal_frame = signal_frame; } - INTDEF (dwfl_frame_dwarf_frame) + +bool +dwfl_frame_eval_expr (Dwfl_Frame *state, const Dwarf_Op *ops, size_t nops, @@ -38,7 +38,7 @@ index 3984c65ce..4885caa13 100644 + return expr_eval (state, frame, ops, nops, result, bias); +} diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h -index fb261698e..1dc080c01 100644 +index fb261698ed..1dc080c01e 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -822,6 +822,12 @@ bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) @@ -54,136 +54,7 @@ index fb261698e..1dc080c01 100644 #ifdef __cplusplus } #endif -commit b32da5a9a88543f144afd50a213afe6fe1d9b25d -Author: Omar Sandoval -Date: Thu Feb 20 11:44:38 2020 -0800 - - libdwfl: export __libdwfl_frame_reg_get as dwfl_frame_register - - This is useful for debuggers that want to dump register values. - -diff --git a/libdw/libdw.map b/libdw/libdw.map -index e0fe21156..5f5946cb1 100644 ---- a/libdw/libdw.map -+++ b/libdw/libdw.map -@@ -376,4 +376,5 @@ ELFUTILS_0.180 { - dwfl_detach_thread; - dwfl_frame_module; - dwfl_frame_dwarf_frame; -+ dwfl_frame_register; - } ELFUTILS_0.177; -diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index 9ada2e550..3984c65ce 100644 ---- a/libdwfl/frame_unwind.c -+++ b/libdwfl/frame_unwind.c -@@ -44,8 +44,7 @@ - #define DWARF_EXPR_STEPS_MAX 0x1000 - - bool --internal_function --__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) -+dwfl_frame_register (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) - { - Ebl *ebl = state->thread->process->ebl; - if (! ebl_dwarf_to_regno (ebl, ®no)) -@@ -59,6 +58,7 @@ __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) - *val = state->regs[regno]; - return true; - } -+INTDEF (dwfl_frame_register) - - bool - internal_function -@@ -81,7 +81,7 @@ __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) - static bool - state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) - { -- if (! __libdwfl_frame_reg_get (state, regno, val)) -+ if (! INTUSE(dwfl_frame_register) (state, regno, val)) - { - __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); - return false; -@@ -628,9 +628,9 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Frame *frame, Dwarf_Addr bias) - } - if (unwound->pc_state == DWFL_FRAME_STATE_ERROR) - { -- if (__libdwfl_frame_reg_get (unwound, -- frame->fde->cie->return_address_register, -- &unwound->pc)) -+ if (INTUSE(dwfl_frame_register) (unwound, -+ frame->fde->cie->return_address_register, -+ &unwound->pc)) - { - /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. - Currently none of the archs supported for unwinding have -@@ -687,7 +687,7 @@ getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) - Dwfl_Frame *state = arg; - assert (firstreg >= 0); - while (nregs--) -- if (! __libdwfl_frame_reg_get (state, firstreg++, regs++)) -+ if (! INTUSE(dwfl_frame_register) (state, firstreg++, regs++)) - return false; - return true; - } -diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h -index b494d4582..fb261698e 100644 ---- a/libdwfl/libdwfl.h -+++ b/libdwfl/libdwfl.h -@@ -817,6 +817,11 @@ int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid, - bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) - __nonnull_attribute__ (1, 2); - -+/* Return the *VALUE of register REGNO in frame STATE. VALUE may be NULL. -+ Returns false if the register value is unknown. */ -+bool dwfl_frame_register (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *value) -+ __nonnull_attribute__ (1); -+ - #ifdef __cplusplus - } - #endif -diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h -index 90d509ece..613ccf016 100644 ---- a/libdwfl/libdwflP.h -+++ b/libdwfl/libdwflP.h -@@ -283,12 +283,6 @@ struct Dwfl_Frame - Dwarf_Addr regs[]; - }; - --/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO. -- No error code is set if the function returns FALSE. */ --bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, -- Dwarf_Addr *val) -- internal_function; -- - /* Store value to Dwfl_Frame->regs indexed by DWARF REGNO. - No error code is set if the function returns FALSE. */ - bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, -@@ -788,6 +782,7 @@ INTDECL (dwfl_getthread_frames) - INTDECL (dwfl_getthreads) - INTDECL (dwfl_thread_getframes) - INTDECL (dwfl_frame_pc) -+INTDECL (dwfl_frame_register) - - /* Leading arguments standard to callbacks passed a Dwfl_Module. */ - #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr -diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c -index c0f1b0d00..d55312b6c 100644 ---- a/libdwfl/linux-core-attach.c -+++ b/libdwfl/linux-core-attach.c -@@ -253,10 +253,9 @@ core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp) - /* PPC provides DWARF register 65 irrelevant for - CFI which clashes with register 108 (LR) we need. - LR (108) is provided earlier (in NT_PRSTATUS) than the # 65. -- FIXME: It depends now on their order in core notes. -- FIXME: It uses private function. */ -+ FIXME: It depends now on their order in core notes. */ - if (regno < nregs -- && __libdwfl_frame_reg_get (thread->unwound, regno, NULL)) -+ && INTUSE(dwfl_frame_register) (thread->unwound, regno, NULL)) - continue; - Dwarf_Word val; - switch (regloc->bits) -commit 1426c2a70c1748cd5a6f4e38410ae4e9796d3037 +commit 5a6524c0b89a71bc712ccab7fc801d12c429bcd5 Author: Omar Sandoval Date: Thu Feb 20 11:18:28 2020 -0800 @@ -199,18 +70,18 @@ Date: Thu Feb 20 11:18:28 2020 -0800 frame, so add dwfl_frame_module. diff --git a/libdw/libdw.map b/libdw/libdw.map -index c8961b3a6..e0fe21156 100644 +index 73f592c03e..f4134e318a 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map -@@ -374,4 +374,6 @@ ELFUTILS_0.180 { - global: +@@ -375,4 +375,6 @@ ELFUTILS_0.180 { dwfl_attach_thread; dwfl_detach_thread; + dwfl_frame_register; + dwfl_frame_module; + dwfl_frame_dwarf_frame; } ELFUTILS_0.177; diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c -index 0ad28e0f5..046f6c2ba 100644 +index 61fad8b9cf..80f2bc1466 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c @@ -68,6 +68,13 @@ state_fetch_pc (Dwfl_Frame *state) @@ -244,10 +115,10 @@ index 0ad28e0f5..046f6c2ba 100644 + state->frame = NULL; + state->moderr = DWFL_E_NOERROR; + state->frameerr = DWFL_E_NOERROR; - state->isactivation = true; + state->signal_frame = false; + state->initial_frame = true; state->pc_state = DWFL_FRAME_STATE_ERROR; - memset (state->regs_set, 0, sizeof (state->regs_set)); -@@ -485,7 +496,7 @@ dwfl_thread_getframes (Dwfl_Thread *thread, +@@ -486,7 +497,7 @@ dwfl_thread_getframes (Dwfl_Thread *thread, if (! cache) { /* The old frame is no longer needed. */ @@ -257,7 +128,7 @@ index 0ad28e0f5..046f6c2ba 100644 state = next; } diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index df755975e..9ada2e550 100644 +index f7459b283d..bbbd73add4 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -523,6 +523,10 @@ new_unwound (Dwfl_Frame *state) @@ -268,10 +139,10 @@ index df755975e..9ada2e550 100644 + unwound->frame = NULL; + unwound->moderr = DWFL_E_NOERROR; + unwound->frameerr = DWFL_E_NOERROR; - unwound->isactivation = false; + unwound->signal_frame = false; + unwound->initial_frame = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; - memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); -@@ -535,22 +539,9 @@ new_unwound (Dwfl_Frame *state) +@@ -536,22 +540,9 @@ new_unwound (Dwfl_Frame *state) later. Therefore we continue unwinding leaving the registers undefined. */ static void @@ -293,10 +164,10 @@ index df755975e..9ada2e550 100644 - } - + Dwfl_Frame *unwound = state->unwound; - if (frame->fde->cie->signal_frame) - { - state->isactivation = true; -@@ -668,7 +659,6 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) + unwound->signal_frame = frame->fde->cie->signal_frame; + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; +@@ -665,7 +656,6 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; } } @@ -304,60 +175,18 @@ index df755975e..9ada2e550 100644 } static bool -@@ -724,28 +714,16 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - assert (ok); - if (! isactivation) - pc--; -- Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); -- if (mod == NULL) -- __libdwfl_seterrno (DWFL_E_NO_DWARF); -- else -+ Dwarf_Addr bias; -+ Dwarf_Frame *frame = INTUSE(dwfl_frame_dwarf_frame) (state, &bias); -+ if (frame != NULL) - { -- Dwarf_Addr bias; -- Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias); -- if (cfi_eh) -- { -- handle_cfi (state, pc - bias, cfi_eh, bias); -- if (state->unwound) -- return; -- } -- Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias); -- if (cfi_dwarf) -- { -- handle_cfi (state, pc - bias, cfi_dwarf, bias); -- if (state->unwound) -- return; -- } -+ if (new_unwound (state) == NULL) -+ __libdwfl_seterrno (DWFL_E_NOMEM); -+ else -+ handle_cfi (state, frame, bias); -+ return; - } -- assert (state->unwound == NULL); - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; -@@ -773,3 +751,66 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - state->unwound->isactivation = true; - } +@@ -709,6 +699,95 @@ readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg) + process->callbacks_arg); } -+ -+Dwfl_Module * -+dwfl_frame_module (Dwfl_Frame *state) + ++/* Internal version of dwfl_frame_module when we already know the PC. */ ++static Dwfl_Module * ++dwfl_frame_module_pc (Dwfl_Frame *state, Dwarf_Addr pc) +{ + if (state->mod != NULL) + return state->mod; + if (state->moderr == DWFL_E_NOERROR) + { -+ Dwarf_Addr pc; -+ bool isactivation; -+ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); -+ if (! isactivation) -+ pc--; + state->mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); + if (state->mod != NULL) + return state->mod; @@ -366,33 +195,28 @@ index df755975e..9ada2e550 100644 + __libdwfl_seterrno (state->moderr); + return NULL; +} -+INTDEF (dwfl_frame_module) + -+Dwarf_Frame * -+dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) ++/* Internal version of dwfl_frame_dwarf_frame when we already know the PC. */ ++static Dwarf_Frame * ++dwfl_frame_dwarf_frame_pc (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_Addr *bias) +{ + if (state->frame == NULL) + { + if (state->frameerr == DWFL_E_NOERROR) + { -+ Dwfl_Module *mod = INTUSE(dwfl_frame_module) (state); ++ Dwfl_Module *mod = dwfl_frame_module_pc (state, pc); + if (mod == NULL) + { + state->frameerr = state->moderr; ++ /* errno is already set. */ + return NULL; + } -+ Dwarf_Addr pc; -+ bool isactivation; -+ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); -+ if (! isactivation) -+ pc--; -+ Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (state->mod, -+ &state->bias); ++ Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (mod, &state->bias); + if (cfi + && INTUSE(dwarf_cfi_addrframe) (cfi, pc - state->bias, + &state->frame) == 0) + goto out; -+ cfi = INTUSE(dwfl_module_dwarf_cfi) (state->mod, &state->bias); ++ cfi = INTUSE(dwfl_module_dwarf_cfi) (mod, &state->bias); + if (cfi + && INTUSE(dwarf_cfi_addrframe) (cfi, pc - state->bias, + &state->frame) == 0) @@ -407,9 +231,85 @@ index df755975e..9ada2e550 100644 + *bias = state->bias; + return state->frame; +} -+INTDEF (dwfl_frame_dwarf_frame) ++ ++Dwfl_Module * ++dwfl_frame_module (Dwfl_Frame *state) ++{ ++ if (state->mod != NULL) ++ return state->mod; ++ if (state->moderr == DWFL_E_NOERROR) ++ { ++ Dwarf_Addr pc; ++ bool isactivation; ++ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); ++ if (! isactivation) ++ pc--; ++ return dwfl_frame_module_pc (state, pc); ++ } ++ __libdwfl_seterrno (state->moderr); ++ return NULL; ++} ++ ++Dwarf_Frame * ++dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) ++{ ++ if (state->frame != NULL) ++ return state->frame; ++ if (state->frameerr == DWFL_E_NOERROR) ++ { ++ Dwarf_Addr pc; ++ bool isactivation; ++ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); ++ if (! isactivation) ++ pc--; ++ return dwfl_frame_dwarf_frame_pc (state, pc, bias); ++ } ++ __libdwfl_seterrno (state->frameerr); ++ return NULL; ++} ++ + void + internal_function + __libdwfl_frame_unwind (Dwfl_Frame *state) +@@ -724,28 +803,16 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + Then we need to unwind from the original, unadjusted PC. */ + if (! state->initial_frame && ! state->signal_frame) + pc--; +- Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); +- if (mod == NULL) +- __libdwfl_seterrno (DWFL_E_NO_DWARF); +- else ++ Dwarf_Addr bias; ++ Dwarf_Frame *frame = dwfl_frame_dwarf_frame_pc (state, pc, &bias); ++ if (frame != NULL) + { +- Dwarf_Addr bias; +- Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias); +- if (cfi_eh) +- { +- handle_cfi (state, pc - bias, cfi_eh, bias); +- if (state->unwound) +- return; +- } +- Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias); +- if (cfi_dwarf) +- { +- handle_cfi (state, pc - bias, cfi_dwarf, bias); +- if (state->unwound) +- return; +- } ++ if (new_unwound (state) == NULL) ++ __libdwfl_seterrno (DWFL_E_NOMEM); ++ else ++ handle_cfi (state, frame, bias); ++ return; + } +- assert (state->unwound == NULL); + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + Ebl *ebl = process->ebl; diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h -index 4167ef7ad..b494d4582 100644 +index 639ed186b6..fb261698ed 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -738,6 +738,16 @@ pid_t dwfl_thread_tid (Dwfl_Thread *thread) @@ -430,7 +330,7 @@ index 4167ef7ad..b494d4582 100644 For every known continuous block of registers +Date: Thu Feb 20 11:44:38 2020 -0800 + + libdwfl: export __libdwfl_frame_reg_get as dwfl_frame_register + + This is useful for debuggers that want to dump register values. + +diff --git a/libdw/libdw.map b/libdw/libdw.map +index c8961b3a6a..73f592c03e 100644 +--- a/libdw/libdw.map ++++ b/libdw/libdw.map +@@ -374,4 +374,5 @@ ELFUTILS_0.180 { + global: + dwfl_attach_thread; + dwfl_detach_thread; ++ dwfl_frame_register; + } ELFUTILS_0.177; +diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c +index d7dfa5a94b..f7459b283d 100644 +--- a/libdwfl/frame_unwind.c ++++ b/libdwfl/frame_unwind.c +@@ -44,8 +44,7 @@ + #define DWARF_EXPR_STEPS_MAX 0x1000 + + bool +-internal_function +-__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) ++dwfl_frame_register (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) + { + Ebl *ebl = state->thread->process->ebl; + if (! ebl_dwarf_to_regno (ebl, ®no)) +@@ -59,6 +58,7 @@ __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) + *val = state->regs[regno]; + return true; + } ++INTDEF (dwfl_frame_register) + + bool + internal_function +@@ -81,7 +81,7 @@ __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) + static bool + state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) + { +- if (! __libdwfl_frame_reg_get (state, regno, val)) ++ if (! INTUSE(dwfl_frame_register) (state, regno, val)) + { + __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); + return false; +@@ -634,9 +634,9 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) + } + if (unwound->pc_state == DWFL_FRAME_STATE_ERROR) + { +- if (__libdwfl_frame_reg_get (unwound, +- frame->fde->cie->return_address_register, +- &unwound->pc)) ++ if (INTUSE(dwfl_frame_register) (unwound, ++ frame->fde->cie->return_address_register, ++ &unwound->pc)) + { + /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. + Currently none of the archs supported for unwinding have +@@ -694,7 +694,7 @@ getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) + Dwfl_Frame *state = arg; + assert (firstreg >= 0); + while (nregs--) +- if (! __libdwfl_frame_reg_get (state, firstreg++, regs++)) ++ if (! INTUSE(dwfl_frame_register) (state, firstreg++, regs++)) + return false; + return true; + } +diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h +index 4167ef7ad8..639ed186b6 100644 +--- a/libdwfl/libdwfl.h ++++ b/libdwfl/libdwfl.h +@@ -807,6 +807,11 @@ int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid, + bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) + __nonnull_attribute__ (1, 2); + ++/* Return the *VALUE of register REGNO in frame STATE. VALUE may be NULL. ++ Returns false if the register value is unknown. */ ++bool dwfl_frame_register (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *value) ++ __nonnull_attribute__ (1); ++ + #ifdef __cplusplus + } + #endif +diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h +index bc088861ff..4ae7c0b3ba 100644 +--- a/libdwfl/libdwflP.h ++++ b/libdwfl/libdwflP.h +@@ -275,12 +275,6 @@ struct Dwfl_Frame + Dwarf_Addr regs[]; + }; + +-/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO. +- No error code is set if the function returns FALSE. */ +-bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, +- Dwarf_Addr *val) +- internal_function; +- + /* Store value to Dwfl_Frame->regs indexed by DWARF REGNO. + No error code is set if the function returns FALSE. */ + bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, +@@ -778,6 +772,7 @@ INTDECL (dwfl_getthread_frames) + INTDECL (dwfl_getthreads) + INTDECL (dwfl_thread_getframes) + INTDECL (dwfl_frame_pc) ++INTDECL (dwfl_frame_register) + + /* Leading arguments standard to callbacks passed a Dwfl_Module. */ + #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr +diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c +index c0f1b0d004..d55312b6cd 100644 +--- a/libdwfl/linux-core-attach.c ++++ b/libdwfl/linux-core-attach.c +@@ -253,10 +253,9 @@ core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp) + /* PPC provides DWARF register 65 irrelevant for + CFI which clashes with register 108 (LR) we need. + LR (108) is provided earlier (in NT_PRSTATUS) than the # 65. +- FIXME: It depends now on their order in core notes. +- FIXME: It uses private function. */ ++ FIXME: It depends now on their order in core notes. */ + if (regno < nregs +- && __libdwfl_frame_reg_get (thread->unwound, regno, NULL)) ++ && INTUSE(dwfl_frame_register) (thread->unwound, regno, NULL)) + continue; + Dwarf_Word val; + switch (regloc->bits) +commit 5ea774858ed9d25f308ccb147f3f430e2b0f8599 Author: Omar Sandoval Date: Mon Oct 7 01:22:39 2019 -0700 @@ -474,7 +494,7 @@ Date: Mon Oct 7 01:22:39 2019 -0700 possible to use the frames after dwfl_thread_getframes returns. diff --git a/libdw/libdw.map b/libdw/libdw.map -index decac05c7..c8961b3a6 100644 +index decac05c7c..c8961b3a6a 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -370,3 +370,8 @@ ELFUTILS_0.177 { @@ -487,10 +507,10 @@ index decac05c7..c8961b3a6 100644 + dwfl_detach_thread; +} ELFUTILS_0.177; diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c -index d5043cbbe..0ad28e0f5 100644 +index 5bbf850e8e..61fad8b9cf 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c -@@ -102,6 +102,29 @@ state_alloc (Dwfl_Thread *thread) +@@ -103,6 +103,29 @@ state_alloc (Dwfl_Thread *thread) return state; } @@ -520,7 +540,7 @@ index d5043cbbe..0ad28e0f5 100644 void internal_function __libdwfl_process_free (Dwfl_Process *process) -@@ -365,6 +388,45 @@ getthread (Dwfl *dwfl, pid_t tid, +@@ -366,6 +389,45 @@ getthread (Dwfl *dwfl, pid_t tid, return err; } @@ -566,7 +586,7 @@ index d5043cbbe..0ad28e0f5 100644 struct one_thread { int (*callback) (Dwfl_Frame *frame, void *arg); -@@ -393,63 +455,55 @@ dwfl_thread_getframes (Dwfl_Thread *thread, +@@ -394,63 +456,55 @@ dwfl_thread_getframes (Dwfl_Thread *thread, int (*callback) (Dwfl_Frame *state, void *arg), void *arg) { @@ -664,7 +684,7 @@ index d5043cbbe..0ad28e0f5 100644 } INTDEF(dwfl_thread_getframes) diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h -index d5fa06d47..4167ef7ad 100644 +index d5fa06d476..4167ef7ad8 100644 --- a/libdwfl/libdwfl.h +++ b/libdwfl/libdwfl.h @@ -763,6 +763,18 @@ int dwfl_getthreads (Dwfl *dwfl, @@ -687,7 +707,7 @@ index d5fa06d47..4167ef7ad 100644 have been processed by the callback, returns -1 on error, or the value of the callback when not DWARF_CB_OK. -1 returned on error will diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h -index 332349d32..ed8239c92 100644 +index 25753de2f8..bc088861ff 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -239,7 +239,8 @@ struct Dwfl_Thread @@ -700,213 +720,7 @@ index 332349d32..ed8239c92 100644 Dwfl_Frame *unwound; void *callbacks_arg; }; -commit a1f60f2e2794859c7767b0b003efb20e3e018904 -Author: Omar Sandoval -Date: Wed May 13 14:18:12 2020 -0700 - - libdwfl: simplify activation frame logic - - When calling a noreturn function, the compiler may omit any code after - the call instruction. As a result, the return address on the stack may - not lie in the FDE for the caller. It might even lie in another symbol. - In the following example, the return address for the _Exit call in foo - is actually the first instruction of bar. - - 0000000000001149 : - 1149: 50 push %rax - 114a: bf 01 00 00 00 mov $0x1,%edi - 114f: e8 dc fe ff ff callq 1030 <_Exit@plt> - - 0000000000001154 : - 1154: b8 37 13 00 00 mov $0x1337,%eax - 1159: c3 retq - - To handle this, libdwfl (and GDB, for that matter) decrements the - program counter when looking up the debugging information for a frame. - - There are two important exceptions. The first is the initial (i.e., - innermost) frame. This is typically supplied by ptrace or a PRSTATUS - note, which contains the exact trapped PC. libdwfl calls this case an - "activation" and doesn't decrement the PC. - - The second exception is signal handling. When a signal is received, the - kernel creates a special signal stack frame so that when the signal - handler returns, it returns to the signal trampoline code responsible - for resuming execution (see sigreturn(2)). - - The return address from the signal frame is the exact interrupted - instruction. Therefore, the interrupted frame (that is, the outer frame - of a signal frame) is also considered an activation. - - The signal frame itself is also considered an activation frame, since - the return address points directly to the signal trampoline. However, - determining that a frame is a signal frame requires looking up the FDE. - To solve this chicken and egg problem, the signal trampoline is padded - so that the debugger can still find the FDE even if it decrements PC - (see [1]). This means that during the initial lookup, we can assume it's - not an activation, and then fix it up after the fact. - - libdwfl annotates the interrupted frame (NB, not the signal frame) with - Dwfl_Frame::signal_frame. dwfl_frame_pc returns that a frame is an - activation if it is the interrupted frame, or if its outer frame is the - interrupted frame (which means it is the signal frame). This requires - unwinding the frame, so when the unwinding code calls dwfl_frame_pc, it - has to open-code the logic for determining whether the activation frame - check. - - This can all be made a lot simpler by instead directly tracking whether - a Dwfl_Frame is an activation frame. This replaces - Dwfl_Frame::initial_frame and Dwfl_Frame::signal_frame with - Dwfl_Frame::isactivation. We set isactivation to true for the initial - frame, the signal frame, and the interrupted frame. - - 1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso/vdso32/sigreturn.S?h=v5.6#n54 - -diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c -index 5bbf850e8..d5043cbbe 100644 ---- a/libdwfl/dwfl_frame.c -+++ b/libdwfl/dwfl_frame.c -@@ -94,8 +94,7 @@ state_alloc (Dwfl_Thread *thread) - if (state == NULL) - return NULL; - state->thread = thread; -- state->signal_frame = false; -- state->initial_frame = true; -+ state->isactivation = true; - state->pc_state = DWFL_FRAME_STATE_ERROR; - memset (state->regs_set, 0, sizeof (state->regs_set)); - thread->unwound = state; -diff --git a/libdwfl/dwfl_frame_pc.c b/libdwfl/dwfl_frame_pc.c -index 296c815b9..a955d995a 100644 ---- a/libdwfl/dwfl_frame_pc.c -+++ b/libdwfl/dwfl_frame_pc.c -@@ -39,26 +39,7 @@ dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) - *pc = state->pc; - ebl_normalize_pc (state->thread->process->ebl, pc); - if (isactivation) -- { -- /* Bottom frame? */ -- if (state->initial_frame) -- *isactivation = true; -- /* *ISACTIVATION is logical union of whether current or previous frame -- state is SIGNAL_FRAME. */ -- else if (state->signal_frame) -- *isactivation = true; -- else -- { -- /* If the previous frame has unwound unsuccessfully just silently do -- not consider it could be a SIGNAL_FRAME. */ -- __libdwfl_frame_unwind (state); -- if (state->unwound == NULL -- || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET) -- *isactivation = false; -- else -- *isactivation = state->unwound->signal_frame; -- } -- } -+ *isactivation = state->isactivation; - return true; - } - INTDEF (dwfl_frame_pc) -diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c -index 83b1abef1..d013dc966 100644 ---- a/libdwfl/dwfl_frame_regs.c -+++ b/libdwfl/dwfl_frame_regs.c -@@ -38,7 +38,6 @@ dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, - { - Dwfl_Frame *state = thread->unwound; - assert (state && state->unwound == NULL); -- assert (state->initial_frame); - for (unsigned regno = firstreg; regno < firstreg + nregs; regno++) - if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg])) - { -@@ -54,7 +53,6 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) - { - Dwfl_Frame *state = thread->unwound; - assert (state && state->unwound == NULL); -- assert (state->initial_frame); - state->pc = pc; - state->pc_state = DWFL_FRAME_STATE_PC_SET; - } -diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index d7dfa5a94..df755975e 100644 ---- a/libdwfl/frame_unwind.c -+++ b/libdwfl/frame_unwind.c -@@ -523,8 +523,7 @@ new_unwound (Dwfl_Frame *state) - state->unwound = unwound; - unwound->thread = thread; - unwound->unwound = NULL; -- unwound->signal_frame = false; -- unwound->initial_frame = false; -+ unwound->isactivation = false; - unwound->pc_state = DWFL_FRAME_STATE_ERROR; - memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); - return unwound; -@@ -552,7 +551,11 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) - return; - } - -- unwound->signal_frame = frame->fde->cie->signal_frame; -+ if (frame->fde->cie->signal_frame) -+ { -+ state->isactivation = true; -+ unwound->isactivation = true; -+ } - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; -@@ -715,14 +718,11 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - { - if (state->unwound) - return; -- /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE -- which would deadlock us. */ - Dwarf_Addr pc; -- bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); -+ bool isactivation; -+ bool ok = INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); - assert (ok); -- /* Check whether this is the initial frame or a signal frame. -- Then we need to unwind from the original, unadjusted PC. */ -- if (! state->initial_frame && ! state->signal_frame) -+ if (! isactivation) - pc--; - Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); - if (mod == NULL) -@@ -755,7 +755,6 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - return; - } - state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; -- // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. - bool signal_frame = false; - if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) - { -@@ -768,5 +767,9 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - return; - } - assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); -- state->unwound->signal_frame = signal_frame; -+ if (signal_frame) -+ { -+ state->isactivation = true; -+ state->unwound->isactivation = true; -+ } - } -diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h -index 25753de2f..332349d32 100644 ---- a/libdwfl/libdwflP.h -+++ b/libdwfl/libdwflP.h -@@ -251,8 +251,7 @@ struct Dwfl_Frame - Dwfl_Thread *thread; - /* Previous (outer) frame. */ - Dwfl_Frame *unwound; -- bool signal_frame : 1; -- bool initial_frame : 1; -+ bool isactivation; - enum - { - /* This structure is still being initialized or there was an error -commit 148c39884329b1279c2fc4c63500f95b95205651 +commit 75ceb320352708c76a2f9a1c71e99d12322f75ea Author: Omar Sandoval Date: Wed Sep 4 17:13:40 2019 -0700 @@ -918,7 +732,7 @@ Date: Wed Sep 4 17:13:40 2019 -0700 build them from. diff --git a/backends/Makefile.am b/backends/Makefile.am -index f4052125b..1beb661eb 100644 +index f4052125bd..1beb661eb1 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -34,7 +34,10 @@ endif @@ -934,7 +748,7 @@ index f4052125b..1beb661eb 100644 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \ tilegx m68k bpf riscv csky diff --git a/configure.ac b/configure.ac -index 12ee2f97c..d68d1a1eb 100644 +index 12ee2f97c1..d68d1a1eb1 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,11 @@ AC_ARG_ENABLE([programs], @@ -950,7 +764,7 @@ index 12ee2f97c..d68d1a1eb 100644 [AS_HELP_STRING([--enable-deterministic-archives], [ar and ranlib default to -D behavior])], [ diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am -index e62e8d14b..a811e2dd1 100644 +index e62e8d14b0..a811e2dd1d 100644 --- a/debuginfod/Makefile.am +++ b/debuginfod/Makefile.am @@ -86,16 +86,20 @@ libdebuginfod.so$(EXEEXT): $(srcdir)/libdebuginfod.map $(libdebuginfod_so_LIBS) @@ -975,7 +789,7 @@ index e62e8d14b..a811e2dd1 100644 EXTRA_DIST = libdebuginfod.map diff --git a/libasm/Makefile.am b/libasm/Makefile.am -index b2bff9292..8a5a9d0f0 100644 +index b2bff92923..8a5a9d0f04 100644 --- a/libasm/Makefile.am +++ b/libasm/Makefile.am @@ -34,8 +34,10 @@ GCC_INCLUDE = -I$(shell $(CC) -print-file-name=include) @@ -1011,7 +825,7 @@ index b2bff9292..8a5a9d0f0 100644 noinst_HEADERS = libasmP.h symbolhash.h diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am -index 59def7d1b..57dc698ed 100644 +index 59def7d1bc..57dc698ed3 100644 --- a/libcpu/Makefile.am +++ b/libcpu/Makefile.am @@ -38,7 +38,10 @@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$( Date: Wed Sep 4 17:13:23 2019 -0700 @@ -1150,7 +964,7 @@ Date: Wed Sep 4 17:13:23 2019 -0700 still to build everything. diff --git a/Makefile.am b/Makefile.am -index bd8926b52..0b13c717f 100644 +index bd8926b523..0b13c717fa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,11 @@ AM_MAKEFLAGS = --no-print-directory @@ -1167,7 +981,7 @@ index bd8926b52..0b13c717f 100644 if DEBUGINFOD SUBDIRS += debuginfod diff --git a/configure.ac b/configure.ac -index a39e800f7..12ee2f97c 100644 +index a39e800f70..12ee2f97c1 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,11 @@ AC_CONFIG_FILES([debuginfod/Makefile]) @@ -1183,7 +997,7 @@ index a39e800f7..12ee2f97c 100644 [AS_HELP_STRING([--enable-deterministic-archives], [ar and ranlib default to -D behavior])], [ diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am -index 51965f65d..e62e8d14b 100644 +index 51965f65db..e62e8d14b0 100644 --- a/debuginfod/Makefile.am +++ b/debuginfod/Makefile.am @@ -57,7 +57,9 @@ libeu = ../lib/libeu.a diff --git a/libdrgn/elfutils/libcpu/ChangeLog b/libdrgn/elfutils/libcpu/ChangeLog index a8b2b951e..a342b7f64 100644 --- a/libdrgn/elfutils/libcpu/ChangeLog +++ b/libdrgn/elfutils/libcpu/ChangeLog @@ -1,3 +1,7 @@ +2020-05-09 Mark Wielaard + + * i386_parse.y (new_bitfield): Call free newp on error. + 2020-04-16 Mark Wielaard * i386_disasm.c (i386_disasm): Replace assert with goto invalid_op diff --git a/libdrgn/elfutils/libcpu/i386_parse.y b/libdrgn/elfutils/libcpu/i386_parse.y index 910d54581..90c7bd934 100644 --- a/libdrgn/elfutils/libcpu/i386_parse.y +++ b/libdrgn/elfutils/libcpu/i386_parse.y @@ -579,6 +579,7 @@ new_bitfield (char *name, unsigned long int num) error (0, 0, "%d: duplicated definition of bitfield '%s'", i386_lineno, name); free (name); + free (newp); return; } diff --git a/libdrgn/elfutils/libdw/libdw.map b/libdrgn/elfutils/libdw/libdw.map index b4fa63631..25ae8b6e6 100644 --- a/libdrgn/elfutils/libdw/libdw.map +++ b/libdrgn/elfutils/libdw/libdw.map @@ -374,8 +374,8 @@ ELFUTILS_0.180 { global: dwfl_attach_thread; dwfl_detach_thread; + dwfl_frame_register; dwfl_frame_module; dwfl_frame_dwarf_frame; - dwfl_frame_register; dwfl_frame_eval_expr; } ELFUTILS_0.177; diff --git a/libdrgn/elfutils/libdwfl/ChangeLog b/libdrgn/elfutils/libdwfl/ChangeLog index 3f9cd6659..4f1ec9da4 100644 --- a/libdrgn/elfutils/libdwfl/ChangeLog +++ b/libdrgn/elfutils/libdwfl/ChangeLog @@ -1,3 +1,14 @@ +2020-05-09 Mark Wielaard + + * find-debuginfo.c (dwfl_standard_find_debuginfo): Return failure + when mod is NULL. + +2020-05-08 Mark Wielaard + + * libdwfl/core-file.c (dwfl_core_file_report): Keep track of + new bool cleanup_user_core and cleanup dwfl->user_core in error + case. + 2020-04-30 Mark Wielaard * find-debuginfo.c (dwfl_standard_find_debuginfo): When mod->dw diff --git a/libdrgn/elfutils/libdwfl/core-file.c b/libdrgn/elfutils/libdwfl/core-file.c index 01109f4bd..a0ccc9b3d 100644 --- a/libdrgn/elfutils/libdwfl/core-file.c +++ b/libdrgn/elfutils/libdwfl/core-file.c @@ -450,6 +450,7 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) return -1; } + bool cleanup_user_core = false; if (dwfl->user_core != NULL) free (dwfl->user_core->executable_for_core); if (executable == NULL) @@ -461,6 +462,7 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) { if (dwfl->user_core == NULL) { + cleanup_user_core = true; dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core)); if (dwfl->user_core == NULL) { @@ -472,6 +474,11 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) dwfl->user_core->executable_for_core = strdup (executable); if (dwfl->user_core->executable_for_core == NULL) { + if (cleanup_user_core) + { + free (dwfl->user_core); + dwfl->user_core = NULL; + } __libdwfl_seterrno (DWFL_E_NOMEM); return -1; } @@ -481,7 +488,15 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) GElf_Phdr notes_phdr; int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr); if (unlikely (ndx <= 0)) - return ndx; + { + if (cleanup_user_core) + { + free (dwfl->user_core->executable_for_core); + free (dwfl->user_core); + dwfl->user_core = NULL; + } + return ndx; + } /* Next, we should follow the chain from DT_DEBUG. */ diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame.c b/libdrgn/elfutils/libdwfl/dwfl_frame.c index 046f6c2ba..80f2bc146 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame.c @@ -105,7 +105,8 @@ state_alloc (Dwfl_Thread *thread) state->frame = NULL; state->moderr = DWFL_E_NOERROR; state->frameerr = DWFL_E_NOERROR; - state->isactivation = true; + state->signal_frame = false; + state->initial_frame = true; state->pc_state = DWFL_FRAME_STATE_ERROR; memset (state->regs_set, 0, sizeof (state->regs_set)); thread->unwound = state; diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c b/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c index a955d995a..296c815b9 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c @@ -39,7 +39,26 @@ dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) *pc = state->pc; ebl_normalize_pc (state->thread->process->ebl, pc); if (isactivation) - *isactivation = state->isactivation; + { + /* Bottom frame? */ + if (state->initial_frame) + *isactivation = true; + /* *ISACTIVATION is logical union of whether current or previous frame + state is SIGNAL_FRAME. */ + else if (state->signal_frame) + *isactivation = true; + else + { + /* If the previous frame has unwound unsuccessfully just silently do + not consider it could be a SIGNAL_FRAME. */ + __libdwfl_frame_unwind (state); + if (state->unwound == NULL + || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET) + *isactivation = false; + else + *isactivation = state->unwound->signal_frame; + } + } return true; } INTDEF (dwfl_frame_pc) diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c b/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c index d013dc966..83b1abef1 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c @@ -38,6 +38,7 @@ dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, { Dwfl_Frame *state = thread->unwound; assert (state && state->unwound == NULL); + assert (state->initial_frame); for (unsigned regno = firstreg; regno < firstreg + nregs; regno++) if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg])) { @@ -53,6 +54,7 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) { Dwfl_Frame *state = thread->unwound; assert (state && state->unwound == NULL); + assert (state->initial_frame); state->pc = pc; state->pc_state = DWFL_FRAME_STATE_PC_SET; } diff --git a/libdrgn/elfutils/libdwfl/find-debuginfo.c b/libdrgn/elfutils/libdwfl/find-debuginfo.c index 4cfd0b8b2..eb68d549d 100644 --- a/libdrgn/elfutils/libdwfl/find-debuginfo.c +++ b/libdrgn/elfutils/libdwfl/find-debuginfo.c @@ -355,6 +355,9 @@ dwfl_standard_find_debuginfo (Dwfl_Module *mod, GElf_Word debuglink_crc, char **debuginfo_file_name) { + if (mod == NULL) + return -1; + /* First try by build ID if we have one. If that succeeds or fails other than just by finding nothing, that's all we do. */ const unsigned char *bits = NULL; diff --git a/libdrgn/elfutils/libdwfl/frame_unwind.c b/libdrgn/elfutils/libdwfl/frame_unwind.c index 4885caa13..a6df26976 100644 --- a/libdrgn/elfutils/libdwfl/frame_unwind.c +++ b/libdrgn/elfutils/libdwfl/frame_unwind.c @@ -527,7 +527,8 @@ new_unwound (Dwfl_Frame *state) unwound->frame = NULL; unwound->moderr = DWFL_E_NOERROR; unwound->frameerr = DWFL_E_NOERROR; - unwound->isactivation = false; + unwound->signal_frame = false; + unwound->initial_frame = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); return unwound; @@ -542,11 +543,7 @@ static void handle_cfi (Dwfl_Frame *state, Dwarf_Frame *frame, Dwarf_Addr bias) { Dwfl_Frame *unwound = state->unwound; - if (frame->fde->cie->signal_frame) - { - state->isactivation = true; - unwound->isactivation = true; - } + unwound->signal_frame = frame->fde->cie->signal_frame; Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; Ebl *ebl = process->ebl; @@ -702,68 +699,14 @@ readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg) process->callbacks_arg); } -void -internal_function -__libdwfl_frame_unwind (Dwfl_Frame *state) -{ - if (state->unwound) - return; - Dwarf_Addr pc; - bool isactivation; - bool ok = INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); - assert (ok); - if (! isactivation) - pc--; - Dwarf_Addr bias; - Dwarf_Frame *frame = INTUSE(dwfl_frame_dwarf_frame) (state, &bias); - if (frame != NULL) - { - if (new_unwound (state) == NULL) - __libdwfl_seterrno (DWFL_E_NOMEM); - else - handle_cfi (state, frame, bias); - return; - } - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; - Ebl *ebl = process->ebl; - if (new_unwound (state) == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return; - } - state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; - bool signal_frame = false; - if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) - { - // Discard the unwind attempt. During next __libdwfl_frame_unwind call - // we may have for example the appropriate Dwfl_Module already mapped. - assert (state->unwound->unwound == NULL); - free (state->unwound); - state->unwound = NULL; - // __libdwfl_seterrno has been called above. - return; - } - assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); - if (signal_frame) - { - state->isactivation = true; - state->unwound->isactivation = true; - } -} - -Dwfl_Module * -dwfl_frame_module (Dwfl_Frame *state) +/* Internal version of dwfl_frame_module when we already know the PC. */ +static Dwfl_Module * +dwfl_frame_module_pc (Dwfl_Frame *state, Dwarf_Addr pc) { if (state->mod != NULL) return state->mod; if (state->moderr == DWFL_E_NOERROR) { - Dwarf_Addr pc; - bool isactivation; - INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); - if (! isactivation) - pc--; state->mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); if (state->mod != NULL) return state->mod; @@ -772,33 +715,28 @@ dwfl_frame_module (Dwfl_Frame *state) __libdwfl_seterrno (state->moderr); return NULL; } -INTDEF (dwfl_frame_module) -Dwarf_Frame * -dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) +/* Internal version of dwfl_frame_dwarf_frame when we already know the PC. */ +static Dwarf_Frame * +dwfl_frame_dwarf_frame_pc (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_Addr *bias) { if (state->frame == NULL) { if (state->frameerr == DWFL_E_NOERROR) { - Dwfl_Module *mod = INTUSE(dwfl_frame_module) (state); + Dwfl_Module *mod = dwfl_frame_module_pc (state, pc); if (mod == NULL) { state->frameerr = state->moderr; + /* errno is already set. */ return NULL; } - Dwarf_Addr pc; - bool isactivation; - INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); - if (! isactivation) - pc--; - Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (state->mod, - &state->bias); + Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (mod, &state->bias); if (cfi && INTUSE(dwarf_cfi_addrframe) (cfi, pc - state->bias, &state->frame) == 0) goto out; - cfi = INTUSE(dwfl_module_dwarf_cfi) (state->mod, &state->bias); + cfi = INTUSE(dwfl_module_dwarf_cfi) (mod, &state->bias); if (cfi && INTUSE(dwarf_cfi_addrframe) (cfi, pc - state->bias, &state->frame) == 0) @@ -813,7 +751,92 @@ dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) *bias = state->bias; return state->frame; } -INTDEF (dwfl_frame_dwarf_frame) + +Dwfl_Module * +dwfl_frame_module (Dwfl_Frame *state) +{ + if (state->mod != NULL) + return state->mod; + if (state->moderr == DWFL_E_NOERROR) + { + Dwarf_Addr pc; + bool isactivation; + INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); + if (! isactivation) + pc--; + return dwfl_frame_module_pc (state, pc); + } + __libdwfl_seterrno (state->moderr); + return NULL; +} + +Dwarf_Frame * +dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) +{ + if (state->frame != NULL) + return state->frame; + if (state->frameerr == DWFL_E_NOERROR) + { + Dwarf_Addr pc; + bool isactivation; + INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); + if (! isactivation) + pc--; + return dwfl_frame_dwarf_frame_pc (state, pc, bias); + } + __libdwfl_seterrno (state->frameerr); + return NULL; +} + +void +internal_function +__libdwfl_frame_unwind (Dwfl_Frame *state) +{ + if (state->unwound) + return; + /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE + which would deadlock us. */ + Dwarf_Addr pc; + bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); + assert (ok); + /* Check whether this is the initial frame or a signal frame. + Then we need to unwind from the original, unadjusted PC. */ + if (! state->initial_frame && ! state->signal_frame) + pc--; + Dwarf_Addr bias; + Dwarf_Frame *frame = dwfl_frame_dwarf_frame_pc (state, pc, &bias); + if (frame != NULL) + { + if (new_unwound (state) == NULL) + __libdwfl_seterrno (DWFL_E_NOMEM); + else + handle_cfi (state, frame, bias); + return; + } + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + Ebl *ebl = process->ebl; + if (new_unwound (state) == NULL) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return; + } + state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; + // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. + bool signal_frame = false; + if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) + { + // Discard the unwind attempt. During next __libdwfl_frame_unwind call + // we may have for example the appropriate Dwfl_Module already mapped. + assert (state->unwound->unwound == NULL); + free (state->unwound); + state->unwound = NULL; + // __libdwfl_seterrno has been called above. + return; + } + assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); + state->unwound->signal_frame = signal_frame; +} bool dwfl_frame_eval_expr (Dwfl_Frame *state, const Dwarf_Op *ops, size_t nops, diff --git a/libdrgn/elfutils/libdwfl/libdwflP.h b/libdrgn/elfutils/libdwfl/libdwflP.h index 613ccf016..7baa3223f 100644 --- a/libdrgn/elfutils/libdwfl/libdwflP.h +++ b/libdrgn/elfutils/libdwfl/libdwflP.h @@ -261,7 +261,8 @@ struct Dwfl_Frame Dwfl_Error moderr; /* Error trying to get frame. */ Dwfl_Error frameerr; - bool isactivation; + bool signal_frame : 1; + bool initial_frame : 1; enum { /* This structure is still being initialized or there was an error @@ -774,8 +775,6 @@ INTDECL (dwfl_pid) INTDECL (dwfl_thread_dwfl) INTDECL (dwfl_thread_tid) INTDECL (dwfl_frame_thread) -INTDECL (dwfl_frame_module) -INTDECL (dwfl_frame_dwarf_frame) INTDECL (dwfl_thread_state_registers) INTDECL (dwfl_thread_state_register_pc) INTDECL (dwfl_getthread_frames) diff --git a/libdrgn/elfutils/libelf/ChangeLog b/libdrgn/elfutils/libelf/ChangeLog index 56f5354c5..fd5518dc4 100644 --- a/libdrgn/elfutils/libelf/ChangeLog +++ b/libdrgn/elfutils/libelf/ChangeLog @@ -1,3 +1,12 @@ +2020-05-08 Mark Wielaard + + * elf_strptr.c (elf_strptr): Check shdr is not NULL. + +2020-05-08 Mark Wielaard + + * elf_getdata.c (__libelf_set_rawdata_wrlock): Check + __gelf_getehdr_rdlock return value. + 2020-04-25 Mark Wielaard * elf_compress.c (__libelf_compress): Remove free (out_buf). diff --git a/libdrgn/elfutils/libelf/elf_getdata.c b/libdrgn/elfutils/libelf/elf_getdata.c index 40fe16945..0d8f8d2ee 100644 --- a/libdrgn/elfutils/libelf/elf_getdata.c +++ b/libdrgn/elfutils/libelf/elf_getdata.c @@ -271,6 +271,8 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn) { GElf_Ehdr ehdr_mem; GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem); + if (unlikely (ehdr == NULL)) + return 1; entsize = SH_ENTSIZE_HASH (ehdr); } else diff --git a/libdrgn/elfutils/libelf/elf_strptr.c b/libdrgn/elfutils/libelf/elf_strptr.c index e72a3a369..c72717074 100644 --- a/libdrgn/elfutils/libelf/elf_strptr.c +++ b/libdrgn/elfutils/libelf/elf_strptr.c @@ -145,7 +145,7 @@ elf_strptr (Elf *elf, size_t idx, size_t offset) else { Elf64_Shdr *shdr = strscn->shdr.e64 ?: __elf64_getshdr_rdlock (strscn); - if (unlikely (shdr->sh_type != SHT_STRTAB)) + if (unlikely (shdr == NULL || shdr->sh_type != SHT_STRTAB)) { /* This is no string section. */ __libelf_seterrno (ELF_E_INVALID_SECTION); diff --git a/libdrgn/elfutils/src/ChangeLog b/libdrgn/elfutils/src/ChangeLog index 83d586071..83fe19eb0 100644 --- a/libdrgn/elfutils/src/ChangeLog +++ b/libdrgn/elfutils/src/ChangeLog @@ -1,3 +1,14 @@ +2020-05-14 Mark Wielaard + + * size.c (show_bsd): Set printf format based on radix. + +2020-05-09 Mark Wielaard + + * elflint.c (process_elf_file): Error out if ebl_openbackend fails. + * objdump.c (handle_elf): Likewise. + * nm.c (handle_elf): Likewise. Move full name string construction + forward, so it can be used in the error message. + 2020-04-17 Mark Wielaard * readelf.c (print_debug): Check .gnu.debuglto_ prefix. diff --git a/libdrgn/elfutils/src/elflint.c b/libdrgn/elfutils/src/elflint.c index 0ef432366..6ad9bc421 100644 --- a/libdrgn/elfutils/src/elflint.c +++ b/libdrgn/elfutils/src/elflint.c @@ -4775,7 +4775,14 @@ process_elf_file (Elf *elf, const char *prefix, const char *suffix, ebl = ebl_openbackend (elf); /* If there is no appropriate backend library we cannot test architecture and OS specific features. Any encountered extension - is an error. */ + is an error. Often we'll get a "dummy" ebl, except if something + really bad happen, like a totally corrupted ELF file or out of + memory situation. */ + if (ebl == NULL) + { + ERROR (gettext ("cannot create backend for ELF file\n")); + return; + } /* Go straight by the gABI, check all the parts in turn. */ check_elf_header (ebl, ehdr, size); diff --git a/libdrgn/elfutils/src/nm.c b/libdrgn/elfutils/src/nm.c index b7c2aed6c..f6ca3b0af 100644 --- a/libdrgn/elfutils/src/nm.c +++ b/libdrgn/elfutils/src/nm.c @@ -1510,8 +1510,17 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, GElf_Ehdr *ehdr; Ebl *ebl; + /* Create the full name of the file. */ + if (prefix != NULL) + cp = mempcpy (cp, prefix, prefix_len); + cp = mempcpy (cp, fname, fname_len); + if (suffix != NULL) + memcpy (cp - 1, suffix, suffix_len + 1); + /* Get the backend for this object file type. */ ebl = ebl_openbackend (elf); + if (ebl == NULL) + INTERNAL_ERROR (fullname); /* We need the ELF header in a few places. */ ehdr = gelf_getehdr (elf, &ehdr_mem); @@ -1530,13 +1539,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, goto out; } - /* Create the full name of the file. */ - if (prefix != NULL) - cp = mempcpy (cp, prefix, prefix_len); - cp = mempcpy (cp, fname, fname_len); - if (suffix != NULL) - memcpy (cp - 1, suffix, suffix_len + 1); - /* Find the symbol table. XXX Can there be more than one? Do we print all? Currently we do. */ diff --git a/libdrgn/elfutils/src/objdump.c b/libdrgn/elfutils/src/objdump.c index a619674f4..82d7bcf6a 100644 --- a/libdrgn/elfutils/src/objdump.c +++ b/libdrgn/elfutils/src/objdump.c @@ -755,6 +755,9 @@ handle_elf (Elf *elf, const char *prefix, const char *fname, /* Get the backend for this object file type. */ Ebl *ebl = ebl_openbackend (elf); + if (ebl == NULL) + error (EXIT_FAILURE, 0, + gettext ("cannot create backend for elf file")); printf ("%s: elf%d-%s\n\n", fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64, diff --git a/libdrgn/elfutils/src/size.c b/libdrgn/elfutils/src/size.c index a25d4471f..e49b64b86 100644 --- a/libdrgn/elfutils/src/size.c +++ b/libdrgn/elfutils/src/size.c @@ -545,8 +545,11 @@ show_bsd (Elf *elf, const char *prefix, const char *fname, datasize += shdr->sh_size; } - printf ("%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" - PRIx64 " %s", + printf (radix == radix_decimal + ? "%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRIx64 " %s" + : radix == radix_hex + ? "%#*" PRIx64 " %#*" PRIx64 " %#*" PRIx64 " %*" PRId64 " %*" PRIx64 " %s" + : "%#*" PRIo64 " %#*" PRIo64 " %#*" PRIo64 " %*" PRId64 " %*" PRIx64 " %s", ddigits - 2, textsize, ddigits - 2, datasize, ddigits - 2, bsssize, diff --git a/libdrgn/elfutils/tests/ChangeLog b/libdrgn/elfutils/tests/ChangeLog index 4e9ae020b..05aab3ef4 100644 --- a/libdrgn/elfutils/tests/ChangeLog +++ b/libdrgn/elfutils/tests/ChangeLog @@ -1,3 +1,8 @@ +2020-05-08 Mark Wielaard + + * elfputzdata.c (main): Explicitly check orig_buf is not NULL + before calling memcmp. + 2020-05-05 Mark Wielaard * testfile-lto-gcc8.bz2: New test file. diff --git a/libdrgn/elfutils/tests/elfputzdata.c b/libdrgn/elfutils/tests/elfputzdata.c index 66ab77ba7..0d9c020ec 100644 --- a/libdrgn/elfutils/tests/elfputzdata.c +++ b/libdrgn/elfutils/tests/elfputzdata.c @@ -105,14 +105,17 @@ main (int argc, char *argv[]) printf ("Unexpected data size for orig section %zd\n", idx); return -1; } - char *orig_buf = malloc (d->d_size); - if (orig_size > 0 && orig_buf == NULL) + char *orig_buf = NULL; + if (orig_size > 0) { - printf ("No memory to copy section %zd data\n", idx); - return -1; + orig_buf = malloc (d->d_size); + if (orig_buf == NULL) + { + printf ("No memory to copy section %zd data\n", idx); + return -1; + } + memcpy (orig_buf, d->d_buf, orig_size); } - if (orig_size > 0) - memcpy (orig_buf, d->d_buf, orig_size); bool forced = false; if (gnu) @@ -175,7 +178,8 @@ main (int argc, char *argv[]) } if (new_size == orig_size - && memcmp (orig_buf, d->d_buf, orig_size) == 0) + && (orig_buf == NULL + || memcmp (orig_buf, d->d_buf, orig_size) == 0)) { printf ("section %zd didn't compress\n", idx); return -1; @@ -211,7 +215,8 @@ main (int argc, char *argv[]) return -1; } if (newer_size != orig_size - && memcmp (orig_buf, d->d_buf, orig_size) != 0) + && (orig_buf == NULL + || memcmp (orig_buf, d->d_buf, orig_size) != 0)) { printf ("section %zd didn't correctly uncompress\n", idx); return -1;