Browse files

pdb: read and write iterator metadata

  • Loading branch information...
1 parent 756b482 commit a871befb703d41ddf8ed3618300ed68d3da50f9f @atykhyy committed May 26, 2011
View
11 Mono.Cecil.Cil/MethodBody.cs
@@ -45,7 +45,9 @@ public sealed class MethodBody : IVariableDefinitionProvider {
internal Collection<Instruction> instructions;
internal Collection<ExceptionHandler> exceptions;
internal Collection<VariableDefinition> variables;
+ internal Collection<InstructionRange> iterator_scopes;
Scope scope;
+ TypeDefinition iterator_type;
public MethodDefinition Method {
get { return method; }
@@ -95,6 +97,15 @@ public sealed class MethodBody : IVariableDefinitionProvider {
set { scope = value; }
}
+ public TypeDefinition IteratorType {
+ get { return iterator_type; }
+ set { iterator_type = value; }
+ }
+
+ public Collection<InstructionRange> IteratorScopes {
+ get { return iterator_scopes ?? (iterator_scopes = new Collection<InstructionRange> ()); }
+ }
+
public ParameterDefinition ThisParameter {
get {
if (method == null || method.DeclaringType == null)
View
38 Mono.Cecil.Cil/Symbols.cs
@@ -47,14 +47,11 @@ public struct ImageDebugDirectory {
public int PointerToRawData;
}
- public sealed class Scope : IVariableDefinitionProvider {
+ public class InstructionRange {
Instruction start;
Instruction end;
- Collection<Scope> scopes;
- Collection<VariableDefinition> variables;
-
public Instruction Start {
get { return start; }
set { start = value; }
@@ -64,6 +61,12 @@ public sealed class Scope : IVariableDefinitionProvider {
get { return end; }
set { end = value; }
}
+ }
+
+ public sealed class Scope : InstructionRange, IVariableDefinitionProvider {
+
+ Collection<Scope> scopes;
+ Collection<VariableDefinition> variables;
public bool HasScopes {
get { return !scopes.IsNullOrEmpty (); }
@@ -92,21 +95,24 @@ public sealed class Scope : IVariableDefinitionProvider {
}
}
- public sealed class ScopeSymbol : IVariableDefinitionProvider {
+ public class RangeSymbol {
internal int start;
internal int end;
- Collection<ScopeSymbol> scopes;
- Collection<VariableDefinition> variables;
-
public int Start {
get { return start; }
}
public int End {
get { return end; }
}
+ }
+
+ public sealed class ScopeSymbol : RangeSymbol, IVariableDefinitionProvider {
+
+ Collection<ScopeSymbol> scopes;
+ Collection<VariableDefinition> variables;
public bool HasScopes {
get { return !scopes.IsNullOrEmpty (); }
@@ -151,11 +157,13 @@ public sealed class MethodSymbols {
internal int code_size;
internal string method_name;
+ internal string iterator_type;
internal ScopeSymbol scope;
internal MetadataToken method_token;
internal MetadataToken local_var_token;
internal Collection<VariableDefinition> variables;
internal Collection<InstructionSymbol> instructions;
+ internal Collection<RangeSymbol> iterator_scopes;
public bool HasVariables {
get { return !variables.IsNullOrEmpty (); }
@@ -179,6 +187,15 @@ public sealed class MethodSymbols {
}
}
+ public Collection<RangeSymbol> IteratorScopes {
+ get {
+ if (iterator_scopes == null)
+ iterator_scopes = new Collection<RangeSymbol> ();
+
+ return iterator_scopes;
+ }
+ }
+
public ScopeSymbol Scope {
get { return scope; }
}
@@ -195,6 +212,11 @@ public sealed class MethodSymbols {
get { return method_token; }
}
+ public string IteratorType {
+ get { return iterator_type; }
+ set { iterator_type = value; }
+ }
+
public MetadataToken LocalVarToken {
get { return local_var_token; }
}
View
5 Mono.Cecil.PE/ByteBuffer.cs
@@ -174,6 +174,11 @@ public double ReadDouble ()
}
#if !READ_ONLY
+ public void Align (int align)
+ {
+ align--;
+ WriteBytes (((position + align) & ~align) - position);
+ }
public void WriteByte (byte value)
{
View
6 symbols/pdb/Mono.Cecil.Pdb/ISymUnmanagedWriter2.cs
@@ -59,7 +59,11 @@ interface ISymUnmanagedWriter2 {
void DefineField_Placeholder ();
void DefineGlobalVariable_Placeholder ();
void Close ();
- void SetSymAttribute_Placeholder ();
+ void SetSymAttribute (
+ [In] SymbolToken method,
+ [In, MarshalAs (UnmanagedType.LPWStr)] string name,
+ [In] uint cData,
+ [In, MarshalAs (UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] signature);
void OpenNamespace ([In, MarshalAs (UnmanagedType.LPWStr)] string name);
void CloseNamespace ();
void UsingNamespace ([In, MarshalAs (UnmanagedType.LPWStr)] string fullName);
View
38 symbols/pdb/Mono.Cecil.Pdb/PdbReader.cs
@@ -114,6 +114,26 @@ public void Read (MethodBody body, InstructionMapper mapper)
ReadSequencePoints (function, mapper);
ReadScopeAndLocals (function.scopes, null, body, mapper);
+
+ if (!string.IsNullOrEmpty (function.iteratorClass))
+ body.IteratorType = body.Method.DeclaringType.GetNestedType (function.iteratorClass);
+
+ if (function.iteratorScopes != null)
+ foreach (Microsoft.Cci.ILocalScope scope in function.iteratorScopes)
+ {
+ InstructionRange range = new InstructionRange ();
+ SetInstructionRange (body, mapper, range, scope.Offset, scope.Length);
+ body.IteratorScopes.Add (range);
+ }
+ }
+
+ static void SetInstructionRange (MethodBody body, InstructionMapper mapper, InstructionRange range, uint offset, uint length)
+ {
+ range.Start = mapper ((int) offset);
+ range.End = mapper ((int)(offset + length));
+
+ if (range.End == null) range.End = body.Instructions[body.Instructions.Count - 1];
+ else range.End = range.End.Previous;
}
static void ReadScopeAndLocals (PdbScope [] scopes, Scope parent, MethodBody body, InstructionMapper mapper)
@@ -128,11 +148,7 @@ static void ReadScopeAndLocals (PdbScope scope, Scope parent, MethodBody body, I
return;
Scope s = new Scope ();
- s.Start = mapper ((int) scope.offset);
- s.End = mapper ((int)(scope.offset + scope.length));
-
- if (s.End == null) s.End = body.Instructions[body.Instructions.Count - 1] ;
- else s.End = s.End.Previous ;
+ SetInstructionRange (body, mapper, s, scope.offset, scope.length);
if (parent != null)
parent.Scopes.Add (s);
@@ -212,6 +228,18 @@ public void Read (MethodSymbols symbols)
ReadSequencePoints (function, symbols);
ReadScopeAndLocals (function.scopes, null, symbols);
+
+ if (!string.IsNullOrEmpty (function.iteratorClass))
+ symbols.IteratorType = function.iteratorClass;
+
+ if (function.iteratorScopes != null)
+ foreach (Microsoft.Cci.ILocalScope scope in function.iteratorScopes)
+ {
+ RangeSymbol range = new RangeSymbol ();
+ range.start = (int) scope.Offset;
+ range.end = (int)(scope.Offset + scope.Length);
+ symbols.IteratorScopes.Add (range);
+ }
}
View
78 symbols/pdb/Mono.Cecil.Pdb/PdbWriter.cs
@@ -82,6 +82,12 @@ public void Write (MethodBody body)
writer.CloseScope (end_offset);
}
+ if (body.IteratorType != null)
+ DefineIteratorType (sym_token, body.IteratorType.Name);
+
+ if (body.iterator_scopes != null)
+ DefineIteratorScopes (sym_token, body.IteratorScopes, body.CodeSize);
+
writer.CloseMethod ();
}
@@ -176,6 +182,72 @@ SymDocumentWriter GetDocument (Document document)
return doc_writer;
}
+ void DefineIteratorType (SymbolToken method_token, string name)
+ {
+ var buffer = new PE.ByteBuffer ();
+ buffer.WriteByte (4);
+ buffer.WriteByte (1);
+ buffer.Align (4);
+ buffer.WriteByte (4);
+ buffer.WriteByte (4);
+ buffer.Align (4);
+
+ var length = 10 + (uint) name.Length * 2;
+ while (length % 4 > 0)
+ length++;
+
+ buffer.WriteUInt32 (length);
+ buffer.WriteBytes (System.Text.Encoding.Unicode.GetBytes (name));
+ buffer.WriteByte (0);
+ buffer.Align (4);
+
+ writer.SetSymAttribute (method_token, "MD2", buffer.length, buffer.buffer);
+ }
+
+ void DefineIteratorScopes (SymbolToken method_token, Collection<RangeSymbol> scopes)
+ {
+ var buffer = new PE.ByteBuffer ();
+ buffer.WriteByte (4);
+ buffer.WriteByte (1);
+ buffer.Align (4);
+ buffer.WriteByte (4);
+ buffer.WriteByte (3);
+ buffer.Align (4);
+
+ buffer.WriteInt32 (scopes.Count * 8 + 12);
+ buffer.WriteInt32 (scopes.Count);
+
+ foreach (RangeSymbol scope in scopes)
+ {
+ buffer.WriteInt32 (scope.Start);
+ buffer.WriteInt32 (scope.End);
+ }
+
+ writer.SetSymAttribute (method_token, "MD2", buffer.length, buffer.buffer);
+ }
+
+ void DefineIteratorScopes (SymbolToken method_token, Collection<InstructionRange> scopes, int code_size)
+ {
+ var buffer = new PE.ByteBuffer ();
+ buffer.WriteByte (4);
+ buffer.WriteByte (1);
+ buffer.Align (4);
+ buffer.WriteByte (4);
+ buffer.WriteByte (3);
+ buffer.Align (4);
+
+ buffer.WriteInt32 (scopes.Count * 8 + 12);
+ buffer.WriteInt32 (scopes.Count);
+
+ foreach (InstructionRange scope in scopes)
+ {
+ buffer.WriteInt32 (scope.Start.Offset);
+ buffer.WriteInt32 (scope.End.Next != null ? scope.End.Next.Offset : code_size);
+ }
+
+ writer.SetSymAttribute (method_token, "MD2", buffer.length, buffer.buffer);
+ }
+
public void Write (MethodSymbols symbols)
{
if (symbols.instructions.IsNullOrEmpty () && !symbols.HasVariables)
@@ -198,6 +270,12 @@ public void Write (MethodSymbols symbols)
writer.CloseScope (end_offset);
}
+ if (!string.IsNullOrEmpty (symbols.IteratorType))
+ DefineIteratorType (sym_token, symbols.IteratorType);
+
+ if (symbols.iterator_scopes != null)
+ DefineIteratorScopes (sym_token, symbols.IteratorScopes);
+
writer.CloseMethod ();
}
View
5 symbols/pdb/Mono.Cecil.Pdb/SymWriter.cs
@@ -76,6 +76,11 @@ public byte[] GetDebugInfo (out ImageDebugDirectory idd)
return debug_info;
}
+ public void SetSymAttribute (SymbolToken method, string name, int length, byte [] data)
+ {
+ m_writer.SetSymAttribute (method, name, (uint) length, data);
+ }
+
public void DefineLocalVariable2 (
string name,
FieldAttributes attributes,

1 comment on commit a871bef

@Rageous

--deleted--

Please sign in to comment.