Exemplo n.º 1
0
        private AttributeBase LoadCode(BigEndianBinaryReader reader, int attributeLength)
        {
            int maxStack  = reader.ReadUInt16();
            int maxLocals = reader.ReadUInt16();

            int codeLength = reader.ReadInt32();

            byte[] code = reader.ReadBytes(codeLength);

            int exceptionTableLength = reader.ReadUInt16();
            var exceptionTable       = new ExceptionTableEntry[exceptionTableLength];

            for (int i = 0; i < exceptionTableLength; i++)
            {
                int startPC        = reader.ReadUInt16();
                int endPC          = reader.ReadUInt16();
                int handlerPC      = reader.ReadUInt16();
                int catchTypeIndex = reader.ReadUInt16();

                exceptionTable[i] = new ExceptionTableEntry(startPC, endPC, handlerPC, catchTypeIndex);
            }

            var attributes = Load(reader);

            return(new CodeAttribute(maxStack, maxLocals, code, exceptionTable, attributes));
        }
Exemplo n.º 2
0
				internal void Read(ClassFile classFile, string[] utf8_cp, Method method, BigEndianBinaryReader br, ClassFileParseOptions options)
				{
					max_stack = br.ReadUInt16();
					max_locals = br.ReadUInt16();
					uint code_length = br.ReadUInt32();
					if(code_length > 65535)
					{
						throw new ClassFormatError("{0} (Invalid Code length {1})", classFile.Name, code_length);
					}
					Instruction[] instructions = new Instruction[code_length + 1];
					int basePosition = br.Position;
					int instructionIndex = 0;
					try
					{
						BigEndianBinaryReader rdr = br.Section(code_length);
						while(!rdr.IsAtEnd)
						{
							instructions[instructionIndex].Read((ushort)(rdr.Position - basePosition), rdr, classFile);
							hasJsr |= instructions[instructionIndex].NormalizedOpCode == NormalizedByteCode.__jsr;
							instructionIndex++;
						}
						// we add an additional nop instruction to make it easier for consumers of the code array
						instructions[instructionIndex++].SetTermNop((ushort)(rdr.Position - basePosition));
					}
					catch(ClassFormatError x)
					{
						// any class format errors in the code block are actually verify errors
						verifyError = x.Message;
					}
					this.instructions = new Instruction[instructionIndex];
					Array.Copy(instructions, 0, this.instructions, 0, instructionIndex);
					// build the pcIndexMap
					int[] pcIndexMap = new int[this.instructions[instructionIndex - 1].PC + 1];
					for(int i = 0; i < pcIndexMap.Length; i++)
					{
						pcIndexMap[i] = -1;
					}
					for(int i = 0; i < instructionIndex - 1; i++)
					{
						pcIndexMap[this.instructions[i].PC] = i;
					}
					// convert branch offsets to indexes
					for(int i = 0; i < instructionIndex - 1; i++)
					{
						switch(this.instructions[i].NormalizedOpCode)
						{
							case NormalizedByteCode.__ifeq:
							case NormalizedByteCode.__ifne:
							case NormalizedByteCode.__iflt:
							case NormalizedByteCode.__ifge:
							case NormalizedByteCode.__ifgt:
							case NormalizedByteCode.__ifle:
							case NormalizedByteCode.__if_icmpeq:
							case NormalizedByteCode.__if_icmpne:
							case NormalizedByteCode.__if_icmplt:
							case NormalizedByteCode.__if_icmpge:
							case NormalizedByteCode.__if_icmpgt:
							case NormalizedByteCode.__if_icmple:
							case NormalizedByteCode.__if_acmpeq:
							case NormalizedByteCode.__if_acmpne:
							case NormalizedByteCode.__ifnull:
							case NormalizedByteCode.__ifnonnull:
							case NormalizedByteCode.__goto:
							case NormalizedByteCode.__jsr:
								this.instructions[i].SetTargetIndex(pcIndexMap[this.instructions[i].Arg1 + this.instructions[i].PC]);
								break;
							case NormalizedByteCode.__tableswitch:
							case NormalizedByteCode.__lookupswitch:
								this.instructions[i].MapSwitchTargets(pcIndexMap);
								break;
						}
					}
					// read exception table
					ushort exception_table_length = br.ReadUInt16();
					exception_table = new ExceptionTableEntry[exception_table_length];
					for(int i = 0; i < exception_table_length; i++)
					{
						ushort start_pc = br.ReadUInt16();
						ushort end_pc = br.ReadUInt16();
						ushort handler_pc = br.ReadUInt16();
						ushort catch_type = br.ReadUInt16();
						if(start_pc >= end_pc
							|| end_pc > code_length
							|| handler_pc >= code_length
							|| (catch_type != 0 && !classFile.SafeIsConstantPoolClass(catch_type)))
						{
							throw new ClassFormatError("Illegal exception table: {0}.{1}{2}", classFile.Name, method.Name, method.Signature);
						}
						classFile.MarkLinkRequiredConstantPoolItem(catch_type);
						// if start_pc, end_pc or handler_pc is invalid (i.e. doesn't point to the start of an instruction),
						// the index will be -1 and this will be handled by the verifier
						int startIndex = pcIndexMap[start_pc];
						int endIndex;
						if (end_pc == code_length)
						{
							// it is legal for end_pc to point to just after the last instruction,
							// but since there isn't an entry in our pcIndexMap for that, we have
							// a special case for this
							endIndex = instructionIndex - 1;
						}
						else
						{
							endIndex = pcIndexMap[end_pc];
						}
						int handlerIndex = pcIndexMap[handler_pc];
						exception_table[i] = new ExceptionTableEntry(startIndex, endIndex, handlerIndex, catch_type, i);
					}
					ushort attributes_count = br.ReadUInt16();
					for(int i = 0; i < attributes_count; i++)
					{
						switch(classFile.GetConstantPoolUtf8String(utf8_cp, br.ReadUInt16()))
						{
							case "LineNumberTable":
								if((options & ClassFileParseOptions.LineNumberTable) != 0)
								{
									BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
									int count = rdr.ReadUInt16();
									lineNumberTable = new LineNumberTableEntry[count];
									for(int j = 0; j < count; j++)
									{
										lineNumberTable[j].start_pc = rdr.ReadUInt16();
										lineNumberTable[j].line_number = rdr.ReadUInt16();
										if(lineNumberTable[j].start_pc >= code_length)
										{
											throw new ClassFormatError("{0} (LineNumberTable has invalid pc)", classFile.Name);
										}
									}
									if(!rdr.IsAtEnd)
									{
										throw new ClassFormatError("{0} (LineNumberTable attribute has wrong length)", classFile.Name);
									}
								}
								else
								{
									br.Skip(br.ReadUInt32());
								}
								break;
							case "LocalVariableTable":
								if((options & ClassFileParseOptions.LocalVariableTable) != 0)
								{
									BigEndianBinaryReader rdr = br.Section(br.ReadUInt32());
									int count = rdr.ReadUInt16();
									localVariableTable = new LocalVariableTableEntry[count];
									for(int j = 0; j < count; j++)
									{
										localVariableTable[j].start_pc = rdr.ReadUInt16();
										localVariableTable[j].length = rdr.ReadUInt16();
										localVariableTable[j].name = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16());
										localVariableTable[j].descriptor = classFile.GetConstantPoolUtf8String(utf8_cp, rdr.ReadUInt16()).Replace('/', '.');
										localVariableTable[j].index = rdr.ReadUInt16();
									}
									// NOTE we're intentionally not checking that we're at the end of the section
									// (optional attributes shouldn't cause ClassFormatError)
								}
								else
								{
									br.Skip(br.ReadUInt32());
								}
								break;
							default:
								br.Skip(br.ReadUInt32());
								break;
						}
					}
					// build the argmap
					string sig = method.Signature;
					List<int> args = new List<int>();
					int pos = 0;
					if(!method.IsStatic)
					{
						args.Add(pos++);
					}
					for(int i = 1; sig[i] != ')'; i++)
					{
						args.Add(pos++);
						switch(sig[i])
						{
							case 'L':
								i = sig.IndexOf(';', i);
								break;
							case 'D':
							case 'J':
								args.Add(-1);
								break;
							case '[':
							{
								while(sig[i] == '[')
								{
									i++;
								}
								if(sig[i] == 'L')
								{
									i = sig.IndexOf(';', i);
								}
								break;
							}
						}
					}
					argmap = args.ToArray();
					if(args.Count > max_locals)
					{
						throw new ClassFormatError("{0} (Arguments can't fit into locals)", classFile.Name);
					}
				}
Exemplo n.º 3
0
        public override CompileAttribute Read(EndianBinaryReader reader, List<CompileConstant> constants, int length)
        {
            MaxStack = reader.ReadInt16();
            MaxLocals = reader.ReadInt16();

            int codeLength = reader.ReadInt32();
            Code = reader.ReadBytes(codeLength);

            ExceptionTable = new List<ExceptionTableEntry>();
            short exceptionCount = reader.ReadInt16();
            for (int i = 0; i < exceptionCount; i++)
            {
                var exception = new ExceptionTableEntry();

                exception.StartPC = reader.ReadInt16();
                exception.EndPC = reader.ReadInt16();
                exception.HandlerPC = reader.ReadInt16();
                exception.CatchType = reader.ReadInt16();

                ExceptionTable.Add(exception);
            }

            Attributes = new List<CompileAttribute>();
            short attributeCount = reader.ReadInt16();
            for (int i = 0; i < attributeCount; i++)
            {
                Attributes.Add(ReadAttribute(reader, constants));
            }

            return this;
        }
Exemplo n.º 4
0
 public Error GetMethodExceptionTable(out ExceptionTableEntry[] entries, ReferenceTypeId referenceType, MethodId method)
 {
     entries = null;
     return Error.NotImplemented;
 }
Exemplo n.º 5
0
			internal void Read(ClassFile classFile, Method method, BigEndianBinaryReader br)
			{
				max_stack = br.ReadUInt16();
				max_locals = br.ReadUInt16();
				uint code_length = br.ReadUInt32();
				if (code_length > 65536)
				{
					throw new ClassFormatError("{0} (Invalid Code length {1})", classFile.Name, code_length);
				}
				Instruction[] instructions = new Instruction[code_length + 1];
				int basePosition = br.Position;
				int instructionIndex = 0;
				try
				{
					BigEndianBinaryReader rdr = br.Section(code_length);
					while (!rdr.IsAtEnd)
					{
						instructions[instructionIndex++].Read((ushort) (rdr.Position - basePosition), rdr);
					}
					// we add an additional nop instruction to make it easier for consumers of the code array
					instructions[instructionIndex++].SetTermNop((ushort) (rdr.Position - basePosition));
				}
				catch (ClassFormatError x)
				{
					// any class format errors in the code block are actually verify errors
					verifyError = x.Message;
				}
				this.instructions = new Instruction[instructionIndex];
				Array.Copy(instructions, 0, this.instructions, 0, instructionIndex);
				ushort exception_table_length = br.ReadUInt16();
				exception_table = new ExceptionTableEntry[exception_table_length];
				for (int i = 0; i < exception_table_length; i++)
				{
					exception_table[i] = new ExceptionTableEntry();
					exception_table[i].start_pc = br.ReadUInt16();
					exception_table[i].end_pc = br.ReadUInt16();
					exception_table[i].handler_pc = br.ReadUInt16();
					exception_table[i].catch_type = br.ReadUInt16();
					exception_table[i].ordinal = i;
				}
				ushort attributes_count = br.ReadUInt16();
				for (int i = 0; i < attributes_count; i++)
				{
					switch (classFile.GetConstantPoolUtf8String(br.ReadUInt16()))
					{
						case "LineNumberTable":
							br.Skip(br.ReadUInt32());
							break;
						case "LocalVariableTable":
							br.Skip(br.ReadUInt32());
							break;
						default:
							br.Skip(br.ReadUInt32());
							break;
					}
				}
				// build the pcIndexMap
				pcIndexMap = new int[this.instructions[instructionIndex - 1].PC + 1];
				for (int i = 0; i < pcIndexMap.Length; i++)
				{
					pcIndexMap[i] = -1;
				}
				for (int i = 0; i < instructionIndex - 1; i++)
				{
					pcIndexMap[this.instructions[i].PC] = i;
				}
				// build the argmap
				string sig = method.Signature;
				ArrayList args = new ArrayList();
				int pos = 0;
				if (!method.IsStatic)
				{
					args.Add(pos++);
				}
				for (int i = 1; sig[i] != ')'; i++)
				{
					args.Add(pos++);
					switch (sig[i])
					{
						case 'L':
							i = sig.IndexOf(';', i);
							break;
						case 'D':
						case 'J':
							args.Add(-1);
							break;
						case '[':
							{
								while (sig[i] == '[')
								{
									i++;
								}
								if (sig[i] == 'L')
								{
									i = sig.IndexOf(';', i);
								}
								break;
							}
					}
				}
				argmap = new int[args.Count];
				args.CopyTo(argmap);
				if (args.Count > max_locals)
				{
					throw new ClassFormatError("{0} (Arguments can't fit into locals)", classFile.Name);
				}
			}