OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [gnu/] [gcj/] [runtime/] [NameFinder.java] - Blame information for rev 756

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 756 jeremybenn
/* NameFinder.java -- Translates addresses to StackTraceElements.
2
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3
 
4
   This file is part of libgcj.
5
 
6
This software is copyrighted work licensed under the terms of the
7
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
8
details.  */
9
 
10
package gnu.gcj.runtime;
11
 
12
import gnu.classpath.Configuration;
13
import gnu.gcj.RawData;
14
 
15
import java.lang.StringBuffer;
16
 
17
import java.io.BufferedReader;
18
import java.io.BufferedWriter;
19
import java.io.InputStreamReader;
20
import java.io.OutputStreamWriter;
21
import java.io.IOException;
22
import java.io.File;
23
import java.util.Collections;
24
import java.util.Iterator;
25
import java.util.HashMap;
26
import java.util.HashSet;
27
import java.util.Set;
28
 
29
 
30
/**
31
 * Lookup addresses (represented as longs) to find source & line number info.
32
 *
33
 * The following system property is available (defaults to true):
34
 * <li>
35
 * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code>
36
 *     Whether an external process, addr2line, should be used to look up
37
 *     source file and line number info. Throwable.printStackTrace() will
38
 *     be faster if this property is set to 'false'.
39
 * </ul>
40
 * <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code>
41
 *     Whether calls to unknown functions (class and method names are unknown)
42
 *     should be removed from the stack trace. </ul>
43
 * </li>
44
 *
45
 * <code>close()</code> should be called to get rid of all resources.
46
 *
47
 * This class is used from <code>java.lang.VMThrowable</code>.
48
 *
49
 * @author Mark Wielaard (mark@klomp.org)
50
 */
51
public class NameFinder
52
{
53
  /**
54
   * The name of the binary to look up.
55
   */
56
  private String binaryFile;
57
  private String sourceFile;
58
  private int lineNum;
59
  private HashMap procs = new HashMap();
60
  /**
61
   * Set of binary files that addr2line should not be called on.
62
   */
63
  private static Set blacklist = Collections.synchronizedSet(new HashSet());
64
 
65
  private static boolean use_addr2line
66
          = Boolean.valueOf(System.getProperty
67
                ("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
68
            ).booleanValue();
69
 
70
  private static boolean show_raw
71
          = Boolean.valueOf(System.getProperty
72
                ("gnu.gcj.runtime.NameFinder.show_raw", "false")
73
            ).booleanValue();
74
 
75
  /**
76
   * Return true if raw addresses should be printed in stacktraces
77
   * when no line number information is available.
78
   */
79
  static final boolean showRaw()
80
  {
81
    return show_raw;
82
  }
83
 
84
  private static final boolean remove_unknown
85
          = Boolean.valueOf(System.getProperty
86
                ("gnu.gcj.runtime.NameFinder.remove_unknown", "true")
87
            ).booleanValue();
88
 
89
  /**
90
   * Return true if non-Java frames should be removed from stack
91
   * traces.
92
   */
93
  static final boolean removeUnknown()
94
  {
95
    return remove_unknown;
96
  }
97
 
98
  class Addr2Line
99
  {
100
    Process proc;
101
    BufferedWriter out;
102
    BufferedReader in;
103
 
104
    Addr2Line(String binaryFile)
105
    {
106
      try
107
      {
108
        String[] exec = new String[] {"addr2line", "-e", binaryFile};
109
        Runtime runtime = Runtime.getRuntime();
110
        proc = runtime.exec(exec);
111
      }
112
      catch (IOException ioe)
113
      {
114
      }
115
 
116
      if (proc != null)
117
      {
118
        in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
119
        out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
120
      }
121
    }
122
 
123
    void close()
124
    {
125
      try
126
      {
127
        if (in != null)
128
          in.close();
129
        if (out != null)
130
          out.close();
131
      }
132
      catch (IOException x) {}
133
      if (proc != null)
134
        proc.destroy();
135
    }
136
  }
137
 
138
  /**
139
   * Create a new NameFinder to lookup names in binaryFile. Call close to get rid of any
140
   * resources created while using the <code>lookup</code> methods.
141
   */
142
  public NameFinder()
143
  {
144
  }
145
 
146
  /**
147
   * Returns the source file name if lookup() was successful. If the source file could not be
148
   * determined, the binary name will be returned instead.
149
   */
150
  public String getSourceFile()
151
  {
152
    String file;
153
    if (sourceFile != null)
154
      file = sourceFile;
155
    else
156
      file = binaryFile;
157
 
158
    return file.substring(file.lastIndexOf(File.separator) + 1, file.length());
159
  }
160
 
161
  /**
162
   * If lookup() was successful, returns the line number of addr. If the line number could not
163
   * be determined, -1 is returned.
164
   */
165
  public int getLineNum()
166
  {
167
    return lineNum;
168
  }
169
 
170
  public void lookup (String file, long addr)
171
  {
172
    binaryFile = file;
173
    sourceFile = null;
174
    lineNum = -1;
175
 
176
    if (! use_addr2line || blacklist.contains(file))
177
      return;
178
    Addr2Line addr2line = (Addr2Line) procs.get(file);
179
    if (addr2line == null)
180
      {
181
      addr2line = new Addr2Line(file);
182
      procs.put(file, addr2line);
183
      }
184
 
185
    if (addr2line.proc == null)
186
      {
187
        use_addr2line = false;
188
        return;
189
      }
190
 
191
    String hexAddr = "0x" + Long.toHexString(addr);
192
    String name;
193
 
194
    try
195
      {
196
      addr2line.out.write(hexAddr);
197
      addr2line.out.newLine();
198
      addr2line.out.flush();
199
      String result = addr2line.in.readLine();
200
 
201
      if (result.indexOf("??") == -1)
202
        {
203
          int split = result.lastIndexOf(':');
204
          sourceFile = result.substring(0, split);
205
          String lineNumStr = result.substring(split + 1, result.length());
206
          lineNum = Integer.parseInt (lineNumStr);
207
        }
208
      else
209
        {
210
          /* This binary has no debug info (assuming addr was valid).
211
             Avoid repeat addr2line invocations. */
212
          blacklist.add(binaryFile);
213
        }
214
      }
215
    catch (IOException ioe)
216
      {
217
      addr2line = null;
218
      }
219
    catch (NumberFormatException x)
220
      {
221
      }
222
  }
223
 
224
  /**
225
   * Returns human readable method name and aguments given a method type
226
   * signature as known to the interpreter and a classname.
227
   */
228
  public static String demangleInterpreterMethod(String m, String cn)
229
  {
230
    int index = 0;
231
    int length = m.length();
232
    StringBuffer sb = new StringBuffer(length);
233
 
234
    // Figure out the real method name
235
    if (m.startsWith("<init>"))
236
      {
237
        String className;
238
        int i = cn.lastIndexOf('.');
239
        if (i < 0)
240
          className = cn;
241
        else
242
          className = cn.substring(i + 1);
243
        sb.append(className);
244
        index += 7;
245
      }
246
    else
247
      {
248
        int i = m.indexOf('(');
249
        if (i > 0)
250
          {
251
            sb.append(m.substring(0,i));
252
            index += i + 1;
253
          }
254
      }
255
 
256
    sb.append('(');
257
 
258
    // Demangle the type arguments
259
    int arrayDepth = 0;
260
    char c = (index < length) ? m.charAt(index) : ')';
261
    while (c != ')')
262
      {
263
        String type;
264
        switch(c)
265
        {
266
          case 'B':
267
            type = "byte";
268
            break;
269
          case 'C':
270
            type = "char";
271
            break;
272
          case 'D':
273
            type = "double";
274
            break;
275
          case 'F':
276
            type = "float";
277
            break;
278
          case 'I':
279
            type = "int";
280
            break;
281
          case 'J':
282
            type = "long";
283
            break;
284
          case 'S':
285
            type = "short";
286
            break;
287
          case 'Z':
288
            type = "boolean";
289
            break;
290
          case 'L':
291
            int i = m.indexOf(';', index);
292
            if (i > 0)
293
              {
294
                type = m.substring(index+1, i);
295
                index = i;
296
              }
297
            else
298
              type = "<unknown ref>";
299
            break;
300
          case '[':
301
            type = "";
302
            arrayDepth++;
303
            break;
304
          default:
305
            type = "<unknown " + c + '>';
306
        }
307
        sb.append(type);
308
 
309
        // Handle arrays
310
        if (c != '[' && arrayDepth > 0)
311
          while (arrayDepth > 0)
312
            {
313
              sb.append("[]");
314
              arrayDepth--;
315
            }
316
 
317
        index++;
318
        char nc = (index < length) ? m.charAt(index) : ')';
319
        if (c != '[' && nc  != ')')
320
          sb.append(", ");
321
        c = nc;
322
      }
323
 
324
    // Stop. We are not interested in the return type.
325
    sb.append(')');
326
    return sb.toString();
327
  }
328
 
329
  /**
330
   * Releases all resources used by this NameFinder.
331
   */
332
  public void close()
333
  {
334
    Iterator itr = procs.values().iterator();
335
    while (itr.hasNext())
336
      {
337
        Addr2Line proc = (Addr2Line) itr.next();
338
        proc.close();
339
      }
340
  }
341
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.