/* NameFinder.java -- Translates addresses to StackTraceElements.
   Copyright (C) 2002, 2004 Free Software Foundation, Inc.

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

package gnu.gcj.runtime;

import gnu.gcj.RawData;

import java.lang.StringBuffer;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.File;

/**
 * Helper class that translates addresses (represented as longs) to a
 * StackTraceElement array.
 *
 * There are a couple of system properties that can be set to manipulate the
 * result (all default to true):
 * <li>
 * <ul><code>gnu.gcj.runtime.NameFinder.demangle</code>
 *     Whether names should be demangled.</ul>
 * <ul><code>gnu.gcj.runtime.NameFinder.sanitize</code></ul>
 *     Whether calls to initialize exceptions and starting the runtime system
 *     should be removed from the stack trace. Only done when names are
 *     demangled.</ul>
 * <ul><code>gnu.gcj.runtime.NameFinder.remove_unknown</code>
 *     Whether calls to unknown functions (class and method names are unknown)
 *     should be removed from the stack trace. Only done when the stack is
 *     sanitized.</ul>
 * <ul><code>gnu.gcj.runtime.NameFinder.remove_internal</code>
 *     Whether runtime internal calls (methods in the internal _Jv_* classes
 *     and functions starting with 'ffi_') should be removed from the stack
 *     trace. Only done when the stack is sanitized.</ul>
 * <ul><code>gnu.gcj.runtime.NameFinder.use_addr2line</code>
 *     Whether an external process (addr2line or addr2name.awk) should be used
 *     as fallback to convert the addresses to function names when the runtime
 *     is unable to do it through <code>dladdr</code>.</ul>
 * </li>
 *
 * <code>close()</code> should be called to get rid of all resources.
 *
 * This class is used from <code>java.lang.VMThrowable</code>.
 *
 * Currently the <code>lookup(long[])</code> method is not thread safe.
 * It can easily be made thread safe by synchronizing access to all external
 * processes when used.
 *   
 * @author Mark Wielaard (mark@klomp.org)
 */
public class NameFinder
{
  // Set these to false when not needed.
  private static final boolean demangle
	  = Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.demangle", "true")
	    ).booleanValue();
  private static final boolean sanitize
	  = Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.sanitize", "true")
	    ).booleanValue();
  private static final boolean remove_unknown
	  = Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.remove_unknown", "true")
	    ).booleanValue();

  // The remove_interpreter name is an old 3.3/3.4 (deprecated) synonym.
  private static final boolean remove_internal
	  = (Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.remove_internal", "true")
			     ).booleanValue()
	     ||
	     Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.remove_interpreter", "true")
                             ).booleanValue()
	     );

  private static final boolean use_addr2line
	  = Boolean.valueOf(System.getProperty
		("gnu.gcj.runtime.NameFinder.use_addr2line", "true")
	    ).booleanValue();

  /**
   * The name of the currently running executable.
   */
  private final String executable;

  /**
   * Process used for demangling names.
   */
  private Process cppfilt;

  private BufferedWriter cppfiltOut;
  private BufferedReader cppfiltIn;

  /**
   * Process used for translating addresses to function/file names.
   */
  private Process addr2line;

  private BufferedWriter addr2lineOut;
  private BufferedReader addr2lineIn;

  /**
   * Flag set if using addr2name.awk instead of addr2line from binutils.
   */
  private boolean usingAddr2name = false;

  /**
   * Creates a new NameFinder. Call close to get rid of any resources
   * created while using the <code>lookup</code> methods.
   */
  public NameFinder()
  {
    executable = getExecutable();
    Runtime runtime = Runtime.getRuntime();
    if (demangle)
    {
      try
	{
	  String[] exec = new String[] {"c++filt", "-s", "java"};
	  cppfilt = runtime.exec(exec);
	  cppfiltIn = new BufferedReader
			(new InputStreamReader(cppfilt.getInputStream()));
	  cppfiltOut = new BufferedWriter
			(new OutputStreamWriter(cppfilt.getOutputStream()));
	}
      catch (IOException ioe)
        {
	  if (cppfilt != null)
	    cppfilt.destroy();
	  cppfilt = null;
	}
    }

    if (use_addr2line)
      {
	try
	  {
	    String[] exec = new String[] {"addr2line", "-f", "-e", executable};
	    addr2line = runtime.exec(exec);
	  }
	catch (IOException ioe)
	  {
	    try
	      {
		String[] exec = new String[] {"addr2name.awk", executable};
		addr2line = runtime.exec(exec);
		usingAddr2name = true;
	      }
	    catch (IOException ioe2) { addr2line = null; }
	  }

	if (addr2line != null)
	  {
	    addr2lineIn = new BufferedReader
	      (new InputStreamReader(addr2line.getInputStream()));
	    addr2lineOut = new BufferedWriter
	      (new OutputStreamWriter(addr2line.getOutputStream()));
	  }
      }
  }

  /**
   * Returns the name of the currently running process.
   */
  native private static String getExecutable();

  /**
   * Tries to use dladdr to create the nth StackTraceElement from the given
   * addresses. Returns null on failure.
   */
  native private StackTraceElement dladdrLookup(RawData addrs, int n);

  /**
   * Returns the nth element from the stack as a hex encoded String.
   */
  native private String getAddrAsString(RawData addrs, int n);

  /**
   * Returns the label that is exported for the given method name.
   */
  native private String getExternalLabel(String name);

  /**
   * If nth element of stack is an interpreted frame, return the
   * element representing the method being interpreted.
   */
  native private StackTraceElement lookupInterp(RawData addrs, int n);

  /**
   * Creates the nth StackTraceElement from the given native stacktrace.
   */
  private StackTraceElement lookup(RawData addrs, int n)
  {
    StackTraceElement result;

    result = lookupInterp(addrs, n);
    if (result == null)
      result = dladdrLookup(addrs, n);
    if (result == null)
      {
	String name = null;
	String file = null;

	String hex = getAddrAsString(addrs, n);
	
	if (addr2line != null)
	  {
	    try
	      {
		addr2lineOut.write(hex);
		addr2lineOut.newLine();
		addr2lineOut.flush();
		name = addr2lineIn.readLine();
		file = addr2lineIn.readLine();

                // addr2line uses symbolic debugging information instead
                // of the actually exported labels as addr2name.awk does.
                // This name might need some modification, depending on 
                // the system, to make it a label like that returned 
                // by addr2name.awk or dladdr.
                if (! usingAddr2name)
                  if (name != null && ! "??".equals (name))
                    name = getExternalLabel (name);
	      }
	    catch (IOException ioe) { addr2line = null; }
	  }

	if (name == null || "??".equals(name))
	  name = hex;

	result = createStackTraceElement(name, file);
      }

    return result;
  }

  /**
   * Given an Throwable and a native stacktrace returns an array of
   * StackTraceElement containing class, method, file and linenumbers.
   */
  public StackTraceElement[] lookup(Throwable t, StackTrace trace)
  {
    RawData addrs = trace.stackTraceAddrs();
    int length = trace.length();

    StackTraceElement[] elements = new StackTraceElement[length];
    for (int i=0; i < length; i++)
      elements[i] = lookup(addrs, i);

    if (demangle && sanitize)
      return sanitizeStack(elements, t);
    else
      return elements;
  }

  
  /**
   * Removes calls to initialize exceptions and the runtime system from
   * the stack trace including stack frames of which nothing usefull is known.
   * Throw away the top of the stack till we find the constructor(s)
   * of this Throwable or at least the contructors of java.lang.Throwable
   * or the actual fillInStackTrace call.
   * Also throw away from the top everything before and including a runtime
   * _Jv_Throw call.
   */
  private static StackTraceElement[] sanitizeStack(StackTraceElement[] elements,
						   Throwable t)
  {
    StackTraceElement[] stack;

    String className = t.getClass().getName();
    String consName;
    int lastDot = className.lastIndexOf('.');
    if (lastDot == -1)
      consName = className + '(';
    else
      consName = className.substring(lastDot + 1) + '(';

    int unknown = 0;
    int internal = 0;
    int last_throw = -1;
    int length = elements.length;
    int end = length-1;
    for (int i = 0; i < length; i++)
      {
	String CName = elements[i].getClassName();
	String MName = elements[i].getMethodName();
	if ((CName == null && MName != null && MName.startsWith("_Jv_Throw"))
	  ||
	   (CName != null
	    && (CName.equals(className)
		|| CName.equals("java.lang.Throwable")
		|| CName.equals("java.lang.VMThrowable"))
	    && MName != null
	    && (MName.startsWith(consName)
		|| MName.startsWith("Throwable(")
		|| MName.startsWith("fillInStackTrace("))))
	  {
	    last_throw = i;
	    // Reset counting of unknown and internal frames.
	    unknown = 0;
	    internal = 0;
	  }
	else if (remove_unknown && CName == null 
		 && (MName == null || MName.startsWith("0x")))
	  unknown++;
	else if (remove_internal
		 && ((CName == null
		      && MName != null && MName.startsWith("ffi_"))
		     || (CName != null && CName.startsWith("_Jv_"))
		     || (CName == null && MName != null
			 && MName.startsWith("_Jv_"))))
	  internal++;
	else if (("java.lang.Thread".equals(CName)
		  || "gnu.java.lang.MainThread".equals(CName))
		 && "run()".equals(MName))
	  {
	    end = i;
	    break;
	  }
      }
    int begin = last_throw+1;

    // Now filter out everything at the start and the end that is not part
    // of the "normal" user program including any elements that are internal
    // calls or have no usefull information whatsoever.
    // Unless that means we filter out all info.
    int nr_elements = end - begin - unknown - internal + 1;
    if ((begin > 0 || end < length-1 || unknown > 0 || internal > 0)
	&& nr_elements > 0)
      {
	stack = new StackTraceElement[nr_elements];
	int pos =0;
	for (int i=begin; i<=end; i++)
	  {
	    String MName = elements[i].getMethodName();
	    String CName = elements[i].getClassName();
	    if (remove_unknown && CName == null 
		 && (MName == null || MName.startsWith("0x")))
	      ; // Skip unknown frame
	    else if (remove_internal
		     && ((CName == null
			  && MName != null && MName.startsWith("ffi_"))
			 || (CName != null && CName.startsWith("_Jv_"))
			 || (CName == null && MName != null
			     && MName.startsWith("_Jv_"))))
	      ; // Skip internal runtime frame
	    else
	      {
		// Null Class or Method name in elements are not allowed.
		if (MName == null || CName == null)
		  {
		    MName = MName == null ? "" : MName;
		    CName = CName == null ? "" : CName;
		    stack[pos] = newElement(elements[i].getFileName(),
					    elements[i].getLineNumber(),
					    CName, MName,
					    elements[i].isNativeMethod());
		  }
		else
		  stack[pos] = elements[i];
		pos++;
	      }
	  }
      }
    else
      stack = elements;

    return stack;
  }

  /**
   * Native helper method to create a StackTraceElement. Needed to work
   * around normal Java access restrictions.
   */
  native static private StackTraceElement newElement(String fileName,
						     int lineNumber,
						     String className,
						     String methName,
						     boolean isNative);

  /**
   * Creates a StackTraceElement given a string and a filename.
   * Splits the given string into the class and method part.
   * The string name will be a demangled to a fully qualified java method
   * string. The string file will be decomposed into a file name and possibly
   * a line number. The name should never be null, but the file may be if it
   * is unknown.
   */
  private StackTraceElement createStackTraceElement(String name, String file)
  {
    if (!demangle)
      return newElement(file, -1, null, name, false);

    String s = demangleName(name);
    String methodName = s;
    String className = null;
    int bracket = s.indexOf('(');
    if (bracket > 0)
      {
	int dot = s.lastIndexOf('.', bracket);
	if (dot > 0)
	  {
	    className = s.substring(0, dot);
	    methodName = s.substring(dot+1, s.length());
	  }
      }

    String fileName = file;
    int line = -1;
    if (fileName != null)
      {
	int colon = file.lastIndexOf(':');
	if (colon > 0)
	  {
	    fileName = file.substring(0, colon);
	    try
	      {
		line = Integer.parseInt(file.substring(colon+1, file.length()));
	      }
	    catch (NumberFormatException nfe) { /* ignore */ }
	  }

	if (line == 0)
	  line =-1;

	if ("".equals(fileName) || "??".equals(fileName))
	  fileName = null;
	else if (fileName != null)
	  {
	    try
	      {
		fileName = new File(fileName).getCanonicalPath();
	      }
	    catch (IOException ioe) { /* ignore */ }
	  }
      }

    return newElement(fileName, line, className, methodName, false);
  }

  /**
   * Demangles the given String if possible. Returns the demangled String or
   * the original string if demangling is impossible.
   */
  private String demangleName(String s)
  {
    if (cppfilt != null)
    {
      try
	{
	  cppfiltOut.write(s);
	  cppfiltOut.newLine();
	  cppfiltOut.flush();
	  return cppfiltIn.readLine();
	}
      catch (IOException ioe) { cppfilt.destroy(); cppfilt = null; }
    }

    return s;
  }

  /**
   * Returns human readable method name and aguments given a method type
   * signature as known to the interpreter and a classname.
   */
  public static String demangleInterpreterMethod(String m, String cn)
  {
    int index = 0;
    int length = m.length();
    StringBuffer sb = new StringBuffer(length);

    // Figure out the real method name
    if (m.startsWith("<init>"))
      {
	String className;
	int i = cn.lastIndexOf('.');
	if (i < 0)
	  className = cn;
	else
	  className = cn.substring(i + 1);
	sb.append(className);
	index += 7;
      }
    else
      {
	int i = m.indexOf('(');
	if (i > 0)
	  {
	    sb.append(m.substring(0,i));
	    index += i + 1;
	  }
      }

    sb.append('(');

    // Demangle the type arguments
    int arrayDepth = 0;
    char c = (index < length) ? m.charAt(index) : ')';
    while (c != ')')
      {
	String type;
	switch(c)
	{
          case 'B':
            type = "byte";
	    break;
          case 'C':
            type = "char";
	    break;
          case 'D':
            type = "double";
	    break;
          case 'F':
            type = "float";
	    break;
          case 'I':
            type = "int";
	    break;
          case 'J':
            type = "long";
	    break;
          case 'S':
            type = "short";
	    break;
          case 'Z':
            type = "boolean";
	    break;
          case 'L':
	    int i = m.indexOf(';', index);
	    if (i > 0)
	      {
		type = m.substring(index+1, i);
		index = i;
	      }
	    else
	      type = "<unknown ref>";
	    break;
          case '[':
	    type = "";
	    arrayDepth++;
	    break;
          default:
	    type = "<unknown " + c + '>';
	}
	sb.append(type);

	// Handle arrays
	if (c != '[' && arrayDepth > 0)
	  while (arrayDepth > 0)
	    {
	      sb.append("[]");
	      arrayDepth--;
	    }

	index++;
	char nc = (index < length) ? m.charAt(index) : ')';
	if (c != '[' && nc  != ')')
	  sb.append(", ");
	c = nc;
      }

    // Stop. We are not interested in the return type.
    sb.append(')');
    return sb.toString();
  }

  /**
   * Releases all resources used by this NameFinder.
   */
  public void close()
  {
    if (cppfilt != null)
      cppfilt.destroy();

    if (addr2line != null)
      addr2line.destroy();
  }

  /**
   * Calls close to get rid of all resources.
   */
  protected void finalize()
  {
    close();
  }
}
