public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { if (!relocsOnly && _imports.ShouldSkipEmittingObjectNode(factory)) { // Don't emit import section node at all if there are no entries in it return; } dataBuilder.EmitReloc(_imports.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); if (!relocsOnly) { dataBuilder.EmitInt(_imports.GetData(factory, false).Data.Length); dataBuilder.EmitShort((short)_flags); dataBuilder.EmitByte((byte)_type); dataBuilder.EmitByte(_entrySize); } if (!_signatures.ShouldSkipEmittingObjectNode(factory)) { dataBuilder.EmitReloc(_signatures.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { dataBuilder.EmitUInt(0); } if (_emitGCRefMap) { dataBuilder.EmitReloc(_gcRefMap, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { dataBuilder.EmitUInt(0); } }
public void EmitJMP(ISymbolNode symbol) { if (symbol.RepresentsIndirectionCell) { throw new NotImplementedException(); } else { Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_BRANCH26); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0x14); } }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.AddSymbol(this); builder.EmitBytes(Encoding.UTF8.GetBytes(_ownerExecutableName)); builder.EmitByte(0); // zero string terminator return(builder.ToObjectData()); }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { if (!_imports.ShouldSkipEmittingObjectNode(factory)) { dataBuilder.EmitReloc(_imports.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { dataBuilder.EmitUInt(0); } if (!relocsOnly) { dataBuilder.EmitReloc(_imports.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE); dataBuilder.EmitShort((short)_flags); dataBuilder.EmitByte((byte)_type); dataBuilder.EmitByte(_entrySize); } if (!_signatures.ShouldSkipEmittingObjectNode(factory)) { dataBuilder.EmitReloc(_signatures.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { dataBuilder.EmitUInt(0); } if (_emitGCRefMap) { dataBuilder.EmitReloc(_gcRefMap, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { dataBuilder.EmitUInt(0); } }
public void EmitJMP(ISymbolNode symbol) { if (symbol.RepresentsIndirectionCell) { // ldr x12, [PC+0xc] EmitLDR(Register.X12, 0xc); // ldr x12, [x12] EmitLDR(Register.X12, Register.X12); // br x12 Builder.EmitUInt(0xd61f0180); Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64); } else { Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_BRANCH26); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0x14); } }
public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { ProfileDataNode nextElementInList = ((ProfileDataSectionNode)ContainingNode).NextElementToEncode; if (nextElementInList != null) { dataBuilder.EmitPointerReloc(nextElementInList, -OffsetFromStartOfObjectToSymbol); } else { dataBuilder.EmitZeroPointer(); } if (relocsOnly) { return; } EcmaMethod ecmaMethod = (EcmaMethod)_methodNode.Method.GetTypicalMethodDefinition(); int startOffset = dataBuilder.CountBytes; var reservation = dataBuilder.ReserveInt(); dataBuilder.EmitInt(0); // CORBBTPROF_METHOD_HEADER::cDetail dataBuilder.EmitInt(ecmaMethod.MetadataReader.GetToken(ecmaMethod.Handle)); // CORBBT_METHOD_INFO::token dataBuilder.EmitInt(_ilSize); // CORBBT_METHOD_INFO::ILSize dataBuilder.EmitInt(_blockCount); // CORBBT_METHOD_INFO::cBlock int sizeOfCORBBTPROF_METHOD_HEADER = dataBuilder.CountBytes - startOffset; Debug.Assert(sizeOfCORBBTPROF_METHOD_HEADER == (OffsetFromStartOfObjectToSymbol - _targetDetails.PointerSize)); dataBuilder.EmitInt(reservation, sizeOfCORBBTPROF_METHOD_HEADER + _profileData.Length); dataBuilder.EmitBytes(_profileData); while ((dataBuilder.CountBytes & (dataBuilder.TargetPointerSize - 1)) != 0) { dataBuilder.EmitByte(0); } }
public override void EmitByte(byte data) { _builder.EmitByte(data); }
public void EmitADD(ref AddrMode addrMode, sbyte immediate) { if (addrMode.Size == AddrModeSize.Int16) { Builder.EmitByte(0x66); } EmitIndirInstruction((byte)((addrMode.Size != AddrModeSize.Int8) ? 0x83 : 0x80), (byte)0, ref addrMode); Builder.EmitByte((byte)immediate); }
public void EmitMOV(Register regDst, Register regSrc) { AddrMode rexAddrMode = new AddrMode(regSrc, null, 0, 0, AddrModeSize.Int64); EmitRexPrefix(regDst, ref rexAddrMode); Builder.EmitByte(0x8B); Builder.EmitByte((byte)(0xC0 | (((int)regDst & 0x07) << 3) | (((int)regSrc & 0x07)))); }
public void EmitJMP(ISymbolNode symbol) { if (symbol.RepresentsIndirectionCell) { // xip0 register num is 0x10 // ADRP xip0, [symbol (21bit ADRP thing)] // 0x90000000 + (xip regnum) Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21); Builder.EmitByte(0x10); Builder.EmitByte(0x00); Builder.EmitByte(0x00); Builder.EmitByte(0x90); // LDR xip0, [xip0 + 12bit LDR page offset reloc)] // 0xF9400000 + ((xip0 regnum) << 5) + (xip regnum) Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L); Builder.EmitByte(0x10); Builder.EmitByte(0x02); Builder.EmitByte(0x40); Builder.EmitByte(0xF9); // BR xip0 // 0xD61F0000 + (xip0 regnum) << 5) Builder.EmitByte(0x00); Builder.EmitByte(0x02); Builder.EmitByte(0x1F); Builder.EmitByte(0xD6); } else { Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_BRANCH26); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0x14); } }
// nop public void EmitNOP() { Builder.EmitByte(0x00); Builder.EmitByte(0xbf); }
public void EmitLEAQ(Register reg, ISymbolNode symbol) { AddrMode rexAddrMode = new AddrMode(Register.RAX, null, 0, 0, AddrModeSize.Int64); EmitRexPrefix(reg, ref rexAddrMode); Builder.EmitByte(0x8D); int regNumLowBits = ((int)reg) & 0x07; int regNumLowBitsShifted = regNumLowBits << 3; byte modRM = (byte)(regNumLowBitsShifted | 0x05); Builder.EmitByte(modRM); Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); }
public void EmitJMP(ISymbolNode symbol) { if (symbol.RepresentsIndirectionCell) { Debug.Assert(false, "The following code to emit an jump stub to an indirection cell is untested. When testing on ARM64 please remove this assert and verify it is correct"); // xip0 register num is 0x10 // ADRP xip0, [symbol (21bit ADRP thing)] // 0x90000000 + (xip regnum) Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21); Builder.EmitByte(0x10); Builder.EmitByte(0x00); Builder.EmitByte(0x00); Builder.EmitByte(0x90); // LDR xip0, [xip0 + 12bit LDR page offset reloc)] // 0xF9400000 + ((xip0 regnum) << 5) + (xip regnum) Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L); Builder.EmitByte(0x10); Builder.EmitByte(0x02); Builder.EmitByte(0x40); Builder.EmitByte(0xF9); // BR xip0 // 0xD61F0000 + (xip0 regnum) << 5) Builder.EmitByte(0x00); Builder.EmitByte(0x02); Builder.EmitByte(0x1F); Builder.EmitByte(0xD6); } else { Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_BRANCH26); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0); Builder.EmitByte(0x14); } }
// push reg public void EmitPUSH(Register reg) { Builder.EmitByte(0x4d); Builder.EmitByte(0xf8); Builder.EmitShort((short)(0x0d04 + ((byte)reg << 12))); }