[COMMITTED] tests: Add backtrace_child_biarch_SOURCES to make distcheck happy.
by Mark Wielaard
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 4 ++++
tests/Makefile.am | 1 +
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 44f4ef6..0081981 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,9 @@
2013-12-10 Mark Wielaard <mjw(a)redhat.com>
+ * Makefile.am (backtrace_child_biarch_SOURCES): New backtrace-child.c.
+
+2013-12-10 Mark Wielaard <mjw(a)redhat.com>
+
* Makefile.am (valgrind_cmd): Remove --trace-children=yes.
* backtrace-subr.sh (check_native_core): Disable valgrind while
dumping core.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 006b232..75a16bd 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -378,6 +378,7 @@ backtrace_LDADD = $(libdw) $(libelf) $(libmudflap)
# backtrace-child-biarch also uses those *_CFLAGS and *_LDLAGS variables:
backtrace_child_CFLAGS = -fPIE
backtrace_child_LDFLAGS = -pie -pthread
+backtrace_child_biarch_SOURCES = backtrace-child.c
backtrace_data_LDADD = $(libdw) $(libelf) $(libmudflap)
backtrace_dwarf_CFLAGS = -Wno-unused-parameter
backtrace_dwarf_LDADD = $(libdw) $(libelf) $(libmudflap)
--
1.7.1
10 years, 4 months
[PATCH] libdw: Handle empty location expression for (indirect) DIE locations.
by Mark Wielaard
During a discussion on irc and offlist Josh pointed out that tests/varlocs
didn't cleanly handly all of the vmlinux kernel debuginfo. That was because
it flagged a DIE referring to another DIE that didn't actually have an
DW_AT_location as DWARF_E_INVALID_DWARF. Causing varlocs to error out.
But Jakub pointed out that isn't correct. It is valid DWARF, it just means
the dereferrenced value of the synthetic pointer isn't available. So this
patch makes sure that in such situations we don't return an error but just
an empty location expression.
With this varlocs can handle all of the vmlinux debuginfo on my machine.
<- snip ->
When dwarf_getlocation_implicit_pointer and dwarf_getlocation_attr
refer to a DIE that doesn't contain a DW_AT_location then don't generate
an error, but return an empty location expression to signal the actual
value pointed to is not available. This isn't invalid DWARF. Also make
sure that __libdw_intern_expression handles empty location expressions.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdw/ChangeLog | 11 +++++++++++
libdw/dwarf_getlocation.c | 11 +++++++++--
libdw/dwarf_getlocation_attr.c | 8 ++++----
libdw/dwarf_getlocation_implicit_pointer.c | 16 ++++++++++++++--
libdw/libdwP.h | 4 ++++
tests/ChangeLog | 5 +++++
tests/varlocs.c | 2 +-
7 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 91e1083..79bb4b5 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,14 @@
+2013-12-09 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwarf_getlocation.c (__libdw_intern_expression): Handle empty
+ location expressions.
+ * dwarf_getlocation_attr.c (dwarf_getlocation_attr): When no
+ location found, return empty location expression.
+ * dwarf_getlocation_implicit_pointer.c
+ (dwarf_getlocation_implicit_pointer): Likewise.
+ (__libdw_empty_loc_attr): New internal function.
+ * libdwP.h (__libdw_empty_loc_attr): Define.
+
2013-11-27 Mark Wielaard <mjw(a)redhat.com>
* libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index ff25fc7..4124ae3 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -202,6 +202,13 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
+ /* Empty location expressions don't have any ops to intern. */
+ if (block->length == 0)
+ {
+ *listlen = 0;
+ return 0;
+ }
+
/* Check whether we already looked at this list. */
struct loc_s fake = { .addr = block->data };
struct loc_s **found = tfind (&fake, cache, loc_compare);
@@ -465,8 +472,8 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
if (unlikely (n == 0))
{
/* This is not allowed.
-
- XXX Is it? */
+ It would mean an empty location expression, which we handled
+ already as a special case above. */
goto invalid;
}
diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c
index bf15584..cb29045 100644
--- a/libdw/dwarf_getlocation_attr.c
+++ b/libdw/dwarf_getlocation_attr.c
@@ -74,8 +74,8 @@ dwarf_getlocation_attr (attr, op, result)
return -1;
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
@@ -88,8 +88,8 @@ dwarf_getlocation_attr (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
diff --git a/libdw/dwarf_getlocation_implicit_pointer.c b/libdw/dwarf_getlocation_implicit_pointer.c
index 322fdb8..f93d17e 100644
--- a/libdw/dwarf_getlocation_implicit_pointer.c
+++ b/libdw/dwarf_getlocation_implicit_pointer.c
@@ -34,6 +34,18 @@
#include <dwarf.h>
+static unsigned char empty_exprloc = 0;
+
+void
+internal_function
+__libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu )
+{
+ attr->code = DW_AT_location;
+ attr->form = DW_FORM_exprloc;
+ attr->valp = &empty_exprloc;
+ attr->cu = cu;
+}
+
int
dwarf_getlocation_implicit_pointer (attr, op, result)
Dwarf_Attribute *attr;
@@ -57,8 +69,8 @@ dwarf_getlocation_implicit_pointer (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
return 0;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index f02a5bf..35ab6e7 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -632,6 +632,10 @@ int __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
internal_function;
#endif /* ENABLE_DWZ */
+/* Fills in the given attribute to point at an empty location expression. */
+void __libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu)
+ internal_function;
+
/* Aliases to avoid PLTs. */
INTDECL (dwarf_aggregate_size)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9e4cd9a..31638d3 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-09 Mark Wielaard <mjw(a)redhat.com>
+
+ * varlocs.c (print_expr): Update comment to explain empty location
+ associated with DW_OP_GNU_implicit_pointer.
+
2013-12-05 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Fix test FAIL with -O2.
diff --git a/tests/varlocs.c b/tests/varlocs.c
index 6f4d490..04f17ff 100644
--- a/tests/varlocs.c
+++ b/tests/varlocs.c
@@ -404,7 +404,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
int locs = dwarf_getlocation_addr (&attrval, addr,
&exprval, &exprval_len, 1);
if (locs == 0)
- printf ("<no location>"); // XXX should that be flagged?
+ printf ("<no location>"); // This means "optimized out".
else if (locs == 1)
print_expr_block (&attrval, exprval, exprval_len, addr);
else
--
1.7.1
10 years, 4 months
[PATCH] Add config/ar-lib to .gitignore
by Josh Stone
Signed-off-by: Josh Stone <jistone(a)redhat.com>
---
.gitignore | 1 +
ChangeLog | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/.gitignore b/.gitignore
index d463556328fe..1eda00b80774 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@ config.h
config.h.in
config.log
config.status
+config/ar-lib
config/config.guess
config/config.sub
config/depcomp
diff --git a/ChangeLog b/ChangeLog
index 1347f1fe7602..c1a42ee5a65d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-09 Josh Stone <jistone(a)redhat.com>
+
+ * .gitignore: Add config/ar-lib, installed due to AM_PROG_AR.
+
2013-12-02 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* configure.ac (CC_BIARCH): Remove AS_IF for it.
--
1.8.4.2
10 years, 4 months
[patch 1/2] Code cleanup: Reindentation
by Jan Kratochvil
Hi Mark,
not sure why it was written this way, I find it easier for the later patch not
to nest too deep.
Thanks,
Jan
libdwfl/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Code cleanup.
* core-file.c (dwfl_core_file_report): Reindent block of code by
continue keyword.
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -500,34 +500,35 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
lastmodp = &(*lastmodp)->next;
for (struct r_debug_info_module *module = r_debug_info.module;
module != NULL; module = module->next)
- if (module->elf != NULL)
- {
- Dwfl_Module *mod;
- mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
- module->fd, module->elf, module->l_addr,
- true, true);
- if (mod == NULL)
- continue;
- module->elf = NULL;
- module->fd = -1;
- /* Move this module to the end of the list, so that we end
- up with a list in the same order as the link_map chain. */
- if (mod->next != NULL)
- {
- if (*lastmodp != mod)
- {
- lastmodp = &dwfl->modulelist;
- while (*lastmodp != mod)
- lastmodp = &(*lastmodp)->next;
- }
- *lastmodp = mod->next;
- mod->next = NULL;
- while (*lastmodp != NULL)
- lastmodp = &(*lastmodp)->next;
- *lastmodp = mod;
- }
- lastmodp = &mod->next;
- }
+ {
+ if (module->elf == NULL)
+ continue;
+ Dwfl_Module *mod;
+ mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
+ module->fd, module->elf, module->l_addr,
+ true, true);
+ if (mod == NULL)
+ continue;
+ module->elf = NULL;
+ module->fd = -1;
+ /* Move this module to the end of the list, so that we end
+ up with a list in the same order as the link_map chain. */
+ if (mod->next != NULL)
+ {
+ if (*lastmodp != mod)
+ {
+ lastmodp = &dwfl->modulelist;
+ while (*lastmodp != mod)
+ lastmodp = &(*lastmodp)->next;
+ }
+ *lastmodp = mod->next;
+ mod->next = NULL;
+ while (*lastmodp != NULL)
+ lastmodp = &(*lastmodp)->next;
+ *lastmodp = mod;
+ }
+ lastmodp = &mod->next;
+ }
clear_r_debug_info (&r_debug_info);
10 years, 4 months
FYI unwinder: tests/ update
by Jan Kratochvil
Hi Mark,
as you requested I have commented more the tests/ part.
It is in: jankratochvil/unwindx86
Thanks,
Jan
diff --git a/tests/backtrace.c b/tests/backtrace.c
index e50399b..36995bc 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -162,7 +162,7 @@ frame_callback (Dwfl_Frame *state, void *frame_arg)
if (! dwfl_frame_pc (state, &pc, &isactivation))
{
error (0, 0, "%s", dwfl_errmsg (-1));
- return 1;
+ return DWARF_CB_ABORT;
}
Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
@@ -204,8 +204,8 @@ thread_callback (Dwfl_Thread *thread, void *thread_arg)
{
case 0:
break;
- case 1:
- return 1;
+ case DWARF_CB_ABORT:
+ return DWARF_CB_ABORT;
case -1:
error (0, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
/* All platforms do not have yet proper unwind termination. */
@@ -232,17 +232,17 @@ dump (pid_t pid, const char *corefile, callback_t *callback,
struct thread_callback thread_callback_data;
thread_callback_data.callback = callback;
thread_callback_data.callback_data = callback_data;
- int err = 0;
+ bool err = false;
switch (dwfl_getthreads (dwfl, thread_callback, &thread_callback_data))
{
case 0:
break;
- case 1:
- err = 1;
+ case DWARF_CB_ABORT:
+ err = true;
break;
case -1:
error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
- err = 1;
+ err = true;
break;
default:
abort ();
diff --git a/tests/run-backtrace.sh b/tests/run-backtrace.sh
index 3f77da3..8e02403 100755
--- a/tests/run-backtrace.sh
+++ b/tests/run-backtrace.sh
@@ -17,32 +17,23 @@
. $srcdir/test-subr.sh
-if [ -z "$VERBOSE" ]; then
- exec >/dev/null
-else
- set -x
-fi
-
-mytestrun()
-{
- echo "$*"
- testrun "$@"
-}
-
+# Verify one of the backtraced threads contains function 'main'.
check_main()
{
if grep -w main $1; then
return
fi
- cat >&2 $1 $3
echo >&2 $2: no main
false
}
+# Without proper ELF symbols resolution we could get inappropriate weak
+# symbol "gsignal" with the same address as the correct symbol "raise".
+# It was fixed by GIT commit 78dec228b3cfb2f9300cd0b682ebf416c9674c91 .
+# [patch] Improve ELF symbols preference (global > weak)
+# https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/0026...
check_gsignal()
{
- # Without proper ELF symbols resolution we could get inappropriate weak
- # symbol "gsignal" with the same address as the correct symbol "raise".
if ! grep -w gsignal $1; then
return
fi
@@ -51,12 +42,15 @@ check_gsignal()
false
}
+# Verify the STDERR output does not contain unexpected errors.
+# In some cases we cannot reliably find out we got behind _start as some
+# operating system do not properly terminate CFI by undefined PC.
+# Ignore it here as it is a bug of OS, not a bug of elfutils.
check_err()
{
if test ! -s $1; then
return
fi
- # In some cases we cannot reliably find out we got behind _start.
if cmp -s <(echo "${abs_builddir}/backtrace: dwfl_thread_getframes: no matching address range") <(uniq <$1); then
return
fi
@@ -65,19 +59,36 @@ check_err()
false
}
+check_all()
+{
+ bt=$1
+ err=$2
+ testname=$3
+ cat $bt $err
+ check_main $bt $testname
+ check_gsignal $bt $testname
+ check_err $err $testname
+}
+
+# Test both 64-bit and 32-bit tracees. Both files will be the same if the
+# current platform does not support different target archs.
for child in backtrace-child{,-biarch}; do
- tempfiles $child{.bt,.err}
+
+ # Backtrace live process.
+ # Do not abort on non-zero exit code due to some warnings of ./backtrace
+ # - see function check_err.
+ tempfiles $child.{bt,err}
(set +ex; testrun ${abs_builddir}/backtrace ${abs_builddir}/$child 1>$child.bt 2>$child.err; true)
- check_main $child.bt $child $child.err
- check_gsignal $child.bt $child
- check_err $child.err $child
+ check_all $child.{bt,err} $child
+
+ # Backtrace core file.
core="core.`ulimit -c unlimited; set +ex; testrun ${abs_builddir}/$child --gencore --run; true`"
- tempfiles $core{,.bt,.err}
+ # Do not abort on non-zero exit code due to some warnings of ./backtrace
+ # - see function check_err.
+ tempfiles $core{,.{bt,err}}
(set +ex; testrun ${abs_builddir}/backtrace ${abs_builddir}/$child $core 1>$core.bt 2>$core.err; true)
- cat $core.{bt,err}
- check_main $core.bt $child-$core $core.err
- check_gsignal $core.bt $child-$core
- check_err $core.err $child-$core
+ check_all $core.{bt,err} $child-$core
+
done
exit 0
10 years, 4 months
[COMMITTED] tests: SKIP backtrace-data and backtrace-dwarf on unsupported arches.
by Mark Wielaard
run-backtrace-data.sh did check stderr whether the arch was unsupported
but the test didn't print that message yet. backtrace-dwarf did print
the message but was missing a check_unsupported test. Also add an explicit
check_main test for backtrace-dwarf.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 5 +++++
tests/backtrace-data.c | 4 +++-
tests/run-backtrace-dwarf.sh | 8 ++++++--
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index b366689..8992568 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-05 Mark Wielaard <mjw(a)redhat.com>
+
+ * backtrace-data.c (main): If unsupported also print to stderr.
+ * run-backtrace-dwarf.sh: Add check_unsupported and check_main.
+
2013-12-04 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (backtrace-child-biarch): Add $(EXEEXT).
diff --git a/tests/backtrace-data.c b/tests/backtrace-data.c
index f54263b..6d21345 100644
--- a/tests/backtrace-data.c
+++ b/tests/backtrace-data.c
@@ -43,8 +43,10 @@
#ifndef __x86_64__
int
-main (void)
+main (int argc __attribute__ ((unused)), char **argv)
{
+ fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
+ argv[0]);
return 77;
}
diff --git a/tests/run-backtrace-dwarf.sh b/tests/run-backtrace-dwarf.sh
index b24215e..2f4ba0f 100755
--- a/tests/run-backtrace-dwarf.sh
+++ b/tests/run-backtrace-dwarf.sh
@@ -15,6 +15,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-. $srcdir/test-subr.sh
+. $srcdir/backtrace-subr.sh
-testrun ${abs_builddir}/backtrace-dwarf
+tempfiles dwarf.{bt,err}
+(set +ex; testrun ${abs_builddir}/backtrace-dwarf 1>dwarf.bt 2>dwarf.err; true)
+cat dwarf.{bt,err}
+check_unsupported dwarf.err dwarf
+check_main dwarf.bt dwarf
--
1.7.1
10 years, 4 months
[COMMITTED] tests: automake 1.13 compatibility fix.
by Mark Wielaard
tests/Makefile.am:65: warning: deprecated feature: target
'backtrace-child-biarch' overrides 'backtrace-child-biarch$(EXEEXT)'
tests/Makefile.am:65: change your target to read
'backtrace-child-biarch$(EXEEXT)'
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 4 ++++
tests/Makefile.am | 2 +-
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9bd2fe8..b366689 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-04 Mark Wielaard <mjw(a)redhat.com>
+
+ * Makefile.am (backtrace-child-biarch): Add $(EXEEXT).
+
2013-12-02 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* Makefile.am (check_PROGRAMS): Add backtrace, backtrace-child,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a74830b..fbcc752 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -62,7 +62,7 @@ check_PROGRAMS += backtrace-child-biarch
endif
# Substitute $(COMPILE).
-backtrace-child-biarch: backtrace-child.c
+backtrace-child-biarch$(EXEEXT): backtrace-child.c
$(CC_BIARCH) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS) $(backtrace_child_CFLAGS) \
--
1.7.1
10 years, 4 months
[unwinder-portable] [patch 3/3] Older OS compatibility bits
by Jan Kratochvil
Hi Mark,
this patch is for the branch 'portable' to be checked in wotj
'jankratochvil/unwindx86', that is for RHEL-5 systems.
It has been verified it is not needed on RHEL-6.
I guess these three patches can be checked into the 'portable' branch
together.
Thanks,
Jan
libdwfl/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Older OS compatibility bits.
* linux-core-attach.c (be64toh, le64toh, be32toh, le32toh): Provide
fallbacks if not defined by system.
tests/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Older OS compatibility bits.
* backtrace-child.c (main): Ignore non-zero ERRNO after pthread_create.
* run-backtrace.sh (check_err): Permit also No DWARF information found.
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -29,6 +29,35 @@
#include "libdwflP.h"
#include <fcntl.h>
#include "system.h"
+#include <endian.h>
+#include <byteswap.h>
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# ifndef be64toh
+# define be64toh(x) bswap_64 (x)
+# endif
+# ifndef le64toh
+# define le64toh(x) (x)
+# endif
+# ifndef be32toh
+# define be32toh(x) bswap_32 (x)
+# endif
+# ifndef le32toh
+# define le32toh(x) (x)
+# endif
+#else
+# ifndef be64toh
+# define be64toh(x) (x)
+# endif
+# ifndef le64toh
+# define le64toh(x) bswap_64 (x)
+# endif
+# ifndef be32toh
+# define be32toh(x) (x)
+# endif
+# ifndef le32toh
+# define le32toh(x) bswap_32 (x)
+# endif
+#endif
#ifndef MIN
# define MIN(a, b) ((a) < (b) ? (a) : (b))
--- a/tests/backtrace-child.c
+++ b/tests/backtrace-child.c
@@ -141,7 +141,7 @@ main (int argc UNUSED, char **argv)
errno = 0;
pthread_t thread;
int i = pthread_create (&thread, NULL, start, NULL);
- assert_perror (errno);
+ errno = 0; // assert_perror (errno); // RHEL-5 may set errno with i == 0
assert (i == 0);
if (ptraceme)
{
--- a/tests/run-backtrace.sh
+++ b/tests/run-backtrace.sh
@@ -60,6 +60,10 @@ check_err()
if cmp -s <(echo "${abs_builddir}/backtrace: dwfl_thread_getframes: no matching address range") <(uniq <$1); then
return
fi
+ if cmp -s <(echo "${abs_builddir}/backtrace: dwfl_thread_getframes: No DWARF information found";
+ echo "${abs_builddir}/backtrace: dwfl_thread_getframes: no matching address range") <(sort -u <$1); then
+ return
+ fi
cat >&2 $1
echo >&2 $2: neither empty nor just out of DWARF
false
10 years, 4 months
[unwinder-portable] [patch 2/3] tests/ Handle missing CFI in .plt
by Jan Kratochvil
Hi Mark,
this patch is for the branch 'portable' to be checked in wotj
'jankratochvil/unwindx86', that is for RHEL-5 systems.
It has been verified it is not needed on RHEL-6.
Jakub Jelinek fixed GNU ld (gold is also fixed now) to provide CFI also for
.plt. But RHEL-5 still does not have it present.
The testsuite was explicitly testing unwinding for .plt. Disable it.
I guess these three patches can be checked into the 'portable' branch
together.
Thanks,
Jan
tests/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Handle missing CFI in .plt
(selfdump_callback): Update frame #0 for function raise.
(prepare_thread): Do not single-step into .plt.
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -297,8 +297,10 @@ selfdump_callback (pid_t tid, unsigned frameno, Dwarf_Addr pc,
switch (frameno)
{
case 0:
- /* .plt has no symbols. */
- assert (symname == NULL);
+ // RHEL-5 has no .plt CFI.
+ assert (symname != NULL && strcmp (symname, "raise") == 0);
+ // /* .plt has no symbols. */
+ // assert (symname == NULL);
break;
case 1:
assert (symname != NULL && strcmp (symname, "sigusr2") == 0);
@@ -346,6 +348,7 @@ prepare_thread (pid_t pid2, Dwarf_Addr plt_start, Dwarf_Addr plt_end,
assert (got == pid2);
assert (WIFSTOPPED (status));
assert (WSTOPSIG (status) == SIGUSR1);
+ return; // RHEL-5 has no .plt CFI.
for (;;)
{
errno = 0;
10 years, 4 months
[unwinder-portable patch 1/3] Handle T-stopped detach for old kernels
by Jan Kratochvil
Hi Mark,
this patch is for the branch 'portable' to be checked in wotj
'jankratochvil/unwindx86', that is for RHEL-5 systems.
It has been verified it is not needed on RHEL-6 (despite RHEL-6 is not yet so
forgiving wrt SIGSTOP like the most recent Linux kernels are).
RHEL-5 kernels were not enough with
ptrace (PTRACE_DETACH, tid, NULL, SIGSTOP);
and they need to explicitly
syscall (__NR_tkill, tid, SIGSTOP);
beforehand.
Moreover for a short time after such PTRACE_DETACH the TID's /proc/PID/status
State may be R (running), so if one tries to PTRACE_ATTACH that time again the
attacher will not notice the process in fact should be T (stopped). Therefore
it detaches the process without __NR_tkill SIGSTOP and the process is no
longer stopped, as it should have been.
For GDB it is handled by:
http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-rhel5-compat.patch
Thanks,
Jan
libdwfl/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Handle T-stopped detach for old kernels.
* linux-pid-attach.c (struct pid_arg): New field stopped.
(ptrace_attach): New parameter stoppedp. Set it appropriately.
(pid_set_initial_registers): Pass the new field.
(pid_thread_detach): Handle the case of STOPPED for old kernels.
(__libdwfl_attach_state_for_pid): Initialize STOPPED.
tests/
2013-11-01 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Handle T-stopped detach for old kernels.
* backtrace.c: Include sys/syscall.h.
(linux_proc_pid_is_stopped): New function.
(ptrace_detach_stopped): Handle old kernels.
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -42,6 +42,8 @@ struct pid_arg
DIR *dir;
/* It is 0 if not used. */
pid_t tid_attached;
+ /* TRUE if the process (first of its threads) was State: T (stopped). */
+ bool stopped;
};
static bool
@@ -69,7 +71,7 @@ linux_proc_pid_is_stopped (pid_t pid)
}
static bool
-ptrace_attach (pid_t tid)
+ptrace_attach (pid_t tid, bool *stoppedp)
{
if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
{
@@ -84,6 +86,7 @@ ptrace_attach (pid_t tid)
above. Which would make the waitpid below wait forever. So emulate
it. Since there can only be one SIGSTOP notification pending this is
safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
+ *stoppedp = true;
syscall (__NR_tkill, tid, SIGSTOP);
ptrace (PTRACE_CONT, tid, NULL, NULL);
}
@@ -213,7 +216,7 @@ pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
struct pid_arg *pid_arg = thread_arg;
assert (pid_arg->tid_attached == 0);
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
- if (! ptrace_attach (tid))
+ if (! ptrace_attach (tid, &pid_arg->stopped))
return false;
pid_arg->tid_attached = tid;
Dwfl_Process *process = thread->process;
@@ -237,7 +240,18 @@ pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
assert (pid_arg->tid_attached == tid);
pid_arg->tid_attached = 0;
- ptrace (PTRACE_DETACH, tid, NULL, NULL);
+ if (! pid_arg->stopped)
+ {
+ ptrace (PTRACE_DETACH, tid, NULL, NULL);
+ return;
+ }
+ syscall (__NR_tkill, tid, SIGSTOP);
+ ptrace (PTRACE_DETACH, tid, NULL, (void *) (intptr_t) SIGSTOP);
+ // Wait till the SIGSTOP settles down.
+ int i;
+ for (i = 0; i < 100000; i++)
+ if (linux_proc_pid_is_stopped (tid))
+ break;
}
static const Dwfl_Thread_Callbacks pid_thread_callbacks =
@@ -271,6 +285,7 @@ __libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
}
pid_arg->dir = dir;
pid_arg->tid_attached = 0;
+ pid_arg->stopped = false;
if (! INTUSE(dwfl_attach_state) (dwfl, EM_NONE, pid, &pid_thread_callbacks,
pid_arg))
{
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -35,6 +35,7 @@
#include <sys/user.h>
#include <fcntl.h>
#include <string.h>
+#include <sys/syscall.h>
#include ELFUTILS_HEADER(dwfl)
static void
@@ -370,13 +371,43 @@ prepare_thread (pid_t pid2, Dwarf_Addr plt_start, Dwarf_Addr plt_end,
#include <unistd.h>
#define tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
+static bool
+linux_proc_pid_is_stopped (pid_t pid)
+{
+ char buffer[64];
+ FILE *procfile;
+ bool retval, have_state;
+
+ snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
+ procfile = fopen (buffer, "r");
+ if (procfile == NULL)
+ return false;
+
+ have_state = false;
+ while (fgets (buffer, sizeof (buffer), procfile) != NULL)
+ if (strncmp (buffer, "State:", 6) == 0)
+ {
+ have_state = true;
+ break;
+ }
+ retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
+ fclose (procfile);
+ return retval;
+}
+
static void
ptrace_detach_stopped (pid_t pid)
{
+ syscall (__NR_tkill, pid, SIGSTOP);
errno = 0;
long l = ptrace (PTRACE_DETACH, pid, NULL, (void *) (intptr_t) SIGSTOP);
assert_perror (errno);
assert (l == 0);
+ // Wait till the SIGSTOP settles down.
+ int i;
+ for (i = 0; i < 100000; i++)
+ if (linux_proc_pid_is_stopped (pid))
+ break;
}
static void
10 years, 4 months