Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / December 2007

Tip: Looking for answers? Try searching our database.

which IL OpCodes call a method

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
kevin - 20 Dec 2007 22:19 GMT
...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

Signature

kevin...

Barry Kelly - 21 Dec 2007 10:10 GMT
> ...using framework 1.0 / 1.1/ 2.0, Mono.Cecil library for introspection
>
[quoted text clipped - 5 lines]
> 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/publications/standards/Ecma-335.htm

-- Barry

Signature

http://barrkel.blogspot.com/

kevin - 21 Dec 2007 15:16 GMT
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)
Signature

kevin...

> > ...using framework 1.0 / 1.1/ 2.0, Mono.Cecil library for introspection
> >
[quoted text clipped - 29 lines]
>
> -- Barry
Mattias Sjögren - 21 Dec 2007 18:02 GMT
>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:

If you just want to know which assemblies are being used it would be a
lot easier to look at the assemblyref table.

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

Signature

Mattias Sjögren [C# MVP]  mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

kevin - 21 Dec 2007 20:16 GMT
> 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
Ben Voigt [C++ MVP] - 24 Dec 2007 19:27 GMT
>> 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
[quoted text clipped - 5 lines]
> 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.

> Thanks.
>
> Kevin
kevin - 24 Dec 2007 21:58 GMT
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
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

********************
Barry Kelly - 25 Dec 2007 00:19 GMT
> 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

Signature

http://barrkel.blogspot.com/

kevin - 26 Dec 2007 16:16 GMT
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.

> 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
Jon Skeet [C# MVP] - 26 Dec 2007 16:24 GMT
> > He means that if you're using dynamic dispatch with polymorphism (aka
> > virtual methods), you don't necessarily know at compile time (and thus
[quoted text clipped - 5 lines]
> 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.)

Signature

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

Ben Voigt [C++ MVP] - 26 Dec 2007 20:38 GMT
> Ben and Berry and Mattias;
> Thanks for your time and responses gentleman.  I learned something over
[quoted text clipped - 16 lines]
> 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.

> Kevin

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.