示例#1
0
        /// <summary>
        /// Patches the section at the given offset with the specified value.
        /// </summary>
        /// <param name="offset">The offset.</param>
        /// <param name="linkType">Type of the link.</param>
        /// <param name="value">The value.</param>
        public void ApplyPatch(long offset, LinkType linkType, long value)
        {
            long pos = this.sectionStream.Position;

            this.sectionStream.Position = offset;

            // Apply the patch
            switch (linkType & LinkType.SizeMask)
            {
            case LinkType.I1:
                this.sectionStream.WriteByte((byte)value);
                break;

            case LinkType.I2:
                this.sectionStream.Write(LittleEndianBitConverter.GetBytes((ushort)value), 0, 2);
                break;

            case LinkType.I4:
                this.sectionStream.Write(LittleEndianBitConverter.GetBytes((uint)value), 0, 4);
                break;

            case LinkType.I8:
                this.sectionStream.Write(LittleEndianBitConverter.GetBytes(value), 0, 8);
                break;
            }

            this.sectionStream.Position = pos;
        }
示例#2
0
        /// <summary>
        /// Emits a label into the code stream.
        /// </summary>
        /// <param name="label">The label name to emit.</param>
        void ICodeEmitter.Label(int label)
        {
            /*
             * FIXME: Labels are used to resolve branches inside a procedure. Branches outside
             * of procedures are handled differently, t.b.d.
             *
             * So we store the current instruction offset with the label info to be able to
             * resolve later backward jumps to this location.
             *
             * Additionally there may have been forward branches to this location, which have not
             * been resolved yet, so we need to scan these and resolve them to the current
             * instruction offset.
             *
             */

            // Save the current position
            long currentPosition = _codeStream.Position, pos;
            // Relative branch offset
            int relOffset;

            if (_labels.TryGetValue(label, out pos))
            {
//              Debug.Assert(pos == currentPosition);
                if (pos != currentPosition)
                {
                    throw new ArgumentException("Label already defined for another code point.", "label");
                }
            }


            else
            {
                // Check if this label has forward references on it...
                _patches.RemoveAll(delegate(Patch p)
                {
                    if (p.label == label)
                    {
                        // Set new position
                        _codeStream.Position = p.position;
                        // Compute relative offset
                        relOffset = (int)currentPosition - ((int)p.position + 4);
                        // Write relative offset to stream
                        byte[] bytes = LittleEndianBitConverter.GetBytes(relOffset);
                        _codeStream.Write(bytes, 0, bytes.Length);

                        // Success
                        return(true);
                    }
                    // Failed
                    return(false);
                });

                // Add this label to the label list, so we can resolve the jump later on
                _labels.Add(label, currentPosition);

                // Reset the position
                _codeStream.Position = currentPosition;

                // HACK: The machine code emitter needs to replace FP constants
                // with an EIP relative address, but these are not possible on x86,
                // so we store the EIP via a call in the right place on the stack
                //if (0 == label)
                //{
                //    // FIXME: This code doesn't need to be emitted if there are no
                //    // large constants used.
                //    _codeStream.WriteByte(0xE8);
                //    WriteImmediate(0);

                //    SigType i4 = new SigType(CilElementType.I4);

                //    RegisterOperand eax = new RegisterOperand(i4, GeneralPurposeRegister.EAX);
                //    Pop(eax);

                //    MemoryOperand mo = new MemoryOperand(i4, GeneralPurposeRegister.EBP, new IntPtr(-8));
                //    Mov(mo, eax);
                //}
            }
        }