/// <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; }
/// <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); //} } }