This is the mail archive of the frysk@sources.redhat.com mailing list for the frysk project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: remote dwarf info using libunwind


On Sep 15, 2006, Mike Cvet <mcvet@redhat.com> wrote:

>> Meanwhile, ok to install in the frysk tree?

> I tested out the new changes and everything looks better than before.
> Looks good to commit, thanks!

Thanks, here are exact patches I checked in.

for frysk-imports/libunwind/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* configure.ac: Don't define UNW_REMOTE_ONLY.
	* src/os-linux.c: Restore #ifndef removed it previous patch.

Index: frysk-imports/libunwind/configure.ac
===================================================================
RCS file: /cvs/frysk/frysk-imports/libunwind/configure.ac,v
retrieving revision 1.4
diff -u -p -r1.4 configure.ac
--- frysk-imports/libunwind/configure.ac 10 Aug 2006 21:53:36 -0000 1.4
+++ frysk-imports/libunwind/configure.ac 16 Sep 2006 05:35:26 -0000
@@ -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-imports/libunwind/src/os-linux.c
===================================================================
RCS file: /cvs/frysk/frysk-imports/libunwind/src/os-linux.c,v
retrieving revision 1.2
diff -u -p -r1.2 os-linux.c
--- frysk-imports/libunwind/src/os-linux.c 8 Sep 2006 18:19:36 -0000 1.2
+++ frysk-imports/libunwind/src/os-linux.c 16 Sep 2006 05:35:26 -0000
@@ -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 */
for frysk-core/frysk/rt/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* StackCallbacks.java (findProcInfo, putUnwindInfo,
	getDynInfoListAddr, getProcName, populate_procinfo,
	populate_procinfo_nounwind, free_proc_info): Remove, obsolete.
	(getPid): New.
	* cni/StackCallbacks.cxx: Delete.

for frysk-imports/lib/unwind/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* UnwindCallbacks.java (findProcInfo, putUnwindInfo,
	getDynInfoListAddr, getProcName): Remove, obsolete.
	(getPid): New.
	* StackTraceCreator.java (UnwindArgs::UPTarg,
	UnwindArgs::unwas): Change to pointer type.
	(arg_hash): New static fields.
	(pointer_to_long, dispatch_todo): New static native methods.
	(register_hashes, unregister_hashes, find_arg_from_long,
	catch_errors): New static methods.
	* cni/StackTraceCreator.cxx (find_unwargs): New.  Use it all over.
	(struct todo): New.
	(StackTraceCreator::dispatch_todo): New.
	(struct access_mem_todo): New.
	(access_mem): Turn into dispatch_todo wrapper.  Rename
	original to...
	(real_access_mem): ... this.  Unwrap incoming arguments.
	(get_proc_name): Use libunwind implementation.
	(StackTraceCreator::unwind_setup): Pass pid to _UPT_create.
	Register args hashes.
	(StackTraceCreator::unwind_finish): Unregister them.
	(StackTraceCreator::pointer_to_long): New.

Index: frysk-core/frysk/rt/StackCallbacks.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/rt/StackCallbacks.java,v
retrieving revision 1.15
diff -u -p -r1.15 StackCallbacks.java
--- frysk-core/frysk/rt/StackCallbacks.java 15 Sep 2006 20:53:13 -0000 1.15
+++ frysk-core/frysk/rt/StackCallbacks.java 16 Sep 2006 05:37:05 -0000
@@ -45,15 +45,6 @@ import frysk.proc.Task;
 import frysk.proc.TaskException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-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;
 
@@ -72,104 +63,6 @@ public class StackCallbacks
     isa = myTask.getIsa();
   }
 
-  public boolean findProcInfo (long procInfo, long addressSpace,
-                               long instructionAddress, boolean needInfo)
-  {
-    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)
-      {
-        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)
-      {
-        logger.log(Level.FINE,
-                        "Libunwind: aborted, could not find dwfl die\n");
-        return false;
-      }
-
-    DwarfDie lowest = die.getScopes(adjustedAddress)[0];
-    if (lowest == null)
-      {
-        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();
-            logger.log(Level.FINE,
-                            "Libunwind: aborted, could not find elf information\n");
-            return false;
-          }
-        catch (ElfException e)
-          {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-            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)
-          {
-            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)
   {
     logger.log(Level.FINE, "Libunwind: reading memory at 0x"
@@ -243,53 +136,10 @@ public class StackCallbacks
     // return 0;
   }
 
-  public String getProcName (long as, long addr)
+  public int getPid ()
   {
-    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)
-  {
-    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-core/frysk/rt/cni/StackCallbacks.cxx
===================================================================
RCS file: frysk-core/frysk/rt/cni/StackCallbacks.cxx
diff -N frysk-core/frysk/rt/cni/StackCallbacks.cxx
--- frysk-core/frysk/rt/cni/StackCallbacks.cxx 25 Jul 2006 16:23:58 -0000 1.6
+++ /dev/null	1 Jan 1970 00:00:00 -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-imports/lib/unwind/StackTraceCreator.java
===================================================================
RCS file: /cvs/frysk/frysk-imports/lib/unwind/StackTraceCreator.java,v
retrieving revision 1.3
diff -u -p -r1.3 StackTraceCreator.java
--- frysk-imports/lib/unwind/StackTraceCreator.java 8 Sep 2006 18:19:36 -0000 1.3
+++ frysk-imports/lib/unwind/StackTraceCreator.java 16 Sep 2006 05:37:06 -0000
@@ -40,6 +40,9 @@
 
 package lib.unwind;
 
+import gnu.gcj.RawDataManaged;
+import java.util.Hashtable;
+
 public class StackTraceCreator
 {
   /**
@@ -62,20 +65,84 @@ 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);
     }
   }
+
+    /* arg_hash maps long values corresponding to the addresses of an
+     * UnwindArgs object and its CBarg and UPTarg fields, to the
+     * UnwindArgs object itself.  This enables us to choose the right
+     * argument to pass to callbacks even when one callback calls
+     * another.  */
+  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;
+  }
+
+  /**
+   * This method is used in combination with dispatch_todo in order to
+   * turn any exception into a -1 return value.  It's used in the
+   * access_mem callback, that would otherwise throw an exception if
+   * given an address not available in the target address space.
+
+   * @param todo The argument to be passed to dispatch_todo.
+   * @return The return value of dispatch_todo, unless it throws a
+   * RuntimeException, in which case -1 is returned.  */
+  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);
 }
Index: frysk-imports/lib/unwind/UnwindCallbacks.java
===================================================================
RCS file: /cvs/frysk/frysk-imports/lib/unwind/UnwindCallbacks.java,v
retrieving revision 1.2
diff -u -p -r1.2 UnwindCallbacks.java
--- frysk-imports/lib/unwind/UnwindCallbacks.java 24 Jul 2006 18:04:01 -0000 1.2
+++ frysk-imports/lib/unwind/UnwindCallbacks.java 16 Sep 2006 05:37:06 -0000
@@ -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-imports/lib/unwind/cni/StackTraceCreator.cxx
===================================================================
RCS file: /cvs/frysk/frysk-imports/lib/unwind/cni/StackTraceCreator.cxx,v
retrieving revision 1.7
diff -u -p -r1.7 StackTraceCreator.cxx
--- frysk-imports/lib/unwind/cni/StackTraceCreator.cxx 8 Sep 2006 18:19:36 -0000 1.7
+++ frysk-imports/lib/unwind/cni/StackTraceCreator.cxx 16 Sep 2006 05:37:06 -0000
@@ -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;
+}
This patch fixes offsets printed in backtraces.  The problem is that
unw_get_proc_info doesn't find unwind info, so machine-specific code
returns a proc_info data structure whose start_ip is the one passed to
unw_get_proc_info, but then unw_get_proc_name succeeds in finding a
symbol name corresponding to that address, and so it sets offset
accordingly.  Then, when we add the offset with the start_ip in the
proc_info data structure, we end up with a bogus address.

for  frysk/frysk-imports/libunwind/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* src/x86/Gget_proc_info.c (unw_get_proc_info): Use
	unw_get_proc_name to build a proper proc_info_t.
	* src/x86_64/Gget_proc_info.c (unw_get_proc_info): Likewise.
	* src/hppa/Gget_proc_info.c (unw_get_proc_info): Likewise.

Index: frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-15 06:33:16.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/hppa/Gget_proc_info.c	2006-09-15 06:34:35.000000000 -0300
@@ -36,8 +36,23 @@ unw_get_proc_info (unw_cursor_t *cursor,
 	 are missing DWARF unwind info.  We don't want to fail in that
 	 case, because those frames are uninteresting and just mark
 	 the end of the frame-chain anyhow.  */
+      int size = 128;
+      unw_word_t offset;
+      int ret;
+
+      do
+	{
+	  char buf[size];
+
+	  ret = unw_get_proc_name (cursor, buf, size, &offset);
+	}
+      while (ret == -UNW_ENOMEM && (size *= 2));
+
+      if (ret != 0)
+	offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 4;
       return 0;
     }
Index: frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-05-31 16:04:20.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86/Gget_proc_info.c	2006-09-15 06:34:12.000000000 -0300
@@ -35,8 +35,23 @@ unw_get_proc_info (unw_cursor_t *cursor,
       /* On x86, it's relatively common to be missing DWARF unwind
 	 info.  We don't want to fail in that case, because the
 	 frame-chain still would let us do a backtrace at least.  */
+      int size = 128;
+      unw_word_t offset;
+      int ret;
+
+      do
+	{
+	  char buf[size];
+
+	  ret = unw_get_proc_name (cursor, buf, size, &offset);
+	}
+      while (ret == -UNW_ENOMEM && (size *= 2));
+
+      if (ret != 0)
+	offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 1;
       return 0;
     }
Index: frysk/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c
===================================================================
--- frysk.orig/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c	2006-05-31 16:04:20.000000000 -0300
+++ frysk/frysk-imports/libunwind/src/x86_64/Gget_proc_info.c	2006-09-15 06:34:40.000000000 -0300
@@ -38,8 +38,23 @@ unw_get_proc_info (unw_cursor_t *cursor,
 	 are missing DWARF unwind info.  We don't want to fail in that
 	 case, because those frames are uninteresting and just mark
 	 the end of the frame-chain anyhow.  */
+      int size = 128;
+      unw_word_t offset;
+      int ret;
+
+      do
+	{
+	  char buf[size];
+
+	  ret = unw_get_proc_name (cursor, buf, size, &offset);
+	}
+      while (ret == -UNW_ENOMEM && (size *= 2));
+
+      if (ret != 0)
+	offset = 0;
+
       memset (pi, 0, sizeof (*pi));
-      pi->start_ip = c->dwarf.ip;
+      pi->start_ip = c->dwarf.ip - offset;
       pi->end_ip = c->dwarf.ip + 1;
       return 0;
     }
-- 
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}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]