HighTechTalks DotNet Forums  

which IL OpCodes call a method

Dotnet Framework (CLR) microsoft.public.dotnet.framework.clr


Discuss which IL OpCodes call a method in the Dotnet Framework (CLR) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
kevin
 
Posts: n/a

Default which IL OpCodes call a method - 12-20-2007 , 05:19 PM






....using framework 1.0 / 1.1/ 2.0, Mono.Cecil library for introspection

I am new to all this fancy smancy IL stuff, so please hold the slaps if this
is obvious...and feel free to point me to "good" and "clear" documention if
that would answer my question.

which IL OpCode represent method calls or object instantiation? I
determined Call, Calli, Callivert and NewObj by writing some quick code and
using Ildasm.exe to inspect the assembly, but there are over 200 codes.

Thanks


--
kevin...

Reply With Quote
  #2  
Old   
Barry Kelly
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-21-2007 , 05:10 AM






kevin wrote:

Quote:
...using framework 1.0 / 1.1/ 2.0, Mono.Cecil library for introspection

I am new to all this fancy smancy IL stuff, so please hold the slaps if this
is obvious...and feel free to point me to "good" and "clear" documention if
that would answer my question.

which IL OpCode represent method calls or object instantiation? I
determined Call, Calli, Callivert and NewObj by writing some quick code and
using Ildasm.exe to inspect the assembly, but there are over 200 codes.
'callvirt' is typically used by C# for calling both virtual and
non-virtual methods. For virtual methods, it's required to get
polymorphism, while with non-virtual method it forces a null reference
exception if the instance is null. Some other .NET languages (e.g.
Delphi for .NET) don't use 'callvirt' for non-virtual methods because
calling an instance method on a null instance isn't necessarily an
error.

'call' is typically used for calling static methods or forcing
non-polymorphic calls, such as when calling the inherited method inside
an overridden method: e.g. 'base.Foo();' inside 'override void Foo();'.

'calli' is an indirect call. It's used to call a function pointer on the
IL stack. Not frequently required.

'newobj' both allocates an object from the heap and calls its
constructor.

This information is in partition III of the CLI standard, ECMA-335:

http://www.ecma-international.org/pu...s/Ecma-335.htm

-- Barry

--
http://barrkel.blogspot.com/


Reply With Quote
  #3  
Old   
kevin
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-21-2007 , 10:16 AM



Thanks Barry.

The table of contents of partition 3 basically answers my question.

So if my purpose is to find all references to in-house assemblies (object
creation, method call and property accessing) would you agree that i can look
for instructions with the following OpCodes:
1. call
2. calli
3. callvert
4. newobj
5. throw (looking for derived exceptions)
--
kevin...


"Barry Kelly" wrote:

Quote:
kevin wrote:

...using framework 1.0 / 1.1/ 2.0, Mono.Cecil library for introspection

I am new to all this fancy smancy IL stuff, so please hold the slaps if this
is obvious...and feel free to point me to "good" and "clear" documention if
that would answer my question.

which IL OpCode represent method calls or object instantiation? I
determined Call, Calli, Callivert and NewObj by writing some quick code and
using Ildasm.exe to inspect the assembly, but there are over 200 codes.

'callvirt' is typically used by C# for calling both virtual and
non-virtual methods. For virtual methods, it's required to get
polymorphism, while with non-virtual method it forces a null reference
exception if the instance is null. Some other .NET languages (e.g.
Delphi for .NET) don't use 'callvirt' for non-virtual methods because
calling an instance method on a null instance isn't necessarily an
error.

'call' is typically used for calling static methods or forcing
non-polymorphic calls, such as when calling the inherited method inside
an overridden method: e.g. 'base.Foo();' inside 'override void Foo();'.

'calli' is an indirect call. It's used to call a function pointer on the
IL stack. Not frequently required.

'newobj' both allocates an object from the heap and calls its
constructor.

This information is in partition III of the CLI standard, ECMA-335:

http://www.ecma-international.org/pu...s/Ecma-335.htm

-- Barry

--
http://barrkel.blogspot.com/


Reply With Quote
  #4  
Old   
kevin
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-21-2007 , 03:16 PM



"Mattias Sjögren" wrote:

Quote:
But if you want to know exactly where in the code those assemblies are
being used, I guess you should look at pretty much any instruction
that involves a memberref or typeref token.
Mattias,

I do indeed what to know when an assembly is used. So are you suggesting
that looking for OpCode Call, Calli, Callvirt, NewObj and Throw will not
suffice?

Thanks.

Kevin


Reply With Quote
  #5  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-24-2007 , 02:27 PM




"kevin" <kevin (AT) discussions (DOT) microsoft.com> wrote

Quote:
"Mattias Sjögren" wrote:

But if you want to know exactly where in the code those assemblies are
being used, I guess you should look at pretty much any instruction
that involves a memberref or typeref token.

Mattias,

I do indeed what to know when an assembly is used. So are you suggesting
that looking for OpCode Call, Calli, Callvirt, NewObj and Throw will not
suffice?
Looking at NewObj will tell you which concrete types are used, unless
generics are involved.

If you need to know when methods are called, you're pretty well out of luck
because they could be called virtually using an interface pointer, then the
typeref and methodref wouldn't even be to your assembly.

Quote:
Thanks.

Kevin



Reply With Quote
  #6  
Old   
kevin
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-24-2007 , 04:58 PM



Ben wrote
Quote:
If you need to know when methods are called, you're pretty well out of luck
because they could be called virtually using an interface pointer, then the
typeref and methodref wouldn't even be to your assembly.
Please explain what you mean... or better yet give an example. The
following code produces the IL that follows. The IL has "callvirt".

********code********

static class TypeProgram
{
static void Main()
{
IKev ik = new KevClass();
KevClass k = new KevClass();
string something = ik.SaySomething();
int isEqual = k.CompareTo((KevClass)ik);
}
}
public interface IKev
{
string SaySomething();
}
public class KevClass: IKev,IComparable<KevClass>
{
#region IKev Members
public string SaySomething()
{
return "I rock!";
}
#endregion
#region IComparable<KevClass> Members
public int CompareTo(KevClass other)
{
return 1;
}
#endregion
}
********************

********IL***********
IL_0000: nop
IL_0001: newobj instance void WindowsApplication1.KevClass::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void WindowsApplication1.KevClass::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: callvirt instance string
WindowsApplication1.IKev::SaySomething()
IL_0013: stloc.2
IL_0014: ldloc.1
IL_0015: ldloc.0
IL_0016: castclass WindowsApplication1.KevClass
IL_001b: callvirt instance int32
WindowsApplication1.KevClass::CompareTo(class WindowsApplication1.KevClass)
IL_0020: stloc.3
IL_0021: ret

********************


Reply With Quote
  #7  
Old   
Barry Kelly
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-24-2007 , 07:19 PM



kevin wrote:

Quote:
Ben wrote
If you need to know when methods are called, you're pretty well out of luck
because they could be called virtually using an interface pointer, then the
typeref and methodref wouldn't even be to your assembly.

Please explain what you mean... or better yet give an example. The
He means that if you're using dynamic dispatch with polymorphism (aka
virtual methods), you don't necessarily know at compile time (and thus
in the assembly) which actual method will be called. You don't know this
because you don't know at compile time the actual type of the instance.
Discovering actual type for all instances requires solving the halting
problem, i.e. impossible.

Another thing not mentioned yet is reflection. Any method might be
called via reflection, and discovering which ones in all cases requires
solving the halting problem.

Here's an example. Trivial static analysis looking for call opcodes
won't find that C is constructed or that its Foo method is called (and
actually, in this case, C.Foo is called statically, not dynamically, due
to runtime generic instantiation in .NET).

---8<---
using System;
class App
{
interface IFoo
{
void Foo();
}
class C : IFoo
{
public void Foo()
{
Console.WriteLine("Foo");
}
}

static void CallFoo<T>()
where T: IFoo, new()
{
new T().Foo();
}

static void Main()
{
CallFoo<C>();
}
}
--->8---

Following IL produced for CallFoo<T>, no C methodref/defs:

---8<---
.method private hidebysig static void CallFoo<.ctor (App/IFoo) T>()
cil managed
{
// Code size 49 (0x31)
.maxstack 2
.locals init (!!T V_0)
IL_0000: nop
IL_0001: ldloca.s V_0
IL_0003: initobj !!T
IL_0009: ldloc.0
IL_000a: box !!T
IL_000f: brfalse.s IL_001c

IL_0011: ldloca.s V_0
IL_0013: initobj !!T
IL_0019: ldloc.0
IL_001a: br.s IL_0021

IL_001c: call !!0
[mscorlib]System.Activator::CreateInstance<!!0>()
IL_0021: stloc.0
IL_0022: ldloca.s V_0
IL_0024: constrained. !!T
IL_002a: callvirt instance void App/IFoo::Foo()
IL_002f: nop
IL_0030: ret
} // end of method App::CallFoo
--->8---

Only type token required for Main method (in executable metadata
tables):

---8<---
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 8 (0x8)
.maxstack 8
IL_0000: nop
IL_0001: call void App::CallFoo<class App/C>()
IL_0006: nop
IL_0007: ret
} // end of method App::Main
--->8---

-- Barry

--
http://barrkel.blogspot.com/


Reply With Quote
  #8  
Old   
kevin
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-26-2007 , 11:16 AM



Ben and Berry and Mattias;
Thanks for your time and responses gentleman. I learned something over
these last couple of days. I hope the holiday (whatever your persuasions)
was good to you and yours.

"Barry Kelly" wrote:
Quote:
He means that if you're using dynamic dispatch with polymorphism (aka
virtual methods), you don't necessarily know at compile time (and thus
in the assembly) which actual method will be called. You don't know this
because you don't know at compile time the actual type of the instance.
Discovering actual type for all instances requires solving the halting
problem, i.e. impossible.
So what was old is new again. Late Binding returns... and after I was made
to feel ashamed about all that VB6 and ASP code!

So in conclusion, I can filter my app to only be concerned with NewObj,
Throw, Call, Calli and Callvirt, but I should understand that I will run into
a few "dead ends".

Kevin


Reply With Quote
  #9  
Old   
Jon Skeet [C# MVP]
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-26-2007 , 11:24 AM



kevin <kevin (AT) discussions (DOT) microsoft.com> wrote:
Quote:
"Barry Kelly" wrote:
He means that if you're using dynamic dispatch with polymorphism (aka
virtual methods), you don't necessarily know at compile time (and thus
in the assembly) which actual method will be called. You don't know this
because you don't know at compile time the actual type of the instance.
Discovering actual type for all instances requires solving the halting
problem, i.e. impossible.

So what was old is new again. Late Binding returns... and after I was made
to feel ashamed about all that VB6 and ASP code!
There's a big difference between "hope that there's a method with this
name at runtime" and "know that there's a method with this name, but
evaluate exactly which implementation to call at runtime".

(Of course, dynamic languages are quite popular these days, but usually
there are additional benefits provided, such as being able to react
different to method calls based on their name if no "real" method is
found.)

--
Jon Skeet - <skeet (AT) pobox (DOT) com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk


Reply With Quote
  #10  
Old   
Ben Voigt [C++ MVP]
 
Posts: n/a

Default Re: which IL OpCodes call a method - 12-26-2007 , 03:38 PM




"kevin" <kevin (AT) discussions (DOT) microsoft.com> wrote

Quote:
Ben and Berry and Mattias;
Thanks for your time and responses gentleman. I learned something over
these last couple of days. I hope the holiday (whatever your persuasions)
was good to you and yours.

"Barry Kelly" wrote:
He means that if you're using dynamic dispatch with polymorphism (aka
virtual methods), you don't necessarily know at compile time (and thus
in the assembly) which actual method will be called. You don't know this
because you don't know at compile time the actual type of the instance.
Discovering actual type for all instances requires solving the halting
problem, i.e. impossible.

So what was old is new again. Late Binding returns... and after I was
made
to feel ashamed about all that VB6 and ASP code!

So in conclusion, I can filter my app to only be concerned with NewObj,
Throw, Call, Calli and Callvirt, but I should understand that I will run
into
a few "dead ends".
You can be assured that those do depend on the type in question, but that
the type may be used other ways that cannot be determined until runtime.

Quote:
Kevin



Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.