source: trunk/third/gcc/libjava/name-finder.cc @ 16960

Revision 16960, 4.1 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16959, which included commits to RCS files with non-trunk default branches.
Line 
1// name-finder.cc - Convert addresses to names
2
3/* Copyright (C) 2000  Red Hat Inc
4
5   This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9details.  */
10
11/**
12 * @author Andrew Haley <aph@cygnus.com>
13 * @date Jan 6  2000
14 */
15
16/* _Jv_name_finder is a class wrapper around a mechanism that can
17   convert address of methods to their names and the names of files in
18   which they appear.
19
20   Right now, the only implementation of this involves running a copy
21   of addr2line, but at some point it is worth building this
22   functionality into libgcj, if only for embedded systems.  */
23
24
25#ifndef _GNU_SOURCE
26#define _GNU_SOURCE 1
27#endif
28
29#include <config.h>
30
31#include <string.h>
32
33#include <gcj/cni.h>
34#include <jvm.h>
35#include <java/lang/Object.h>
36#include <java-threads.h>
37#include <java/lang/Throwable.h>
38#include <java/io/PrintStream.h>
39#include <java/io/PrintWriter.h>
40
41#include <sys/types.h>
42
43#include <stdlib.h>
44#include <stdio.h>
45
46#ifdef HAVE_UNISTD_H
47#include <unistd.h>
48#endif
49
50#ifdef HAVE_DLFCN_H
51#include <dlfcn.h>
52#endif
53
54#include <name-finder.h>
55
56/* Create a new name finder which will perform address lookups on an
57   executable. */
58
59_Jv_name_finder::_Jv_name_finder (char *executable)
60{
61#if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
62  error = 0;
63
64  char *argv[6];
65  {
66    int arg = 0;
67#ifdef __ia64__
68    argv[arg++] = "addr2name.awk";
69#else
70    argv[arg++] = "addr2line";
71    argv[arg++] = "-C";
72    argv[arg++] = "-f";
73    argv[arg++] = "-e";
74#endif
75    argv[arg++] = executable;
76    argv[arg] = NULL;
77  }
78
79  error |= pipe (f_pipe) < 0;
80  error |= pipe (b_pipe) < 0;
81
82  if (error)
83    return;
84
85  pid = fork ();
86  if (pid == 0)
87    {
88      close (f_pipe[1]);
89      close (b_pipe[0]);
90      dup2 (f_pipe[0], fileno (stdin));
91      dup2 (b_pipe[1], fileno (stdout));
92      execvp (argv[0], argv);
93      _exit (127);
94    }
95
96  close (f_pipe [0]);
97  close (b_pipe [1]);
98
99  if (pid < 0)
100    {
101      error |= 1;
102      return;
103    }
104
105  b_pipe_fd = fdopen (b_pipe[0], "r");
106  error |= !b_pipe_fd;
107#endif
108}
109
110/* Convert a pointer to hex. */
111
112void
113_Jv_name_finder::toHex (void *p)
114{
115  unsigned long long n = (unsigned long long)p;
116  int digits = sizeof (void *) * 2;
117
118  strcpy (hex, "0x");
119  for (int i = digits - 1; i >= 0; i--)
120    {
121      int digit = n % 16;
122     
123      n /= 16;
124      hex[i+2] = digit > 9 ? 'a' + digit - 10 : '0' + digit;
125    }
126  hex [digits+2] = 0;
127}   
128
129/* Given a pointer to a function or method, try to convert it into a
130   name and the appropriate line and source file.  The caller passes
131   the code pointer in p.
132
133   Returns false if the lookup fails.  Even if this happens, the field
134   he will have been correctly filled in with the pointer.  */
135
136bool
137_Jv_name_finder::lookup (void *p)
138{
139  extern char **_Jv_argv;
140  toHex (p);
141     
142#if defined (HAVE_DLFCN_H) && defined (HAVE_DLADDR)
143  {
144    Dl_info dl_info;
145   
146    if (dladdr (p, &dl_info))
147      {
148        if (dl_info.dli_fname)
149          strncpy (file_name, dl_info.dli_fname, sizeof file_name);
150        if (dl_info.dli_sname)
151          strncpy (method_name, dl_info.dli_sname, sizeof method_name);
152       
153       /* Don't trust dladdr() if the address is from the main program. */
154       if (dl_info.dli_fname != NULL
155           && dl_info.dli_sname != NULL
156           && (_Jv_argv == NULL || strcmp (file_name, _Jv_argv[0]) != 0))
157         return true;
158      }
159  }
160#endif
161
162#if defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP)
163  if (error)
164    return false;
165
166  error |= write (f_pipe[1], hex, strlen (hex)) < 0;
167  if (error)
168    return false;
169  error |= write (f_pipe[1], "\n", 1) < 0;
170  if (error)
171    return false;
172
173  error |= (fgets (method_name, sizeof method_name, b_pipe_fd) == NULL);
174  if (error)
175    return false;
176  error |= (fgets (file_name, sizeof file_name, b_pipe_fd) == NULL);
177  if (error)
178    return false;
179
180  char *newline = strchr (method_name, '\n');
181  if (newline)
182    *newline = 0;
183  newline = strchr (file_name, '\n');
184  if (newline)
185    *newline = 0;
186
187  return true;
188
189#else
190  return false;
191#endif /* defined (HAVE_PIPE) && defined (HAVE_FORK) && defined (HAVE_EXECVP) */
192}
Note: See TracBrowser for help on using the repository browser.