Пример #1
0
		/// <summary>Construct a ClassFileWriter for a class.</summary>
		/// <remarks>Construct a ClassFileWriter for a class.</remarks>
		/// <param name="className">
		/// the name of the class to write, including
		/// full package qualification.
		/// </param>
		/// <param name="superClassName">
		/// the name of the superclass of the class
		/// to write, including full package qualification.
		/// </param>
		/// <param name="sourceFileName">
		/// the name of the source file to use for
		/// producing debug information, or null if debug information
		/// is not desired
		/// </param>
		public ClassFileWriter(string className, string superClassName, string sourceFileName)
		{
			generatedClassName = className;
			itsConstantPool = new ConstantPool(this);
			itsThisClassIndex = itsConstantPool.AddClass(className);
			itsSuperClassIndex = itsConstantPool.AddClass(superClassName);
			if (sourceFileName != null)
			{
				itsSourceFileNameIndex = itsConstantPool.AddUtf8(sourceFileName);
			}
			// All "new" implementations are supposed to output ACC_SUPER as a
			// class flag. This is specified in the first JVM spec, so it should
			// be old enough that it's okay to always set it.
			itsFlags = ACC_PUBLIC | ACC_SUPER;
		}
Пример #2
0
		internal static void Print(int[] locals, int localsTop, int[] stack, int stackTop, ConstantPool pool)
		{
			System.Console.Out.Write("locals: ");
			System.Console.Out.WriteLine(ToString(locals, localsTop, pool));
			System.Console.Out.Write("stack: ");
			System.Console.Out.WriteLine(ToString(stack, stackTop, pool));
			System.Console.Out.WriteLine();
		}
Пример #3
0
		internal static void Print(int[] locals, int[] stack, ConstantPool pool)
		{
			Print(locals, locals.Length, stack, stack.Length, pool);
		}
Пример #4
0
		internal static string ToString(int[] types, int typesTop, ConstantPool pool)
		{
			StringBuilder sb = new StringBuilder();
			sb.Append("[");
			for (int i = 0; i < typesTop; i++)
			{
				if (i > 0)
				{
					sb.Append(", ");
				}
				sb.Append(ToString(types[i], pool));
			}
			sb.Append("]");
			return sb.ToString();
		}
Пример #5
0
		internal static string ToString(int[] types, ConstantPool pool)
		{
			return ToString(types, types.Length, pool);
		}
Пример #6
0
		/// <summary>Merge two verification types.</summary>
		/// <remarks>
		/// Merge two verification types.
		/// In most cases, the verification types must be the same. For example,
		/// INTEGER and DOUBLE cannot be merged and an exception will be thrown.
		/// The basic rules are:
		/// - If the types are equal, simply return one.
		/// - If either type is TOP, return TOP.
		/// - If either type is NULL, return the other type.
		/// - If both types are objects, find the lowest common ancestor in the
		/// class hierarchy.
		/// This method uses reflection to traverse the class hierarchy. Therefore,
		/// it is assumed that the current class being generated is never the target
		/// of a full object-object merge, which would need to load the current
		/// class reflectively.
		/// </remarks>
		internal static int Merge(int current, int incoming, ConstantPool pool)
		{
			int currentTag = GetTag(current);
			int incomingTag = GetTag(incoming);
			bool currentIsObject = currentTag == Org.Mozilla.Classfile.TypeInfo.OBJECT_TAG;
			bool incomingIsObject = incomingTag == Org.Mozilla.Classfile.TypeInfo.OBJECT_TAG;
			if (current == incoming || (currentIsObject && incoming == NULL))
			{
				return current;
			}
			else
			{
				if (currentTag == Org.Mozilla.Classfile.TypeInfo.TOP || incomingTag == Org.Mozilla.Classfile.TypeInfo.TOP)
				{
					return Org.Mozilla.Classfile.TypeInfo.TOP;
				}
				else
				{
					if (current == NULL && incomingIsObject)
					{
						return incoming;
					}
					else
					{
						if (currentIsObject && incomingIsObject)
						{
							string currentName = GetPayloadAsType(current, pool);
							string incomingName = GetPayloadAsType(incoming, pool);
							// The class file always has the class and super names in the same
							// spot. The constant order is: class_data, class_name, super_data,
							// super_name.
							string currentlyGeneratedName = (string)pool.GetConstantData(2);
							string currentlyGeneratedSuperName = (string)pool.GetConstantData(4);
							// If any of the merged types are the class that's currently being
							// generated, automatically start at the super class instead. At
							// this point, we already know the classes are different, so we
							// don't need to handle that case.
							if (currentName.Equals(currentlyGeneratedName))
							{
								currentName = currentlyGeneratedSuperName;
							}
							if (incomingName.Equals(currentlyGeneratedName))
							{
								incomingName = currentlyGeneratedSuperName;
							}
							Type currentClass = GetClassFromInternalName(currentName);
							Type incomingClass = GetClassFromInternalName(incomingName);
							if (currentClass.IsAssignableFrom(incomingClass))
							{
								return current;
							}
							else
							{
								if (incomingClass.IsAssignableFrom(currentClass))
								{
									return incoming;
								}
								else
								{
									if (incomingClass.IsInterface || currentClass.IsInterface)
									{
										// For verification purposes, Sun specifies that interfaces are
										// subtypes of Object. Therefore, we know that the merge result
										// involving interfaces where one is not assignable to the
										// other results in Object.
										return OBJECT("java/lang/Object", pool);
									}
									else
									{
										Type commonClass = incomingClass.BaseType;
										while (commonClass != null)
										{
											if (commonClass.IsAssignableFrom(currentClass))
											{
												string name = commonClass.FullName;
												name = ClassFileWriter.GetSlashedForm(name);
												return OBJECT(name, pool);
											}
											commonClass = commonClass.BaseType;
										}
									}
								}
							}
						}
					}
				}
			}
			throw new ArgumentException("bad merge attempt between " + ToString(current, pool) + " and " + ToString(incoming, pool));
		}
Пример #7
0
		internal static string ToString(int type, ConstantPool pool)
		{
			int tag = GetTag(type);
			switch (tag)
			{
				case Org.Mozilla.Classfile.TypeInfo.TOP:
				{
					return "top";
				}

				case Org.Mozilla.Classfile.TypeInfo.INTEGER:
				{
					return "int";
				}

				case Org.Mozilla.Classfile.TypeInfo.FLOAT:
				{
					return "float";
				}

				case Org.Mozilla.Classfile.TypeInfo.DOUBLE:
				{
					return "double";
				}

				case Org.Mozilla.Classfile.TypeInfo.LONG:
				{
					return "long";
				}

				case Org.Mozilla.Classfile.TypeInfo.NULL:
				{
					return "null";
				}

				case Org.Mozilla.Classfile.TypeInfo.UNINITIALIZED_THIS:
				{
					return "uninitialized_this";
				}

				default:
				{
					if (tag == Org.Mozilla.Classfile.TypeInfo.OBJECT_TAG)
					{
						return GetPayloadAsType(type, pool);
					}
					else
					{
						if (tag == Org.Mozilla.Classfile.TypeInfo.UNINITIALIZED_VAR_TAG)
						{
							return "uninitialized";
						}
						else
						{
							throw new ArgumentException("bad type");
						}
					}
					break;
				}
			}
		}
Пример #8
0
		/// <summary>Create type information from an internal type.</summary>
		/// <remarks>Create type information from an internal type.</remarks>
		internal static int FromType(string type, ConstantPool pool)
		{
			if (type.Length == 1)
			{
				switch (type[0])
				{
					case 'B':
					case 'C':
					case 'S':
					case 'Z':
					case 'I':
					{
						// sbyte
						// unicode char
						// short
						// boolean
						// all of the above are verified as integers
						return INTEGER;
					}

					case 'D':
					{
						return DOUBLE;
					}

					case 'F':
					{
						return FLOAT;
					}

					case 'J':
					{
						return LONG;
					}

					default:
					{
						throw new ArgumentException("bad type");
					}
				}
			}
			return Org.Mozilla.Classfile.TypeInfo.OBJECT(type, pool);
		}
Пример #9
0
		/// <summary>
		/// Treat the result of getPayload as a constant pool index and fetch the
		/// corresponding String mapped to it.
		/// </summary>
		/// <remarks>
		/// Treat the result of getPayload as a constant pool index and fetch the
		/// corresponding String mapped to it.
		/// Only works on OBJECT types.
		/// </remarks>
		internal static string GetPayloadAsType(int typeInfo, ConstantPool pool)
		{
			if (GetTag(typeInfo) == OBJECT_TAG)
			{
				return (string)pool.GetConstantData(GetPayload(typeInfo));
			}
			throw new ArgumentException("expecting object type");
		}
Пример #10
0
		internal static int OBJECT(string type, ConstantPool pool)
		{
			return OBJECT(pool.AddClass(type));
		}
Пример #11
0
		/// <summary>Merge an operand stack or local variable array with incoming state.</summary>
		/// <remarks>
		/// Merge an operand stack or local variable array with incoming state.
		/// They are treated the same way; by this point, it should already be
		/// ensured that the array sizes are the same, which is the only additional
		/// constraint that is imposed on merging operand stacks (the local variable
		/// array is always the same size).
		/// </remarks>
		private bool MergeState(int[] current, int[] incoming, int size, ConstantPool pool)
		{
			bool changed = false;
			for (int i = 0; i < size; i++)
			{
				int currentType = current[i];
				current[i] = TypeInfo.Merge(current[i], incoming[i], pool);
				if (currentType != current[i])
				{
					changed = true;
				}
			}
			return changed;
		}
Пример #12
0
		internal bool Merge(int[] locals, int localsTop, int[] stack, int stackTop, ConstantPool pool)
		{
			if (!isInitialized)
			{
				System.Array.Copy(locals, 0, this.locals, 0, localsTop);
				this.stack = new int[stackTop];
				System.Array.Copy(stack, 0, this.stack, 0, stackTop);
				isInitialized = true;
				return true;
			}
			else
			{
				if (this.locals.Length == localsTop && this.stack.Length == stackTop)
				{
					bool localsChanged = MergeState(this.locals, locals, localsTop, pool);
					bool stackChanged = MergeState(this.stack, stack, stackTop, pool);
					return localsChanged || stackChanged;
				}
				else
				{
					throw new ArgumentException("bad merge attempt");
				}
			}
		}