1da0c48c4Sopenharmony_ci# Copyright (C) 2013, 2015 Red Hat, Inc.
2da0c48c4Sopenharmony_ci# This file is part of elfutils.
3da0c48c4Sopenharmony_ci#
4da0c48c4Sopenharmony_ci# This file is free software; you can redistribute it and/or modify
5da0c48c4Sopenharmony_ci# it under the terms of the GNU General Public License as published by
6da0c48c4Sopenharmony_ci# the Free Software Foundation; either version 3 of the License, or
7da0c48c4Sopenharmony_ci# (at your option) any later version.
8da0c48c4Sopenharmony_ci#
9da0c48c4Sopenharmony_ci# elfutils is distributed in the hope that it will be useful, but
10da0c48c4Sopenharmony_ci# WITHOUT ANY WARRANTY; without even the implied warranty of
11da0c48c4Sopenharmony_ci# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12da0c48c4Sopenharmony_ci# GNU General Public License for more details.
13da0c48c4Sopenharmony_ci#
14da0c48c4Sopenharmony_ci# You should have received a copy of the GNU General Public License
15da0c48c4Sopenharmony_ci# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16da0c48c4Sopenharmony_ci
17da0c48c4Sopenharmony_ci. $srcdir/test-subr.sh
18da0c48c4Sopenharmony_ci
19da0c48c4Sopenharmony_ci# Verify one of the backtraced threads contains function 'main'.
20da0c48c4Sopenharmony_cicheck_main()
21da0c48c4Sopenharmony_ci{
22da0c48c4Sopenharmony_ci  if grep -w main $1; then
23da0c48c4Sopenharmony_ci    return
24da0c48c4Sopenharmony_ci  fi
25da0c48c4Sopenharmony_ci  echo >&2 $2: no main
26da0c48c4Sopenharmony_ci  false
27da0c48c4Sopenharmony_ci}
28da0c48c4Sopenharmony_ci
29da0c48c4Sopenharmony_ci# Without proper ELF symbols resolution we could get inappropriate weak
30da0c48c4Sopenharmony_ci# symbol "gsignal" with the same address as the correct symbol "raise".
31da0c48c4Sopenharmony_ci# It was fixed by GIT commit 78dec228b3cfb2f9300cd0b682ebf416c9674c91 .
32da0c48c4Sopenharmony_ci# [patch] Improve ELF symbols preference (global > weak)
33da0c48c4Sopenharmony_ci# https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/002624.html
34da0c48c4Sopenharmony_cicheck_gsignal()
35da0c48c4Sopenharmony_ci{
36da0c48c4Sopenharmony_ci  if ! grep -w gsignal $1; then
37da0c48c4Sopenharmony_ci    return
38da0c48c4Sopenharmony_ci  fi
39da0c48c4Sopenharmony_ci  echo >&2 $2: found gsignal
40da0c48c4Sopenharmony_ci  false
41da0c48c4Sopenharmony_ci}
42da0c48c4Sopenharmony_ci
43da0c48c4Sopenharmony_ci
44da0c48c4Sopenharmony_ci# Makes sure we saw the function that initiated the backtrace
45da0c48c4Sopenharmony_ci# when the core was generated through the tests backtrace --gencore.
46da0c48c4Sopenharmony_ci# This might disappear when frame pointer chasing gone bad.
47da0c48c4Sopenharmony_cicheck_backtracegen()
48da0c48c4Sopenharmony_ci{
49da0c48c4Sopenharmony_ci  if grep -w backtracegen $1; then
50da0c48c4Sopenharmony_ci    return
51da0c48c4Sopenharmony_ci  fi
52da0c48c4Sopenharmony_ci  echo >&2 $2: no backtracegen
53da0c48c4Sopenharmony_ci  false
54da0c48c4Sopenharmony_ci}
55da0c48c4Sopenharmony_ci
56da0c48c4Sopenharmony_ci# Verify the STDERR output does not contain unexpected errors.
57da0c48c4Sopenharmony_ci# In some cases we cannot reliably find out we got behind _start as some
58da0c48c4Sopenharmony_ci# operating system do not properly terminate CFI by undefined PC.
59da0c48c4Sopenharmony_ci# Ignore it here as it is a bug of OS, not a bug of elfutils.
60da0c48c4Sopenharmony_cicheck_err()
61da0c48c4Sopenharmony_ci{
62da0c48c4Sopenharmony_ci  if [ $(grep -E -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range|address out of range|Invalid register|\(null\))$' \
63da0c48c4Sopenharmony_ci         | wc -c) \
64da0c48c4Sopenharmony_ci       -eq 0 ]
65da0c48c4Sopenharmony_ci  then
66da0c48c4Sopenharmony_ci    return
67da0c48c4Sopenharmony_ci  fi
68da0c48c4Sopenharmony_ci  echo >&2 $2: neither empty nor just out of DWARF
69da0c48c4Sopenharmony_ci  false
70da0c48c4Sopenharmony_ci}
71da0c48c4Sopenharmony_ci
72da0c48c4Sopenharmony_cicheck_all()
73da0c48c4Sopenharmony_ci{
74da0c48c4Sopenharmony_ci  bt=$1
75da0c48c4Sopenharmony_ci  err=$2
76da0c48c4Sopenharmony_ci  testname=$3
77da0c48c4Sopenharmony_ci  check_main $bt $testname
78da0c48c4Sopenharmony_ci  check_gsignal $bt $testname
79da0c48c4Sopenharmony_ci  check_err $err $testname
80da0c48c4Sopenharmony_ci}
81da0c48c4Sopenharmony_ci
82da0c48c4Sopenharmony_cicheck_unsupported()
83da0c48c4Sopenharmony_ci{
84da0c48c4Sopenharmony_ci  err=$1
85da0c48c4Sopenharmony_ci  testname=$2
86da0c48c4Sopenharmony_ci  if grep -q ': Unwinding not supported for this architecture$' $err; then
87da0c48c4Sopenharmony_ci    echo >&2 $testname: arch not supported
88da0c48c4Sopenharmony_ci    test_cleanup
89da0c48c4Sopenharmony_ci    exit 77
90da0c48c4Sopenharmony_ci  fi
91da0c48c4Sopenharmony_ci}
92da0c48c4Sopenharmony_ci
93da0c48c4Sopenharmony_cicheck_native_unsupported()
94da0c48c4Sopenharmony_ci{
95da0c48c4Sopenharmony_ci  err=$1
96da0c48c4Sopenharmony_ci  testname=$2
97da0c48c4Sopenharmony_ci  check_unsupported $err $testname
98da0c48c4Sopenharmony_ci
99da0c48c4Sopenharmony_ci  # ARM is special. It is supported, but it doesn't use .eh_frame by default
100da0c48c4Sopenharmony_ci  # making the native tests fail unless debuginfo (for glibc) is installed
101da0c48c4Sopenharmony_ci  # and we can fall back on .debug_frame for the CFI.
102da0c48c4Sopenharmony_ci  case "`uname -m`" in
103da0c48c4Sopenharmony_ci    arm* )
104da0c48c4Sopenharmony_ci      if grep -E 'dwfl_thread_getframes(.*)No DWARF information found' $err; then
105da0c48c4Sopenharmony_ci	echo >&2 $testname: arm needs debuginfo installed for all libraries
106da0c48c4Sopenharmony_ci	exit 77
107da0c48c4Sopenharmony_ci      fi
108da0c48c4Sopenharmony_ci    ;;
109da0c48c4Sopenharmony_ci  esac
110da0c48c4Sopenharmony_ci}
111da0c48c4Sopenharmony_ci
112da0c48c4Sopenharmony_cicheck_core()
113da0c48c4Sopenharmony_ci{
114da0c48c4Sopenharmony_ci  arch=$1
115da0c48c4Sopenharmony_ci  testfiles backtrace.$arch.{exec,core}
116da0c48c4Sopenharmony_ci  tempfiles backtrace.$arch.{bt,err}
117da0c48c4Sopenharmony_ci  echo ./backtrace ./backtrace.$arch.{exec,core}
118da0c48c4Sopenharmony_ci  testrun ${abs_builddir}/backtrace -e ./backtrace.$arch.exec --core=./backtrace.$arch.core 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
119da0c48c4Sopenharmony_ci  cat backtrace.$arch.{bt,err}
120da0c48c4Sopenharmony_ci  check_unsupported backtrace.$arch.err backtrace.$arch.core
121da0c48c4Sopenharmony_ci  check_all backtrace.$arch.{bt,err} backtrace.$arch.core
122da0c48c4Sopenharmony_ci  check_backtracegen backtrace.$arch.bt backtrace.$arch.core
123da0c48c4Sopenharmony_ci}
124da0c48c4Sopenharmony_ci
125da0c48c4Sopenharmony_ci# Backtrace live process.
126da0c48c4Sopenharmony_ci# Do not abort on non-zero exit code due to some warnings of ./backtrace
127da0c48c4Sopenharmony_ci# - see function check_err.
128da0c48c4Sopenharmony_cicheck_native()
129da0c48c4Sopenharmony_ci{
130da0c48c4Sopenharmony_ci  child=$1
131da0c48c4Sopenharmony_ci  tempfiles $child.{bt,err}
132da0c48c4Sopenharmony_ci  (set +ex; testrun ${abs_builddir}/backtrace --backtrace-exec=${abs_builddir}/$child 1>$child.bt 2>$child.err; true)
133da0c48c4Sopenharmony_ci  cat $child.{bt,err}
134da0c48c4Sopenharmony_ci  check_native_unsupported $child.err $child
135da0c48c4Sopenharmony_ci  check_all $child.{bt,err} $child
136da0c48c4Sopenharmony_ci}
137da0c48c4Sopenharmony_ci
138da0c48c4Sopenharmony_ci# Backtrace core file.
139da0c48c4Sopenharmony_cicheck_native_core()
140da0c48c4Sopenharmony_ci{
141da0c48c4Sopenharmony_ci# systemd-coredump/coredumpctl doesn't seem to like concurrent core dumps
142da0c48c4Sopenharmony_ci# use a lock file (fd 200) tests/core-dump-backtrace.lock
143da0c48c4Sopenharmony_ci(
144da0c48c4Sopenharmony_ci  child=$1
145da0c48c4Sopenharmony_ci
146da0c48c4Sopenharmony_ci  # Disable valgrind while dumping core.
147da0c48c4Sopenharmony_ci  SAVED_VALGRIND_CMD="$VALGRIND_CMD"
148da0c48c4Sopenharmony_ci  unset VALGRIND_CMD
149da0c48c4Sopenharmony_ci
150da0c48c4Sopenharmony_ci  # Wait for lock for 10 seconds or skip.
151da0c48c4Sopenharmony_ci  flock -x -w 10 200 || exit 77;
152da0c48c4Sopenharmony_ci
153da0c48c4Sopenharmony_ci  # Skip the test if we cannot adjust core ulimit.
154da0c48c4Sopenharmony_ci  pid="`ulimit -c unlimited || exit 77; set +ex; testrun ${abs_builddir}/$child --gencore; true`"
155da0c48c4Sopenharmony_ci  core="core.$pid"
156da0c48c4Sopenharmony_ci  # see if /proc/sys/kernel/core_uses_pid is set to 0
157da0c48c4Sopenharmony_ci  if [ -f core ]; then
158da0c48c4Sopenharmony_ci    mv core "$core"
159da0c48c4Sopenharmony_ci  fi
160da0c48c4Sopenharmony_ci  type -P coredumpctl && have_coredumpctl=1 || have_coredumpctl=0
161da0c48c4Sopenharmony_ci  if [ ! -f "$core" -a $have_coredumpctl -eq 1 ]; then
162da0c48c4Sopenharmony_ci    # Maybe systemd-coredump took it. But give it some time to dump first...
163da0c48c4Sopenharmony_ci    sleep 1
164da0c48c4Sopenharmony_ci    coredumpctl --output="$core" dump $pid || rm -f $core
165da0c48c4Sopenharmony_ci
166da0c48c4Sopenharmony_ci    # Try a couple of times after waiting some more if something went wrong...
167da0c48c4Sopenharmony_ci    if [ ! -f "$core" ]; then
168da0c48c4Sopenharmony_ci      sleep 2
169da0c48c4Sopenharmony_ci      coredumpctl --output="$core" dump $pid || rm -f $core
170da0c48c4Sopenharmony_ci    fi
171da0c48c4Sopenharmony_ci
172da0c48c4Sopenharmony_ci    if [ ! -f "$core" ]; then
173da0c48c4Sopenharmony_ci      sleep 3
174da0c48c4Sopenharmony_ci      coredumpctl --output="$core" dump $pid || rm -f $core
175da0c48c4Sopenharmony_ci    fi
176da0c48c4Sopenharmony_ci  fi
177da0c48c4Sopenharmony_ci  if [ ! -f "$core" ]; then
178da0c48c4Sopenharmony_ci    # In some containers our view of pids is confused. Since tests are
179da0c48c4Sopenharmony_ci    # run in a new fresh directory any core here is most like is ours.
180da0c48c4Sopenharmony_ci    if ls core.[0-9]* 1> /dev/null 2>&1; then
181da0c48c4Sopenharmony_ci      mv core.[0-9]* "$core"
182da0c48c4Sopenharmony_ci    fi
183da0c48c4Sopenharmony_ci  fi
184da0c48c4Sopenharmony_ci  if [ ! -f "$core" ]; then
185da0c48c4Sopenharmony_ci    echo "No $core file generated";
186da0c48c4Sopenharmony_ci    exit 77;
187da0c48c4Sopenharmony_ci  fi
188da0c48c4Sopenharmony_ci
189da0c48c4Sopenharmony_ci  if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
190da0c48c4Sopenharmony_ci    VALGRIND_CMD="$SAVED_VALGRIND_CMD"
191da0c48c4Sopenharmony_ci    export VALGRIND_CMD
192da0c48c4Sopenharmony_ci  fi
193da0c48c4Sopenharmony_ci
194da0c48c4Sopenharmony_ci  # Do not abort on non-zero exit code due to some warnings of ./backtrace
195da0c48c4Sopenharmony_ci  # - see function check_err.
196da0c48c4Sopenharmony_ci  tempfiles $core{,.{bt,err}}
197da0c48c4Sopenharmony_ci  (set +ex; testrun ${abs_builddir}/backtrace -e ${abs_builddir}/$child --core=$core 1>$core.bt 2>$core.err; true)
198da0c48c4Sopenharmony_ci  cat $core.{bt,err}
199da0c48c4Sopenharmony_ci  check_native_unsupported $core.err $child-$core
200da0c48c4Sopenharmony_ci  check_all $core.{bt,err} $child-$core
201da0c48c4Sopenharmony_ci  rm $core{,.{bt,err}}
202da0c48c4Sopenharmony_ci) 200>${abs_builddir}/core-dump-backtrace.lock
203da0c48c4Sopenharmony_ci}
204