mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2024-11-30 17:04:22 +01:00
Minidumps never contain MD_LINUX_DSO_DEBUG info when breakpad is in a shared library
A=Mike Hommey <mh@glandium.org> R=ted at http://breakpad.appspot.com/422002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1044 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
67364c1326
commit
0e91d185ca
38
Makefile.am
38
Makefile.am
@ -32,7 +32,7 @@
|
||||
|
||||
# This allows #includes to be relative to src/
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
AM_CFLAGS =
|
||||
AM_CXXFLAGS =
|
||||
|
||||
if ANDROID_HOST
|
||||
@ -53,6 +53,12 @@ AM_CXXFLAGS += \
|
||||
-Werror=overloaded-virtual
|
||||
endif
|
||||
|
||||
if LINUX_HOST
|
||||
# Build as PIC on Linux, for linux_client_unittest_shlib
|
||||
AM_CFLAGS += -fPIC
|
||||
AM_CXXFLAGS += -fPIC
|
||||
endif
|
||||
|
||||
# Specify include paths for ac macros
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
@ -281,6 +287,9 @@ check_PROGRAMS += \
|
||||
endif
|
||||
|
||||
if LINUX_HOST
|
||||
EXTRA_PROGRAMS = \
|
||||
src/client/linux/linux_client_unittest_shlib
|
||||
|
||||
check_PROGRAMS += \
|
||||
src/client/linux/linux_client_unittest
|
||||
|
||||
@ -321,7 +330,7 @@ src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(PTHREAD_CFLAGS)
|
||||
src_client_linux_linux_dumper_unittest_helper_LDFLAGS=$(PTHREAD_CFLAGS)
|
||||
src_client_linux_linux_dumper_unittest_helper_CC=$(PTHREAD_CC)
|
||||
|
||||
src_client_linux_linux_client_unittest_SOURCES = \
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES = \
|
||||
src/client/linux/handler/exception_handler_unittest.cc \
|
||||
src/client/linux/minidump_writer/directory_reader_unittest.cc \
|
||||
src/client/linux/minidump_writer/line_reader_unittest.cc \
|
||||
@ -343,17 +352,20 @@ src_client_linux_linux_client_unittest_SOURCES = \
|
||||
src/processor/minidump.cc \
|
||||
src/processor/pathname_stripper.cc
|
||||
if ANDROID_HOST
|
||||
src_client_linux_linux_client_unittest_SOURCES += \
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES += \
|
||||
src/common/android/breakpad_getcontext.S
|
||||
endif
|
||||
|
||||
src_client_linux_linux_client_unittest_CPPFLAGS = \
|
||||
src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
src_client_linux_linux_client_unittest_LDADD = \
|
||||
src_client_linux_linux_client_unittest_shlib_LDFLAGS = \
|
||||
-shared \
|
||||
-Wl,-h,linux_client_unittest_shlib
|
||||
src_client_linux_linux_client_unittest_shlib_LDADD = \
|
||||
src/client/linux/handler/exception_handler.o \
|
||||
src/client/linux/handler/minidump_descriptor.o \
|
||||
src/client/linux/log/log.o \
|
||||
@ -373,17 +385,27 @@ src_client_linux_linux_client_unittest_LDADD = \
|
||||
src/common/string_conversion.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
if ANDROID_HOST
|
||||
src_client_linux_linux_client_unittest_SOURCES += \
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES += \
|
||||
src/common/android/breakpad_getcontext_unittest.cc
|
||||
src_client_linux_linux_client_unittest_LDFLAGS = \
|
||||
src_client_linux_linux_client_unittest_shlib_LDFLAGS += \
|
||||
-llog
|
||||
endif
|
||||
|
||||
src_client_linux_linux_client_unittest_DEPENDENCIES = \
|
||||
src_client_linux_linux_client_unittest_shlib_DEPENDENCIES = \
|
||||
src/client/linux/linux_dumper_unittest_helper \
|
||||
src/client/linux/libbreakpad_client.a \
|
||||
src/libbreakpad.a
|
||||
|
||||
src_client_linux_linux_client_unittest_SOURCES =
|
||||
src_client_linux_linux_client_unittest_LDFLAGS = \
|
||||
-Wl,-rpath,'$$ORIGIN'
|
||||
|
||||
src_client_linux_linux_client_unittest_LDADD = \
|
||||
src/client/linux/linux_client_unittest_shlib
|
||||
|
||||
src_client_linux_linux_client_unittest_DEPENDENCIES = \
|
||||
src/client/linux/linux_client_unittest_shlib
|
||||
|
||||
if !DISABLE_TOOLS
|
||||
src_tools_linux_core2md_core2md_SOURCES = \
|
||||
src/tools/linux/core2md/core2md.cc \
|
||||
|
752
Makefile.in
752
Makefile.in
File diff suppressed because it is too large
Load Diff
10
aclocal.m4
vendored
10
aclocal.m4
vendored
@ -1,4 +1,4 @@
|
||||
# generated automatically by aclocal 1.11.3 -*- Autoconf -*-
|
||||
# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
|
||||
@ -14,8 +14,8 @@
|
||||
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
|
||||
[m4_warning([this file was generated for autoconf 2.68.
|
||||
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
|
||||
[m4_warning([this file was generated for autoconf 2.69.
|
||||
You have another version of autoconf. It may work, but is not guaranteed to.
|
||||
If you have problems, you may need to regenerate the build system entirely.
|
||||
To do so, use the procedure documented by the package, typically `autoreconf'.])])
|
||||
@ -38,7 +38,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
|
||||
[am__api_version='1.11'
|
||||
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
|
||||
dnl require some minimum version. Point them to the right macro.
|
||||
m4_if([$1], [1.11.3], [],
|
||||
m4_if([$1], [1.11.6], [],
|
||||
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
|
||||
])
|
||||
|
||||
@ -54,7 +54,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
|
||||
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
|
||||
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
|
||||
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
|
||||
[AM_AUTOMAKE_VERSION([1.11.3])dnl
|
||||
[AM_AUTOMAKE_VERSION([1.11.6])dnl
|
||||
m4_ifndef([AC_AUTOCONF_VERSION],
|
||||
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
|
||||
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
|
||||
|
@ -73,6 +73,9 @@ case $TEST_PROGRAM_NAME in
|
||||
# linux_client_unittest will call another executable at runtime, ensure
|
||||
# it is installed too.
|
||||
adb_install "$TEST_PROGRAM_DIR/linux_dumper_unittest_helper" "$TEST_DIR"
|
||||
# linux_client_unittest loads a shared library at runtime, ensure it is
|
||||
# installed too.
|
||||
adb_install "$TEST_PROGRAM_DIR/linux_client_unittest_shlib" "$TEST_DIR"
|
||||
;;
|
||||
basic_source_line_resolver_unittest)
|
||||
DATA_FILES="module1.out \
|
||||
@ -121,7 +124,7 @@ done
|
||||
adb_install "$TEST_PROGRAM" "$TEST_DIR"
|
||||
|
||||
# Run it
|
||||
adb_shell "cd $TEST_DIR && ./$TEST_PROGRAM_NAME $@"
|
||||
adb_shell "cd $TEST_DIR && LD_LIBRARY_PATH=. ./$TEST_PROGRAM_NAME $@"
|
||||
|
||||
# Note: exiting here will call cleanup_exit which will remove the temporary
|
||||
# files from the device.
|
||||
|
196
configure
vendored
196
configure
vendored
@ -1,13 +1,11 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.68 for breakpad 0.1.
|
||||
# Generated by GNU Autoconf 2.69 for breakpad 0.1.
|
||||
#
|
||||
# Report bugs to <google-breakpad-dev@googlegroups.com>.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
#
|
||||
#
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
@ -136,6 +134,31 @@ export LANGUAGE
|
||||
# CDPATH.
|
||||
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
|
||||
|
||||
# Use a proper internal environment variable to ensure we don't fall
|
||||
# into an infinite loop, continuously re-executing ourselves.
|
||||
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
|
||||
_as_can_reexec=no; export _as_can_reexec;
|
||||
# We cannot yet assume a decent shell, so we have to provide a
|
||||
# neutralization value for shells without unset; and this also
|
||||
# works around shells that cannot unset nonexistent variables.
|
||||
# Preserve -v and -x to the replacement shell.
|
||||
BASH_ENV=/dev/null
|
||||
ENV=/dev/null
|
||||
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
|
||||
case $- in # ((((
|
||||
*v*x* | *x*v* ) as_opts=-vx ;;
|
||||
*v* ) as_opts=-v ;;
|
||||
*x* ) as_opts=-x ;;
|
||||
* ) as_opts= ;;
|
||||
esac
|
||||
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
|
||||
# Admittedly, this is quite paranoid, since all the known shells bail
|
||||
# out after a failed `exec'.
|
||||
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
|
||||
as_fn_exit 255
|
||||
fi
|
||||
# We don't want this to propagate to other subprocesses.
|
||||
{ _as_can_reexec=; unset _as_can_reexec;}
|
||||
if test "x$CONFIG_SHELL" = x; then
|
||||
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
|
||||
emulate sh
|
||||
@ -169,7 +192,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
|
||||
else
|
||||
exitcode=1; echo positional parameters were not saved.
|
||||
fi
|
||||
test x\$exitcode = x0 || exit 1"
|
||||
test x\$exitcode = x0 || exit 1
|
||||
test -x / || exit 1"
|
||||
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
|
||||
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
|
||||
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
|
||||
@ -214,6 +238,7 @@ IFS=$as_save_IFS
|
||||
|
||||
|
||||
if test "x$CONFIG_SHELL" != x; then :
|
||||
export CONFIG_SHELL
|
||||
# We cannot yet assume a decent shell, so we have to provide a
|
||||
# neutralization value for shells without unset; and this also
|
||||
# works around shells that cannot unset nonexistent variables.
|
||||
@ -221,14 +246,17 @@ IFS=$as_save_IFS
|
||||
BASH_ENV=/dev/null
|
||||
ENV=/dev/null
|
||||
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
|
||||
export CONFIG_SHELL
|
||||
case $- in # ((((
|
||||
*v*x* | *x*v* ) as_opts=-vx ;;
|
||||
*v* ) as_opts=-v ;;
|
||||
*x* ) as_opts=-x ;;
|
||||
* ) as_opts= ;;
|
||||
esac
|
||||
exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
|
||||
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
|
||||
# Admittedly, this is quite paranoid, since all the known shells bail
|
||||
# out after a failed `exec'.
|
||||
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
|
||||
exit 255
|
||||
fi
|
||||
|
||||
if test x$as_have_required = xno; then :
|
||||
@ -331,6 +359,14 @@ $as_echo X"$as_dir" |
|
||||
|
||||
|
||||
} # as_fn_mkdir_p
|
||||
|
||||
# as_fn_executable_p FILE
|
||||
# -----------------------
|
||||
# Test if FILE is an executable regular file.
|
||||
as_fn_executable_p ()
|
||||
{
|
||||
test -f "$1" && test -x "$1"
|
||||
} # as_fn_executable_p
|
||||
# as_fn_append VAR VALUE
|
||||
# ----------------------
|
||||
# Append the text in VALUE to the end of the definition contained in VAR. Take
|
||||
@ -452,6 +488,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
|
||||
chmod +x "$as_me.lineno" ||
|
||||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
|
||||
|
||||
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
|
||||
# already done that, so ensure we don't try to do so again and fall
|
||||
# in an infinite loop. This has already happened in practice.
|
||||
_as_can_reexec=no; export _as_can_reexec
|
||||
# Don't try to exec as it changes $[0], causing all sort of problems
|
||||
# (the dirname of $[0] is not the place where we might find the
|
||||
# original and so on. Autoconf is especially sensitive to this).
|
||||
@ -486,16 +526,16 @@ if (echo >conf$$.file) 2>/dev/null; then
|
||||
# ... but there are two gotchas:
|
||||
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
|
||||
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
|
||||
# In both cases, we have to default to `cp -p'.
|
||||
# In both cases, we have to default to `cp -pR'.
|
||||
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
elif ln conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s=ln
|
||||
else
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
else
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
|
||||
rmdir conf$$.dir 2>/dev/null
|
||||
@ -507,28 +547,8 @@ else
|
||||
as_mkdir_p=false
|
||||
fi
|
||||
|
||||
if test -x / >/dev/null 2>&1; then
|
||||
as_test_x='test -x'
|
||||
else
|
||||
if ls -dL / >/dev/null 2>&1; then
|
||||
as_ls_L_option=L
|
||||
else
|
||||
as_ls_L_option=
|
||||
fi
|
||||
as_test_x='
|
||||
eval sh -c '\''
|
||||
if test -d "$1"; then
|
||||
test -d "$1/.";
|
||||
else
|
||||
case $1 in #(
|
||||
-*)set "./$1";;
|
||||
esac;
|
||||
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
|
||||
???[sx]*):;;*)false;;esac;fi
|
||||
'\'' sh
|
||||
'
|
||||
fi
|
||||
as_executable_p=$as_test_x
|
||||
as_executable_p=as_fn_executable_p
|
||||
|
||||
# Sed expression to map a string onto a valid CPP name.
|
||||
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
||||
@ -1201,8 +1221,6 @@ target=$target_alias
|
||||
if test "x$host_alias" != x; then
|
||||
if test "x$build_alias" = x; then
|
||||
cross_compiling=maybe
|
||||
$as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
|
||||
If a cross compiler is detected then cross compile mode will be used" >&2
|
||||
elif test "x$build_alias" != "x$host_alias"; then
|
||||
cross_compiling=yes
|
||||
fi
|
||||
@ -1455,9 +1473,9 @@ test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
breakpad configure 0.1
|
||||
generated by GNU Autoconf 2.68
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This configure script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it.
|
||||
_ACEOF
|
||||
@ -1650,7 +1668,7 @@ $as_echo "$ac_try_echo"; } >&5
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest$ac_exeext && {
|
||||
test "$cross_compiling" = yes ||
|
||||
$as_test_x conftest$ac_exeext
|
||||
test -x conftest$ac_exeext
|
||||
}; then :
|
||||
ac_retval=0
|
||||
else
|
||||
@ -1795,7 +1813,7 @@ This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by breakpad $as_me 0.1, which was
|
||||
generated by GNU Autoconf 2.68. Invocation command line was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
||||
@ -2284,7 +2302,7 @@ case $as_dir/ in #((
|
||||
# by default.
|
||||
for ac_prog in ginstall scoinst install; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
|
||||
if test $ac_prog = install &&
|
||||
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
|
||||
# AIX install. It has an incompatible calling convention.
|
||||
@ -2453,7 +2471,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_STRIP="${ac_tool_prefix}strip"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -2493,7 +2511,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_STRIP="strip"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -2544,7 +2562,7 @@ do
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_prog in mkdir gmkdir; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
{ test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
|
||||
as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
|
||||
case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
|
||||
'mkdir (GNU coreutils) '* | \
|
||||
'mkdir (coreutils) '* | \
|
||||
@ -2597,7 +2615,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_AWK="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -2892,7 +2910,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -2932,7 +2950,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -2985,7 +3003,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}cc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -3026,7 +3044,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
|
||||
ac_prog_rejected=yes
|
||||
continue
|
||||
@ -3084,7 +3102,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -3128,7 +3146,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -3574,8 +3592,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
struct stat;
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
@ -3943,7 +3960,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -3983,7 +4000,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="gcc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -4036,7 +4053,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="${ac_tool_prefix}cc"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -4077,7 +4094,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
|
||||
ac_prog_rejected=yes
|
||||
continue
|
||||
@ -4135,7 +4152,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -4179,7 +4196,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -4375,8 +4392,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
struct stat;
|
||||
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
|
||||
struct buf { int x; };
|
||||
FILE * (*rcsopen) (struct buf *, struct stat *, int);
|
||||
@ -4880,7 +4896,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -4924,7 +4940,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_CXX="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -5254,7 +5270,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -5294,7 +5310,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ac_ct_RANLIB="ranlib"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -5356,7 +5372,7 @@ do
|
||||
for ac_prog in grep ggrep; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
{ test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
|
||||
as_fn_executable_p "$ac_path_GREP" || continue
|
||||
# Check for GNU ac_path_GREP and select it if it is found.
|
||||
# Check for GNU $ac_path_GREP
|
||||
case `"$ac_path_GREP" --version 2>&1` in
|
||||
@ -5422,7 +5438,7 @@ do
|
||||
for ac_prog in egrep; do
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
|
||||
{ test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
|
||||
as_fn_executable_p "$ac_path_EGREP" || continue
|
||||
# Check for GNU ac_path_EGREP and select it if it is found.
|
||||
# Check for GNU $ac_path_EGREP
|
||||
case `"$ac_path_EGREP" --version 2>&1` in
|
||||
@ -5821,7 +5837,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_ax_pthread_config="yes"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -5982,7 +5998,7 @@ do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
ac_cv_prog_PTHREAD_CC="$ac_prog"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
@ -6658,16 +6674,16 @@ if (echo >conf$$.file) 2>/dev/null; then
|
||||
# ... but there are two gotchas:
|
||||
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
|
||||
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
|
||||
# In both cases, we have to default to `cp -p'.
|
||||
# In both cases, we have to default to `cp -pR'.
|
||||
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
elif ln conf$$.file conf$$ 2>/dev/null; then
|
||||
as_ln_s=ln
|
||||
else
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
else
|
||||
as_ln_s='cp -p'
|
||||
as_ln_s='cp -pR'
|
||||
fi
|
||||
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
|
||||
rmdir conf$$.dir 2>/dev/null
|
||||
@ -6727,28 +6743,16 @@ else
|
||||
as_mkdir_p=false
|
||||
fi
|
||||
|
||||
if test -x / >/dev/null 2>&1; then
|
||||
|
||||
# as_fn_executable_p FILE
|
||||
# -----------------------
|
||||
# Test if FILE is an executable regular file.
|
||||
as_fn_executable_p ()
|
||||
{
|
||||
test -f "$1" && test -x "$1"
|
||||
} # as_fn_executable_p
|
||||
as_test_x='test -x'
|
||||
else
|
||||
if ls -dL / >/dev/null 2>&1; then
|
||||
as_ls_L_option=L
|
||||
else
|
||||
as_ls_L_option=
|
||||
fi
|
||||
as_test_x='
|
||||
eval sh -c '\''
|
||||
if test -d "$1"; then
|
||||
test -d "$1/.";
|
||||
else
|
||||
case $1 in #(
|
||||
-*)set "./$1";;
|
||||
esac;
|
||||
case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
|
||||
???[sx]*):;;*)false;;esac;fi
|
||||
'\'' sh
|
||||
'
|
||||
fi
|
||||
as_executable_p=$as_test_x
|
||||
as_executable_p=as_fn_executable_p
|
||||
|
||||
# Sed expression to map a string onto a valid CPP name.
|
||||
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
|
||||
@ -6770,7 +6774,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by breakpad $as_me 0.1, which was
|
||||
generated by GNU Autoconf 2.68. Invocation command line was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
CONFIG_HEADERS = $CONFIG_HEADERS
|
||||
@ -6836,10 +6840,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
breakpad config.status 0.1
|
||||
configured by $0, generated by GNU Autoconf 2.68,
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
This config.status script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it."
|
||||
|
||||
@ -6930,7 +6934,7 @@ fi
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
if \$ac_cs_recheck; then
|
||||
set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
|
||||
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
|
||||
shift
|
||||
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
|
||||
CONFIG_SHELL='$SHELL'
|
||||
|
@ -66,20 +66,24 @@ inline static bool IsMappedFileOpenUnsafe(
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// All interesting auvx entry types are below AT_SYSINFO_EHDR
|
||||
#define AT_MAX AT_SYSINFO_EHDR
|
||||
|
||||
LinuxDumper::LinuxDumper(pid_t pid)
|
||||
: pid_(pid),
|
||||
crash_address_(0),
|
||||
crash_signal_(0),
|
||||
crash_thread_(0),
|
||||
threads_(&allocator_, 8),
|
||||
mappings_(&allocator_) {
|
||||
mappings_(&allocator_),
|
||||
auxv_(&allocator_, AT_MAX + 1) {
|
||||
}
|
||||
|
||||
LinuxDumper::~LinuxDumper() {
|
||||
}
|
||||
|
||||
bool LinuxDumper::Init() {
|
||||
return EnumerateThreads() && EnumerateMappings();
|
||||
return ReadAuxv() && EnumerateThreads() && EnumerateMappings();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -131,58 +135,30 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
return success;
|
||||
}
|
||||
|
||||
void*
|
||||
LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(pid_t pid) const {
|
||||
bool LinuxDumper::ReadAuxv() {
|
||||
char auxv_path[NAME_MAX];
|
||||
if (!BuildProcPath(auxv_path, pid, "auxv"))
|
||||
return NULL;
|
||||
if (!BuildProcPath(auxv_path, pid_, "auxv")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the AT_SYSINFO_EHDR entry for linux-gate.so
|
||||
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
|
||||
// information.
|
||||
int fd = sys_open(auxv_path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
elf_aux_entry one_aux_entry;
|
||||
bool res = false;
|
||||
while (sys_read(fd,
|
||||
&one_aux_entry,
|
||||
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
|
||||
one_aux_entry.a_type != AT_NULL) {
|
||||
if (one_aux_entry.a_type == AT_SYSINFO_EHDR) {
|
||||
sys_close(fd);
|
||||
return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
|
||||
if (one_aux_entry.a_type <= AT_MAX) {
|
||||
auxv_[one_aux_entry.a_type] = one_aux_entry.a_un.a_val;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
sys_close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void*
|
||||
LinuxDumper::FindEntryPoint(pid_t pid) const {
|
||||
char auxv_path[NAME_MAX];
|
||||
if (!BuildProcPath(auxv_path, pid, "auxv"))
|
||||
return NULL;
|
||||
|
||||
int fd = sys_open(auxv_path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find the AT_ENTRY entry
|
||||
elf_aux_entry one_aux_entry;
|
||||
while (sys_read(fd,
|
||||
&one_aux_entry,
|
||||
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
|
||||
one_aux_entry.a_type != AT_NULL) {
|
||||
if (one_aux_entry.a_type == AT_ENTRY) {
|
||||
sys_close(fd);
|
||||
return reinterpret_cast<void*>(one_aux_entry.a_un.a_val);
|
||||
}
|
||||
}
|
||||
sys_close(fd);
|
||||
return NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool LinuxDumper::EnumerateMappings() {
|
||||
@ -192,15 +168,17 @@ bool LinuxDumper::EnumerateMappings() {
|
||||
|
||||
// linux_gate_loc is the beginning of the kernel's mapping of
|
||||
// linux-gate.so in the process. It doesn't actually show up in the
|
||||
// maps list as a filename, so we use the aux vector to find it's
|
||||
// load location and special case it's entry when creating the list
|
||||
// of mappings.
|
||||
const void* linux_gate_loc;
|
||||
linux_gate_loc = FindBeginningOfLinuxGateSharedLibrary(pid_);
|
||||
// maps list as a filename, but it can be found using the AT_SYSINFO_EHDR
|
||||
// aux vector entry, which gives the information necessary to special
|
||||
// case its entry when creating the list of mappings.
|
||||
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
|
||||
// information.
|
||||
const void* linux_gate_loc =
|
||||
reinterpret_cast<void *>(auxv_[AT_SYSINFO_EHDR]);
|
||||
// Although the initial executable is usually the first mapping, it's not
|
||||
// guaranteed (see http://crosbug.com/25355); therefore, try to use the
|
||||
// actual entry point to find the mapping.
|
||||
const void* entry_point_loc = FindEntryPoint(pid_);
|
||||
const void* entry_point_loc = reinterpret_cast<void *>(auxv_[AT_ENTRY]);
|
||||
|
||||
const int fd = sys_open(maps_path, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
|
@ -59,6 +59,9 @@ typedef Elf32_auxv_t elf_aux_entry;
|
||||
#elif defined(__x86_64)
|
||||
typedef Elf64_auxv_t elf_aux_entry;
|
||||
#endif
|
||||
|
||||
typedef typeof(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
|
||||
|
||||
// When we find the VDSO mapping in the process's address space, this
|
||||
// is the name we use for it when writing it to the minidump.
|
||||
// This should always be less than NAME_MAX!
|
||||
@ -124,6 +127,7 @@ class LinuxDumper {
|
||||
const wasteful_vector<pid_t> &threads() { return threads_; }
|
||||
const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
|
||||
const MappingInfo* FindMapping(const void* address) const;
|
||||
const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
|
||||
|
||||
// Find a block of memory to take as the stack given the top of stack pointer.
|
||||
// stack: (output) the lowest address in the memory area
|
||||
@ -151,15 +155,6 @@ class LinuxDumper {
|
||||
unsigned int mapping_id,
|
||||
uint8_t identifier[sizeof(MDGUID)]);
|
||||
|
||||
// Utility method to find the location of where the kernel has
|
||||
// mapped linux-gate.so in memory(shows up in /proc/pid/maps as
|
||||
// [vdso], but we can't guarantee that it's the only virtual dynamic
|
||||
// shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR
|
||||
// is the safest way to go.)
|
||||
void* FindBeginningOfLinuxGateSharedLibrary(pid_t pid) const;
|
||||
// Utility method to find the entry point location.
|
||||
void* FindEntryPoint(pid_t pid) const;
|
||||
|
||||
uintptr_t crash_address() const { return crash_address_; }
|
||||
void set_crash_address(uintptr_t crash_address) {
|
||||
crash_address_ = crash_address;
|
||||
@ -172,6 +167,8 @@ class LinuxDumper {
|
||||
void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
|
||||
|
||||
protected:
|
||||
bool ReadAuxv();
|
||||
|
||||
virtual bool EnumerateMappings();
|
||||
|
||||
virtual bool EnumerateThreads() = 0;
|
||||
@ -206,6 +203,9 @@ class LinuxDumper {
|
||||
|
||||
// Info from /proc/<pid>/maps.
|
||||
wasteful_vector<MappingInfo*> mappings_;
|
||||
|
||||
// Info from /proc/<pid>/auxv
|
||||
wasteful_vector<elf_aux_val_t> auxv_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
@ -287,7 +287,8 @@ TEST(LinuxPtraceDumperTest, MappingsIncludeLinuxGate) {
|
||||
LinuxPtraceDumper dumper(getpid());
|
||||
ASSERT_TRUE(dumper.Init());
|
||||
|
||||
void* linux_gate_loc = dumper.FindBeginningOfLinuxGateSharedLibrary(getpid());
|
||||
void* linux_gate_loc =
|
||||
reinterpret_cast<void *>(dumper.auxv()[AT_SYSINFO_EHDR]);
|
||||
ASSERT_TRUE(linux_gate_loc);
|
||||
bool found_linux_gate = false;
|
||||
|
||||
|
@ -423,40 +423,9 @@ class MinidumpWriter {
|
||||
}
|
||||
|
||||
bool Dump() {
|
||||
// The dynamic linker makes information available that helps gdb find all
|
||||
// DSOs loaded into the program. If we can access this information, we dump
|
||||
// it to a MD_LINUX_DSO_DEBUG stream.
|
||||
struct r_debug* r_debug = NULL;
|
||||
uint32_t dynamic_length = 0;
|
||||
#if !defined(__ANDROID__)
|
||||
// This code assumes the crashing process is the same as this process and
|
||||
// may hang or take a long time to complete if not so.
|
||||
// Thus, we skip this code for a post-mortem based dump.
|
||||
if (!dumper_->IsPostMortem()) {
|
||||
// The Android NDK is missing structure definitions for most of this.
|
||||
// For now, it's simpler just to skip it.
|
||||
for (int i = 0;;) {
|
||||
ElfW(Dyn) dyn;
|
||||
dynamic_length += sizeof(dyn);
|
||||
// NOTE: Use of _DYNAMIC assumes this is the same process as the
|
||||
// crashing process. This loop will go forever if it's out of bounds.
|
||||
dumper_->CopyFromProcess(&dyn, GetCrashThread(), _DYNAMIC+i++,
|
||||
sizeof(dyn));
|
||||
if (dyn.d_tag == DT_DEBUG) {
|
||||
r_debug = (struct r_debug*)dyn.d_un.d_ptr;
|
||||
continue;
|
||||
} else if (dyn.d_tag == DT_NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// A minidump file contains a number of tagged streams. This is the number
|
||||
// of stream which we write.
|
||||
unsigned kNumWriters = 12;
|
||||
if (r_debug)
|
||||
++kNumWriters;
|
||||
unsigned kNumWriters = 13;
|
||||
|
||||
TypedMDRVA<MDRawHeader> header(&minidump_writer_);
|
||||
TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
|
||||
@ -533,12 +502,10 @@ class MinidumpWriter {
|
||||
NullifyDirectoryEntry(&dirent);
|
||||
dir.CopyIndex(dir_index++, &dirent);
|
||||
|
||||
if (r_debug) {
|
||||
dirent.stream_type = MD_LINUX_DSO_DEBUG;
|
||||
if (!WriteDSODebugStream(&dirent, r_debug, dynamic_length))
|
||||
if (!WriteDSODebugStream(&dirent))
|
||||
NullifyDirectoryEntry(&dirent);
|
||||
dir.CopyIndex(dir_index++, &dirent);
|
||||
}
|
||||
|
||||
// If you add more directory entries, don't forget to update kNumWriters,
|
||||
// above.
|
||||
@ -1000,13 +967,58 @@ class MinidumpWriter {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteDSODebugStream(MDRawDirectory* dirent, struct r_debug* r_debug,
|
||||
uint32_t dynamic_length) {
|
||||
bool WriteDSODebugStream(MDRawDirectory* dirent) {
|
||||
#if defined(__ANDROID__)
|
||||
return false;
|
||||
#else
|
||||
// The caller provided us with a pointer to "struct r_debug". We can
|
||||
// look up the "r_map" field to get a linked list of all loaded DSOs.
|
||||
ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
|
||||
char* base;
|
||||
int phnum = dumper_->auxv()[AT_PHNUM];
|
||||
if (!phnum || !phdr)
|
||||
return false;
|
||||
|
||||
// Assume the program base is at the beginning of the same page as the PHDR
|
||||
base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
|
||||
|
||||
// Search for the program PT_DYNAMIC segment
|
||||
ElfW(Addr) dyn_addr = 0;
|
||||
for (; phnum >= 0; phnum--, phdr++) {
|
||||
ElfW(Phdr) ph;
|
||||
dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph));
|
||||
// Adjust base address with the virtual address of the PT_LOAD segment
|
||||
// corresponding to offset 0
|
||||
if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
|
||||
base -= ph.p_vaddr;
|
||||
}
|
||||
if (ph.p_type == PT_DYNAMIC) {
|
||||
dyn_addr = ph.p_vaddr;
|
||||
}
|
||||
}
|
||||
if (!dyn_addr)
|
||||
return false;
|
||||
|
||||
ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
|
||||
|
||||
// The dynamic linker makes information available that helps gdb find all
|
||||
// DSOs loaded into the program. If this information is indeed available,
|
||||
// dump it to a MD_LINUX_DSO_DEBUG stream.
|
||||
struct r_debug* r_debug = NULL;
|
||||
uint32_t dynamic_length = 0;
|
||||
|
||||
for (int i = 0;;) {
|
||||
ElfW(Dyn) dyn;
|
||||
dynamic_length += sizeof(dyn);
|
||||
dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++, sizeof(dyn));
|
||||
if (dyn.d_tag == DT_DEBUG) {
|
||||
r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
|
||||
continue;
|
||||
} else if (dyn.d_tag == DT_NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The "r_map" field of that r_debug struct contains a linked list of all
|
||||
// loaded DSOs.
|
||||
// Our list of DSOs potentially is different from the ones in the crashing
|
||||
// process. So, we have to be careful to never dereference pointers
|
||||
// directly. Instead, we use CopyFromProcess() everywhere.
|
||||
@ -1069,10 +1081,10 @@ class MinidumpWriter {
|
||||
debug.get()->dso_count = dso_count;
|
||||
debug.get()->brk = (void*)debug_entry.r_brk;
|
||||
debug.get()->ldbase = (void*)debug_entry.r_ldbase;
|
||||
debug.get()->dynamic = (void*)&_DYNAMIC;
|
||||
debug.get()->dynamic = dynamic;
|
||||
|
||||
char *dso_debug_data = new char[dynamic_length];
|
||||
dumper_->CopyFromProcess(dso_debug_data, GetCrashThread(), &_DYNAMIC,
|
||||
dumper_->CopyFromProcess(dso_debug_data, GetCrashThread(), dynamic,
|
||||
dynamic_length);
|
||||
debug.CopyIndexAfterObject(0, dso_debug_data, dynamic_length);
|
||||
delete[] dso_debug_data;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -172,7 +173,8 @@ TEST(MinidumpWriterTest, MappingInfo) {
|
||||
|
||||
ExceptionHandler::CrashContext context;
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.tid = 1;
|
||||
ASSERT_EQ(0, getcontext(&context.context));
|
||||
context.tid = child;
|
||||
|
||||
AutoTempDir temp_dir;
|
||||
string templ = temp_dir.path() + "/minidump-writer-unittest";
|
||||
@ -210,6 +212,20 @@ TEST(MinidumpWriterTest, MappingInfo) {
|
||||
EXPECT_EQ(kMemoryName, module->code_file());
|
||||
EXPECT_EQ(module_identifier, module->debug_identifier());
|
||||
|
||||
u_int32_t len;
|
||||
// These streams are expected to be there
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_THREAD_LIST_STREAM, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_MEMORY_LIST_STREAM, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_EXCEPTION_STREAM, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_SYSTEM_INFO_STREAM, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CPU_INFO, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_PROC_STATUS, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CMD_LINE, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_ENVIRON, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_AUXV, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_MAPS, &len));
|
||||
EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_DSO_DEBUG, &len));
|
||||
|
||||
close(fds[1]);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user