singrdk/base/Windows/mkmsil/msil/MetaDataMethod.cs

375 lines
13 KiB
C#

//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
using System;
using System.Collections;
using System.IO;
using Bartok.DebugInfo;
namespace Bartok.MSIL
{
public class MetaDataMethod: MetaDataObject {
// Constructor Methods
internal MetaDataMethod(int rva, short implFlags, short flags,
string name, Signature signature,
int paramIndex) {
this.rva = rva;
this.implFlags = implFlags;
this.flags = flags;
this.name = name;
this.signature = signature;
this.paramIndex = paramIndex;
}
// These are technically not constructor methods, but they are meant to
// be used to set up the object
internal void AddGenericParam(MetaDataGenericParam genericParam) {
if (this.genericParamList == null) {
this.genericParamList = new ArrayList(2);
}
if (genericParam.Number != this.genericParamList.Count) {
throw new MetaDataLoader.IllegalMetaDataFormatException
("Generic parameters out of order - is this allowed?");
}
this.genericParamList.Add(genericParam);
}
internal void registerReferences(int paramCount,
MetaDataMethod[] paramOwners) {
if (this.paramIndex <= paramCount) {
paramOwners[this.paramIndex] = this;
}
}
internal void resolveReferences(MetaDataLoader loader,
MetaDataMethod[] paramOwners) {
this.signature = signature.resolve(loader);
// paramOwners[paramOwners.Length-1] == null, so this is safe
int paramEndIndex = this.paramIndex;
while (paramOwners[paramEndIndex] == this) {
paramEndIndex++;
}
int paramCount = paramEndIndex - this.paramIndex;
this.paramArray = loader.getParams(this.paramIndex, paramCount);
int limit = this.paramArray.Length;
if (paramCount != limit) {
MetaDataParam resultParam = loader.getParam(this.paramIndex);
resultParam.resolveReferences(this);
}
for (int i = 0; i < limit; i++) {
this.paramArray[i].resolveReferences(this);
}
}
internal void loadInstructions(MetaDataLoader mdLoader,
PELoader peLoader,
Stream fileStream,
int[] lines,
int[] columns,
int[] offsets,
String srcFileName,
int count) {
if (this.rva != 0) {
if ((this.flags & (short) MethodAttributes.PinvokeImpl) == 0 ||
(this.flags & (short) MethodAttributes.UnmanagedExport) != 0) {
int codeOffset = peLoader.VaToOffset(rva);
this.instructions =
Instruction.getInstructions(mdLoader, fileStream,
codeOffset, lines, columns,
offsets, srcFileName, count,
out this.ehTable,
out this.bbTable,
out this.maxStack,
out this.locals,
out this.initLocals);
}
else {
Console.WriteLine("Not loading embedded native code for "+
this);
}
}
}
internal void setParent(MetaDataTypeDefinition parent) {
this.parent = parent;
}
// Access Methods
// of MetaDataGenericParam
public ArrayList GenericParamList {
get {
return this.genericParamList;
}
}
public Instruction[] Instructions {
get {
return this.instructions;
}
}
public EHClause[] EHTable {
get {
return this.ehTable;
}
}
// An array of basic block start indices in "Instructions"
public int[] BBTable {
get {
return this.bbTable;
}
}
public int MaxStack {
get {
return this.maxStack;
}
}
public Signature.Type[] Locals {
get {
return this.locals;
}
}
// Bitmask described by MethodImplAttributes
public short ImplFlags {
get {
return this.implFlags;
}
}
// Bitmask described by MethodAttributes
public short Flags {
get {
return this.flags;
}
}
public string FullName {
get {
if (this.parent != null) {
return this.parent.FullName + "." + this.Name;
}
else {
return this.Name;
}
}
}
public string Name {
get {
return this.name;
}
}
public SignatureMethod Signature {
get {
return (SignatureMethod) this.signature;
}
}
public MetaDataParam[] Parameters {
get {
return this.paramArray;
}
}
public MetaDataTypeDefinition Parent {
get {
return this.parent;
}
}
public int Rva {
get { return rva; }
}
public bool IsEmpty {
get { return isEmpty; }
set { isEmpty = value; }
}
public bool InitLocals {
get { return initLocals; }
}
public DebugLineNumber BaseLineNumber {
get { return baseLineNumber; }
set { baseLineNumber = value; }
}
public DebugLineNumber LastLineNumber {
get { return lastLineNumber; }
set { lastLineNumber = value; }
}
public int NumOfLines {
get { return numOfLines; }
set { numOfLines = value; }
}
public String SrcFileName {
get { return srcFileName; }
set { srcFileName = value; }
}
public bool HasDebugInfo {
get { return hasDebugInfo; }
set { hasDebugInfo = value; }
}
public String[] LocalVarNames {
get { return localVarNames; }
set { localVarNames = value; }
}
// Debug Methods
public override string ToString() {
return ("MetaDataMethod("+this.FullName+")");
}
public override string ToStringLong() {
System.Text.StringBuilder sb =
new System.Text.StringBuilder("MetaDataMethod(");
if (this.genericParamList != null
&& this.genericParamList.Count > 0) {
sb.Append("GenericParams<");
foreach (MetaDataGenericParam param in this.genericParamList) {
sb.Append(param.ToString());
sb.Append(",");
}
sb.Remove(sb.Length-1, 1);
sb.Append(">,");
}
sb.Append(this.rva);
sb.Append(",");
sb.Append(this.implFlags.ToString("x"));
sb.Append(",");
sb.Append(this.flags.ToString("x"));
sb.Append(",");
if (this.parent != null) {
sb.Append(this.parent.FullName);
sb.Append(".");
}
sb.Append(this.name);
sb.Append(",");
sb.Append(this.signature);
sb.Append(",");
if (this.paramArray == null) {
sb.Append(this.paramIndex);
}
else if (this.paramArray.Length == 0) {
sb.Append("No parameters");
}
else {
sb.Append("parameters(");
foreach (MetaDataParam param in this.paramArray) {
sb.Append(param.ToString());
sb.Append(",");
}
sb.Remove(sb.Length-1, 1);
sb.Append(")");
}
sb.Append(")");
return sb.ToString();
}
// State
private readonly int rva;
private ArrayList genericParamList;
private Instruction[] instructions;
private EHClause[] ehTable;
private int[] bbTable;
private int maxStack;
private Signature.Type[] locals;
private readonly short implFlags;
private readonly short flags;
private readonly string name;
private Signature signature;
private readonly int paramIndex;
private MetaDataParam[] paramArray;
private MetaDataTypeDefinition parent;
private bool isEmpty;
private bool initLocals;
// information for debugging
private DebugLineNumber baseLineNumber;
private DebugLineNumber lastLineNumber;
private int numOfLines;
private String srcFileName;
private bool hasDebugInfo;
private String[] localVarNames;
// Internal Classes
// Section 22.1.7 of ECMA spec, Section II
public enum MethodImplAttributes
{
// code impl mask
CodeTypeMask = 0x0003, // Flags about code type.
IL = 0x0000, // Method impl is IL.
Native = 0x0001, // Method impl is native.
OPTIL = 0x0002, // Method impl is OPTIL
Runtime = 0x0003, // Method impl is provided by the runtime.
// managed mask
ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged.
Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed.
Managed = 0x0000, // Method impl is managed.
// implementation info and interop
ForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios.
PreserveSig = 0x0080, // Indicates method sig is not to be mangled to do HRESULT conversion.
InternalCall = 0x1000, // Reserved for internal use.
Synchronized = 0x0020, // Method is single threaded through the body.
NoInlining = 0x0008, // Method may not be inlined.
MaxMethodImplVal = 0xffff // Range check value
}
public enum MethodAttributes {
// member access attributes
MemberAccessMask = 0x0007, // Use this mask to retrieve accessibility information.
PrivateScope = 0x0000, // Member not referenceable.
Private = 0x0001, // Accessible only by the parent type.
FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
Assem = 0x0003, // Accessibly by anyone in the Assembly.
Family = 0x0004, // Accessible only by type and sub-types.
FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
// method contract attributes.
Static = 0x0010, // Defined on type, else per instance.
Final = 0x0020, // Method may not be overridden.
Virtual = 0x0040, // Method virtual.
HideBySig = 0x0080, // Method hides by name+sig, else just by name.
// vtable layout mask - Use this mask to retrieve vtable attributes.
VtableLayoutMask = 0x0100,
ReuseSlot = 0x0000, // The default.
NewSlot = 0x0100, // Method always gets a new slot in the vtable.
// method implementation attributes.
Abstract = 0x0400, // Method does not provide an implementation.
SpecialName = 0x0800, // Method is special. Name describes how.
// interop attributes
PinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke.
UnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code.
// Reserved flags for runtime use only.
ReservedMask = 0xd000,
RTSpecialName = 0x1000, // Runtime should check name encoding.
HasSecurity = 0x4000, // Method has security associate with it.
RequireSecObject = 0x8000 // Method calls another method containing security code.
}
}
}