Skip to content

Commit

Permalink
(Logical change 1.3)
Browse files Browse the repository at this point in the history
  • Loading branch information
mostang.com!davidm committed Feb 15, 2002
1 parent 63669f7 commit 7fbfe0a
Show file tree
Hide file tree
Showing 36 changed files with 5,984 additions and 0 deletions.
1 change: 1 addition & 0 deletions BitKeeper/etc/logging_ok
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
davidm@panda.mostang.com
340 changes: 340 additions & 0 deletions COPYING

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
2002-01-18 David Mosberger-Tang <David.Mosberger@acm.org>

* src/ia64/parser.c (__ia64_unw_create_state_record): Set
IA64_FLAG_HAS_HANDLER if the unwind info descriptors indicate that
there a handler.

* src/ia64/regs.c (__ia64_access_reg): Return zero for UNW_REG_HANDLER
in frames that don't have a personality routine.

* src/ia64/unwind_i.h (IA64_FLAG_HAS_HANDLER): New flag.

* src/ia64/regs.c (__ia64_access_reg): When reading UNW_REG_HANDLER,
account for the fact that the personality address is gp-relative.

* src/ia64/parser.c (__ia64_unw_create_state_record): Fix
initialization of segbase and len.

2002-01-17 David Mosberger-Tang <David.Mosberger@acm.org>

* include/unwind-ia64.h: Include via "unwind.h" to ensure
the file is picked up from same directory.

2002-01-16 David Mosberger-Tang <David.Mosberger@acm.org>

* include/unwind.h: Define UNW_ESTOPUNWIND. This error code may
be returned by acquire_unwind_info() to force termination of
unwinding. An application may want to do this when encountering a
call frame for dynamically generated code, for example.

* unwind.h: Pass opaque argument pointer to acquire_unwind_info()
and release_unwind_info() like we do for access_mem() etc.

2002-01-14 David Mosberger-Tang <David.Mosberger@acm.org>

* Version 0.0 released.

2002-01-11 David Mosberger-Tang <David.Mosberger@acm.org>

* ChangeLog created.
74 changes: 74 additions & 0 deletions NOTES
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
The central data structure of the unwind API is the unwind cursor.
This structure tracks the frame registers and the preserved registers.
The distinction between frame registers and preserved registers is
important: the former represent the *current* value of a register (as
it existed at the current IP); the latter represent the *saved* value
of a register (i.e., the value that existed on entry to the current
procedure). The unwind API defines a handful of well-known frame
"registers":

- ip: the instruction pointer (pc)
- rp: the return pointer (rp, aka "return address" or "return link")
- sp: the stack pointer (memory stack pointer, in the case of ia64)
- fp: the frame pointer
- first_ip: the starting address of the current "procedure"
- handler: a pointer to an architecture & language-specific
"personality" routine
- lsda: a pointer to an architecture & language-specific
data-area

The API defines no well-known preserved registers. Each architecture
can define additional registers as needed. Of course, a portable
application may only rely on well-known registers. The names for
preserved registers are defined in the architecture-specific header
file <unwind-ARCH.h>. For example, to get the IA-64-specific register
names, an application would do:

#include <unwind-ia64.h>

The API is designed to handle two primary cases: unwinding within the
current (local) process and unwinding of another ("remote") process
(e.g., through ptrace()). In the local case, the initial machine
state is captured by an unwind context (currently the same as
ucontext_t). In the remote case, the initial machine state is
captured by an unwind accessor structure, which provides callback
routines for reading/writing memory and registers and for obtaining
unwind information.

Once a cursor has been initialized, you can step through the call
chain with the unw_step() routine. The frame registers and the
preserved state can then be accessed with unw_get_reg() or modified
with unw_set_reg(). For floating-point registers, there are separate
unw_get_fpreg() and unw_set_fpreg() routines (on some arches, e.g.,
Alpha, these could be just aliases for unw_{g,s}et_reg()). The
unw_resume() routine can be used to resume execution at an arbitrary
point in the call-chain (as identified by an unwind cursor). This is
intended for exception handling and, at least for now, the intention
is to support this routine only for the local case. Kevin, if you
feel gdb could benefit from such a routine, I'd be interested to hear
about it.

Note that it is perfectly legal to make copies of the unwind cursor.
This makes it possible, e.g., to obtain an unwind context, modify the
state in an earlier call frame, and then resume execution at the point
at which the unwind context was captured.

Here is a quick example of how to use the unwind API to do a simple
stack trace:

unw_cursor_t cursor;
unw_word_t ip, sp;
ucontext_t uc;

getcontext(&uc);
unw_init_local(&cursor, &uc);
do
{
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf ("ip=%016lx sp=%016lx\n", ip, sp);
}
while (unw_step (&cursor) > 0);

Note that this particular example should work on pretty much any
architecture, as it doesn't rely on any arch-specific registers.
46 changes: 46 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
This is version 0.0 of the unwind library. At the moment, only the
IA-64 Linux (IPF Linux) platform is supported and even that support
has received only light testing. Consequently, this release is
intended primarily to expose the unwind API to more developers and to
collect feedback on what does and does not work. Having said that,
backtracing through gcc-generated code might work reasonably well.

There is virtually no documentation at the moment. A brief outline of
the unwind API is in file NOTES. To get a feel for how things are
intended to work, you may also want to take a look at include/unwind.h
and include/unwind-ia64.h. Finally, the test program in
src/tests/bt.c shows two ways of how to do a simple backtrace: one
uses libunwind directly, the other uses a libunwind-based
implementation of the backtrace() function. The test program in
src/tests/exc.c shows the basics of how to do exception handling with
this library.

The following steps should be used to compile and install this library:

$ cd src
$ make dep
$ make
$ make install prefix=PREFIX

where PREFIX is the installation prefix. By default, a prefix of /usr
is used, such that libunwind.a is installed in /usr/lib and unwind.h
is installed in /usr/include. For testing, you may want to use a
prefix of /usr/local instead.

Please direct all questions regarding this library to:

libunwind@linux.hpl.hp.com

For spam protection, you'll have to subscribe to this list before
posting a question. You can do this by sending a mail to
libunwind-request@linux.hpl.hp.com with a body of:

subscribe libunwind

Note: the host that is running this list is behind a firewall, so
you'll not be able to use the Web interface to manage your
subscription. Send a mail containing "help" to
libunwind-request@linux.hpl.hp.com for information on how to manage
your subscription via email.

--david
1 change: 1 addition & 0 deletions include/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#undef SIGCONTEXT_HAS_AR25_AND_AR26
2 changes: 2 additions & 0 deletions include/libunwind-config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#define UNW_TARGET_IA64
#undef UNW_LOCAL_ONLY
99 changes: 99 additions & 0 deletions include/libunwind-ia64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/* libunwind - a platform-independent unwind library
Copyright (C) 2001-2002 Hewlett-Packard Co
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of libunwind.
libunwind 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, or (at your option)
any later version.
libunwind 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public
License. */

#include <ucontext.h>

typedef enum
{
/* Note: general registers are excepted to start with index 0.
This convention facilitates architecture-independent
implementation of the C++ exception handling ABI. See
_Unwind_SetGR() and _Unwind_GetGR() for details. */
UNW_IA64_GR = 0, /* general registers (r0..r127) */
UNW_IA64_GP = UNW_IA64_GR + 1,
UNW_IA64_SP = UNW_IA64_GR + 12,
UNW_IA64_TP = UNW_IA64_GR + 13,

UNW_IA64_NAT = UNW_IA64_GR + 128, /* NaT registers (nat0..nat127) */

UNW_IA64_FR = UNW_IA64_NAT + 128, /* fp registers (f0..f127) */

UNW_IA64_AR = UNW_IA64_FR + 128, /* application registers (ar0..r127) */
UNW_IA64_AR_RSC = UNW_IA64_AR + 16,
UNW_IA64_AR_BSP = UNW_IA64_AR + 17,
UNW_IA64_AR_BSPSTORE = UNW_IA64_AR + 18,
UNW_IA64_AR_RNAT = UNW_IA64_AR + 19,
UNW_IA64_AR_25 = UNW_IA64_AR + 25, /* reserved (scratch) */
UNW_IA64_AR_26 = UNW_IA64_AR + 26, /* reserved (scratch) */
UNW_IA64_AR_CCV = UNW_IA64_AR + 32,
UNW_IA64_AR_UNAT = UNW_IA64_AR + 36,
UNW_IA64_AR_FPSR = UNW_IA64_AR + 40,
UNW_IA64_AR_PFS = UNW_IA64_AR + 64,
UNW_IA64_AR_LC = UNW_IA64_AR + 65,
UNW_IA64_AR_EC = UNW_IA64_AR + 66,

UNW_IA64_BR = UNW_IA64_AR + 128, /* branch registers (b0..p7) */
UNW_IA64_PR = UNW_IA64_BR + 8, /* predicate registers (p0..p63) */
UNW_IA64_CFM,

/* frame info (read-only): */
UNW_IA64_CURRENT_BSP, /* read-only */

UNW_TDEP_LAST_REG = UNW_IA64_CURRENT_BSP
}
ia64_regnum_t;

/* Info needed for a single IA-64 unwind. A pointer to this structure
is expected in the acquire/release callbacks of the unwind
accessors. */
typedef struct unw_ia64_table
{
const char *name; /* table name (or NULL if none) */
unw_word_t gp; /* global pointer for this load-module */
unw_word_t segbase; /* base for offsets in the unwind table */
unw_word_t length; /* number of entries in unwind table array */

/* Local copy of the unwind descriptor table: */
const struct ia64_unwind_table_entry *array;

/* Local copy of the unwind descriptor information. This is
initialized such that adding the unwind entry's info_offset
yields the address at which the corresponding descriptors can
be found. */
const unsigned char *unwind_info_base;
}
unw_ia64_table_t;

/* On IA-64, we can directly use ucontext_t as the unwind context. */
typedef ucontext_t unw_tdep_context_t;

/* XXX this is not ideal: an application should not be prevented from
using the "getcontext" name just because it's using libunwind. We
can't just use __getcontext() either, because that isn't exported
by glibc... */
#define unw_tdep_getcontext(uc) getcontext(uc)
Loading

0 comments on commit 7fbfe0a

Please sign in to comment.