This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
Re: remote dwarf info using libunwind
On Sep 12, 2006, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Sep 12, 2006, Tom Tromey <tromey@redhat.com> wrote:
Alexandre> Adding more stack frames gives it more stack space to sync
Alexandre> up, and then it does display function names correctly, but
Alexandre> it still fails to print file/line numbers. I'm yet to
Alexandre> figure out why.
>> I've got some more data for you.
> Thanks. Last night I found a very serious problem in my patch. The
> combination of libunwind-ptrace with our own ptrace stuff is not
> working at all, it's just by sheer luck that we some accurate unwind
> info. Whenever libunwind attempts to read memory from the underlying
> process (which it currently doesn't because I passed it the wrong
> pid), it would crash because the argument to the callback data is to
> the ptrace info only, not to the original pointer that contains
> pointers to both unw-ptrace and frysk data. So we lose.
> I started working on a patch to mend that, but couldn't finish it last
> night. Will do today, I hope.
Here's something that works much better. We now get symbols out of
glibc's dynamic libraries too, but there's still something broken in
the way compute addresses for stack traces.
The internal computations are carried out correctly, but when
frysk::rt::StackFrame::initialize() calls unw_get_proc_info(), it
often gets back a fake procedure spec because we can't find unwind
info for it (apparently because of the lack for dyn_list_addr or some
such), so it returns proc_info with a one-byte range covering only the
given IP, but when it calls unw_get_proc_name(), it uses a difference
piece of code that succeeds in locating information about the
procedure, and then it sets offset according to that base address, so
we end up adding the offset to the wrong base address and get wrong
info printed out.
It still fails to print line numbers for main and for kernel vdso
syscalls and their callers, but other than that, it's much better than
before.
The patch is not quite ready for public consumption (still missing a
ChangeLog, for one), but I thought I'd post it for people who'd like
to use it as is.
My plan is to use the same code htat unw_get_proc_name() uses to
locate the procedure info and use that in unw_get_proc_info as a
fallback, but that will have to wait until I get some sleep.
I actually took a stab at dyn_list_addr, but I can't quite figure out
whether this is even to be found somewhere in the memory map of the
target process. At first I thought it was supposed to be the dynamic
loader's linked list of dynamic libs, but that's not it. Does anyone
know?
Index: frysk/frysk-core/frysk/rt/StackCallbacks.java
===================================================================
--- frysk.orig/frysk-core/frysk/rt/StackCallbacks.java 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-core/frysk/rt/StackCallbacks.java 2006-09-13 04:57:18.000000000 -0300
@@ -42,15 +42,6 @@ package frysk.rt;
import java.util.logging.Level;
-import lib.dw.DwarfDie;
-import lib.dw.Dwfl;
-import lib.dw.DwflDieBias;
-import lib.elf.Elf;
-import lib.elf.ElfCommand;
-import lib.elf.ElfData;
-import lib.elf.ElfException;
-import lib.elf.ElfFileException;
-import lib.elf.ElfSection;
import lib.unwind.RegisterX86;
import lib.unwind.UnwindCallbacks;
import frysk.proc.Host;
@@ -72,104 +63,6 @@ public class StackCallbacks
isa = myTask.getIsa();
}
- public boolean findProcInfo (long procInfo, long addressSpace,
- long instructionAddress, boolean needInfo)
- {
- Host.logger.log(Level.FINE, "Libunwind: findProcInfo for 0x"
- + Long.toHexString(instructionAddress) + "\n");
-
- Dwfl dwfl = new Dwfl(myTask.getTid());
- DwflDieBias bias = dwfl.getDie(instructionAddress);
-
- if (bias == null)
- {
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not find dwfl die and bias\n");
- return false;
- }
-
- DwarfDie die = bias.die;
- long adjustedAddress = instructionAddress - bias.bias;
-
- if (die == null)
- {
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not find dwfl die\n");
- return false;
- }
-
- DwarfDie lowest = die.getScopes(adjustedAddress)[0];
- if (lowest == null)
- {
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not find lowest scope information\n");
- return false;
- }
-
- if (needInfo)
- {
- Elf elf = null;
- // elf = dwfl.getModule(adjustedAddress).getElf().elf;
- try
- {
- elf = new Elf(myTask.getTid(), ElfCommand.ELF_C_READ);
- }
- catch (ElfFileException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not find elf information\n");
- return false;
- }
- catch (ElfException e)
- {
- // TODO Auto-generated catch block
- e.printStackTrace();
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not find elf information\n");
- return false;
- }
-
- ElfSection found = null;
- for (int i = 0; i < elf.getSectionCount(); i++)
- {
- ElfSection current = elf.getSection(i);
- if (current.getSectionHeader().name.equals(".debug_frame"))
- {
- found = current;
- break;
- }
- }
-
- if (found == null)
- {
- Host.logger.log(Level.FINE,
- "Libunwind: aborted, could not .debug_frame section\n");
- return false;
- }
-
- populate_procinfo(procInfo, lowest.getLowPC(), lowest.getHighPC(), 0,
- 0, 0, found.getData());
- }
- else
- populate_procinfo_nounwind(procInfo, lowest.getLowPC(),
- lowest.getHighPC(), 0, 0, 0);
-
- return true;
- }
-
- public void putUnwindInfo (long addressSpace, long procInfo)
- {
- free_proc_info(procInfo);
- }
-
- public long getDynInfoListAddr (long addressSpace)
- {
- // No such thing :)
- return 0;
- }
-
public long accessMem (long addressSpace, long addr)
{
Host.logger.log(Level.FINE, "Libunwind: reading memory at 0x"
@@ -179,7 +72,8 @@ public class StackCallbacks
long value = myTask.getMemory().getInt(addr);
Host.logger.log(Level.FINE, "Libunwind: read value 0x"
- + Long.toHexString(value) + "\n");
+ + Long.toHexString(value) + "\n");
+
return value;
}
@@ -243,53 +137,10 @@ public class StackCallbacks
// return 0;
}
- public String getProcName (long as, long addr)
+ public int getPid ()
{
- Host.logger.log(Level.FINE, "Libunwind: getting procedure name at 0x"
- + Long.toHexString(addr) + "\n");
-
- Dwfl dwfl = new Dwfl(myTask.getTid());
- DwflDieBias bias = dwfl.getDie(addr);
- if (bias == null)
- return "";
- DwarfDie die = bias.die;
- if (die == null)
- return "";
-
- DwarfDie lowest = die.getScopes(addr - bias.bias)[0];
- if (lowest == null)
- return "";
-
- return lowest.getName();
+ /* FIXME: this relies on the hashCode of a ProcId returning the
+ * actual id. */
+ return myTask.getProc().getId().hashCode();
}
-
- public long getProcOffset (long as, long addr)
- {
- Host.logger.log(Level.FINE, "Libunwind: getting procedure offset at 0x"
- + Long.toHexString(addr) + "\n");
-
- Dwfl dwfl = new Dwfl(myTask.getTid());
- DwflDieBias bias = dwfl.getDie(addr);
- if (bias == null)
- return 0;
- DwarfDie die = bias.die;
- if (die == null)
- return 0;
-
- DwarfDie lowest = die.getScopes(addr - bias.bias)[0];
- if (lowest == null)
- return 0;
-
- return addr - lowest.getLowPC();
- }
-
- private native void populate_procinfo (long procInfo, long lowPC,
- long highPC, long lsda, long gp,
- long flags, ElfData debug_frame);
-
- private native void populate_procinfo_nounwind (long procInfo, long lowPC,
- long highPC, long lsda,
- long gp, long flags);
-
- private native void free_proc_info (long proc_info);
}
Index: frysk/frysk-core/frysk/rt/cni/StackCallbacks.cxx
===================================================================
--- frysk.orig/frysk-core/frysk/rt/cni/StackCallbacks.cxx 2006-09-13 02:14:24.000000000 -0300
+++ /dev/null 1970-01-01 00:00:00.000000000 +0000
@@ -1,91 +0,0 @@
-// This file is part of the program FRYSK.
-//
-// Copyright 2005, Red Hat Inc.
-//
-// FRYSK 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; version 2 of the License.
-//
-// FRYSK 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 FRYSK; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-//
-// In addition, as a special exception, Red Hat, Inc. gives You the
-// additional right to link the code of FRYSK with code not covered
-// under the GNU General Public License ("Non-GPL Code") and to
-// distribute linked combinations including the two, subject to the
-// limitations in this paragraph. Non-GPL Code permitted under this
-// exception must only link to the code of FRYSK through those well
-// defined interfaces identified in the file named EXCEPTION found in
-// the source code files (the "Approved Interfaces"). The files of
-// Non-GPL Code may instantiate templates or use macros or inline
-// functions from the Approved Interfaces without causing the
-// resulting work to be covered by the GNU General Public
-// License. Only Red Hat, Inc. may make changes or additions to the
-// list of Approved Interfaces. You must obey the GNU General Public
-// License in all respects for all of the FRYSK code and other code
-// used in conjunction with FRYSK except the Non-GPL Code covered by
-// this exception. If you modify this file, you may extend this
-// exception to your version of the file, but you are not obligated to
-// do so. If you do not wish to provide this exception without
-// modification, you must delete this exception statement from your
-// version and license this file solely under the GPL without
-// exception.
-
-#include <libunwind.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <gcj/cni.h>
-
-#include "frysk/rt/StackCallbacks.h"
-#include "../frysk-imports/lib/elf/ElfData.h"
-
-void
-frysk::rt::StackCallbacks::populate_procinfo(
- jlong procInfo, jlong lowPC, jlong highPC, jlong lsda, jlong gp, jlong flags,
- lib::elf::ElfData* debug_frame)
-{
- unw_proc_info_t *proc_info = (unw_proc_info_t *) procInfo;
-
- proc_info->start_ip = (unw_word_t) lowPC;
- proc_info->end_ip = (unw_word_t) highPC;
- proc_info->lsda = (unw_word_t) lsda;
- proc_info->gp = (unw_word_t) gp;
- proc_info->flags = (unw_word_t) flags;
- proc_info->format = UNW_INFO_FORMAT_TABLE;
-
- int data_size = (int) debug_frame->getSize();
- unsigned char* frame_data = (unsigned char*) malloc(data_size);
-
- for(int i = 0; i < data_size; i++)
- frame_data[i] = (unsigned char) debug_frame->getByte((jlong) i);
-
- proc_info->unwind_info_size = data_size;
- proc_info->unwind_info = (void *) frame_data;
-}
-
-void
-frysk::rt::StackCallbacks::populate_procinfo_nounwind(
- jlong procInfo, jlong lowPC, jlong highPC, jlong lsda, jlong gp, jlong flags)
-{
- unw_proc_info_t *proc_info = (unw_proc_info_t *) procInfo;
-
- proc_info->start_ip = (unw_word_t) lowPC;
- proc_info->end_ip = (unw_word_t) highPC;
- proc_info->lsda = (unw_word_t) lsda;
- proc_info->gp = (unw_word_t) gp;
- proc_info->flags = (unw_word_t) flags;
- proc_info->unwind_info = NULL;
-}
-
-void
-frysk::rt::StackCallbacks::free_proc_info(jlong proc_info)
-{
- if(((unw_proc_info_t *) proc_info)->unwind_info != NULL)
- JvFree(((unw_proc_info_t *) proc_info)->unwind_info);
-}
Index: frysk/frysk-imports/lib/unwind/UnwindCallbacks.java
===================================================================
--- frysk.orig/frysk-imports/lib/unwind/UnwindCallbacks.java 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-imports/lib/unwind/UnwindCallbacks.java 2006-09-13 02:14:48.000000000 -0300
@@ -42,40 +42,6 @@ package lib.unwind;
public interface UnwindCallbacks
{
/**
- * Retrieves the information about a procedure that will be needed to unwind
- * it. If needinfo is true the returned struct does not need to contain values
- * for format, unwind_info_size, and unwind_info
- * @param procInfo TODO
- * @param addressSpace The unwind address space
- * @param instructionAddress The address within the procedure whose
- * information is needed
- * @param needInfo Whether or not to fill in extra information
- *
- * @return The value of the pointer to the returned struct.
- */
- boolean findProcInfo (long procInfo, long addressSpace,
- long instructionAddress, boolean needInfo);
-
- /**
- * Releases the resources allocated by the call to findProcInfo with needInfo
- * set to true.
- *
- * @param addressSpace The unwind address space
- * @param procInfo The value of the pointer to the proc info struc to be
- * freed.
- */
- void putUnwindInfo (long addressSpace, long procInfo);
-
- /**
- * Gets the address of the head of the dynamic unwind-info registration list,
- * or zero if no such record exist.
- *
- * @param as
- * @return the address of the head of the list, or zero if no list exists.
- */
- long getDynInfoListAddr (long addressSpace);
-
- /**
* Reads a word of memory from from the given address
*
* @param as The unwind_addr_space
@@ -139,21 +105,8 @@ public interface UnwindCallbacks
int resume (long as, long cp);
/**
- * Returns the name of a static (not dynamically generated) procedure.
- *
- * @param as The unw_addr_space
- * @param addr An address within the procedure to get the name of
- * @return The name of the procedure
- */
- String getProcName (long as, long addr);
-
- /**
- * Returns the offset within the procudure that the current address is located
- * at
- *
- * @param as The unw_addr_space
- * @param addr The address to get the offset of.
- * @return The offset from the start of the current procedure to addr.
- */
- long getProcOffset (long as, long addr);
+ * Obtain the PID of the target process.
+ *
+ * @return the PID of the target process. */
+ int getPid ();
}
Index: frysk/frysk-imports/lib/unwind/cni/StackTraceCreator.cxx
===================================================================
--- frysk.orig/frysk-imports/lib/unwind/cni/StackTraceCreator.cxx 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-imports/lib/unwind/cni/StackTraceCreator.cxx 2006-09-13 05:12:20.000000000 -0300
@@ -57,64 +57,102 @@ typedef lib::unwind::StackTraceCreator$U
* functionality
***************************/
+static inline unwargs *find_unwarg(void *arg, ::unw_addr_space_t as)
+{
+ return lib::unwind::StackTraceCreator::find_arg_from_long
+ ((jlong)arg, (gnu::gcj::RawDataManaged *)as);
+}
+
/*
* Get misc. proc info
*/
int find_proc_info (::unw_addr_space_t as, ::unw_word_t ip,
- ::unw_proc_info_t *pip, int need_unwind_info, void *arg)
+ ::unw_proc_info_t *pip, int need_unwind_info,
+ void *arg)
{
- return _UPT_find_proc_info (as, ip, pip, need_unwind_info,
- (void *)((unwargs *)arg)->UPTarg);
+ return _UPT_find_proc_info (as, ip, pip, need_unwind_info,
+ find_unwarg (arg, as)->UPTarg);
}
/*
* Free space allocated during find_proc_info
*/
void put_unwind_info (::unw_addr_space_t as, ::unw_proc_info_t *pip,
- void *arg)
+ void *arg)
{
- return _UPT_put_unwind_info (as, pip,
- (void *)((unwargs *)arg)->UPTarg);
+ return _UPT_put_unwind_info (as, pip, find_unwarg (arg, as)->UPTarg);
}
/*
* Get the head of the dynamic unwind registration list.
*/
int get_dyn_info_list_addr (::unw_addr_space_t as, ::unw_word_t *dilap,
- void *arg)
+ void *arg)
{
- return _UPT_get_dyn_info_list_addr (as, dilap,
- (void *)((unwargs *)arg)->UPTarg);
+ return _UPT_get_dyn_info_list_addr (as, dilap,
+ find_unwarg (arg, as)->UPTarg);
}
+struct todo {
+ jint (*func) (struct todo *arg);
+};
+
+jint
+lib::unwind::StackTraceCreator::dispatch_todo (gnu::gcj::RawDataManaged *todo_)
+{
+ struct todo *todo = (struct todo *)todo_;
+ return todo->func (todo);
+}
+
+struct access_mem_todo {
+ struct todo todo;
+ ::unw_addr_space_t as;
+ ::unw_word_t addr;
+ ::unw_word_t *valp;
+ int write;
+ void *arg;
+};
+
/*
* Perform memory read/write
*/
-int access_mem (::unw_addr_space_t as, ::unw_word_t addr,
- ::unw_word_t *valp, int write, void *arg)
+jint real_access_mem (struct todo *todo_)
{
- lib::unwind::UnwindCallbacks *cb = ((unwargs *)arg)->CBarg;
+ struct access_mem_todo *todo = (struct access_mem_todo *)todo_;
+
+ lib::unwind::UnwindCallbacks *cb = find_unwarg (todo->arg,
+ todo->as)->CBarg;
// we've separated read and write in the java interface for simplicity
- if(write == 0){
- jlong retval = cb->accessMem ((jlong) as, (jlong) addr);
- *valp = (::unw_word_t) retval;
+ if(todo->write == 0){
+ jlong retval = cb->accessMem ((jlong) todo->as,
+ (jlong) todo->addr);
+ *todo->valp = (::unw_word_t) retval;
}
else{
- cb->writeMem ((jlong) as, (jlong) addr, (jlong) *valp);
+ cb->writeMem ((jlong) todo->as, (jlong) todo->addr,
+ (jlong) *todo->valp);
}
return 0;
}
+int access_mem (::unw_addr_space_t as, ::unw_word_t addr,
+ ::unw_word_t *valp, int write, void *arg) {
+ struct access_mem_todo todo = {
+ { real_access_mem }, as, addr, valp, write, arg
+ };
+ return lib::unwind::StackTraceCreator::catch_errors
+ ((gnu::gcj::RawDataManaged *)&todo);
+}
+
/*
* perform register read/write
*/
-int access_reg(::unw_addr_space_t as,
- ::unw_regnum_t regnum, ::unw_word_t *valp,
- int write, void *arg)
+int access_reg(::unw_addr_space_t as, ::unw_regnum_t regnum,
+ ::unw_word_t *valp, int write, void *arg)
{
- lib::unwind::UnwindCallbacks *cb = ((unwargs *)arg)->CBarg;
+ lib::unwind::UnwindCallbacks *cb = find_unwarg (arg, as)->CBarg;
// read and write are separated in the java interface
if(write == 0){
@@ -131,11 +169,10 @@ int access_reg(::unw_addr_space_t as,
/*
* Perform a floating point register read/write
*/
-int access_fpreg(::unw_addr_space_t as,
- ::unw_regnum_t regnum, ::unw_fpreg_t *fpvalp,
- int write, void *arg)
+int access_fpreg(::unw_addr_space_t as, ::unw_regnum_t regnum,
+ ::unw_fpreg_t *fpvalp, int write, void *arg)
{
- lib::unwind::UnwindCallbacks *cb = ((unwargs *)arg)->CBarg;
+ lib::unwind::UnwindCallbacks *cb = find_unwarg (arg, as)->CBarg;
if(write == 0){
jdouble retval = cb->accessFpreg ((jlong) as, (jlong) regnum);
@@ -151,10 +188,9 @@ int access_fpreg(::unw_addr_space_t as,
/*
* Resumes the process at the provided stack level
*/
-int resume(::unw_addr_space_t as,
- ::unw_cursor_t *cp, void *arg)
+int resume(::unw_addr_space_t as, ::unw_cursor_t *cp, void *arg)
{
- lib::unwind::UnwindCallbacks *cb = ((unwargs *)arg)->CBarg;
+ lib::unwind::UnwindCallbacks *cb = find_unwarg (arg, as)->CBarg;
return (int) cb->resume ((jlong) as, (jlong) cp);
}
@@ -164,25 +200,11 @@ int resume(::unw_addr_space_t as,
* the offset from the start of the procedure.
*/
int get_proc_name(::unw_addr_space_t as,
- ::unw_word_t addr, char *bufp,
- size_t buf_len, ::unw_word_t *offp, void *arg)
+ ::unw_word_t addr, char *bufp,
+ size_t buf_len, ::unw_word_t *offp, void *arg)
{
- lib::unwind::UnwindCallbacks *cb = ((unwargs *)arg)->CBarg;
-
- jstring name = cb->getProcName ((jlong) as, (jlong) addr);
- jlong offset = cb->getProcOffset ((jlong) as, (jlong) addr);
-
- *offp = (::unw_word_t) offset;
- if((unsigned int) buf_len <= (unsigned int) name->length ()){
- JvGetStringUTFRegion (name, 0, buf_len, bufp);
- bufp[buf_len-1] = '\0';
- return -UNW_ENOMEM;
- }
- else{
- JvGetStringUTFRegion (name, 0, name->length (), bufp);
- bufp[name->length ()] = '\0';
- return 0;
- }
+ return _UPT_get_proc_name (as, addr, bufp, buf_len, offp,
+ find_unwarg (arg, as)->UPTarg);
}
lib::unwind::FrameCursor*
@@ -197,12 +219,14 @@ lib::unwind::StackTraceCreator::unwind_s
// Initialize libunwind
::unw_addr_space_t addr_space = ::unw_create_addr_space(&accessors, 0);
- args->unwas = (jlong)addr_space;
+ args->unwas = (gnu::gcj::RawDataManaged *)addr_space;
::unw_cursor_t cursor;
- /* Since we're not actually using ptrace, the PID below is unused. */
- args->UPTarg = (jlong)_UPT_create (/* PID = */ 0);
- ::unw_init_remote(&cursor, addr_space, args);
+ /* Since we're not actually using ptrace, the PID below is unused. */
+ args->UPTarg = (gnu::gcj::RawDataManaged *)
+ _UPT_create (args->CBarg->getPid());
+ register_hashes (args);
+ ::unw_init_remote(&cursor, addr_space, args);
::unw_set_caching_policy(addr_space, UNW_CACHE_PER_THREAD);
// Create the frame objects and return the top (most recent one)
@@ -221,12 +245,16 @@ lib::unwind::StackTraceCreator::unwind_s
return base_frame;
}
-void
-lib::unwind::StackTraceCreator::unwind_finish (unwargs *args)
+void lib::unwind::StackTraceCreator::unwind_finish (unwargs *args)
{
- unw_destroy_addr_space ((unw_addr_space_t)args->unwas);
- args->unwas = 0;
- _UPT_destroy ((void*)args->UPTarg);
- args->UPTarg = 0;
+ unregister_hashes (args);
+ unw_destroy_addr_space ((unw_addr_space_t)args->unwas);
+ args->unwas = 0;
+ _UPT_destroy ((void*)args->UPTarg);
+ args->UPTarg = 0;
}
+jlong lib::unwind::StackTraceCreator::pointer_to_long (java::lang::Object *obj)
+{
+ return (jlong)obj;
+}
Index: frysk/frysk-imports/libunwind/configure
===================================================================
--- frysk.orig/frysk-imports/libunwind/configure 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-imports/libunwind/configure 2006-09-13 02:25:07.000000000 -0300
@@ -4357,7 +4357,6 @@ fi
CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE"
-CFLAGS="${CFLAGS} -DUNW_REMOTE_ONLY"
# Check whether --enable-debug or --disable-debug was given.
if test "${enable_debug+set}" = set; then
Index: frysk/frysk-imports/libunwind/configure.ac
===================================================================
--- frysk.orig/frysk-imports/libunwind/configure.ac 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-imports/libunwind/configure.ac 2006-09-13 02:14:48.000000000 -0300
@@ -34,7 +34,6 @@ AC_TYPE_SIGNAL
AC_TYPE_SIZE_T
CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE"
-CFLAGS="${CFLAGS} -DUNW_REMOTE_ONLY"
AC_ARG_ENABLE(debug,
[ --enable-debug turn on debug support (slows down execution)],
Index: frysk/frysk-imports/libunwind/src/os-linux.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/os-linux.c 2006-09-13 02:14:24.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/os-linux.c 2006-09-13 02:14:48.000000000 -0300
@@ -23,6 +23,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER L
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+#ifndef UNW_REMOTE_ONLY
#include <limits.h>
#include <stdio.h>
@@ -54,3 +55,4 @@ tdep_get_elf_image (struct elf_image *ei
return elf_map_image (ei, path);
}
+#endif /* UNW_REMOTE_ONLY */
Index: frysk/frysk-imports/lib/unwind/StackTraceCreator.java
===================================================================
--- frysk.orig/frysk-imports/lib/unwind/StackTraceCreator.java 2006-09-13 02:14:38.000000000 -0300
+++ frysk/frysk-imports/lib/unwind/StackTraceCreator.java 2006-09-13 05:10:46.000000000 -0300
@@ -40,6 +40,9 @@
package lib.unwind;
+import gnu.gcj.RawDataManaged;
+import java.util.Hashtable;
+
public class StackTraceCreator
{
/**
@@ -62,20 +65,70 @@ public class StackTraceCreator
{
public UnwindCallbacks CBarg;
- public long UPTarg;
+ public RawDataManaged UPTarg;
- public long unwas;
+ public RawDataManaged unwas;
public UnwindArgs (UnwindCallbacks CBarg)
{
this.CBarg = CBarg;
- this.UPTarg = 0;
- this.unwas = 0;
+ this.UPTarg = null;
+ this.unwas = null;
+
+ /* register_hashes must be called later, from within
+ unwind_setup(). Calling it within an if (false) avoids a
+ warning about the unused method. */
+ if (false)
+ try {
+ register_hashes (this);
+ } catch (UnwindException _) {
+ }
}
public void finalize ()
{
+ /* unregister_hashes could be called here, but we call it in
+ unwind_finish(), to mirror the constructor above. */
+ if (false)
+ unregister_hashes (this);
unwind_finish(this);
}
}
+
+ private static Hashtable arg_hash = new Hashtable();
+ private static native long pointer_to_long (Object obj);
+
+ private static void register_hashes (UnwindArgs args)
+ throws UnwindException {
+ if (args.CBarg == null || args.UPTarg == null)
+ throw new UnwindException ("Internal error in unwinder set up");
+ arg_hash.put (new Long (pointer_to_long (args)), args);
+ arg_hash.put (new Long (pointer_to_long (args.CBarg)), args);
+ arg_hash.put (new Long (pointer_to_long (args.UPTarg)), args);
+ }
+
+ private static void unregister_hashes (UnwindArgs args) {
+ arg_hash.remove (new Long (pointer_to_long (args.UPTarg)));
+ arg_hash.remove (new Long (pointer_to_long (args.CBarg)));
+ arg_hash.remove (new Long (pointer_to_long (args)));
+ }
+
+ public static UnwindArgs find_arg_from_long (long val,
+ RawDataManaged unwas)
+ throws UnwindException {
+ UnwindArgs arg = (UnwindArgs) arg_hash.get (new Long (val));
+ if (arg.unwas != unwas)
+ throw new UnwindException ("Internal error in unwinder use");
+ return arg;
+ }
+
+ public static int catch_errors (RawDataManaged todo) {
+ try {
+ return dispatch_todo (todo);
+ } catch (RuntimeException whatever) {
+ return -1;
+ }
+ }
+
+ private static native int dispatch_todo (RawDataManaged todo);
}
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America http://www.fsfla.org/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}