/// <summary> /// Initializes a new instance of the <see cref="MemberOperand"/> class. /// </summary> /// <param name="method">The method to reference.</param> /// <exception cref="System.ArgumentNullException"><paramref name="method"/> is null.</exception> public MemberOperand(RuntimeMethod method) : base(new SigType(CilElementType.I), null, IntPtr.Zero) { if (method == null) throw new ArgumentNullException(@"method"); this.member = method; }
/// <summary> /// Initializes a new instance of the <see cref="MemberOperand"/> class. /// </summary> /// <param name="member">The member to reference.</param> /// <param name="type">The type of data held in the operand.</param> /// <param name="offset">The offset From the base register or absolute address to retrieve.</param> public MemberOperand(RuntimeMember member, SigType type, IntPtr offset) : base(type, null, offset) { if (member == null) throw new ArgumentNullException(@"member"); this.member = member; }
/// <summary> /// Initializes a new instance of <see cref="MemberOperand"/>. /// </summary> /// <param name="field">The runtime field to reference.</param> /// <exception cref="System.ArgumentNullException"><paramref name="field"/> is null.</exception> public MemberOperand(RuntimeField field) : base(field.Type, null, IntPtr.Zero) { if (field == null) throw new ArgumentNullException(@"field"); this.member = field; }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="linkType">The type of link required.</param> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="methodRelativeBase">The base virtualAddress, if a relative link is required.</param> /// <param name="target">The method or static field to link against.</param> /// <param name="offset">An offset to apply to the link target.</param> /// <returns></returns> public override long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, RuntimeMember target, IntPtr offset) { return base.Link(linkType, method, methodOffset, methodRelativeBase, target, offset); }
/// <summary> /// Checks that <paramref name="member"/> is a member, which can be linked. /// </summary> /// <param name="member">The member to check.</param> /// <returns> /// True, if the member is valid for linking. /// </returns> protected bool IsValid(RuntimeMember member) { return (member is RuntimeMethod || (member is RuntimeField && FieldAttributes.Static == (FieldAttributes.Static & ((RuntimeField)member).Attributes))); }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="linkType">The type of link required.</param> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="methodRelativeBase">The base virtualAddress, if a relative link is required.</param> /// <param name="target">The method or static field to link against.</param> /// <param name="offset">An offset to apply to the link target.</param> /// <returns> /// The return value is the preliminary virtualAddress to place in the generated machine /// code. On 32-bit systems, only the lower 32 bits are valid. The above are not used. An implementation of /// IAssemblyLinker may not rely on 64-bits being stored in the memory defined by position. /// </returns> public long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, RuntimeMember target, IntPtr offset) { CheckImplementation(); return this.implementation.Link(linkType, method, methodOffset, methodRelativeBase, target, offset); }
/// <summary> /// Retrieves a linker symbol. /// </summary> /// <param name="member">The runtime member to retrieve a symbol for.</param> /// <returns> /// A linker symbol, which represents the runtime member. /// </returns> public LinkerSymbol GetSymbol(RuntimeMember member) { CheckImplementation(); return this.implementation.GetSymbol(member); }
/// <summary> /// Creates a canonical symbol name for the given runtime member /// </summary> /// <param name="member">The runtime member to create a symbol name for</param> /// <returns>A string containing the canonical symbol name for the given runtime member</returns> public string CreateSymbolName(RuntimeMember member) { CheckImplementation(); return this.implementation.CreateSymbolName(member); }
/// <summary> /// Allocates memory in the specified section. /// </summary> /// <param name="symbol">The metadata member to allocate space for.</param> /// <param name="section">The executable section to allocate From.</param> /// <param name="size">The number of bytes to allocate. If zero, indicates an unknown amount of memory is required.</param> /// <param name="alignment">The alignment. A value of zero indicates the use of a default alignment for the section.</param> /// <returns>A stream, which can be used to populate the section.</returns> public Stream Allocate(RuntimeMember symbol, SectionKind section, int size, int alignment) { CheckImplementation(); return this.implementation.Allocate(symbol, section, size, alignment); }
/// <summary> /// Allocates memory in the specified section. /// </summary> /// <param name="member">The metadata member to allocate space for.</param> /// <param name="section">The executable section to allocate From.</param> /// <param name="size">The number of bytes to allocate. If zero, indicates an unknown amount of memory is required.</param> /// <param name="alignment">The alignment. A value of zero indicates the use of a default alignment for the section.</param> /// <returns>A stream, which can be used to populate the section.</returns> public virtual Stream Allocate(RuntimeMember member, SectionKind section, int size, int alignment) { // Create a canonical symbol name string name = CreateSymbolName(member); // Create a stream return Allocate(name, section, size, alignment); }
/// <summary> /// Determines if the given runtime member can be resolved immediately. /// </summary> /// <param name="member">The runtime member to determine resolution of.</param> /// <param name="virtualAddress">Receives the determined virtualAddress of the runtime member.</param> /// <returns> /// The method returns true, when it was successfully resolved. /// </returns> protected bool IsResolved(RuntimeMember member, out long virtualAddress) { // Is this a method? RuntimeMethod method = member as RuntimeMethod; if (null != method && method.ImplAttributes == MethodImplAttributes.InternalCall) { virtualAddress = ResolveInternalCall(method); return (0 != virtualAddress); } return IsResolved(CreateSymbolName(member), out virtualAddress); }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="linkType">The type of link required.</param> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="methodRelativeBase">The base virtualAddress, if a relative link is required.</param> /// <param name="target">The method or static field to link against.</param> /// <param name="offset">An offset to apply to the link target.</param> public virtual long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, RuntimeMember target, IntPtr offset) { Debug.Assert(IsValid(target), @"Invalid RuntimeMember passed to IAssemblyLinker.Link"); if (!IsValid(target)) throw new ArgumentException(@"RuntimeMember is not a static field or method.", @"member"); long address; if (!IsResolved(target, out address)) { address = Link(linkType, method, methodOffset, methodRelativeBase, CreateSymbolName(target), offset); } else { address += offset.ToInt64(); } return address; }
/// <summary> /// Retrieves a linker symbol. /// </summary> /// <param name="member">The runtime member to retrieve a symbol for.</param> /// <returns> /// A linker symbol, which represents the runtime member. /// </returns> /// <exception cref="System.ArgumentNullException"><paramref name="member"/> is null.</exception> /// <exception cref="System.ArgumentException">There's no symbol of the given name.</exception> public LinkerSymbol GetSymbol(RuntimeMember member) { if (member == null) throw new ArgumentNullException(@"member"); string symbolName = CreateSymbolName(member); return GetSymbol(symbolName); }
/// <summary> /// Creates a symbol name. /// </summary> /// <param name="symbol">The symbol name.</param> /// <returns>A string, which represents the symbol name.</returns> public string CreateSymbolName(RuntimeMember symbol) { if (symbol == null) throw new ArgumentNullException(@"symbol"); if (symbol is RuntimeMethod) return CreateSymbolName(symbol as RuntimeMethod); else if (symbol is RuntimeType) return CreateSymbolName(symbol as RuntimeType); else { string name; RuntimeType declaringType = symbol.DeclaringType; if (declaringType != null) { string declaringTypeSymbolName = CreateSymbolName(declaringType); name = String.Format("{0}.{1}", declaringTypeSymbolName, symbol.Name); } else { name = symbol.Name; } return name; } }
/// <summary> /// Issues a linker request for the given runtime method. /// </summary> /// <param name="method">The method the patched code belongs to.</param> /// <param name="methodOffset">The offset inside the method where the patch is placed.</param> /// <param name="linkType">The type of link required.</param> /// <param name="methodRelativeBase">The base address, if a relative link is required.</param> /// <param name="target">The method or static field to link against.</param> /// <returns> /// The return value is the preliminary address to place in the generated machine /// code. On 32-bit systems, only the lower 32 bits are valid. The above are not used. An implementation of /// IAssemblyLinker may not rely on 64-bits being stored in the memory defined by position. /// </returns> public virtual long Link(LinkType linkType, RuntimeMethod method, int methodOffset, int methodRelativeBase, RuntimeMember target) { return 0; }
/// <summary> /// Allocates the specified member. /// </summary> /// <param name="member">The member.</param> /// <param name="section">The section.</param> /// <param name="size">The size.</param> /// <param name="alignment">The alignment.</param> /// <returns></returns> public virtual Stream Allocate(RuntimeMember member, SectionKind section, int size, int alignment) { return null; }
/// <summary> /// Allocates memory in the specified section. /// </summary> /// <param name="member">The metadata member to allocate space for.</param> /// <param name="section">The executable section to allocate from.</param> /// <param name="size">The number of bytes to allocate. If zero, indicates an unknown amount of memory is required.</param> /// <param name="alignment">The alignment. A value of zero indicates the use of a default alignment for the section.</param> /// <returns> /// A stream, which can be used to populate the section. /// </returns> public override Stream Allocate(RuntimeMember member, SectionKind section, int size, int alignment) { string name = CreateSymbolName(member); LinkerStream stream = (LinkerStream)base.Allocate(name, section, size, alignment); try { VirtualMemoryStream vms = (VirtualMemoryStream)stream.BaseStream; // Save the member address member.Address = new IntPtr(vms.Base.ToInt64() + vms.Position); LinkerSymbol symbol = this.GetSymbol(name); symbol.VirtualAddress = member.Address; } catch { stream.Dispose(); throw; } return stream; }