Patchwork [RFC] Make libbacktrace more standalone

login
register
mail settings
Submitter Alexander Monakov
Date May 13, 2013, 5:02 p.m.
Message ID <alpine.LNX.2.00.1305132046140.26719@monopod.intra.ispras.ru>
Download mbox | patch
Permalink /patch/243464/
State New
Headers show

Comments

Alexander Monakov - May 13, 2013, 5:02 p.m.
On Wed, 8 May 2013, Ian Lance Taylor wrote:
> > +#ifdef IN_GCC
> 
> Where is IN_GCC defined?

I've amended configure.ac to provide a new configuration flag
('--enable-standalone') and add -DIN_GCC to EXTRA_FLAGS unless that flag is
given.  Previously I've misread grep output and thought that IN_GCC is defined
globally.

> This isn't right.  Using test -n "${with_target_subdir}" tests whether
> libbacktrace is being built as a target library, using the newly built
> compiler.  It does not test whether it is being used in a standalone
> build.  with_target_subdir will be empty when building libbacktrace as
> part of the host compiler.  In that case we still want to use
> include/dwarf2.def, and we do not want to give an error if the system
> does not have dwarf.h.

Sorry.  I'm amended that sequence to test $enable_standalone instead.

> > +#include "backtrace.h"
> > +#include "internal.h"
> 
> Please keep these after the #include of the other header files.

Done.

> > +#ifdef IN_GCC
> >  #include "dwarf2.h"
> >  #include "filenames.h"
> > +#else
> > +#include <dwarf.h>
> > +typedef int dwarf_attribute;
> > +typedef int dwarf_form;
> > +typedef int dwarf_tag;
> >
> > -#include "backtrace.h"
> > -#include "internal.h"
> > +#define IS_ABSOLUTE_PATH(f) ((f)[0] == '/')
> > +#endif
> 
> In the case where IN_GCC is defined, where are the types
> dwarf_attribute, dwarf_form, and dwarf_tag defined?

In GCC's own dwarf2.h as enum tags; dwarf.h uses anonymous enums.

> When IN_GCC is defined, something needs to ensure that
> HAVE_DWARF2_FISSION and HAVE_DWARF2_DWZ_MULTIFILE are defined.

It is ensured by defining have_dwarf2_* unconditionally to "yes" in that
case.

Updated patch below.  Thanks!

libbacktrace/Changelog:
2013-05-13  Alexander Monakov  <amonakov@ispras.ru>

	* btest.c: [!IN_GCC] (IS_DIR_SEPARATOR): Define.
	* configure.ac: (standalone): New configuration flag.
	(EXTRA_FLAGS): Add -DIN_GCC unless building standalone.
	(HAVE_DWARF2_FISSION, HAVE_DWARF2_DWZ_MULTIFILE): New
	tests.  Use ...
	* dwarf.c: (read_attribute): ... here.
	[!IN_GCC] Use system dwarf.h. 
	[!IN_GCC] (dwarf_attribute, dwarf_form, dwarf_tag): Typedef to int.
	Update all uses.
	[!IN_GCC] (IS_ABSOLUTE_PATH): Define.
	(read_line_program): Avoid use of DW_LNS_extended_op.
	* configure: Regenerate.
	* config.h.in: Regenerate.
	* Makefile.in: Regenerate.
Tom Tromey - May 13, 2013, 8:45 p.m.
>>>>> "Alexander" == Alexander Monakov <amonakov@ispras.ru> writes:

Alexander> In GCC's own dwarf2.h as enum tags; dwarf.h uses anonymous enums.

I'm curious to know which dwarf2.h you are testing against and/or intend
to support.  I think there is more than one.

Tom
Alexander Monakov - May 13, 2013, 9:01 p.m.
On Tue, May 14, 2013 at 12:45 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Alexander" == Alexander Monakov <amonakov@ispras.ru> writes:
>
> Alexander> In GCC's own dwarf2.h as enum tags; dwarf.h uses anonymous enums.
>
> I'm curious to know which dwarf2.h you are testing against and/or intend
> to support.  I think there is more than one.

Either dwarf.h from libdwarf (the "official" one if I understand
correctly), or dwarf.h provided by elfutils or libdw. Right now I'm
testing against /usr/include/dwarf.h provided by elfutils package on
Gentoo.

As far as I know, those are very similar except for presence of some
enum values, hence the configure checks.

Alexander

Patch

diff --git a/libbacktrace/btest.c b/libbacktrace/btest.c
index cc647b8..1516099 100644
--- a/libbacktrace/btest.c
+++ b/libbacktrace/btest.c
@@ -38,7 +38,11 @@  POSSIBILITY OF SUCH DAMAGE.  */
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef IN_GCC
 #include "filenames.h"
+#else
+#define IS_DIR_SEPARATOR(c) ((c) == '/')
+#endif
 
 #include "backtrace.h"
 #include "backtrace-supported.h"
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 28b2a1c..ae23da4 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -58,6 +58,9 @@  AM_MAINTAINER_MODE
 AC_ARG_WITH(target-subdir,
 [  --with-target-subdir=SUBDIR      Configuring in a subdirectory for target])
 
+AC_ARG_ENABLE(standalone,
+[  --enable-standalone     Do not use internal GCC headers])
+
 # We must force CC to /not/ be precious variables; otherwise
 # the wrong, non-multilib-adjusted value will be used in multilibs.
 # As a side effect, we have to subst CFLAGS ourselves.
@@ -72,7 +75,7 @@  AC_PROG_RANLIB
 
 AC_PROG_AWK
 case "$AWK" in
-"") AC_MSG_ERROR([can't build without awk]) ;;
+"") AC_MSG_ERROR([cannot build without awk]) ;;
 esac
 
 LT_INIT([disable-shared])
@@ -125,6 +128,10 @@  else
     EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
   fi
 fi
+
+if test "${enable_standalone}" != "yes"; then
+  EXTRA_FLAGS="$EXTRA_FLAGS -DIN_GCC"
+fi
 AC_SUBST(EXTRA_FLAGS)
 
 ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wstrict-prototypes \
@@ -314,6 +321,40 @@  if test "$have_getexecname" = "yes"; then
   AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
 fi
 
+# Check for DWARF2 extensions
+if test "${enable_standalone}" != "yes"; then
+  have_dwarf2_fission=yes
+  have_dwarf2_dwz_multifile=yes
+else
+  AC_CHECK_HEADER([dwarf.h],
+    [
+      AC_MSG_CHECKING([for DW_FORM_GNU_addr_index])
+      AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM(
+	  [#include <dwarf.h>],
+	  [int i = DW_FORM_GNU_addr_index;])],
+	[have_dwarf2_fission=yes],
+	[have_dwarf2_fission=no])
+      AC_MSG_RESULT([$have_dwarf2_fission])
+      AC_MSG_CHECKING([for DW_FORM_GNU_ref_alt])
+      AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM(
+	  [#include <dwarf.h>],
+	  [int i = DW_FORM_GNU_ref_alt;])],
+	[have_dwarf2_dwz_multifile=yes],
+	[have_dwarf2_dwz_multifile=no])
+      AC_MSG_RESULT([$have_dwarf2_dwz_multifile])],
+    [AC_MSG_ERROR([dwarf.h required when building standalone])])
+fi
+if test "$have_dwarf2_fission" = "yes"; then
+  AC_DEFINE(HAVE_DWARF2_FISSION, 1,
+	    [Define if DWARF2 Fission enumeration values are defined.])
+fi
+if test "$have_dwarf2_dwz_multifile" = "yes"; then
+  AC_DEFINE(HAVE_DWARF2_DWZ_MULTFILE, 1,
+	    [Define if DWARF2 DWZ multifile enumeration values are defined.])
+fi
+
 AC_CACHE_CHECK([whether tests can run],
   [libbacktrace_cv_sys_native],
   [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 501afe5..8441e17 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -37,8 +37,17 @@  POSSIBILITY OF SUCH DAMAGE.  */
 #include <string.h>
 #include <sys/types.h>
 
+#ifdef IN_GCC
 #include "dwarf2.h"
 #include "filenames.h"
+#else
+#include <dwarf.h>
+typedef int dwarf_attribute;
+typedef int dwarf_form;
+typedef int dwarf_tag;
+
+#define IS_ABSOLUTE_PATH(f) ((f)[0] == '/')
+#endif
 
 #include "backtrace.h"
 #include "internal.h"
@@ -89,9 +98,9 @@  struct dwarf_buf
 struct attr
 {
   /* The attribute name.  */
-  enum dwarf_attribute name;
+  dwarf_attribute name;
   /* The attribute form.  */
-  enum dwarf_form form;
+  dwarf_form form;
 };
 
 /* A single DWARF abbreviation.  */
@@ -101,7 +110,7 @@  struct abbrev
   /* The abbrev code--the number used to refer to the abbrev.  */
   uint64_t code;
   /* The entry tag.  */
-  enum dwarf_tag tag;
+  dwarf_tag tag;
   /* Non-zero if this abbrev has child entries.  */
   int has_children;
   /* The number of attributes.  */
@@ -653,7 +662,7 @@  free_abbrevs (struct backtrace_state *state, struct abbrevs *abbrevs,
    forms, because we don't care about them.  */
 
 static int
-read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
+read_attribute (dwarf_form form, struct dwarf_buf *buf,
 		int is_dwarf64, int version, int addrsize,
 		const unsigned char *dwarf_str, size_t dwarf_str_size,
 		struct attr_val *val)
@@ -760,7 +769,7 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
 	uint64_t form;
 
 	form = read_uleb128 (buf);
-	return read_attribute ((enum dwarf_form) form, buf, is_dwarf64,
+	return read_attribute ((dwarf_form) form, buf, is_dwarf64,
 			       version, addrsize, dwarf_str, dwarf_str_size,
 			       val);
       }
@@ -779,6 +788,7 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->encoding = ATTR_VAL_REF_TYPE;
       val->u.uint = read_uint64 (buf);
       return 1;
+#ifdef HAVE_DWARF2_FISSION
     case DW_FORM_GNU_addr_index:
       val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_uleb128 (buf);
@@ -787,6 +797,8 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_uleb128 (buf);
       return 1;
+#endif
+#ifdef HAVE_DWARF2_DWZ_MULTFILE
     case DW_FORM_GNU_ref_alt:
       val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
@@ -795,6 +807,7 @@  read_attribute (enum dwarf_form form, struct dwarf_buf *buf,
       val->encoding = ATTR_VAL_REF_SECTION;
       val->u.uint = read_offset (buf, is_dwarf64);
       return 1;
+#endif
     default:
       dwarf_buf_error (buf, "unrecognized DWARF form");
       return 0;
@@ -1087,7 +1100,7 @@  read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
 	break;
 
       a.code = code;
-      a.tag = (enum dwarf_tag) read_uleb128 (&abbrev_buf);
+      a.tag = (dwarf_tag) read_uleb128 (&abbrev_buf);
       a.has_children = read_byte (&abbrev_buf);
 
       count_buf = abbrev_buf;
@@ -1121,8 +1134,8 @@  read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
 	      form = read_uleb128 (&abbrev_buf);
 	      if (name == 0)
 		break;
-	      attrs[num_attrs].name = (enum dwarf_attribute) name;
-	      attrs[num_attrs].form = (enum dwarf_form) form;
+	      attrs[num_attrs].name = (dwarf_attribute) name;
+	      attrs[num_attrs].form = (dwarf_form) form;
 	      ++num_attrs;
 	    }
 	}
@@ -1746,10 +1759,11 @@  read_line_program (struct backtrace_state *state, struct dwarf_data *ddata,
 	  add_line (state, ddata, address, filename, lineno,
 		    line_buf->error_callback, line_buf->data, vec);
 	}
-      else if (op == DW_LNS_extended_op)
+      else if (!op)
 	{
 	  uint64_t len;
 
+	  /* Extended opcode.  */
 	  len = read_uleb128 (line_buf);
 	  op = read_byte (line_buf);
 	  switch (op)
diff --git a/libbacktrace/configure b/libbacktrace/configure
index 46ad9ee..8724e6d 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -723,6 +723,7 @@  ac_user_opts='
 enable_option_checking
 enable_maintainer_mode
 with_target_subdir
+enable_standalone
 enable_shared
 enable_static
 with_pic
@@ -1363,6 +1364,7 @@  Optional Features:
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
   --enable-maintainer-mode  enable make rules and dependencies not useful
 			  (and sometimes confusing) to the casual installer
+  --enable-standalone     Do not use internal GCC headers
   --enable-shared[=PKGS]  build shared libraries [default=no]
   --enable-static[=PKGS]  build static libraries [default=yes]
   --enable-fast-install[=PKGS]
@@ -4326,6 +4328,12 @@  if test "${with_target_subdir+set}" = set; then :
 fi
 
 
+# Check whether --enable-standalone was given.
+if test "${enable_standalone+set}" = set; then :
+  enableval=$enable_standalone;
+fi
+
+
 # We must force CC to /not/ be precious variables; otherwise
 # the wrong, non-multilib-adjusted value will be used in multilibs.
 # As a side effect, we have to subst CFLAGS ourselves.
@@ -5011,7 +5019,7 @@  fi
 done
 
 case "$AWK" in
-"") as_fn_error "can't build without awk" "$LINENO" 5 ;;
+"") as_fn_error "cannot build without awk" "$LINENO" 5 ;;
 esac
 
 case `pwd` in
@@ -11081,7 +11089,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11084 "configure"
+#line 11092 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11187,7 +11195,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11190 "configure"
+#line 11198 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11557,6 +11565,10 @@  $as_echo "$libbacktrace_cv_c_random_seed_string" >&6; }
   fi
 fi
 
+if test "${enable_standalone}" != "yes"; then
+  EXTRA_FLAGS="$EXTRA_FLAGS -DIN_GCC"
+fi
+
 
 WARN_FLAGS=
 save_CFLAGS="$CFLAGS"
@@ -12371,6 +12383,73 @@  $as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
 
 fi
 
+# Check for DWARF2 extensions
+if test "${enable_standalone}" != "yes"; then
+  have_dwarf2_fission=yes
+  have_dwarf2_dwz_multifile=yes
+else
+  ac_fn_c_check_header_mongrel "$LINENO" "dwarf.h" "ac_cv_header_dwarf_h" "$ac_includes_default"
+if test "x$ac_cv_header_dwarf_h" = x""yes; then :
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DW_FORM_GNU_addr_index" >&5
+$as_echo_n "checking for DW_FORM_GNU_addr_index... " >&6; }
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <dwarf.h>
+int
+main ()
+{
+int i = DW_FORM_GNU_addr_index;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_dwarf2_fission=yes
+else
+  have_dwarf2_fission=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dwarf2_fission" >&5
+$as_echo "$have_dwarf2_fission" >&6; }
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DW_FORM_GNU_ref_alt" >&5
+$as_echo_n "checking for DW_FORM_GNU_ref_alt... " >&6; }
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <dwarf.h>
+int
+main ()
+{
+int i = DW_FORM_GNU_ref_alt;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_dwarf2_dwz_multifile=yes
+else
+  have_dwarf2_dwz_multifile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_dwarf2_dwz_multifile" >&5
+$as_echo "$have_dwarf2_dwz_multifile" >&6; }
+else
+  as_fn_error "dwarf.h required when building standalone" "$LINENO" 5
+fi
+
+
+fi
+if test "$have_dwarf2_fission" = "yes"; then
+
+$as_echo "#define HAVE_DWARF2_FISSION 1" >>confdefs.h
+
+fi
+if test "$have_dwarf2_dwz_multifile" = "yes"; then
+
+$as_echo "#define HAVE_DWARF2_DWZ_MULTFILE 1" >>confdefs.h
+
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tests can run" >&5
 $as_echo_n "checking whether tests can run... " >&6; }
 if test "${libbacktrace_cv_sys_native+set}" = set; then :
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in
index 48ff63f..46a3a65 100644
--- a/libbacktrace/config.h.in
+++ b/libbacktrace/config.h.in
@@ -13,6 +13,12 @@ 
 /* Define if dl_iterate_phdr is available. */
 #undef HAVE_DL_ITERATE_PHDR
 
+/* Define if DWARF2 DWZ multifile enumeration values are defined. */
+#undef HAVE_DWARF2_DWZ_MULTFILE
+
+/* Define if DWARF2 Fission enumeration values are defined. */
+#undef HAVE_DWARF2_FISSION
+
 /* Define to 1 if you have the fcntl function */
 #undef HAVE_FCNTL
 
diff --git a/libbacktrace/Makefile.in b/libbacktrace/Makefile.in
index 971406b..eff3ba9 100644
--- a/libbacktrace/Makefile.in
+++ b/libbacktrace/Makefile.in
@@ -16,7 +16,7 @@ 
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012 Free Software Foundation, Inc.
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are