/*
 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot;

import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.types.basic.*;
import sun.jvm.hotspot.utilities.*;

/** <P> This is the cross-platform TypeDataBase used by the Oop
    hierarchy. The decision was made to make this cross-platform by
    having the VM export the necessary symbols via a built-in table;
    see src/share/vm/runtime/vmStructs.[ch]pp for more details. </P>

    <P> <B>WARNING</B>: clients should refer to this class through the
    TypeDataBase interface and not directly to the HotSpotTypeDataBase
    type. </P>

    <P> NOTE: since we are fetching the sizes of the Java primitive types
 */

public class HotSpotTypeDataBase extends BasicTypeDataBase {
  private Debugger symbolLookup;
  private String[] jvmLibNames;
  private static final int UNINITIALIZED_SIZE = -1;
  private static final int C_INT8_SIZE  = 1;
  private static final int C_INT32_SIZE = 4;
  private static final int C_INT64_SIZE = 8;
  private static int pointerSize = UNINITIALIZED_SIZE;
  // Counter to ensure read loops terminate:
  private static final int MAX_DUPLICATE_DEFINITIONS = 100;
  private int duplicateDefCount = 0;

  private static final boolean DEBUG;
  static {
    DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG")
            != null;
  }

  /** <P> This requires a SymbolLookup mechanism as well as the
      MachineDescription. Note that we do not need a NameMangler since
      we use the vmStructs mechanism to avoid looking up C++
      symbols. </P>

      <P> NOTE that it is guaranteed that this constructor will not
      attempt to fetch any Java values from the remote process, only C
      integers and addresses. This is required because we are fetching
      the sizes of the Java primitive types from the remote process,
      implying that attempting to fetch them before their sizes are
      known is illegal. </P>

      <P> Throws NoSuchSymbolException if a problem occurred while
      looking up one of the bootstrapping symbols related to the
      VMStructs table in the remote VM; this may indicate that the
      remote process is not actually a HotSpot VM. </P>
  */
  public HotSpotTypeDataBase(MachineDescription machDesc,
                             VtblAccess vtblAccess,
                             Debugger symbolLookup,
                             String[] jvmLibNames) throws NoSuchSymbolException {
    super(machDesc, vtblAccess);
    this.symbolLookup = symbolLookup;
    this.jvmLibNames = jvmLibNames;

    readVMTypes();
    initializePrimitiveTypes();
    readVMStructs();
    readVMIntConstants();
    readVMLongConstants();
    readExternalDefinitions();
  }

  public Type lookupType(String cTypeName, boolean throwException) {
    Type fieldType = super.lookupType(cTypeName, false);
    if (fieldType == null && cTypeName.startsWith("const ")) {
      fieldType = (BasicType)lookupType(cTypeName.substring(6), false);
    }
    if (fieldType == null && cTypeName.endsWith(" const")) {
        fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false);
    }
    if (fieldType == null) {
      if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">")) {
        String ttype = cTypeName.substring("GrowableArray<".length(),
                                            cTypeName.length() - 1);
        Type templateType = lookupType(ttype, false);
        if (templateType == null && typeNameIsPointerType(ttype)) {
          templateType = recursiveCreateBasicPointerType(ttype);
        }
        if (templateType == null) {
          lookupOrFail(ttype);
        }

        BasicType basicTargetType = createBasicType(cTypeName, false, false, false);

        // transfer fields from GenericGrowableArray to template instance
        BasicType generic = lookupOrFail("GenericGrowableArray");
        BasicType specific = lookupOrFail("GrowableArray<int>");
        basicTargetType.setSize(specific.getSize());
        Iterator fields = generic.getFields();
        while (fields.hasNext()) {
          Field f = (Field)fields.next();
          basicTargetType.addField(internalCreateField(basicTargetType, f.getName(),
                                                       f.getType(), f.isStatic(),
                                                       f.getOffset(), null));
        }
        fieldType = basicTargetType;
      }
    }
    if (fieldType == null && typeNameIsPointerType(cTypeName)) {
      fieldType = recursiveCreateBasicPointerType(cTypeName);
    }
    if (fieldType == null && throwException) {
      super.lookupType(cTypeName, true);
    }
    return fieldType;
  }

  private void readVMTypes() {
    // Get the variables we need in order to traverse the VMTypeEntry[]
    long typeEntryTypeNameOffset;
    long typeEntrySuperclassNameOffset;
    long typeEntryIsOopTypeOffset;
    long typeEntryIsIntegerTypeOffset;
    long typeEntryIsUnsignedOffset;
    long typeEntrySizeOffset;
    long typeEntryArrayStride;

    // Fetch the address of the VMTypeEntry*. We get this symbol first
    // and try to use it to make sure that symbol lookup is working.
    Address entryAddr = lookupInProcess("gHotSpotVMTypes");
    //    System.err.println("gHotSpotVMTypes address = " + entryAddr);
    // Dereference this once to get the pointer to the first VMTypeEntry
    //    dumpMemory(entryAddr, 80);
    entryAddr = entryAddr.getAddressAt(0);

    if (entryAddr == null) {
      throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue");
    }

    typeEntryTypeNameOffset       = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
    typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
    typeEntryIsOopTypeOffset      = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
    typeEntryIsIntegerTypeOffset  = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
    typeEntryIsUnsignedOffset     = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
    typeEntrySizeOffset           = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
    typeEntryArrayStride          = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");

    if (typeEntryArrayStride == 0L) {
      throw new RuntimeException("zero stride: cannot read types.");
    }

    // Start iterating down it until we find an entry with no name
    Address typeNameAddr = null;
    do {
      // Fetch the type name first
      typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset);
      if (typeNameAddr != null) {
        String typeName = CStringUtilities.getString(typeNameAddr);

        String superclassName = null;
        Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset);
        if (superclassNameAddr != null) {
          superclassName = CStringUtilities.getString(superclassNameAddr);
        }

        boolean isOopType     = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0);
        boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0);
        boolean isUnsigned    = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0);
        long size             = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true);

        createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size);
        if (pointerSize == UNINITIALIZED_SIZE && typeName.equals("void*")) {
          pointerSize = (int)size;
        }
      }

      entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
    } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);

    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      throw new RuntimeException("too many duplicate definitions");
    }
  }

  private void initializePrimitiveTypes() {
    // Look up the needed primitive types by name...they had better be present
    setJBooleanType(lookupPrimitiveType("jboolean"));
    setJByteType   (lookupPrimitiveType("jbyte"));
    setJCharType   (lookupPrimitiveType("jchar"));
    setJDoubleType (lookupPrimitiveType("jdouble"));
    setJFloatType  (lookupPrimitiveType("jfloat"));
    setJIntType    (lookupPrimitiveType("jint"));
    setJLongType   (lookupPrimitiveType("jlong"));
    setJShortType  (lookupPrimitiveType("jshort"));

    // Indicate that these are the Java primitive types
    ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJByteType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJCharType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJIntType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJLongType()).setIsJavaPrimitiveType(true);
    ((BasicType) getJShortType()).setIsJavaPrimitiveType(true);
  }

  private Type lookupPrimitiveType(String typeName) {
    Type type = lookupType(typeName, false);
    if (type == null) {
      throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" +
                                 typeName + "\" in the remote VM's VMStructs table. This type is required in " +
                                 "order to determine the size of Java primitive types. Can not continue.");
    }
    return type;
  }

  private void readExternalDefinitions() {
    String file = System.getProperty("sun.jvm.hotspot.typedb");
    if (file != null) {
      System.out.println("Reading " + file);
      BufferedReader in = null;
      try {
        StreamTokenizer t = new StreamTokenizer(in = new BufferedReader(new InputStreamReader(new FileInputStream(file))));
        t.resetSyntax();
        t.wordChars('\u0000','\uFFFF');
        t.whitespaceChars(' ', ' ');
        t.whitespaceChars('\n', '\n');
        t.whitespaceChars('\r', '\r');
        t.quoteChar('\"');
        t.eolIsSignificant(true);
        while (t.nextToken() != StreamTokenizer.TT_EOF) {
          if (t.ttype == StreamTokenizer.TT_EOL) {
            continue;
          }

          if (t.sval.equals("field")) {
            t.nextToken();
            BasicType containingType = (BasicType)lookupType(t.sval);
            t.nextToken();
            String fieldName = t.sval;

            // The field's Type must already be in the database -- no exceptions
            t.nextToken();
            Type fieldType = lookupType(t.sval);
            t.nextToken();
            boolean isStatic = Boolean.valueOf(t.sval).booleanValue();
            t.nextToken();
            long offset = Long.parseLong(t.sval);
            t.nextToken();
            Address staticAddress = null;
            if (isStatic) {
              throw new InternalError("static fields not supported");
            }

            // check to see if the field already exists
            Iterator i = containingType.getFields();
            boolean defined = false;
            while (i.hasNext()) {
              Field f = (Field) i.next();
              if (f.getName().equals(fieldName)) {
                if (f.isStatic() != isStatic) {
                  throw new RuntimeException("static/nonstatic mismatch: " + fieldName);
                }
                if (!isStatic) {
                  if (f.getOffset() != offset) {
                    throw new RuntimeException("bad redefinition of field offset: " + fieldName);
                  }
                } else {
                  if (!f.getStaticFieldAddress().equals(staticAddress)) {
                    throw new RuntimeException("bad redefinition of field location: " + fieldName);
                  }
                }
                if (f.getType() != fieldType) {
                  System.out.println(fieldType);
                  System.out.println(f.getType());
                  throw new RuntimeException("bad redefinition of field type: " + fieldName);
                }
                defined = true;
                break;
              }
            }

            if (!defined) {
              // Create field by type
              createField(containingType,
                          fieldName, fieldType,
                          isStatic,
                          offset,
                          staticAddress);
            }
          } else if (t.sval.equals("type")) {
            t.nextToken();
            String typeName = t.sval;
            t.nextToken();
            String superclassName = t.sval;
            if (superclassName.equals("null")) {
              superclassName = null;
            }
            t.nextToken();
            boolean isOop = Boolean.valueOf(t.sval).booleanValue();
            t.nextToken();
            boolean isInteger = Boolean.valueOf(t.sval).booleanValue();
            t.nextToken();
            boolean isUnsigned = Boolean.valueOf(t.sval).booleanValue();
            t.nextToken();
            long size = Long.parseLong(t.sval);

            BasicType type = null;
            try {
              type = (BasicType)lookupType(typeName);
            } catch (RuntimeException e) {
            }
            if (type != null) {
              if (type.isOopType() != isOop) {
                throw new RuntimeException("oop mismatch in type definition: " + typeName);
              }
              if (type.isCIntegerType() != isInteger) {
                throw new RuntimeException("integer type mismatch in type definition: " + typeName);
              }
              if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {
                throw new RuntimeException("unsigned mismatch in type definition: " + typeName);
              }
              if (type.getSuperclass() == null) {
                if (superclassName != null) {
                  if (type.getSize() == -1) {
                    type.setSuperclass(lookupType(superclassName));
                  } else {
                    throw new RuntimeException("unexpected superclass in type definition: " + typeName);
                  }
                }
              } else {
                if (superclassName == null) {
                  throw new RuntimeException("missing superclass in type definition: " + typeName);
                }
                if (!type.getSuperclass().getName().equals(superclassName)) {
                  throw new RuntimeException("incorrect superclass in type definition: " + typeName);
                }
              }
              if (type.getSize() != size) {
                if (type.getSize() == -1 || type.getSize() == 0) {
                  type.setSize(size);
                } else {
                  throw new RuntimeException("size mismatch in type definition: " + typeName + ": " + type.getSize() + " != " + size);
                }
              }
            }

            if (lookupType(typeName, false) == null) {
              // Create type
              createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);
            }
          } else {
            throw new InternalError("\"" + t.sval + "\"");
          }
        }
      } catch (IOException ioe) {
        ioe.printStackTrace();
      } finally {
        try {
          in.close();
        } catch (Exception e) {
        }
      }
    }
  }

  private void readVMStructs() {
    // Get the variables we need in order to traverse the VMStructEntry[]
    long structEntryTypeNameOffset;
    long structEntryFieldNameOffset;
    long structEntryTypeStringOffset;
    long structEntryIsStaticOffset;
    long structEntryOffsetOffset;
    long structEntryAddressOffset;
    long structEntryArrayStride;

    structEntryTypeNameOffset     = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset");
    structEntryFieldNameOffset    = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset");
    structEntryTypeStringOffset   = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset");
    structEntryIsStaticOffset     = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset");
    structEntryOffsetOffset       = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset");
    structEntryAddressOffset      = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
    structEntryArrayStride        = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");

    if (structEntryArrayStride == 0L) {
      throw new RuntimeException("zero stride: cannot read types.");
    }

    // Fetch the address of the VMStructEntry*
    Address entryAddr = lookupInProcess("gHotSpotVMStructs");
    // Dereference this once to get the pointer to the first VMStructEntry
    entryAddr = entryAddr.getAddressAt(0);
    if (entryAddr == null) {
      throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue");
    }

    // Start iterating down it until we find an entry with no name
    Address fieldNameAddr = null;
    String typeName = null;
    String fieldName = null;
    String typeString = null;
    boolean isStatic = false;
    long offset = 0;
    Address staticFieldAddr = null;
    long size = 0;
    long index = 0;
    String opaqueName = "<opaque>";
    lookupOrCreateClass(opaqueName, false, false, false);

    do {
      // Fetch the field name first
      fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset);
      if (fieldNameAddr != null) {
        fieldName = CStringUtilities.getString(fieldNameAddr);

        // Now the rest of the names. Keep in mind that the type name
        // may be NULL, indicating that the type is opaque.
        Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset);
        if (addr == null) {
          throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index);
        }
        typeName = CStringUtilities.getString(addr);

        addr = entryAddr.getAddressAt(structEntryTypeStringOffset);
        if (addr == null) {
          typeString = opaqueName;
        } else {
          typeString = CStringUtilities.getString(addr);
        }

        isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0);
        if (isStatic) {
          staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset);
          offset = 0;
        } else {
          offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true);
          staticFieldAddr = null;
        }

        // The containing Type must already be in the database -- no exceptions
        BasicType containingType = lookupOrFail(typeName);

        // The field's Type must already be in the database -- no exceptions
        BasicType fieldType = (BasicType)lookupType(typeString);

        // Create field by type
        createField(containingType, fieldName, fieldType,
                    isStatic, offset, staticFieldAddr);
      }

      ++index;
      entryAddr = entryAddr.addOffsetTo(structEntryArrayStride);
    } while (fieldNameAddr != null);
  }

  private void readVMIntConstants() {
    // Get the variables we need in order to traverse the VMIntConstantEntry[]
    long intConstantEntryNameOffset;
    long intConstantEntryValueOffset;
    long intConstantEntryArrayStride;

    intConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset");
    intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
    intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");

    if (intConstantEntryArrayStride == 0L) {
      throw new RuntimeException("zero stride: cannot read types.");
    }


    // Fetch the address of the VMIntConstantEntry*
    Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
    // Dereference this once to get the pointer to the first VMIntConstantEntry
    entryAddr = entryAddr.getAddressAt(0);
    if (entryAddr == null) {
      throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue");
    }

    // Start iterating down it until we find an entry with no name
    Address nameAddr = null;
    do {
      // Fetch the type name first
      nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset);
      if (nameAddr != null) {
        String name = CStringUtilities.getString(nameAddr);
        int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false);

        // Be a little resilient
        Integer oldValue = lookupIntConstant(name, false);
        if (oldValue == null) {
          addIntConstant(name, value);
        } else {
          if (oldValue.intValue() != value) {
            throw new RuntimeException("Error: the integer constant \"" + name +
                                       "\" had its value redefined (old was " + oldValue +
                                       ", new is " + value + ". Aborting.");
          } else {
            System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
                               "had its value declared as " + value + " twice. Continuing.");
            duplicateDefCount++;
          }
        }
      }

      entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);

    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      throw new RuntimeException("too many duplicate definitions");
    }
  }

  private void readVMLongConstants() {
    // Get the variables we need in order to traverse the VMLongConstantEntry[]
    long longConstantEntryNameOffset;
    long longConstantEntryValueOffset;
    long longConstantEntryArrayStride;

    longConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset");
    longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
    longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");

    if (longConstantEntryArrayStride == 0L) {
      throw new RuntimeException("zero stride: cannot read types.");
    }

    // Fetch the address of the VMLongConstantEntry*
    Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
    // Dereference this once to get the pointer to the first VMLongConstantEntry
    entryAddr = entryAddr.getAddressAt(0);
    if (entryAddr == null) {
      throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue");
    }

    // Start iterating down it until we find an entry with no name
    Address nameAddr = null;
    do {
      // Fetch the type name first
      nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset);
      if (nameAddr != null) {
        String name = CStringUtilities.getString(nameAddr);
        int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true);

        // Be a little resilient
        Long oldValue = lookupLongConstant(name, false);
        if (oldValue == null) {
          addLongConstant(name, value);
        } else {
          if (oldValue.longValue() != value) {
            throw new RuntimeException("Error: the long constant \"" + name +
                                       "\" had its value redefined (old was " + oldValue +
                                       ", new is " + value + ". Aborting.");
          } else {
            System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
                               "had its value declared as " + value + " twice. Continuing.");
            duplicateDefCount++;
          }
        }
      }

      entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);

    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      throw new RuntimeException("too many duplicate definitions.");
    }
  }

  private BasicType lookupOrFail(String typeName) {
    BasicType type = (BasicType) lookupType(typeName, false);
    if (type == null) {
      throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " +
                                 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " +
                                 "in the debug build of that VM). Can not continue.");
    }
    return type;
  }

  private long getLongValueFromProcess(String symbol) {
    return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true);
  }

  private Address lookupInProcess(String symbol) throws NoSuchSymbolException {
    // FIXME: abstract away the loadobject name
    for (int i = 0; i < jvmLibNames.length; i++) {
      Address addr = symbolLookup.lookup(jvmLibNames[i], symbol);
      if (addr != null) {
        return addr;
      }
    }
    String errStr = "(";
    for (int i = 0; i < jvmLibNames.length; i++) {
      errStr += jvmLibNames[i];
      if (i < jvmLibNames.length - 1) {
        errStr += ", ";
      }
    }
    errStr += ")";
    throw new NoSuchSymbolException(symbol,
                                    "Could not find symbol \"" + symbol +
                                    "\" in any of the known library names " +
                                    errStr);
  }

  private BasicType lookupOrCreateClass(String typeName, boolean isOopType,
                                        boolean isIntegerType, boolean isUnsigned) {
    BasicType type = (BasicType) lookupType(typeName, false);
    if (type == null) {
      // Create a new type
      type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned);
    }
    return type;
  }

  /** Creates a new BasicType, initializes its size to -1 so we can
      test to ensure that all types' sizes are initialized by VMTypes,
      and adds it to the database. Takes care of initializing integer
      and oop types properly. */
  private BasicType createBasicType(String typeName, boolean isOopType,
                                    boolean isIntegerType, boolean isUnsigned) {

    BasicType type = null;

    if (isIntegerType) {
      type = new BasicCIntegerType(this, typeName, isUnsigned);
    } else {
      if (typeNameIsPointerType(typeName)) {
        type = recursiveCreateBasicPointerType(typeName);
      } else {
        type = new BasicType(this, typeName);
      }

      if (isOopType) {
        // HACK: turn markOop into a C integer type. This allows
        // proper handling of it in the Serviceability Agent. (FIXME
        // -- consider doing something different here)
        if (typeName.equals("markOop")) {
          type = new BasicCIntegerType(this, typeName, true);
        } else {
          type.setIsOopType(true);
        }
      }
    }

    type.setSize(UNINITIALIZED_SIZE);
    addType(type);
    return type;
  }

  /** Recursively creates a PointerType from the string representation
      of the type's name. Note that this currently needs some
      workarounds due to incomplete information in the VMStructs
      database. */
  private BasicPointerType recursiveCreateBasicPointerType(String typeName) {
    BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false);
    if (result != null) {
      return result;
    }
    String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim();
    Type targetType = null;
    if (typeNameIsPointerType(targetTypeName)) {
      targetType = lookupType(targetTypeName, false);
      if (targetType == null) {
        targetType = recursiveCreateBasicPointerType(targetTypeName);
      }
    } else {
      targetType = lookupType(targetTypeName, false);
      if (targetType == null) {
        // Workaround for missing C integer types in database.
        // Also looks like we can't throw an exception for other
        // missing target types because there are some in old
        // VMStructs tables that didn't have the target type declared.
        // For this case, we create basic types that never get filled
        // in.

        if (targetTypeName.equals("char") ||
            targetTypeName.equals("const char")) {
          // We don't have a representation of const-ness of C types in the SA
          BasicType basicTargetType = createBasicType(targetTypeName, false, true, false);
          basicTargetType.setSize(1);
          targetType = basicTargetType;
        } else if (targetTypeName.equals("u_char")) {
          BasicType basicTargetType = createBasicType(targetTypeName, false, true, true);
          basicTargetType.setSize(1);
          targetType = basicTargetType;
        } else {
          if (DEBUG) {
            System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\"");
          }
          targetType = createBasicType(targetTypeName, false, false, false);
        }
      }
    }
    result = new BasicPointerType(this, typeName, targetType);
    if (pointerSize == UNINITIALIZED_SIZE && !typeName.equals("void*")) {
      // void* must be declared early so that other pointer types can use that to set their size.
      throw new InternalError("void* type hasn't been seen when parsing " + typeName);
    }
    result.setSize(pointerSize);
    addType(result);
    return result;
  }

  private boolean typeNameIsPointerType(String typeName) {
    int i = typeName.length() - 1;
    while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) {
      --i;
    }
    if (i >= 0 && typeName.charAt(i) == '*') {
      return true;
    }
    return false;
  }

    public void createType(String typeName, String superclassName,
                           boolean isOopType, boolean isIntegerType,
                           boolean isUnsigned, long size) {
        // See whether we have a superclass
        BasicType superclass = null;
        if (superclassName != null) {
            // Fetch or create it (FIXME: would get oop types wrong if
            // they had a hierarchy; consider using lookupOrFail)
            superclass = lookupOrCreateClass(superclassName, false, false, false);
        }

        // Lookup or create the current type
        BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned);
        // Set superclass and/or ensure it's correct
        if (superclass != null) {
            if (curType.getSuperclass() == null) {
                // Set the superclass in the current type
                curType.setSuperclass(superclass);
            }

            if (curType.getSuperclass() != superclass) {
                throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
                                           "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " +
                                           superclass.getName() + ").");
            }
        }

        // Classes are created with a size of UNINITIALIZED_SIZE.
        // Set size if necessary.
        if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) {
            curType.setSize(size);
        } else {
            if (curType.getSize() != size) {
                throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
                                           "had its size redefined (old was " + curType.getSize() + ", new is " + size + ").");
            }

            if (!typeNameIsPointerType(typeName)) {
                System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
                                   "had its size declared as " + size + " twice. Continuing.");
                duplicateDefCount++;
            }
        }

    }

    /** "Virtual constructor" for fields based on type */
    public void createField(BasicType containingType,
                            String name, Type type, boolean isStatic,
                            long offset, Address staticFieldAddress) {
        // Add field to containing type
        containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress));
    }

    Field internalCreateField(BasicType containingType,
                              String name, Type type, boolean isStatic,
                              long offset, Address staticFieldAddress) {
    // "Virtual constructor" based on type
    if (type.isOopType()) {
      return new BasicOopField(this, containingType, name, type,
                               isStatic, offset, staticFieldAddress);
    }

    if (type instanceof CIntegerType) {
      return new BasicCIntegerField(this, containingType, name, type,
                                    isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJBooleanType())) {
      return new BasicJBooleanField(this, containingType, name, type,
                                    isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJByteType())) {
      return new BasicJByteField(this, containingType, name, type,
                                 isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJCharType())) {
      return new BasicJCharField(this, containingType, name, type,
                                 isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJDoubleType())) {
      return new BasicJDoubleField(this, containingType, name, type,
                                   isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJFloatType())) {
      return new BasicJFloatField(this, containingType, name, type,
                                  isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJIntType())) {
      return new BasicJIntField(this, containingType, name, type,
                                isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJLongType())) {
      return new BasicJLongField(this, containingType, name, type,
                                 isStatic, offset, staticFieldAddress);
    }

    if (type.equals(getJShortType())) {
      return new BasicJShortField(this, containingType, name, type,
                                  isStatic, offset, staticFieldAddress);
    }

    // Unknown ("opaque") type. Instantiate ordinary Field.
    return new BasicField(this, containingType, name, type,
                          isStatic, offset, staticFieldAddress);
  }

  // For debugging
  private void dumpMemory(Address addr, int len) {
    int i = 0;
    while (i < len) {
      System.err.print(addr.addOffsetTo(i) + ":");
      for (int j = 0; j < 8 && i < len; i++, j++) {
        String s = Long.toHexString(addr.getCIntegerAt(i, 1, true));
        System.err.print(" 0x");
        for (int k = 0; k < 2 - s.length(); k++) {
          System.err.print("0");
        }
        System.err.print(s);
      }
      System.err.println();
    }
  }
}
