Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* RFA: libunwind basic support
@ 2003-10-15 21:29 J. Johnston
  2003-10-15 22:40 ` Kevin Buettner
  2003-10-16 20:19 ` Andrew Cagney
  0 siblings, 2 replies; 9+ messages in thread
From: J. Johnston @ 2003-10-15 21:29 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1017 bytes --]

The attached patch adds basic libunwind frame support.  I will be shortly 
submitting an ia64-tdep.c patch which works in conjunction with this patch.  The 
libunwind code is protected by looking for the libunwind header files to 
compile.  At runtime, the libunwind frame sniffer will fail if either the 
libunwind library cannot be dynamically loaded or the frame in question does not 
have proper libunwind info.

For configuration I have added checks for libunwind.h and libunwind-ia64.h as 
this is being added for ia64 support only at present.  Regarding testing, I have 
this code working with my ia64 changes.  I have tested on systems with the 
libunwind-0.92 library/headers installed and not installed.

Ok to commit?

2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>

	* libunwind-frame.c: New file.
	* libunwind-frame.h: New file.
	* configure.in: Add checks for libunwind.h and libunwind-ia64.h.
	* configure: Regenerated.
	* Makefile.in: Add support for libunwind-frame.o.
	* config.in: Regenerated.



[-- Attachment #2: libunwind.patch1 --]
[-- Type: text/plain, Size: 14624 bytes --]

Index: libunwind-frame.c
===================================================================
RCS file: libunwind-frame.c
diff -N libunwind-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.c	15 Oct 2003 21:13:26 -0000
@@ -0,0 +1,349 @@
+/* Frame unwinder for frames using the libunwind library.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Jeff Johnston
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+
+#ifdef HAVE_LIBUNWIND_H
+
+#include "inferior.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "regcache.h"
+
+#include <dlfcn.h>
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
+
+#include "libunwind-frame.h"
+
+#include "complaints.h"
+
+static int libunwind_initialized;
+static struct gdbarch_data *libunwind_descr_handle;
+
+#ifndef LIBUNWIND_SO
+#define LIBUNWIND_SO "libunwind.so"
+#endif
+
+/* Required function pointers from libunwind.  */
+static int (*unw_get_reg_p) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
+static int (*unw_get_fpreg_p) (unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
+static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t, unw_save_loc_t *);
+static int (*unw_step_p) (unw_cursor_t *);
+static int (*unw_init_remote_p) (unw_cursor_t *, unw_addr_space_t, void *);
+static unw_addr_space_t (*unw_create_addr_space_p) (unw_accessors_t *, int);
+static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t, unw_dyn_info_t *,
+					 unw_proc_info_t *, int, void *);
+static unw_word_t (*unw_find_dyn_list_p) (unw_addr_space_t, void *, size_t,
+					  unw_word_t, unw_word_t, void *);
+
+
+struct libunwind_frame_cache
+{
+  CORE_ADDR base;
+  CORE_ADDR func_addr;
+  unw_cursor_t cursor;
+};
+
+#define STRINGIFY2(name)	#name
+#define STRINGIFY(name)		STRINGIFY2(name)
+
+static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
+static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
+static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
+static char *step_name = STRINGIFY(UNW_OBJ(step));
+static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
+static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
+static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
+static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
+
+void
+libunwind_set_descr_handle (void *handle)
+{
+  libunwind_descr_handle = handle;
+}
+
+static struct libunwind_descr *
+libunwind_descr (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, libunwind_descr_handle);
+}
+
+static struct libunwind_frame_cache *
+libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  unw_word_t fp;
+  unw_regnum_t uw_sp_regnum;
+  struct libunwind_frame_cache *cache;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  if (*this_cache)
+    return *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
+
+  cache->func_addr = frame_func_unwind (next_frame);
+
+  /* Get a cursor to the previous frame.  We do this by initializing
+     a cursor and stepping back to the frame level prior to the one we are 
+     currently in.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  unw_init_remote_p (&cache->cursor, as, next_frame);
+  unw_step_p (&cache->cursor);
+
+  /* To get base address, get sp from previous frame.  */
+  uw_sp_regnum = descr->gdb2uw (SP_REGNUM);
+  ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
+  if (ret < 0)
+    error ("Can't get libunwind sp register.");
+
+  cache->base = (CORE_ADDR)fp;
+
+  *this_cache = cache;
+  return cache;
+}
+
+unw_word_t 
+libunwind_find_dyn_list (unw_addr_space_t as, void *table, size_t table_size,
+			 unw_word_t segbase, unw_word_t gp, void *arg)
+{
+  return unw_find_dyn_list_p (as, table, table_size, segbase, gp, arg);
+}
+
+static const struct frame_unwind libunwind_frame_unwind =
+{
+  NORMAL_FRAME,
+  libunwind_frame_this_id,
+  libunwind_frame_prev_register
+};
+
+const struct frame_unwind *
+libunwind_frame_sniffer (struct frame_info *next_frame)
+{
+  unw_cursor_t cursor;
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  /* Get a cursor to the previous frame.  We do this by initializing
+     a cursor and stepping back to the frame level prior to the one we are 
+     currently in.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  ret = unw_init_remote_p (&cursor, as, next_frame);
+
+  if (ret >= 0)
+    ret = unw_step_p (&cursor);
+
+  if (ret < 0)
+    return NULL;
+
+  return &libunwind_frame_unwind;
+}
+
+void
+libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+		      struct frame_id *this_id)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->func_addr);
+}
+
+void
+libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+			       int regnum, int *optimizedp,
+			       enum lval_type *lvalp, CORE_ADDR *addrp,
+			       int *realnump, void *valuep)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  void *ptr;
+  unw_cursor_t *c;
+  unw_save_loc_t sl;
+  int i, ret;
+  unw_word_t intval;
+  unw_fpreg_t fpval;
+  unw_regnum_t uw_regnum;
+  struct libunwind_descr *descr;
+
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  uw_regnum = descr->gdb2uw (regnum);
+
+  gdb_assert (regnum >= 0);
+
+  if (!target_has_registers)
+    error ("No registers.");
+
+  *optimizedp = 0;
+  *addrp = 0;
+  *lvalp = not_lval;
+  *realnump = -1;
+
+  memset (valuep, 0, DEPRECATED_REGISTER_RAW_SIZE (regnum));
+
+  if (uw_regnum < 0)
+    return;
+
+  if (descr->is_fpreg (uw_regnum))
+    {
+      ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
+      ptr = &fpval;
+    }
+  else
+    {
+      ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
+      ptr = &intval;
+    }
+
+  if (ret < 0)
+    return;
+
+  memcpy (valuep, ptr, DEPRECATED_REGISTER_RAW_SIZE (regnum));
+
+  if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
+    return;
+
+  switch (sl.type)
+    {
+    case UNW_SLT_NONE:
+      *optimizedp = 1;
+      break;
+
+    case UNW_SLT_MEMORY:
+      *lvalp = lval_memory;
+      *addrp = sl.u.addr;
+      break;
+
+    case UNW_SLT_REG:
+      *lvalp = lval_register;
+      *realnump = regnum;
+      break;
+    }
+} 
+
+CORE_ADDR
+libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
+
+int
+libunwind_search_unwind_table (void *as, long ip, void *di,
+			       void *pi, int need_unwind_info, void *args)
+{
+  return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip, 
+				    di, pi, need_unwind_info, args);
+}
+
+static int
+libunwind_load (void)
+{
+  void *handle;
+
+  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
+  if (handle == NULL)
+    return 0;
+
+  /* Initialize pointers to the dynamic library functions we will use.  */
+
+  unw_get_reg_p = dlsym (handle, get_reg_name);
+  if (unw_get_reg_p == NULL)
+    return 0;
+
+  unw_get_fpreg_p = dlsym (handle, get_fpreg_name);
+  if (unw_get_fpreg_p == NULL)
+    return 0;
+
+  unw_get_saveloc_p = dlsym (handle, get_saveloc_name);
+  if (unw_get_saveloc_p == NULL)
+    return 0;
+
+  unw_step_p = dlsym (handle, step_name);
+  if (unw_step_p == NULL)
+    return 0;
+
+  unw_init_remote_p = dlsym (handle, init_remote_name);
+  if (unw_init_remote_p == NULL)
+    return 0;
+
+  unw_create_addr_space_p = dlsym (handle, create_addr_space_name);
+  if (unw_create_addr_space_p == NULL)
+    return 0;
+
+  unw_search_unwind_table_p = dlsym (handle, search_unwind_table_name);
+  if (unw_search_unwind_table_p == NULL)
+    return 0;
+
+  unw_find_dyn_list_p = dlsym (handle, find_dyn_list_name);
+  if (unw_find_dyn_list_p == NULL)
+    return 0;
+   
+  return 1;
+}
+
+int
+libunwind_is_initialized (void)
+{
+  return libunwind_initialized;
+}
+
+#endif /* HAVE_LIBUNWIND_H  */
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_libunwind_frame (void);
+
+void
+_initialize_libunwind_frame (void)
+{
+#ifdef HAVE_LIBUNWIND_H
+  libunwind_initialized = libunwind_load ();
+#endif  
+}
Index: libunwind-frame.h
===================================================================
RCS file: libunwind-frame.h
diff -N libunwind-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.h	15 Oct 2003 21:13:26 -0000
@@ -0,0 +1,71 @@
+/* Frame unwinder for frames with libunwind frame information.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Jeff Johnston.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_LIBUNWIND_H
+
+#ifndef LIBUNWIND_FRAME_H
+#define LIBUNWIND_FRAME_H 1
+
+#include "libunwind.h"
+
+struct frame_info;
+
+struct libunwind_descr
+{
+  int (*gdb2uw) (int);
+  int (*uw2gdb) (int);
+  int (*is_fpreg) (int);
+  void *accessors;
+};
+
+const struct frame_unwind *
+libunwind_frame_sniffer (struct frame_info *next_frame);
+
+void
+libunwind_set_descr_handle (void *handle);
+
+void
+libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+			 struct frame_id *this_id);
+void
+libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+			       int regnum, int *optimizedp,
+			       enum lval_type *lvalp, CORE_ADDR *addrp,
+			       int *realnump, void *valuep);
+CORE_ADDR
+libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache);
+
+int
+libunwind_is_initialized (void);
+
+int
+libunwind_search_unwind_table (void *as, long ip, void *di,
+			       void *pi, int need_unwind_info, void *args);
+
+unw_word_t
+libunwind_find_dyn_list (unw_addr_space_t, void *, size_t,
+			 unw_word_t, unw_word_t, void *);
+     
+#endif /* libunwind-frame.h */
+
+#endif /* HAVE_LIBUNWIND_H  */
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.456
diff -u -r1.456 Makefile.in
--- Makefile.in	11 Oct 2003 15:22:39 -0000	1.456
+++ Makefile.in	15 Oct 2003 21:13:27 -0000
@@ -701,6 +701,7 @@
 jv_lang_h = jv-lang.h
 kod_h = kod.h
 language_h = language.h
+libunwind_frame_h = libunwind-frame.h
 linespec_h = linespec.h
 linux_nat_h = linux-nat.h
 m2_lang_h = m2-lang.h
@@ -890,6 +891,7 @@
 	ui-out.o cli-out.o \
 	varobj.o wrapper.o \
 	jv-lang.o jv-valprint.o jv-typeprint.o \
+	libunwind-frame.o \
 	m2-lang.o p-lang.o p-typeprint.o p-valprint.o \
 	scm-exp.o scm-lang.o scm-valprint.o \
 	sentinel-frame.o \
@@ -1271,6 +1273,7 @@
 	i386gnu-nat.c i386gnu-tdep.c \
 	ia64-linux-nat.c ia64-linux-tdep.c ia64-tdep.c \
 	infptrace.c inftarg.c irix4-nat.c irix5-nat.c \
+	libunwind-frame.c \
 	lynx-nat.c m3-nat.c \
 	m68hc11-tdep.c \
 	m68k-tdep.c \
@@ -1890,7 +1893,7 @@
 	$(arch_utils_h) $(floatformat_h) $(regcache_h) $(reggroups_h) \
 	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(doublest_h) \
 	$(value_h) $(gdb_assert_h) $(objfiles_h) $(elf_common_h) \
-	$(elf_bfd_h) $(dis_asm_h)
+	$(elf_bfd_h) $(dis_asm_h) $(libunwind_frame_h)
 infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
 	$(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
 	$(symfile_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h)
@@ -1938,6 +1941,10 @@
 language.o: language.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(value_h) $(gdbcmd_h) $(expression_h) $(language_h) $(target_h) \
 	$(parser_defs_h) $(jv_lang_h) $(demangle_h)
+libunwind-frame.o: libunwind-frame.c $(defs_h) \
+	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
+	$(gdbtypes_h) $(symtab_h) $(objfiles_h) $(regcache_h) \
+	$(gdb_assert_h) $(gdb_string_h) $(complaints_h) $(libunwind_frame_h)
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
 	$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
Index: configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.132
diff -u -r1.132 configure.in
--- configure.in	3 Sep 2003 15:02:48 -0000	1.132
+++ configure.in	15 Oct 2003 21:13:27 -0000
@@ -319,6 +319,8 @@
 AC_HEADER_DIRENT
 AC_HEADER_STAT
 AC_HEADER_STDC
+AC_CHECK_HEADERS(libunwind.h)
+AC_CHECK_HEADERS(libunwind-ia64.h)
 AC_CHECK_HEADERS(link.h)
 AC_CHECK_HEADERS(nlist.h)
 AC_CHECK_HEADERS(poll.h sys/poll.h)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-10-15 21:29 RFA: libunwind basic support J. Johnston
@ 2003-10-15 22:40 ` Kevin Buettner
  2003-10-16 20:19 ` Andrew Cagney
  1 sibling, 0 replies; 9+ messages in thread
From: Kevin Buettner @ 2003-10-15 22:40 UTC (permalink / raw)
  To: J. Johnston, gdb-patches

On Oct 15,  5:29pm, J. Johnston wrote:

> The attached patch adds basic libunwind frame support.  I will be shortly 
> submitting an ia64-tdep.c patch which works in conjunction with this patch.  The 
> libunwind code is protected by looking for the libunwind header files to 
> compile.  At runtime, the libunwind frame sniffer will fail if either the 
> libunwind library cannot be dynamically loaded or the frame in question does not 
> have proper libunwind info.
> 
> For configuration I have added checks for libunwind.h and libunwind-ia64.h as 
> this is being added for ia64 support only at present.  Regarding testing, I have 
> this code working with my ia64 changes.  I have tested on systems with the 
> libunwind-0.92 library/headers installed and not installed.
> 
> Ok to commit?
> 
> 2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>
> 
> 	* libunwind-frame.c: New file.
> 	* libunwind-frame.h: New file.
> 	* configure.in: Add checks for libunwind.h and libunwind-ia64.h.
> 	* configure: Regenerated.
> 	* Makefile.in: Add support for libunwind-frame.o.
> 	* config.in: Regenerated.

It looks okay to me.

I'm not sure who needs to approve this though -- if it's me, then you
have my approval.

Kevin


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-10-15 21:29 RFA: libunwind basic support J. Johnston
  2003-10-15 22:40 ` Kevin Buettner
@ 2003-10-16 20:19 ` Andrew Cagney
  2003-10-16 21:38   ` J. Johnston
  1 sibling, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-10-16 20:19 UTC (permalink / raw)
  To: J. Johnston; +Cc: gdb-patches

Jeff,

Is it possible to post (or commit to a branch) the other 
(work-in-progress?) parts to this change?
Ignoring a few nits, this code appears to be going in the right 
direction, however its hard to tell without seeing things in toto.

> The attached patch adds basic libunwind frame support.  I will be shortly submitting an ia64-tdep.c patch which works in conjunction with this patch.  The libunwind code is protected by looking for the libunwind header files to compile.  At runtime, the libunwind frame sniffer will fail if either the libunwind library cannot be dynamically loaded or the frame in question does not have proper libunwind info.

First some straight legal questions:

- from where can libunwind be obtained?

- who owns it?

- what are its licence terms, and are they GPL compatible?

- is it considered a "system library" (like libc, or libthread_db)?

- have you used, or refered to David Mossberger's [sp] old libunwind 
patch (it was eventually contributed to the FSF).

> For configuration I have added checks for libunwind.h and libunwind-ia64.h as this is being added for ia64 support only at present.  Regarding testing, I have this code working with my ia64 changes.  I have tested on systems with the libunwind-0.92 library/headers installed and not installed.

I see, to make this optional, you've wrapped the code in #ifdef 
HAVE_LIBUNWIND_H, and then modified the Makefile so that it is 
unconditionally built :-(

These files should only be linked in when when needed, or at least only 
when there's a libunwind around.  Have a look at --with-mmalloc and 
--with-sysroot for how to implement the option --with-libunwind which 
lets the user force their inclusion; and --disable-gdbcli, --enable-tui, 
and --enable-sim for idea's on how to make linking the object files 
optional.

> 2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>
> 
>     * libunwind-frame.c: New file.
>     * libunwind-frame.h: New file.
>     * configure.in: Add checks for libunwind.h and libunwind-ia64.h.
>     * configure: Regenerated.
>     * Makefile.in: Add support for libunwind-frame.o.
>     * config.in: Regenerated.

Without seeing the rest of the code I'm really not in a position to 
comment on the technical design.

However, a quick glance did through up a few nits.  I'm noting them now, 
so that, hopefully an additional round trip can be avoided later.

+   Contributed by Jeff Johnston

Legal nit.  "Written by Jeff Johnston, contributed by Red Hat Inc.", you 
don't have an assignment on file.

> +void
> +libunwind_set_descr_handle (void *handle)
> +{
> +  libunwind_descr_handle = handle;
> +}

I don't understand this.  A guess is that this is trying to implement a 
mechanism that lets an external module set this modules per-architecture 
data?  If that is the case, then can you have a look at the 
set_gdbarch_data doco and regrroups.c's reggroup_add method for how to 
do this?

+#define STRINGIFY2(name)	#name
+#define STRINGIFY(name)		STRINGIFY2(name)
+
+static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
+static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
+static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
+static char *step_name = STRINGIFY(UNW_OBJ(step));
+static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
+static char *create_addr_space_name = 
STRINGIFY(UNW_OBJ(create_addr_space));
+static char *search_unwind_table_name = 
STRINGIFY(UNW_OBJ(search_unwind_table));
+static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));

I don't understand this.  A guess is that UNW_OBJ() is doing something 
evil (use "include/sym-cat.h") to those names and having the array (use 
"static const char <name>[] = ..." and local to libunwind_load) makes 
ones debugging life much easier?  If this is the case, can you add some 
commentary?

+  memset (valuep, 0, DEPRECATED_REGISTER_RAW_SIZE (regnum));

? you probably want register_size().

+static int
+libunwind_load (void)
+{
+  void *handle;
+
+  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
+  if (handle == NULL)
+    return 0;

For thread-db.c I added code that printed out the library that was 
loaded.  Should the same be done here?   Note that, due to querks with 
the way GDB starts up, the message needs to be delayed - see thread-db.c 
for more details.

+const struct frame_unwind *
+libunwind_frame_sniffer (struct frame_info *next_frame);

can you please write the declaration thus:

const struct frame_unwind *libunwind_frame_sniffer (....

so that it is consistent with the rest of GDB.

Andrew



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-10-16 20:19 ` Andrew Cagney
@ 2003-10-16 21:38   ` J. Johnston
  2003-10-22 23:38     ` J. Johnston
  0 siblings, 1 reply; 9+ messages in thread
From: J. Johnston @ 2003-10-16 21:38 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Andrew Cagney wrote:
> Jeff,
> 
> Is it possible to post (or commit to a branch) the other 
> (work-in-progress?) parts to this change?
> Ignoring a few nits, this code appears to be going in the right 
> direction, however its hard to tell without seeing things in toto.
> 
>> The attached patch adds basic libunwind frame support.  I will be 
>> shortly submitting an ia64-tdep.c patch which works in conjunction 
>> with this patch.  The libunwind code is protected by looking for the 
>> libunwind header files to compile.  At runtime, the libunwind frame 
>> sniffer will fail if either the libunwind library cannot be 
>> dynamically loaded or the frame in question does not have proper 
>> libunwind info.
> 
> 
> First some straight legal questions:
> 
> - from where can libunwind be obtained?
>

http://www.hpl.hp.com/research/linux/libunwind/

> - who owns it?
> 

Hewlitt-Packard

> - what are its licence terms, and are they GPL compatible?
> 

It has a BSD-like license.  Yes, it is GPL compatible.


Copyright (c) 2002 Hewlett-Packard Co.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

> - is it considered a "system library" (like libc, or libthread_db)?
> 

I would have to say no.  It is currently an optional library.  This is one of 
the reasons I chose to use a dynamic load mechanism.

> - have you used, or refered to David Mossberger's [sp] old libunwind 
> patch (it was eventually contributed to the FSF).
> 

No.  Not in this code.

>> For configuration I have added checks for libunwind.h and 
>> libunwind-ia64.h as this is being added for ia64 support only at 
>> present.  Regarding testing, I have this code working with my ia64 
>> changes.  I have tested on systems with the libunwind-0.92 
>> library/headers installed and not installed.
> 
> 
> I see, to make this optional, you've wrapped the code in #ifdef 
> HAVE_LIBUNWIND_H, and then modified the Makefile so that it is 
> unconditionally built :-(
> 
> These files should only be linked in when when needed, or at least only 
> when there's a libunwind around.  Have a look at --with-mmalloc and 
> --with-sysroot for how to implement the option --with-libunwind which 
> lets the user force their inclusion; and --disable-gdbcli, --enable-tui, 
> and --enable-sim for idea's on how to make linking the object files 
> optional.
> 

I'll take a look.  The only thing this allows a user to do is to build gdb on a 
system that it can legimately build libunwind support and purposely disable it 
at configuration.  Can you disable dwarf2 cfi support?  If not, why would you 
want to do this for libunwind which is a similar level of functionality?

>> 2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>
>>
>>     * libunwind-frame.c: New file.
>>     * libunwind-frame.h: New file.
>>     * configure.in: Add checks for libunwind.h and libunwind-ia64.h.
>>     * configure: Regenerated.
>>     * Makefile.in: Add support for libunwind-frame.o.
>>     * config.in: Regenerated.
> 
> 
> Without seeing the rest of the code I'm really not in a position to 
> comment on the technical design.
> 
> However, a quick glance did through up a few nits.  I'm noting them now, 
> so that, hopefully an additional round trip can be avoided later.
> 
> +   Contributed by Jeff Johnston
> 
> Legal nit.  "Written by Jeff Johnston, contributed by Red Hat Inc.", you 
> don't have an assignment on file.
> 

Will change.


>> +void
>> +libunwind_set_descr_handle (void *handle)
>> +{
>> +  libunwind_descr_handle = handle;
>> +}
> 
> 
> I don't understand this.  A guess is that this is trying to implement a 
> mechanism that lets an external module set this modules per-architecture 
> data?  If that is the case, then can you have a look at the 
> set_gdbarch_data doco and regrroups.c's reggroup_add method for how to 
> do this?
> 

I did look at said functionality originally.  I ran into a problem which this 
solved.  I will have to look again to see what the problem was because I don't 
remember off-hand.

> +#define STRINGIFY2(name)    #name
> +#define STRINGIFY(name)        STRINGIFY2(name)
> +
> +static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
> +static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
> +static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
> +static char *step_name = STRINGIFY(UNW_OBJ(step));
> +static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
> +static char *create_addr_space_name = 
> STRINGIFY(UNW_OBJ(create_addr_space));
> +static char *search_unwind_table_name = 
> STRINGIFY(UNW_OBJ(search_unwind_table));
> +static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
> 
> I don't understand this.  A guess is that UNW_OBJ() is doing something 
> evil (use "include/sym-cat.h") to those names and having the array (use 
> "static const char <name>[] = ..." and local to libunwind_load) makes 
> ones debugging life much easier?  If this is the case, can you add some 
> commentary?
> 

Yes.  The libunwind code is slightly ugly with respect to the fact that the 
function names are not aliased with generic names.  They all have platform 
prefixes so I must spell them out.  Function names are generated automatically 
using the UNW_OBJ macro.

> +  memset (valuep, 0, DEPRECATED_REGISTER_RAW_SIZE (regnum));
> 
> ? you probably want register_size().
> 

Yes.

> +static int
> +libunwind_load (void)
> +{
> +  void *handle;
> +
> +  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
> +  if (handle == NULL)
> +    return 0;
> 
> For thread-db.c I added code that printed out the library that was 
> loaded.  Should the same be done here?   Note that, due to querks with 
> the way GDB starts up, the message needs to be delayed - see thread-db.c 
> for more details.
> 

IMO, there is little value-add.  There are architecture messages that will print 
out whether libunwind is being used or not.  The problems with libthread-db 
don't exist in this case.

> +const struct frame_unwind *
> +libunwind_frame_sniffer (struct frame_info *next_frame);
> 
> can you please write the declaration thus:
> 
> const struct frame_unwind *libunwind_frame_sniffer (....
> 
> so that it is consistent with the rest of GDB.
> 

Ok.  I copied the declaration from below and forget to rejoin the lines.

-- Jeff J.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-10-16 21:38   ` J. Johnston
@ 2003-10-22 23:38     ` J. Johnston
  2003-11-11 23:09       ` Andrew Cagney
  0 siblings, 1 reply; 9+ messages in thread
From: J. Johnston @ 2003-10-22 23:38 UTC (permalink / raw)
  To: J. Johnston; +Cc: Andrew Cagney, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 8088 bytes --]

Please see latest patch attached which addresses questions below.  I have added 
a configuration option: --enable-libunwind per your suggestion.

Ok so far?  I have to wait for Kevin to get through my intermediate patch before 
I can send you the ia64-tdep.c side of the libunwind patch.

2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>
	* libunwind-frame.c: New file.
	* libunwind-frame.h: New file.
	* configure.in: Add --enable-libunwind option support.
	* configure: Regenerated.
	* Makefile.in: Add support for libunwind-frame.o.
	* config.in: Regenerated.


J. Johnston wrote:
> Andrew Cagney wrote:
> 
>> Jeff,
>>
>> Is it possible to post (or commit to a branch) the other 
>> (work-in-progress?) parts to this change?
>> Ignoring a few nits, this code appears to be going in the right 
>> direction, however its hard to tell without seeing things in toto.
>>
>>> The attached patch adds basic libunwind frame support.  I will be 
>>> shortly submitting an ia64-tdep.c patch which works in conjunction 
>>> with this patch.  The libunwind code is protected by looking for the 
>>> libunwind header files to compile.  At runtime, the libunwind frame 
>>> sniffer will fail if either the libunwind library cannot be 
>>> dynamically loaded or the frame in question does not have proper 
>>> libunwind info.
>>
>>
>>
>> First some straight legal questions:
>>
>> - from where can libunwind be obtained?
>>
> 
> http://www.hpl.hp.com/research/linux/libunwind/
> 
>> - who owns it?
>>
> 
> Hewlitt-Packard
> 
>> - what are its licence terms, and are they GPL compatible?
>>
> 
> It has a BSD-like license.  Yes, it is GPL compatible.
> 
> 
> Copyright (c) 2002 Hewlett-Packard Co.
> 
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
> 
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
> 
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> 
>> - is it considered a "system library" (like libc, or libthread_db)?
>>
> 
> I would have to say no.  It is currently an optional library.  This is 
> one of the reasons I chose to use a dynamic load mechanism.
> 
>> - have you used, or refered to David Mossberger's [sp] old libunwind 
>> patch (it was eventually contributed to the FSF).
>>
> 
> No.  Not in this code.
> 
>>> For configuration I have added checks for libunwind.h and 
>>> libunwind-ia64.h as this is being added for ia64 support only at 
>>> present.  Regarding testing, I have this code working with my ia64 
>>> changes.  I have tested on systems with the libunwind-0.92 
>>> library/headers installed and not installed.
>>
>>
>>
>> I see, to make this optional, you've wrapped the code in #ifdef 
>> HAVE_LIBUNWIND_H, and then modified the Makefile so that it is 
>> unconditionally built :-(
>>
>> These files should only be linked in when when needed, or at least 
>> only when there's a libunwind around.  Have a look at --with-mmalloc 
>> and --with-sysroot for how to implement the option --with-libunwind 
>> which lets the user force their inclusion; and --disable-gdbcli, 
>> --enable-tui, and --enable-sim for idea's on how to make linking the 
>> object files optional.
>>
> 
> I'll take a look.  The only thing this allows a user to do is to build 
> gdb on a system that it can legimately build libunwind support and 
> purposely disable it at configuration.  Can you disable dwarf2 cfi 
> support?  If not, why would you want to do this for libunwind which is a 
> similar level of functionality?
> 
>>> 2003-10-15  Jeff Johnston  <jjohnstn@redhat.com>
>>>
>>>     * libunwind-frame.c: New file.
>>>     * libunwind-frame.h: New file.
>>>     * configure.in: Add checks for libunwind.h and libunwind-ia64.h.
>>>     * configure: Regenerated.
>>>     * Makefile.in: Add support for libunwind-frame.o.
>>>     * config.in: Regenerated.
>>
>>
>>
>> Without seeing the rest of the code I'm really not in a position to 
>> comment on the technical design.
>>
>> However, a quick glance did through up a few nits.  I'm noting them 
>> now, so that, hopefully an additional round trip can be avoided later.
>>
>> +   Contributed by Jeff Johnston
>>
>> Legal nit.  "Written by Jeff Johnston, contributed by Red Hat Inc.", 
>> you don't have an assignment on file.
>>
> 
> Will change.
> 
> 
>>> +void
>>> +libunwind_set_descr_handle (void *handle)
>>> +{
>>> +  libunwind_descr_handle = handle;
>>> +}
>>
>>
>>
>> I don't understand this.  A guess is that this is trying to implement 
>> a mechanism that lets an external module set this modules 
>> per-architecture data?  If that is the case, then can you have a look 
>> at the set_gdbarch_data doco and regrroups.c's reggroup_add method for 
>> how to do this?
>>
> 
> I did look at said functionality originally.  I ran into a problem which 
> this solved.  I will have to look again to see what the problem was 
> because I don't remember off-hand.
> 
>> +#define STRINGIFY2(name)    #name
>> +#define STRINGIFY(name)        STRINGIFY2(name)
>> +
>> +static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
>> +static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
>> +static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
>> +static char *step_name = STRINGIFY(UNW_OBJ(step));
>> +static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
>> +static char *create_addr_space_name = 
>> STRINGIFY(UNW_OBJ(create_addr_space));
>> +static char *search_unwind_table_name = 
>> STRINGIFY(UNW_OBJ(search_unwind_table));
>> +static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
>>
>> I don't understand this.  A guess is that UNW_OBJ() is doing something 
>> evil (use "include/sym-cat.h") to those names and having the array 
>> (use "static const char <name>[] = ..." and local to libunwind_load) 
>> makes ones debugging life much easier?  If this is the case, can you 
>> add some commentary?
>>
> 
> Yes.  The libunwind code is slightly ugly with respect to the fact that 
> the function names are not aliased with generic names.  They all have 
> platform prefixes so I must spell them out.  Function names are 
> generated automatically using the UNW_OBJ macro.
> 
>> +  memset (valuep, 0, DEPRECATED_REGISTER_RAW_SIZE (regnum));
>>
>> ? you probably want register_size().
>>
> 
> Yes.
> 
>> +static int
>> +libunwind_load (void)
>> +{
>> +  void *handle;
>> +
>> +  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
>> +  if (handle == NULL)
>> +    return 0;
>>
>> For thread-db.c I added code that printed out the library that was 
>> loaded.  Should the same be done here?   Note that, due to querks with 
>> the way GDB starts up, the message needs to be delayed - see 
>> thread-db.c for more details.
>>
> 
> IMO, there is little value-add.  There are architecture messages that 
> will print out whether libunwind is being used or not.  The problems 
> with libthread-db don't exist in this case.
> 
>> +const struct frame_unwind *
>> +libunwind_frame_sniffer (struct frame_info *next_frame);
>>
>> can you please write the declaration thus:
>>
>> const struct frame_unwind *libunwind_frame_sniffer (....
>>
>> so that it is consistent with the rest of GDB.
>>
> 
> Ok.  I copied the declaration from below and forget to rejoin the lines.
> 
> -- Jeff J.
> 
> 

[-- Attachment #2: libunwind.patch1a --]
[-- Type: text/plain, Size: 16036 bytes --]

Index: libunwind-frame.c
===================================================================
RCS file: libunwind-frame.c
diff -N libunwind-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.c	22 Oct 2003 23:36:21 -0000
@@ -0,0 +1,376 @@
+/* Frame unwinder for frames using the libunwind library.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Written by Jeff Johnston, contributed by Red Hat Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+
+#ifdef HAVE_LIBUNWIND_H
+
+#include "inferior.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "regcache.h"
+
+#include <dlfcn.h>
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
+
+#include "libunwind-frame.h"
+
+#include "complaints.h"
+
+static int libunwind_initialized;
+static struct gdbarch_data *libunwind_descr_handle;
+
+#ifndef LIBUNWIND_SO
+#define LIBUNWIND_SO "libunwind.so"
+#endif
+
+/* Required function pointers from libunwind.  */
+static int (*unw_get_reg_p) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
+static int (*unw_get_fpreg_p) (unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
+static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t, unw_save_loc_t *);
+static int (*unw_step_p) (unw_cursor_t *);
+static int (*unw_init_remote_p) (unw_cursor_t *, unw_addr_space_t, void *);
+static unw_addr_space_t (*unw_create_addr_space_p) (unw_accessors_t *, int);
+static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t, unw_dyn_info_t *,
+					 unw_proc_info_t *, int, void *);
+static unw_word_t (*unw_find_dyn_list_p) (unw_addr_space_t, void *, size_t,
+					  unw_word_t, unw_word_t, void *);
+
+
+struct libunwind_frame_cache
+{
+  CORE_ADDR base;
+  CORE_ADDR func_addr;
+  unw_cursor_t cursor;
+};
+
+#define STRINGIFY2(name)	#name
+#define STRINGIFY(name)		STRINGIFY2(name)
+
+static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
+static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
+static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
+static char *step_name = STRINGIFY(UNW_OBJ(step));
+static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
+static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
+static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
+static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
+
+static struct libunwind_descr *
+libunwind_descr (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, libunwind_descr_handle);
+}
+
+static void *
+libunwind_descr_init (struct gdbarch *gdbarch)
+{
+  struct libunwind_descr *descr = GDBARCH_OBSTACK_ZALLOC (gdbarch,
+							  struct libunwind_descr);
+  return descr;
+}
+
+void
+libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *descr)
+{
+  struct libunwind_descr *arch_descr;
+
+  gdb_assert (gdbarch != NULL);
+
+  arch_descr = gdbarch_data (gdbarch, libunwind_descr_handle);
+
+  if (arch_descr == NULL)
+    {
+      /* First time here.  Must initialize data area.  */
+      arch_descr = libunwind_descr_init (gdbarch);
+      set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
+    }
+
+  /* Copy new descriptor info into arch descriptor.  */
+  arch_descr->gdb2uw = descr->gdb2uw;
+  arch_descr->uw2gdb = descr->uw2gdb;
+  arch_descr->is_fpreg = descr->is_fpreg;
+  arch_descr->accessors = descr->accessors;
+}
+
+static struct libunwind_frame_cache *
+libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  unw_word_t fp;
+  unw_regnum_t uw_sp_regnum;
+  struct libunwind_frame_cache *cache;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  if (*this_cache)
+    return *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
+
+  cache->func_addr = frame_func_unwind (next_frame);
+
+  /* Get a cursor to the previous frame.  We do this by initializing
+     a cursor and stepping back to the frame level prior to the one we are 
+     currently in.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  unw_init_remote_p (&cache->cursor, as, next_frame);
+  unw_step_p (&cache->cursor);
+
+  /* To get base address, get sp from previous frame.  */
+  uw_sp_regnum = descr->gdb2uw (SP_REGNUM);
+  ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
+  if (ret < 0)
+    error ("Can't get libunwind sp register.");
+
+  cache->base = (CORE_ADDR)fp;
+
+  *this_cache = cache;
+  return cache;
+}
+
+unw_word_t 
+libunwind_find_dyn_list (unw_addr_space_t as, void *table, size_t table_size,
+			 unw_word_t segbase, unw_word_t gp, void *arg)
+{
+  return unw_find_dyn_list_p (as, table, table_size, segbase, gp, arg);
+}
+
+static const struct frame_unwind libunwind_frame_unwind =
+{
+  NORMAL_FRAME,
+  libunwind_frame_this_id,
+  libunwind_frame_prev_register
+};
+
+const struct frame_unwind *
+libunwind_frame_sniffer (struct frame_info *next_frame)
+{
+  unw_cursor_t cursor;
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  /* Get a cursor to the previous frame.  We do this by initializing
+     a cursor and stepping back to the frame level prior to the one we are 
+     currently in.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  ret = unw_init_remote_p (&cursor, as, next_frame);
+
+  if (ret >= 0)
+    ret = unw_step_p (&cursor);
+
+  if (ret < 0)
+    return NULL;
+
+  return &libunwind_frame_unwind;
+}
+
+void
+libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+		      struct frame_id *this_id)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->func_addr);
+}
+
+void
+libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+			       int regnum, int *optimizedp,
+			       enum lval_type *lvalp, CORE_ADDR *addrp,
+			       int *realnump, void *valuep)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  void *ptr;
+  unw_cursor_t *c;
+  unw_save_loc_t sl;
+  int i, ret;
+  unw_word_t intval;
+  unw_fpreg_t fpval;
+  unw_regnum_t uw_regnum;
+  struct libunwind_descr *descr;
+
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  uw_regnum = descr->gdb2uw (regnum);
+
+  gdb_assert (regnum >= 0);
+
+  if (!target_has_registers)
+    error ("No registers.");
+
+  *optimizedp = 0;
+  *addrp = 0;
+  *lvalp = not_lval;
+  *realnump = -1;
+
+  memset (valuep, 0, register_size (current_gdbarch, regnum));
+
+  if (uw_regnum < 0)
+    return;
+
+  if (descr->is_fpreg (uw_regnum))
+    {
+      ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
+      ptr = &fpval;
+    }
+  else
+    {
+      ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
+      ptr = &intval;
+    }
+
+  if (ret < 0)
+    return;
+
+  memcpy (valuep, ptr, register_size (current_gdbarch, regnum));
+
+  if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
+    return;
+
+  switch (sl.type)
+    {
+    case UNW_SLT_NONE:
+      *optimizedp = 1;
+      break;
+
+    case UNW_SLT_MEMORY:
+      *lvalp = lval_memory;
+      *addrp = sl.u.addr;
+      break;
+
+    case UNW_SLT_REG:
+      *lvalp = lval_register;
+      *realnump = regnum;
+      break;
+    }
+} 
+
+CORE_ADDR
+libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
+
+int
+libunwind_search_unwind_table (void *as, long ip, void *di,
+			       void *pi, int need_unwind_info, void *args)
+{
+  return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip, 
+				    di, pi, need_unwind_info, args);
+}
+
+static int
+libunwind_load (void)
+{
+  void *handle;
+
+  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
+  if (handle == NULL)
+    return 0;
+
+  /* Initialize pointers to the dynamic library functions we will use.  */
+
+  unw_get_reg_p = dlsym (handle, get_reg_name);
+  if (unw_get_reg_p == NULL)
+    return 0;
+
+  unw_get_fpreg_p = dlsym (handle, get_fpreg_name);
+  if (unw_get_fpreg_p == NULL)
+    return 0;
+
+  unw_get_saveloc_p = dlsym (handle, get_saveloc_name);
+  if (unw_get_saveloc_p == NULL)
+    return 0;
+
+  unw_step_p = dlsym (handle, step_name);
+  if (unw_step_p == NULL)
+    return 0;
+
+  unw_init_remote_p = dlsym (handle, init_remote_name);
+  if (unw_init_remote_p == NULL)
+    return 0;
+
+  unw_create_addr_space_p = dlsym (handle, create_addr_space_name);
+  if (unw_create_addr_space_p == NULL)
+    return 0;
+
+  unw_search_unwind_table_p = dlsym (handle, search_unwind_table_name);
+  if (unw_search_unwind_table_p == NULL)
+    return 0;
+
+  unw_find_dyn_list_p = dlsym (handle, find_dyn_list_name);
+  if (unw_find_dyn_list_p == NULL)
+    return 0;
+   
+  return 1;
+}
+
+int
+libunwind_is_initialized (void)
+{
+  return libunwind_initialized;
+}
+
+#endif /* HAVE_LIBUNWIND_H  */
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_libunwind_frame (void);
+
+void
+_initialize_libunwind_frame (void)
+{
+#ifdef HAVE_LIBUNWIND_H
+  libunwind_descr_handle = register_gdbarch_data (libunwind_descr_init);
+
+  libunwind_initialized = libunwind_load ();
+#endif  
+}
Index: libunwind-frame.h
===================================================================
RCS file: libunwind-frame.h
diff -N libunwind-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.h	22 Oct 2003 23:36:21 -0000
@@ -0,0 +1,63 @@
+/* Frame unwinder for frames with libunwind frame information.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Jeff Johnston.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_LIBUNWIND_H
+
+#ifndef LIBUNWIND_FRAME_H
+#define LIBUNWIND_FRAME_H 1
+
+#include "libunwind.h"
+
+struct frame_info;
+
+struct libunwind_descr
+{
+  int (*gdb2uw) (int);
+  int (*uw2gdb) (int);
+  int (*is_fpreg) (int);
+  void *accessors;
+};
+
+const struct frame_unwind *libunwind_frame_sniffer (struct frame_info *next_frame);
+
+void libunwind_frame_set_descr (struct gdbarch *arch, struct libunwind_descr *descr);
+
+void libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+			      struct frame_id *this_id);
+void libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+				    int regnum, int *optimizedp,
+				    enum lval_type *lvalp, CORE_ADDR *addrp,
+				    int *realnump, void *valuep);
+CORE_ADDR libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache);
+
+int libunwind_is_initialized (void);
+
+int libunwind_search_unwind_table (void *as, long ip, void *di,
+				   void *pi, int need_unwind_info, void *args);
+
+unw_word_t libunwind_find_dyn_list (unw_addr_space_t, void *, size_t,
+				    unw_word_t, unw_word_t, void *);
+     
+#endif /* libunwind-frame.h */
+
+#endif /* HAVE_LIBUNWIND_H  */
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.458
diff -u -r1.458 Makefile.in
--- Makefile.in	18 Oct 2003 18:41:22 -0000	1.458
+++ Makefile.in	22 Oct 2003 23:36:21 -0000
@@ -701,6 +701,7 @@
 jv_lang_h = jv-lang.h
 kod_h = kod.h
 language_h = language.h
+libunwind_frame_h = libunwind-frame.h
 linespec_h = linespec.h
 linux_nat_h = linux-nat.h
 m2_lang_h = m2-lang.h
@@ -1271,6 +1272,7 @@
 	i386gnu-nat.c i386gnu-tdep.c \
 	ia64-linux-nat.c ia64-linux-tdep.c ia64-tdep.c \
 	infptrace.c inftarg.c irix4-nat.c irix5-nat.c \
+	libunwind-frame.c \
 	lynx-nat.c m3-nat.c \
 	m68hc11-tdep.c \
 	m68k-tdep.c \
@@ -1897,7 +1899,7 @@
 	$(arch_utils_h) $(floatformat_h) $(regcache_h) $(reggroups_h) \
 	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(doublest_h) \
 	$(value_h) $(gdb_assert_h) $(objfiles_h) $(elf_common_h) \
-	$(elf_bfd_h) $(dis_asm_h)
+	$(elf_bfd_h) $(dis_asm_h) $(libunwind_frame_h)
 infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
 	$(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
 	$(symfile_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h)
@@ -1945,6 +1947,10 @@
 language.o: language.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(value_h) $(gdbcmd_h) $(expression_h) $(language_h) $(target_h) \
 	$(parser_defs_h) $(jv_lang_h) $(demangle_h)
+libunwind-frame.o: libunwind-frame.c $(defs_h) \
+	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
+	$(gdbtypes_h) $(symtab_h) $(objfiles_h) $(regcache_h) \
+	$(gdb_assert_h) $(gdb_string_h) $(complaints_h) $(libunwind_frame_h)
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
 	$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
Index: configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.132
diff -u -r1.132 configure.in
--- configure.in	3 Sep 2003 15:02:48 -0000	1.132
+++ configure.in	22 Oct 2003 23:36:21 -0000
@@ -192,6 +192,33 @@
     enable_gdbtk=no ;;
 esac
 
+# Enable libunwind support.
+AC_ARG_ENABLE(libunwind,
+[  --enable-libunwind          enable libunwind frame unwinding support],
+  [case $enableval in
+    yes | no)
+      ;;
+    *)
+      AC_MSG_ERROR([bad value $enableval for --enable-libunwind]) ;;
+  esac])
+if test x"$enable_libunwind" = xyes; then
+  # We currently only support libunwind on selected platforms.
+  case $host in
+    ia64*)
+      ;;
+    *)
+      AC_MSG_WARN([libunwind isn't supported on $host; disabling])
+      enable_libunwind=no ;;
+  esac
+  if test x"$enable_libunwind" = xyes; then
+    AC_CHECK_HEADERS(libunwind.h)
+    AC_CHECK_HEADERS(libunwind-ia64.h)
+    CONFIG_OBS="$CONFIG_OBS libunwind-frame.o"
+    CONFIG_DEPS="$CONFIG_DEPS libunwind-frame.o"
+    CONFIG_SRCS="$CONFIG_SRCS libunwind-frame.c"
+  fi
+fi
+
 # Profiling support.
 AC_ARG_ENABLE(profiling,
 [  --enable-profiling      enable profiling of GDB],

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-10-22 23:38     ` J. Johnston
@ 2003-11-11 23:09       ` Andrew Cagney
  2003-11-13 23:07         ` J. Johnston
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-11-11 23:09 UTC (permalink / raw)
  To: J. Johnston; +Cc: gdb-patches


>> +#define STRINGIFY2(name)    #name
>> +#define STRINGIFY(name)        STRINGIFY2(name)
>> +
>> +static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
>> +static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
>> +static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
>> +static char *step_name = STRINGIFY(UNW_OBJ(step));
>> +static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
>> +static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
>> +static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
>> +static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
>> 
>> I don't understand this.  A guess is that UNW_OBJ() is doing something evil (use "include/sym-cat.h") to those names and having the array (use "static const char <name>[] = ..." and local to libunwind_load) makes ones debugging life much easier?  If this is the case, can you add some commentary?

> Yes.  The libunwind code is slightly ugly with respect to the fact that the function names are not aliased with generic names.  They all have platform prefixes so I must spell them out.  Function names are generated automatically using the UNW_OBJ macro.

Can you please add this to the file as a comment.



> +void
> +libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *descr)
> +{
> +  struct libunwind_descr *arch_descr;
> +
> +  gdb_assert (gdbarch != NULL);
> +
> +  arch_descr = gdbarch_data (gdbarch, libunwind_descr_handle);
> +
> +  if (arch_descr == NULL)
> +    {
> +      /* First time here.  Must initialize data area.  */
> +      arch_descr = libunwind_descr_init (gdbarch);
> +      set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
> +    }
> +
> +  /* Copy new descriptor info into arch descriptor.  */
> +  arch_descr->gdb2uw = descr->gdb2uw;
> +  arch_descr->uw2gdb = descr->uw2gdb;
> +  arch_descr->is_fpreg = descr->is_fpreg;
> +  arch_descr->accessors = descr->accessors;
> +}

Yes!  Now the architecture has-a libunwind structure.

Doesn't the configury make this:

> +#ifdef HAVE_LIBUNWIND_H

redundant?

> +  libunwind_descr_handle = register_gdbarch_data (libunwind_descr_init);
> +
> +  libunwind_initialized = libunwind_load ();
> +#endif  

> +   Contributed by Jeff Johnston.

(redhat)


> +const struct frame_unwind *libunwind_frame_sniffer (struct frame_info *next_frame);

Comments for this one ...

> +void libunwind_frame_set_descr (struct gdbarch *arch, struct libunwind_descr *descr);
> +
> +void libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
> +			      struct frame_id *this_id);
> +void libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
> +				    int regnum, int *optimizedp,
> +				    enum lval_type *lvalp, CORE_ADDR *addrp,
> +				    int *realnump, void *valuep);
> +CORE_ADDR libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache);
> +
> +int libunwind_is_initialized (void);
> +
> +int libunwind_search_unwind_table (void *as, long ip, void *di,
> +				   void *pi, int need_unwind_info, void *args);

Also comments for this one ...

> +unw_word_t libunwind_find_dyn_list (unw_addr_space_t, void *, size_t,
> +				    unw_word_t, unw_word_t, void *);

> Index: Makefile.in

Yep.

> +	libunwind-frame.c \

> -	$(elf_bfd_h) $(dis_asm_h)
> +	$(elf_bfd_h) $(dis_asm_h) $(libunwind_frame_h)

> +libunwind-frame.o: libunwind-frame.c $(defs_h) \
> +	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
> +	$(gdbtypes_h) $(symtab_h) $(objfiles_h) $(regcache_h) \
> +	$(gdb_assert_h) $(gdb_string_h) $(complaints_h) $(libunwind_frame_h)

> Index: configure.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/configure.in,v
> retrieving revision 1.132
> diff -u -r1.132 configure.in
> --- configure.in	3 Sep 2003 15:02:48 -0000	1.132
> +++ configure.in	22 Oct 2003 23:36:21 -0000
> @@ -192,6 +192,33 @@
>      enable_gdbtk=no ;;
>  esac

Based on 12.1 Working With External Software
http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_12.html#SEC130

I suspect that this should be --with (external libunwind software), and 
not --enable (gdb feature), although, to be honest, its hard to tell 
which it should be.

Anyone?

> +# Enable libunwind support.
> +AC_ARG_ENABLE(libunwind,
> +[  --enable-libunwind          enable libunwind frame unwinding support],
> +  [case $enableval in
> +    yes | no)

The behavior should be:

--{with,enable}-libunwind
Enable libunwind unconditionally.

--{without,disable}-libunwind
Disable libunwind unconditionally

> +      ;;
> +    *)
> +      AC_MSG_ERROR([bad value $enableval for --enable-libunwind]) ;;
> +  esac]

<none>
Check for "libunwind.h" and "libunwind-ia64.h" and if present, enable 
it.  Something like:
     AC_CHECK_HEADERS(libunwind.h)
     AC_CHECK_HEADERS(libunwind-ia64.h)
     test $ac_cv_have_libunwind_h = yes && enable_libunwind=yes

)

And then just:

> +  if test x"$enable_libunwind" = xyes; then
> +    AC_CHECK_HEADERS(libunwind.h)
> +    AC_CHECK_HEADERS(libunwind-ia64.h)
> +    CONFIG_OBS="$CONFIG_OBS libunwind-frame.o"
> +    CONFIG_DEPS="$CONFIG_DEPS libunwind-frame.o"
> +    CONFIG_SRCS="$CONFIG_SRCS libunwind-frame.c"

but also AC_DEFINE(HAVE_LIBUNWIND) so that it can be used.

Andrew



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-11-11 23:09       ` Andrew Cagney
@ 2003-11-13 23:07         ` J. Johnston
  2003-11-14  0:06           ` Andrew Cagney
  0 siblings, 1 reply; 9+ messages in thread
From: J. Johnston @ 2003-11-13 23:07 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 6370 bytes --]

Patch resubmitted.  See comments below.


Andrew Cagney wrote:
> 
>>> +#define STRINGIFY2(name)    #name
>>> +#define STRINGIFY(name)        STRINGIFY2(name)
>>> +
>>> +static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
>>> +static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
>>> +static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_saveloc));
>>> +static char *step_name = STRINGIFY(UNW_OBJ(step));
>>> +static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
>>> +static char *create_addr_space_name = 
>>> STRINGIFY(UNW_OBJ(create_addr_space));
>>> +static char *search_unwind_table_name = 
>>> STRINGIFY(UNW_OBJ(search_unwind_table));
>>> +static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
>>>
>>> I don't understand this.  A guess is that UNW_OBJ() is doing 
>>> something evil (use "include/sym-cat.h") to those names and having 
>>> the array (use "static const char <name>[] = ..." and local to 
>>> libunwind_load) makes ones debugging life much easier?  If this is 
>>> the case, can you add some commentary?
> 
> 
>> Yes.  The libunwind code is slightly ugly with respect to the fact 
>> that the function names are not aliased with generic names.  They all 
>> have platform prefixes so I must spell them out.  Function names are 
>> generated automatically using the UNW_OBJ macro.
> 
> 
> Can you please add this to the file as a comment.
> 

Done.

> 
> 
>> +void
>> +libunwind_frame_set_descr (struct gdbarch *gdbarch, struct 
>> libunwind_descr *descr)
>> +{
>> +  struct libunwind_descr *arch_descr;
>> +
>> +  gdb_assert (gdbarch != NULL);
>> +
>> +  arch_descr = gdbarch_data (gdbarch, libunwind_descr_handle);
>> +
>> +  if (arch_descr == NULL)
>> +    {
>> +      /* First time here.  Must initialize data area.  */
>> +      arch_descr = libunwind_descr_init (gdbarch);
>> +      set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
>> +    }
>> +
>> +  /* Copy new descriptor info into arch descriptor.  */
>> +  arch_descr->gdb2uw = descr->gdb2uw;
>> +  arch_descr->uw2gdb = descr->uw2gdb;
>> +  arch_descr->is_fpreg = descr->is_fpreg;
>> +  arch_descr->accessors = descr->accessors;
>> +}
> 
> 
> Yes!  Now the architecture has-a libunwind structure.
> 
> Doesn't the configury make this:
> 
>> +#ifdef HAVE_LIBUNWIND_H
> 
> 
> redundant?
>

It is possible for the user to enable libunwind but the header files are not 
there.  I am guessing you would prefer compilation to fail in this case so I 
have removed the check.

>> +  libunwind_descr_handle = register_gdbarch_data (libunwind_descr_init);
>> +
>> +  libunwind_initialized = libunwind_load ();
>> +#endif  
> 
> 
>> +   Contributed by Jeff Johnston.
> 
> 
> (redhat)
> 

Changed.

> 
>> +const struct frame_unwind *libunwind_frame_sniffer (struct frame_info 
>> *next_frame);
> 
> 
> Comments for this one ...
> 

Done.

>> +void libunwind_frame_set_descr (struct gdbarch *arch, struct 
>> libunwind_descr *descr);
>> +
>> +void libunwind_frame_this_id (struct frame_info *next_frame, void 
>> **this_cache,
>> +                  struct frame_id *this_id);
>> +void libunwind_frame_prev_register (struct frame_info *next_frame, 
>> void **this_cache,
>> +                    int regnum, int *optimizedp,
>> +                    enum lval_type *lvalp, CORE_ADDR *addrp,
>> +                    int *realnump, void *valuep);
>> +CORE_ADDR libunwind_frame_base_address (struct frame_info 
>> *next_frame, void **this_cache);
>> +
>> +int libunwind_is_initialized (void);
>> +
>> +int libunwind_search_unwind_table (void *as, long ip, void *di,
>> +                   void *pi, int need_unwind_info, void *args);
> 
> 
> Also comments for this one ...
> 

I have added comments for the search unwind table call.

>> +unw_word_t libunwind_find_dyn_list (unw_addr_space_t, void *, size_t,
>> +                    unw_word_t, unw_word_t, void *);
> 
> 
>> Index: Makefile.in
> 
> 
> Yep.
> 
>> +    libunwind-frame.c \
> 
> 
>> -    $(elf_bfd_h) $(dis_asm_h)
>> +    $(elf_bfd_h) $(dis_asm_h) $(libunwind_frame_h)
> 
> 
>> +libunwind-frame.o: libunwind-frame.c $(defs_h) \
>> +    $(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
>> +    $(gdbtypes_h) $(symtab_h) $(objfiles_h) $(regcache_h) \
>> +    $(gdb_assert_h) $(gdb_string_h) $(complaints_h) $(libunwind_frame_h)
> 
> 
>> Index: configure.in
>> ===================================================================
>> RCS file: /cvs/src/src/gdb/configure.in,v
>> retrieving revision 1.132
>> diff -u -r1.132 configure.in
>> --- configure.in    3 Sep 2003 15:02:48 -0000    1.132
>> +++ configure.in    22 Oct 2003 23:36:21 -0000
>> @@ -192,6 +192,33 @@
>>      enable_gdbtk=no ;;
>>  esac
> 
> 
> Based on 12.1 Working With External Software
> http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_12.html#SEC130 
> 
> 
> I suspect that this should be --with (external libunwind software), and 
> not --enable (gdb feature), although, to be honest, its hard to tell 
> which it should be.
> 
> Anyone?
>

 From discussions with Jeff Law when I was doing configuration for newlib, he 
told me that --enable should be used for on/off decisions in preference to 
--with.  I don't personally care so I have switched to --with.

>> +# Enable libunwind support.
>> +AC_ARG_ENABLE(libunwind,
>> +[  --enable-libunwind          enable libunwind frame unwinding 
>> support],
>> +  [case $enableval in
>> +    yes | no)
> 
> 
> The behavior should be:
> 
> --{with,enable}-libunwind
> Enable libunwind unconditionally.
> 
> --{without,disable}-libunwind
> Disable libunwind unconditionally
> 
>> +      ;;
>> +    *)
>> +      AC_MSG_ERROR([bad value $enableval for --enable-libunwind]) ;;
>> +  esac]
> 
> 
> <none>
> Check for "libunwind.h" and "libunwind-ia64.h" and if present, enable 
> it.  Something like:
>     AC_CHECK_HEADERS(libunwind.h)
>     AC_CHECK_HEADERS(libunwind-ia64.h)
>     test $ac_cv_have_libunwind_h = yes && enable_libunwind=yes
> 
> )
> 
> And then just:
> 
>> +  if test x"$enable_libunwind" = xyes; then
>> +    AC_CHECK_HEADERS(libunwind.h)
>> +    AC_CHECK_HEADERS(libunwind-ia64.h)
>> +    CONFIG_OBS="$CONFIG_OBS libunwind-frame.o"
>> +    CONFIG_DEPS="$CONFIG_DEPS libunwind-frame.o"
>> +    CONFIG_SRCS="$CONFIG_SRCS libunwind-frame.c"
> 
> 
> but also AC_DEFINE(HAVE_LIBUNWIND) so that it can be used.
> 

Done.



[-- Attachment #2: libunwind.patch2 --]
[-- Type: text/plain, Size: 17309 bytes --]

Index: libunwind-frame.c
===================================================================
RCS file: libunwind-frame.c
diff -N libunwind-frame.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.c	13 Nov 2003 23:05:04 -0000
@@ -0,0 +1,388 @@
+/* Frame unwinder for frames using the libunwind library.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Written by Jeff Johnston, contributed by Red Hat Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+
+#include "inferior.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "regcache.h"
+
+#include <dlfcn.h>
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
+
+#include "libunwind-frame.h"
+
+#include "complaints.h"
+
+static int libunwind_initialized;
+static struct gdbarch_data *libunwind_descr_handle;
+
+#ifndef LIBUNWIND_SO
+#define LIBUNWIND_SO "libunwind.so"
+#endif
+
+/* Required function pointers from libunwind.  */
+static int (*unw_get_reg_p) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
+static int (*unw_get_fpreg_p) (unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
+static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t, unw_save_loc_t *);
+static int (*unw_step_p) (unw_cursor_t *);
+static int (*unw_init_remote_p) (unw_cursor_t *, unw_addr_space_t, void *);
+static unw_addr_space_t (*unw_create_addr_space_p) (unw_accessors_t *, int);
+static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t, unw_dyn_info_t *,
+					 unw_proc_info_t *, int, void *);
+static unw_word_t (*unw_find_dyn_list_p) (unw_addr_space_t, void *, size_t,
+					  unw_word_t, unw_word_t, void *);
+
+
+struct libunwind_frame_cache
+{
+  CORE_ADDR base;
+  CORE_ADDR func_addr;
+  unw_cursor_t cursor;
+};
+
+/* We need to qualify the function names with a platform-specific prefix to match 
+   the names used by the libunwind library.  The UNW_OBJ macro is provided by the
+   libunwind.h header file.  */
+#define STRINGIFY2(name)	#name
+#define STRINGIFY(name)		STRINGIFY2(name)
+
+static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
+static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
+static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc));
+static char *step_name = STRINGIFY(UNW_OBJ(step));
+static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
+static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
+static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
+static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
+
+static struct libunwind_descr *
+libunwind_descr (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, libunwind_descr_handle);
+}
+
+static void *
+libunwind_descr_init (struct gdbarch *gdbarch)
+{
+  struct libunwind_descr *descr = GDBARCH_OBSTACK_ZALLOC (gdbarch,
+							  struct libunwind_descr);
+  return descr;
+}
+
+void
+libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *descr)
+{
+  struct libunwind_descr *arch_descr;
+
+  gdb_assert (gdbarch != NULL);
+
+  arch_descr = gdbarch_data (gdbarch, libunwind_descr_handle);
+
+  if (arch_descr == NULL)
+    {
+      /* First time here.  Must initialize data area.  */
+      arch_descr = libunwind_descr_init (gdbarch);
+      set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
+    }
+
+  /* Copy new descriptor info into arch descriptor.  */
+  arch_descr->gdb2uw = descr->gdb2uw;
+  arch_descr->uw2gdb = descr->uw2gdb;
+  arch_descr->is_fpreg = descr->is_fpreg;
+  arch_descr->accessors = descr->accessors;
+}
+
+static struct libunwind_frame_cache *
+libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  unw_word_t fp;
+  unw_regnum_t uw_sp_regnum;
+  struct libunwind_frame_cache *cache;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  if (*this_cache)
+    return *this_cache;
+
+  /* Allocate a new cache.  */
+  cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
+
+  cache->func_addr = frame_func_unwind (next_frame);
+
+  /* Get a libunwind cursor to the previous frame.  We do this by initializing
+     a cursor.  Libunwind treats a new cursor as the top of stack and will get
+     the current register set via the libunwind register accessor.  Now, we
+     provide the platform-specific accessors and we set up the register accessor to use
+     the frame register unwinding interfaces so that we properly get the registers for
+     the current frame rather than the top.  We then use the  unw_step function to 
+     move the libunwind cursor back one frame.  We can later use this cursor to find previous 
+     registers via the unw_get_reg interface which will invoke libunwind's special logic.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  unw_init_remote_p (&cache->cursor, as, next_frame);
+  unw_step_p (&cache->cursor);
+
+  /* To get base address, get sp from previous frame.  */
+  uw_sp_regnum = descr->gdb2uw (SP_REGNUM);
+  ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
+  if (ret < 0)
+    error ("Can't get libunwind sp register.");
+
+  cache->base = (CORE_ADDR)fp;
+
+  *this_cache = cache;
+  return cache;
+}
+
+unw_word_t 
+libunwind_find_dyn_list (unw_addr_space_t as, void *table, size_t table_size,
+			 unw_word_t segbase, unw_word_t gp, void *arg)
+{
+  return unw_find_dyn_list_p (as, table, table_size, segbase, gp, arg);
+}
+
+static const struct frame_unwind libunwind_frame_unwind =
+{
+  NORMAL_FRAME,
+  libunwind_frame_this_id,
+  libunwind_frame_prev_register
+};
+
+/* Verify if there is sufficient libunwind information for the frame to use
+   libunwind frame unwinding.  */
+const struct frame_unwind *
+libunwind_frame_sniffer (struct frame_info *next_frame)
+{
+  unw_cursor_t cursor;
+  unw_accessors_t *acc;
+  unw_addr_space_t as;
+  struct libunwind_descr *descr;
+  int i, ret;
+
+  /* To test for libunwind unwind support, initialize a cursor to the current frame and try to back
+     up.  We use this same method when setting up the frame cache (see libunwind_frame_cache()).
+     If libunwind returns success for this operation, it means that it has found sufficient
+     libunwind unwinding information to do so.  */
+
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  acc = descr->accessors;
+  as =  unw_create_addr_space_p (acc,
+				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+				 ? __BIG_ENDIAN
+				 : __LITTLE_ENDIAN);
+
+  ret = unw_init_remote_p (&cursor, as, next_frame);
+
+  if (ret >= 0)
+    ret = unw_step_p (&cursor);
+
+  if (ret < 0)
+    return NULL;
+
+  return &libunwind_frame_unwind;
+}
+
+void
+libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+		      struct frame_id *this_id)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->func_addr);
+}
+
+void
+libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+			       int regnum, int *optimizedp,
+			       enum lval_type *lvalp, CORE_ADDR *addrp,
+			       int *realnump, void *valuep)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  void *ptr;
+  unw_cursor_t *c;
+  unw_save_loc_t sl;
+  int i, ret;
+  unw_word_t intval;
+  unw_fpreg_t fpval;
+  unw_regnum_t uw_regnum;
+  struct libunwind_descr *descr;
+
+  /* Convert from gdb register number to libunwind register number.  */
+  descr = libunwind_descr (get_frame_arch (next_frame));
+  uw_regnum = descr->gdb2uw (regnum);
+
+  gdb_assert (regnum >= 0);
+
+  if (!target_has_registers)
+    error ("No registers.");
+
+  *optimizedp = 0;
+  *addrp = 0;
+  *lvalp = not_lval;
+  *realnump = -1;
+
+  memset (valuep, 0, register_size (current_gdbarch, regnum));
+
+  if (uw_regnum < 0)
+    return;
+
+  /* To get the previous register, we use the libunwind register APIs with
+     the cursor we have already pushed back to the previous frame.  */
+
+  if (descr->is_fpreg (uw_regnum))
+    {
+      ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
+      ptr = &fpval;
+    }
+  else
+    {
+      ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
+      ptr = &intval;
+    }
+
+  if (ret < 0)
+    return;
+
+  memcpy (valuep, ptr, register_size (current_gdbarch, regnum));
+
+  if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
+    return;
+
+  switch (sl.type)
+    {
+    case UNW_SLT_NONE:
+      *optimizedp = 1;
+      break;
+
+    case UNW_SLT_MEMORY:
+      *lvalp = lval_memory;
+      *addrp = sl.u.addr;
+      break;
+
+    case UNW_SLT_REG:
+      *lvalp = lval_register;
+      *realnump = regnum;
+      break;
+    }
+} 
+
+CORE_ADDR
+libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct libunwind_frame_cache *cache =
+    libunwind_frame_cache (next_frame, this_cache);
+
+  return cache->base;
+}
+
+/* The following is a glue routine to call the libunwind unwind table
+   search function to get unwind information for a specified ip address.  */ 
+int
+libunwind_search_unwind_table (void *as, long ip, void *di,
+			       void *pi, int need_unwind_info, void *args)
+{
+  return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip, 
+				    di, pi, need_unwind_info, args);
+}
+
+static int
+libunwind_load (void)
+{
+  void *handle;
+
+  handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
+  if (handle == NULL)
+    return 0;
+
+  /* Initialize pointers to the dynamic library functions we will use.  */
+
+  unw_get_reg_p = dlsym (handle, get_reg_name);
+  if (unw_get_reg_p == NULL)
+    return 0;
+
+  unw_get_fpreg_p = dlsym (handle, get_fpreg_name);
+  if (unw_get_fpreg_p == NULL)
+    return 0;
+
+  unw_get_saveloc_p = dlsym (handle, get_saveloc_name);
+  if (unw_get_saveloc_p == NULL)
+    return 0;
+
+  unw_step_p = dlsym (handle, step_name);
+  if (unw_step_p == NULL)
+    return 0;
+
+  unw_init_remote_p = dlsym (handle, init_remote_name);
+  if (unw_init_remote_p == NULL)
+    return 0;
+
+  unw_create_addr_space_p = dlsym (handle, create_addr_space_name);
+  if (unw_create_addr_space_p == NULL)
+    return 0;
+
+  unw_search_unwind_table_p = dlsym (handle, search_unwind_table_name);
+  if (unw_search_unwind_table_p == NULL)
+    return 0;
+
+  unw_find_dyn_list_p = dlsym (handle, find_dyn_list_name);
+  if (unw_find_dyn_list_p == NULL)
+    return 0;
+   
+  return 1;
+}
+
+int
+libunwind_is_initialized (void)
+{
+  return libunwind_initialized;
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_libunwind_frame (void);
+
+void
+_initialize_libunwind_frame (void)
+{
+  libunwind_descr_handle = register_gdbarch_data (libunwind_descr_init);
+
+  libunwind_initialized = libunwind_load ();
+}
Index: libunwind-frame.h
===================================================================
RCS file: libunwind-frame.h
diff -N libunwind-frame.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libunwind-frame.h	13 Nov 2003 23:05:04 -0000
@@ -0,0 +1,63 @@
+/* Frame unwinder for frames with libunwind frame information.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by Jeff Johnston.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_LIBUNWIND_H
+
+#ifndef LIBUNWIND_FRAME_H
+#define LIBUNWIND_FRAME_H 1
+
+#include "libunwind.h"
+
+struct frame_info;
+
+struct libunwind_descr
+{
+  int (*gdb2uw) (int);
+  int (*uw2gdb) (int);
+  int (*is_fpreg) (int);
+  void *accessors;
+};
+
+const struct frame_unwind *libunwind_frame_sniffer (struct frame_info *next_frame);
+
+void libunwind_frame_set_descr (struct gdbarch *arch, struct libunwind_descr *descr);
+
+void libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
+			      struct frame_id *this_id);
+void libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+				    int regnum, int *optimizedp,
+				    enum lval_type *lvalp, CORE_ADDR *addrp,
+				    int *realnump, void *valuep);
+CORE_ADDR libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache);
+
+int libunwind_is_initialized (void);
+
+int libunwind_search_unwind_table (void *as, long ip, void *di,
+				   void *pi, int need_unwind_info, void *args);
+
+unw_word_t libunwind_find_dyn_list (unw_addr_space_t, void *, size_t,
+				    unw_word_t, unw_word_t, void *);
+     
+#endif /* libunwind-frame.h */
+
+#endif /* HAVE_LIBUNWIND_H  */
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.468
diff -u -r1.468 Makefile.in
--- Makefile.in	3 Nov 2003 17:03:11 -0000	1.468
+++ Makefile.in	13 Nov 2003 23:05:04 -0000
@@ -707,6 +707,7 @@
 jv_lang_h = jv-lang.h
 kod_h = kod.h
 language_h = language.h
+libunwind_frame_h = libunwind-frame.h
 linespec_h = linespec.h
 linux_nat_h = linux-nat.h
 m2_lang_h = m2-lang.h
@@ -1279,6 +1280,7 @@
 	i386gnu-nat.c i386gnu-tdep.c \
 	ia64-linux-nat.c ia64-linux-tdep.c ia64-tdep.c \
 	infptrace.c inftarg.c irix4-nat.c irix5-nat.c \
+	libunwind-frame.c \
 	lynx-nat.c m3-nat.c \
 	m68hc11-tdep.c \
 	m68k-tdep.c \
@@ -1910,7 +1912,7 @@
 	$(arch_utils_h) $(floatformat_h) $(regcache_h) $(reggroups_h) \
 	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(doublest_h) \
 	$(value_h) $(gdb_assert_h) $(objfiles_h) $(elf_common_h) \
-	$(elf_bfd_h) $(dis_asm_h)
+	$(elf_bfd_h) $(dis_asm_h) $(libunwind_frame_h)
 infcall.o: infcall.c $(defs_h) $(breakpoint_h) $(target_h) $(regcache_h) \
 	$(inferior_h) $(gdb_assert_h) $(block_h) $(gdbcore_h) $(language_h) \
 	$(symfile_h) $(gdbcmd_h) $(command_h) $(gdb_string_h) $(infcall_h)
@@ -1958,6 +1960,10 @@
 language.o: language.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(value_h) $(gdbcmd_h) $(expression_h) $(language_h) $(target_h) \
 	$(parser_defs_h) $(jv_lang_h) $(demangle_h)
+libunwind-frame.o: libunwind-frame.c $(defs_h) \
+	$(frame_h) $(frame_base_h) $(frame_unwind_h) $(gdbcore_h) \
+	$(gdbtypes_h) $(symtab_h) $(objfiles_h) $(regcache_h) \
+	$(gdb_assert_h) $(gdb_string_h) $(complaints_h) $(libunwind_frame_h)
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
 	$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
Index: configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.132
diff -u -r1.132 configure.in
--- configure.in	3 Sep 2003 15:02:48 -0000	1.132
+++ configure.in	13 Nov 2003 23:05:05 -0000
@@ -192,6 +192,30 @@
     enable_gdbtk=no ;;
 esac
 
+# Libunwind support.
+AC_ARG_WITH(libunwind,
+[  --with-libunwind            Use libunwind frame unwinding support],
+[case "${withval}" in
+  yes)  enable_libunwind=yes ;;
+  no)   enable_libunwind=no ;;
+  *)    AC_MSG_ERROR(bad value ${withval} for GDB with-libunwind option) ;;
+esac],[
+  AC_CHECK_HEADERS(libunwind.h)
+  AC_CHECK_HEADERS(libunwind-ia64.h)
+  if test x"$ac_cv_header_libunwind_h" = xyes -a x"$ac_cv_header_libunwind_ia64_h" = xyes; then
+    enable_libunwind=yes;
+  fi
+])
+   
+if test x"$enable_libunwind" = xyes; then
+  AC_CHECK_HEADERS(libunwind.h)
+  AC_CHECK_HEADERS(libunwind-ia64.h)
+  AC_DEFINE(HAVE_LIBUNWIND, 1)
+  CONFIG_OBS="$CONFIG_OBS libunwind-frame.o"
+  CONFIG_DEPS="$CONFIG_DEPS libunwind-frame.o"
+  CONFIG_SRCS="$CONFIG_SRCS libunwind-frame.c"
+fi
+
 # Profiling support.
 AC_ARG_ENABLE(profiling,
 [  --enable-profiling      enable profiling of GDB],

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-11-13 23:07         ` J. Johnston
@ 2003-11-14  0:06           ` Andrew Cagney
  2003-11-14 21:19             ` J. Johnston
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Cagney @ 2003-11-14  0:06 UTC (permalink / raw)
  To: J. Johnston; +Cc: gdb-patches


> It is possible for the user to enable libunwind but the header files are not there.  I am guessing you would prefer compilation to fail in this case so I have removed the check.

Yes.  If the user forces the use of libunwind, but it isn't there, the 
user should loose.

> I have added comments for the search unwind table call.

Thanks.


> Index: configure.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/configure.in,v
> retrieving revision 1.132
> diff -u -r1.132 configure.in
> --- configure.in    3 Sep 2003 15:02:48 -0000    1.132
> +++ configure.in    22 Oct 2003 23:36:21 -0000
> @@ -192,6 +192,33 @@
>      enable_gdbtk=no ;;
>  esac
> 
> 
> Based on 12.1 Working With External Software
> http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_12.html#SEC130
> 
> I suspect that this should be --with (external libunwind software), and not --enable (gdb feature), although, to be honest, its hard to tell which it should be.
> 
> Anyone?
> 
> 
> From discussions with Jeff Law when I was doing configuration for newlib, he told me that --enable should be used for on/off decisions in preference to --with.  I don't personally care so I have switched to --with.

Thanks.

You're right that the lines are blured.  enable/disable is for 
controlling the presence of an internal feature while with/without is 
for controlling a dependency/use of an external program, or library. 
Unfortunatly, here the decision to build GDB with/without the external 
libunwind library has the consequence of determining if GDB should 
enable/disable the internal (but not user visible) libunwind unwinder. 
I think, based on the presence of X as an example in the manual, the 
with/without takes precidence.

So, yes all ok.
Andrew



> Index: libunwind-frame.c



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: RFA: libunwind basic support
  2003-11-14  0:06           ` Andrew Cagney
@ 2003-11-14 21:19             ` J. Johnston
  0 siblings, 0 replies; 9+ messages in thread
From: J. Johnston @ 2003-11-14 21:19 UTC (permalink / raw)
  To: Andrew Cagney; +Cc: gdb-patches

Patch checked in.  I forgot acconfig.h in the original patch which just added 
the #undef HAVE_LIBUNWIND reference.  The following is the amended ChangeLog entry.

2003-11-14  Jeff Johnston  <jjohnstn@redhat.com>

         * libunwind-frame.c: New file.
         * libunwind-frame.h: New file.
         * acconfig.h (HAVE_LIBUNWIND): #undef reference added.
         * configure.in: Add --with-libunwind option support.  Define
         HAVE_LIBUNWIND if libunwind support selected / defaulted.
         Also check for libunwind.h and libunwind-ia64.h headers.
         * configure: Regenerated.
         * Makefile.in: Add support for libunwind-frame.o.
         * config.in: Regenerated.

Thanks,

-- Jeff J.

Andrew Cagney wrote:
> 
>> It is possible for the user to enable libunwind but the header files 
>> are not there.  I am guessing you would prefer compilation to fail in 
>> this case so I have removed the check.
> 
> 
> Yes.  If the user forces the use of libunwind, but it isn't there, the 
> user should loose.
> 
>> I have added comments for the search unwind table call.
> 
> 
> Thanks.
> 
> 
>> Index: configure.in
>> ===================================================================
>> RCS file: /cvs/src/src/gdb/configure.in,v
>> retrieving revision 1.132
>> diff -u -r1.132 configure.in
>> --- configure.in    3 Sep 2003 15:02:48 -0000    1.132
>> +++ configure.in    22 Oct 2003 23:36:21 -0000
>> @@ -192,6 +192,33 @@
>>      enable_gdbtk=no ;;
>>  esac
>>
>>
>> Based on 12.1 Working With External Software
>> http://www.gnu.org/software/autoconf/manual/autoconf-2.57/html_chapter/autoconf_12.html#SEC130 
>>
>>
>> I suspect that this should be --with (external libunwind software), 
>> and not --enable (gdb feature), although, to be honest, its hard to 
>> tell which it should be.
>>
>> Anyone?
>>
>>
>> From discussions with Jeff Law when I was doing configuration for 
>> newlib, he told me that --enable should be used for on/off decisions 
>> in preference to --with.  I don't personally care so I have switched 
>> to --with.
> 
> 
> Thanks.
> 
> You're right that the lines are blured.  enable/disable is for 
> controlling the presence of an internal feature while with/without is 
> for controlling a dependency/use of an external program, or library. 
> Unfortunatly, here the decision to build GDB with/without the external 
> libunwind library has the consequence of determining if GDB should 
> enable/disable the internal (but not user visible) libunwind unwinder. I 
> think, based on the presence of X as an example in the manual, the 
> with/without takes precidence.
> 
> So, yes all ok.
> Andrew
> 
> 
> 
>> Index: libunwind-frame.c
> 
> 
> 
> 


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2003-11-14 21:19 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-10-15 21:29 RFA: libunwind basic support J. Johnston
2003-10-15 22:40 ` Kevin Buettner
2003-10-16 20:19 ` Andrew Cagney
2003-10-16 21:38   ` J. Johnston
2003-10-22 23:38     ` J. Johnston
2003-11-11 23:09       ` Andrew Cagney
2003-11-13 23:07         ` J. Johnston
2003-11-14  0:06           ` Andrew Cagney
2003-11-14 21:19             ` J. Johnston

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox