Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0c213d0

Browse files
committed
C#: Extract function pointer types from CIL
1 parent 5fa0dd7 commit 0c213d0

13 files changed

Lines changed: 228 additions & 12 deletions

File tree

csharp/extractor/Semmle.Extraction.CIL/Entities/CilTypeKind.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public enum CilTypeKind
88
ValueOrRefType,
99
TypeParameter,
1010
Array,
11-
Pointer
11+
Pointer,
12+
FunctionPointer
1213
}
1314
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Reflection.Metadata;
5+
6+
namespace Semmle.Extraction.CIL.Entities
7+
{
8+
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
9+
{
10+
private readonly MethodSignature<Type> signature;
11+
12+
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
13+
{
14+
this.signature = signature;
15+
}
16+
17+
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
18+
19+
public override string Name
20+
{
21+
get
22+
{
23+
using var id = new StringWriter();
24+
WriteName(
25+
id.Write,
26+
t => id.Write(t.Name),
27+
signature
28+
);
29+
return id.ToString();
30+
}
31+
}
32+
33+
public override Namespace? ContainingNamespace => Cx.GlobalNamespace;
34+
35+
public override Type? ContainingType => null;
36+
37+
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
38+
39+
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
40+
41+
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
42+
43+
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
44+
45+
public override void WriteId(TextWriter trapFile, bool inContext)
46+
{
47+
WriteName(
48+
trapFile.Write,
49+
t => t.WriteId(trapFile, inContext),
50+
signature
51+
);
52+
}
53+
54+
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
55+
{
56+
write("delegate* ");
57+
write(GetCallingConvention(signature.Header.CallingConvention));
58+
write("<");
59+
foreach (var pt in signature.ParameterTypes)
60+
{
61+
writeType(pt);
62+
write(",");
63+
}
64+
writeType(signature.ReturnType);
65+
write(">");
66+
}
67+
68+
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
69+
{
70+
if (callingConvention == SignatureCallingConvention.Default)
71+
{
72+
return "managed";
73+
}
74+
75+
if (callingConvention == SignatureCallingConvention.Unmanaged)
76+
{
77+
return "unmanaged";
78+
}
79+
80+
return $"unmanaged[{callingConvention}]";
81+
}
82+
83+
public override IEnumerable<IExtractionProduct> Contents
84+
{
85+
get
86+
{
87+
foreach (var c in base.Contents)
88+
{
89+
yield return c;
90+
}
91+
92+
var retType = signature.ReturnType;
93+
if (retType is ModifiedType mt)
94+
{
95+
retType = mt.Unmodified;
96+
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
97+
}
98+
yield return Tuples.cil_function_pointer_return_type(this, retType);
99+
100+
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
101+
102+
var i = 0;
103+
foreach (var p in signature.ParameterTypes)
104+
{
105+
var t = p;
106+
if (t is ModifiedType mtparam)
107+
{
108+
t = mtparam.Unmodified;
109+
yield return Tuples.cil_custom_modifiers(this, mtparam.Modifier, mtparam.IsRequired);
110+
}
111+
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
112+
}
113+
}
114+
}
115+
}
116+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Semmle.Extraction.CIL.Entities
2+
{
3+
internal interface IParameterizable : IEntity
4+
{
5+
6+
}
7+
}

csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities
99
/// <summary>
1010
/// A method entity.
1111
/// </summary>
12-
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
12+
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
1313
{
1414
protected MethodTypeParameter[]? genericParams;
1515
protected GenericContext gc;

csharp/extractor/Semmle.Extraction.CIL/Entities/ModifiedType.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired)
3737

3838
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
3939

40-
public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException();
40+
public override void WriteId(TextWriter trapFile, bool inContext)
41+
{
42+
Unmodified.WriteId(trapFile, inContext);
43+
trapFile.Write(IsRequired ? " modreq" : " modopt");
44+
trapFile.Write("(");
45+
Modifier.WriteId(trapFile, inContext);
46+
trapFile.Write(")");
47+
}
4148
}
4249
}

csharp/extractor/Semmle.Extraction.CIL/Entities/Parameter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ namespace Semmle.Extraction.CIL.Entities
88
/// </summary>
99
internal sealed class Parameter : LabelledEntity
1010
{
11-
private readonly Method method;
11+
private readonly IParameterizable method;
1212
private readonly int index;
1313
private readonly Type type;
1414

15-
public Parameter(Context cx, Method m, int i, Type t) : base(cx)
15+
public Parameter(Context cx, IParameterizable m, int i, Type t) : base(cx)
1616
{
1717
method = m;
1818
index = i;

csharp/extractor/Semmle.Extraction.CIL/Entities/SignatureDecoder.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,20 @@ public void WriteId(TextWriter trapFile, GenericContext gc)
4848

4949
private struct FnPtr : ITypeSignature
5050
{
51+
private readonly MethodSignature<ITypeSignature> signature;
52+
53+
public FnPtr(MethodSignature<ITypeSignature> signature)
54+
{
55+
this.signature = signature;
56+
}
5157

5258
public void WriteId(TextWriter trapFile, GenericContext gc)
5359
{
54-
trapFile.Write("<method signature>");
60+
FunctionPointerType.WriteName(
61+
trapFile.Write,
62+
t => t.WriteId(trapFile, gc),
63+
signature
64+
);
5565
}
5666
}
5767

@@ -62,7 +72,7 @@ ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetByReferenceType(IType
6272
new ByRef(elementType);
6373

6474
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) =>
65-
new FnPtr();
75+
new FnPtr(signature);
6676

6777
private class Instantiation : ITypeSignature
6878
{

csharp/extractor/Semmle.Extraction.CIL/Entities/TypeSignatureDecoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Type IConstructedTypeProvider<Type>.GetByReferenceType(Type elementType) =>
2323
elementType; // ??
2424

2525
Type ISignatureTypeProvider<Type, GenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) =>
26-
cx.ErrorType; // Don't know what to do !!
26+
cx.Populate(new FunctionPointerType(cx, signature));
2727

2828
Type IConstructedTypeProvider<Type>.GetGenericInstantiation(Type genericType, ImmutableArray<Type> typeArguments) =>
2929
genericType.Construct(typeArguments);

csharp/extractor/Semmle.Extraction.CIL/Tuples.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ internal static Tuple cil_local_variable(LocalVariable l, MethodImplementation m
8686
internal static Tuple cil_method(Method method, string name, Type declType, Type returnType) =>
8787
new Tuple("cil_method", method, name, declType, returnType);
8888

89+
internal static Tuple cil_function_pointer_return_type(FunctionPointerType fnptr, Type returnType) =>
90+
new Tuple("cil_function_pointer_return_type", fnptr, returnType);
91+
92+
internal static Tuple cil_function_pointer_calling_conventions(FunctionPointerType fnptr, System.Reflection.Metadata.SignatureCallingConvention callingConvention) =>
93+
new Tuple("cil_function_pointer_calling_conventions", fnptr, (int)callingConvention);
94+
8995
internal static Tuple cil_method_implementation(MethodImplementation impl, Method method, Assembly assembly) =>
9096
new Tuple("cil_method_implementation", impl, method, assembly);
9197

@@ -101,7 +107,7 @@ internal static Tuple cil_method_stack_size(MethodImplementation method, int sta
101107
internal static Tuple cil_newslot(Method method) =>
102108
new Tuple("cil_newslot", method);
103109

104-
internal static Tuple cil_parameter(Parameter p, Method m, int i, Type t) =>
110+
internal static Tuple cil_parameter(Parameter p, IParameterizable m, int i, Type t) =>
105111
new Tuple("cil_parameter", p, m, i, t);
106112

107113
internal static Tuple cil_parameter_in(Parameter p) =>

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,7 @@ case @cil_type.kind of
16951695
| 1 = @cil_typeparameter
16961696
| 2 = @cil_array_type
16971697
| 3 = @cil_pointer_type
1698+
| 4 = @cil_function_pointer_type
16981699
;
16991700

17001701
cil_type(
@@ -1713,6 +1714,10 @@ cil_array_type(
17131714
int element_type: @cil_type ref,
17141715
int rank: int ref);
17151716

1717+
cil_function_pointer_return_type(
1718+
unique int id: @cil_function_pointer_type ref,
1719+
int return_type: @cil_type ref);
1720+
17161721
cil_method(
17171722
unique int id: @cil_method,
17181723
string name: string ref,
@@ -1746,12 +1751,13 @@ cil_field(
17461751
@cil_variable = @cil_field | @cil_stack_variable;
17471752
@cil_stack_variable = @cil_local_variable | @cil_parameter;
17481753
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
1749-
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type
1754+
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
1755+
@cil_parameterizable = @cil_method | @cil_function_pointer_type;
17501756

1751-
#keyset[method, index]
1757+
#keyset[parameterizable, index]
17521758
cil_parameter(
17531759
unique int id: @cil_parameter,
1754-
int method: @cil_method ref,
1760+
int parameterizable: @cil_parameterizable ref,
17551761
int index: int ref,
17561762
int param_type: @cil_type ref);
17571763

@@ -1796,6 +1802,10 @@ cil_local_variable(
17961802
int index: int ref,
17971803
int var_type: @cil_type ref);
17981804

1805+
cil_function_pointer_calling_conventions(
1806+
int id: @cil_function_pointer_type ref,
1807+
int kind: int ref);
1808+
17991809
// CIL handlers (exception handlers etc).
18001810

18011811
case @cil_handler.kind of

0 commit comments

Comments
 (0)