Laden...

[gelöst] Zielmethode eines Call-Befehls auf CIL-Ebene ermitteln

Erstellt von zommi vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.067 Views
zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 14 Jahren
[gelöst] Zielmethode eines Call-Befehls auf CIL-Ebene ermitteln

Hallo,

ich spiele grad etwas mit dem Reflection.Emit-Namespace. Mein ziel ist eine bereits existierende Methode komplett nachzubauen.

Dazu hole ich mir den CIL-Code einer existierenden Methode mit GetType() GetMethod(...) GetMethodBody() GetILAsByteArray() und parse ihn zurück in eine Abfolge von OpCodes & passenden Operanden. Aus diesen baue ich dann mit ILGenerator und dem Emit(...) eine neue DynamicMethod, die ich dann aufrufe und hoffe, dass genau das selbe passiert, wie bei der Ausgangsmethode =).

Für eine Methode wie


static int foo(int x) {return x*4 +2;}

klappt das auch super aber für eine Methode wie


static int foo(int x) {return bar(x);}

klappt das nicht.
Anscheinend hakt das mit dem Call-Befehl Ein-/Auslesen irgendwie.

Folgende Beobachtungen habe ich gemacht:1.Der Operand des Call-Befehls aus der Ausgangsmethode ist eine Zahl und entspricht dem MethodInfo.MetadataToken der bar-Methode. 1.Wenn ich denn Call Befehl per Hand emittiere, also mit

Emit(OpCodes.Call, barMethodInfo);

dann klappt es auch.

Nur ein

Emit(OpCodes.Call, barMethodInfo.MetadataToken);

klappt nicht ! (Aber aus dem Byte-Code bekomme ich nur das MetadataToken ausgelesen)

Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen? Bzw. irgendwie anders das zum Laufen zu bekommen?

Ich hoffe, ich konnte mein Anliegen rüberbringen, falls nicht: nachfragen 🙂

beste Grüße
zommi

PS: Mit Mono.Cecil geht das vielleicht irgendwie. Aber ich wollte es schon gern mit dem Standard-Framework versuchen.
PS2: Wenn ich auch mal in den emittierten CIL-Code blicken könnte, wäre das auch schön. Aber ein GetILAsByteArray() klappt bei einer DynamicMethod bringt immer nen Fehler. 🤔

2.891 Beiträge seit 2004
vor 14 Jahren

Hallo zommi,

Mein ziel ist eine bereits existierende Methode komplett nachzubauen. Also wenn ich dich richtig verstehe, willst nicht du manuell eine Methode nachbauen, sondern ein Programm soll dynamisch beliebige Methoden nachbauen(?)

Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen

Hast du mal MethodBase.GetMethodFromHandle (MethodInfo ist eine Spezialisierung von MethodBase) ausprobiert?

Gruß,
dN!3L

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo zommi,

Gibt es eine Möglichkeit aus dem MetadataToken an die MethodInfo zu kommen? Bzw. irgendwie anders das zum Laufen zu bekommen?

leider kann ich nur sehr diffus antworten: Ob man über das MetadataToken ran kommt, weiß ich nicht, aber rankommen muss man irgendwie. Der Reflector schafft es ja auch.

herbivore

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 14 Jahren

Hi, danke erstmal für die Antworten,

@dN!3L,
über die Methode bin ich auch schon gestolpert, klappt aber auch nicht 🙁
GetMethodFromHandle braucht eben ein RunTimeMethodHandle und kein int32.
Außerdem ist

myMethodInfo.MethodHandle.Value != myMethodInfo.MetadataToken

@herbivore
jaja. gehen muss es 🙂
Und prinzipiell müsste es ja auch gehen, wenn ich die komplette Assembly + alle referenzierten durchgehe, dort alle Typen und darin alle Methoden; mir von denen die MetadataToken hole und vergleiche. Aber das ist mir etwas zu viel BruteForce-Suche 😉
(mhh.. wobei ich das natürlich einmal initial machen könnte und dann n Dictionary vorhalten...mhh...)

@dN!3l, (Klappe, die zweite)

Also wenn ich dich richtig verstehe, willst du nicht manuell eine Methode nachbauen, sondern ein Programm soll dynamisch beliebige Methoden nachbauen(?)

Genau 👍 Also das simple Nachbauen ist die erste Stufe. Ein späteres Modifizieren ist die zweite. (Und insgesamt einer kleiner Schritt zu einem CIL-CIL-Optimierer)

viele grüße
zommi

2.891 Beiträge seit 2004
vor 14 Jahren

Hi zommi,

dann nimm Module.ResolveMethod. (Gibt auch noch andere Resolve*-Member von Module).


MethodInfo methodInfo = typeof(object).GetMethod("ToString");
MethodBase methodBase = methodInfo.Module.ResolveMethod(methodInfo.MetadataToken);
if (methodInfo==methodBase)
	Console.WriteLine("Yeehaa!");

Und insgesamt einer kleiner Schritt zu einem CIL-CIL-Optimierer

Naja, Phoenix wurde ja für sowas entworfen. Aber mach's lieber selbst, mit Phoenix zu arbeiten ist das letzte...

Gruß,
dN!3L

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 14 Jahren

Yeehaa

Du sagst es 😁
Diese Methode schickt der Himmel !

Danke
beste Grüße
zommi