Field read and write

55 views
Skip to first unread message

Wee Li Yen

unread,
Jan 7, 2010, 9:04:53 PM1/7/10
to Mono.Cecil
Hi,
 
Anyone knows why

public double PIValue = Math.PI; (with or without static)

is not detected as a field read or write?

 

I need to get PIValue is written and Math.PI is read.

Note that I used opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld to detect written and opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldsflda to detect field write.

 

                if (operand.GetType() == typeof(FieldDefinition))
                {
                    FieldDefinition fd = (FieldDefinition)operand;
                    if (opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld)
                    {
                        readOrWritten = " (is written)";
                    }
                    if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldsflda)
                    {
                        readOrWritten = " (is read)";
                    }
                    Console.WriteLine("\t\t[field(currAsm)_used] " + fd.Name + " (" + opCode + ") " + readOrWritten);
                }
                if (operand.GetType() == typeof(FieldReference))
                {
                    FieldReference fr = (FieldReference)operand;
                    if (opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld)
                    {
                        readOrWritten = " (is written)";                       
                    }
                    if (opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldsflda)
                    {
                        readOrWritten = " (is read)";
                    }

Thanks,

LY

Wee Li Yen

unread,
Jan 7, 2010, 9:09:25 PM1/7/10
to Mono.Cecil
Correction to a typo error below...


 
Hi,
 
Anyone knows why

public double PIValue = Math.PI; (with or without static)

is not detected as a field read or write?

 

I need to get PIValue is written and Math.PI is read.

Note that I used opCode == OpCodes.Stfld || opCode == OpCodes.Stsfld to detect written and opCode == OpCodes.Ldfld || opCode == OpCodes.Ldsfld || opCode == OpCodes.Ldsflda to detect read.

Jb Evain

unread,
Jan 8, 2010, 3:18:44 AM1/8/10
to mono-...@googlegroups.com
Hey,

On 1/8/10, Wee Li Yen <weel...@hotmail.com> wrote:
> public double PIValue = Math.PI; (with or without static)

If you had bothered to look at the definition of Math.PI you would
know. It's defined as follows:

public const double PI = 3.14159265358979323846;

Meaning the compiler will inline its value whenever it's used.

--
Jb Evain <j...@nurv.fr>

Li Yen Wee

unread,
Jan 8, 2010, 4:45:40 AM1/8/10
to Mono.Cecil
But how has it got to do with me not being able to detect the field PIValue as written and Math.PI as read?
Cos i am able to detect that in eclipse.
 
Can you explain it in more details? Thx.

 
> Date: Fri, 8 Jan 2010 09:18:44 +0100
> Subject: Re: [mono-cecil] Field read and write
> From: j...@nurv.fr
> To: mono-...@googlegroups.com

Windows 7: Find the right PC for you. Learn more.

Jb Evain

unread,
Jan 8, 2010, 4:58:42 AM1/8/10
to mono-...@googlegroups.com
2010/1/8 Li Yen Wee <weel...@hotmail.com>:

> But how has it got to do with me not being able to detect the field PIValue
> as written and Math.PI as read?

Again, if you had bothered to investigate a little bit you would know.
PI is defined as a constant, so the compiler will inline its value
everywhere it's used

var pi = Math.PI is compiled as:

ldc.r8 3.1415926535897931
stloc pi

So if you want to detect where PI is used, you have to check for the
`ldc.r8 Math.PI` pattern.

--
Jb Evain <j...@nurv.fr>

Wee Li Yen

unread,
Jan 10, 2010, 7:08:26 AM1/10/10
to mono-...@googlegroups.com
Sorry to bother you on this issue again.

I print out all the instructions from VisitInstruction (BaseCodeVisitor) in
this way:

OpCode opCode = instr.OpCode;
object operand = instr.Operand;
Console.Write("###" + opCode + " " + ((operand != null)?
operand.ToString() : "") + "###");
Console.WriteLine();

But I don't see ldc.r8 Math.PI...

Do you know why? Thanks...


--------------------------------------------------
From: "Jb Evain" <j...@nurv.fr>
Sent: Friday, January 08, 2010 5:58 PM
To: <mono-...@googlegroups.com>


Subject: Re: [mono-cecil] Field read and write

> 2010/1/8 Li Yen Wee <weel...@hotmail.com>:

> --
> --
> mono-cecil

Tommy Carlier

unread,
Jan 10, 2010, 7:21:12 AM1/10/10
to mono-...@googlegroups.com
Because Math.PI is a constant, the compiler will just copy its value to the location of where it's used. So, if your code says "double pi = Math.PI;", the compiler will translate it to "double pi = 3.1415926...;". That's why there are no references to Math.PI.

2010/1/10 Wee Li Yen <weel...@hotmail.com>
--
--
mono-cecil

Wee Li Yen

unread,
Jan 10, 2010, 7:57:52 AM1/10/10
to mono-...@googlegroups.com
Tommy, so what u mean is there is no way I can detect field read and write in this case?
 
But how come Jb said "So if you want to detect where PI is used, you have to check for the `ldc.r8 Math.PI` pattern."? My previous post was trying to say that I can't find this.


--
--
mono-cecil

Tommy Carlier

unread,
Jan 10, 2010, 8:19:49 AM1/10/10
to mono-...@googlegroups.com
That's right. Try this (if you're on Windows): compile an application that references a constant (like Math.PI), and open that compiled application in Reflector. The call the Math.PI will have been replaced by a constant value.

Jb Evain

unread,
Jan 10, 2010, 11:07:44 AM1/10/10
to mono-...@googlegroups.com
On Sun, Jan 10, 2010 at 1:57 PM, Wee Li Yen <weel...@hotmail.com> wrote:
> But how come Jb said "So if you want to detect where PI is used, you have to
> check for the `ldc.r8 Math.PI` pattern."? My previous post was trying to say
> that I can't find this.

ldc.r8 takes a value. What am saying is that you can assume that if
you encounter a ldc.r8 which has a double operand containing the value
of Math.PI, you can assume that it's what you're looking for.

--
Jb Evain <j...@nurv.fr>

Wee Li Yen

unread,
Jan 10, 2010, 11:15:57 AM1/10/10
to mono-...@googlegroups.com
I didn't see any constant PI value. If I hv seen that I would hv noticed that.
 
I am on Windows... What do u mean by "open that compiled application in Reflector"? I never used that before.
 
I am writing an application using Visual Studio. Nothing wrong with my code right?


--
--
mono-cecil

Wee Li Yen

unread,
Jan 10, 2010, 11:18:27 AM1/10/10
to mono-...@googlegroups.com
I didn't encounter that too. Strange...

Doing this (below) in VisitInstruction should have be fine right?

OpCode opCode = instr.OpCode;
object operand = instr.Operand;
Console.Write("###" + opCode + " " + ((operand != null)? operand.ToString()
: "") + "###");
Console.WriteLine();

--------------------------------------------------
From: "Jb Evain" <j...@nurv.fr>
Sent: Monday, January 11, 2010 12:07 AM


To: <mono-...@googlegroups.com>
Subject: Re: [mono-cecil] Field read and write

> On Sun, Jan 10, 2010 at 1:57 PM, Wee Li Yen <weel...@hotmail.com> wrote:

> --
> --
> mono-cecil

Tommy Carlier

unread,
Jan 10, 2010, 11:32:58 AM1/10/10
to mono-...@googlegroups.com
Reflector is a very cool tool that you can use to inspect .NET assemblies. It can decompile IL-code back to C# (at least, it tries to, and a lot of times it doesn't work, but usually it's pretty good at it). I think it's one of the most popular tools for .NET developers.
It's like a more advanced version of ILDasm.

--
--
mono-cecil

Wee Li Yen

unread,
Jan 15, 2010, 5:33:56 AM1/15/10
to mono-...@googlegroups.com
Hi Jb,

I know what u mean now. What u mentioned below "var pi = Math.PI" is a local
variable declaration. I would be able to see the following if I used it as a
variable declaration, but what I meant is I want a field declaration.

> ldc.r8 3.1415926535897931
> stloc pi

Field declaration eg: "public double pi = Math.PI;"

But I can only detect this field when I assign this value to the field in a
method.
If I put it as a field declaration or assign this value to the field in a
ctr, I won't be able to see the above instr.

Is there anyway I can see it even if I put it as a field declaration or
overwrite the field in a ctr?

Hope to hear a reply from you, thanks.
Li Yen


--------------------------------------------------
From: "Jb Evain" <j...@nurv.fr>
Sent: Friday, January 08, 2010 5:58 PM
To: <mono-...@googlegroups.com>

Subject: Re: [mono-cecil] Field read and write

> 2010/1/8 Li Yen Wee <weel...@hotmail.com>:

> --
> --
> mono-cecil

Jb Evain

unread,
Jan 15, 2010, 7:32:41 AM1/15/10
to mono-...@googlegroups.com
Hey,

On Fri, Jan 15, 2010 at 11:33 AM, Wee Li Yen <weel...@hotmail.com> wrote:
> Field declaration eg: "public double pi = Math.PI;"
>
> But I can only detect this field when I assign this value to the field in a
> method.
> If I put it as a field declaration or assign this value to the field in a
> ctr, I won't be able to see the above instr.

You will, it will be assigned in the constructor of the type. You'll
see something like:

ldc.r8 3.14....
stfld pi

--
Jb Evain <j...@nurv.fr>

Wee Li Yen

unread,
Jan 22, 2010, 8:49:28 AM1/22/10
to mono-...@googlegroups.com
Hi Jb,

Sorry for the very late reply, as I was busy with other projects...

I didn't see what u mentioned below when it is assigned in the constructor,
only see it in methods.
Can u double confirm it by testing it out?

Then I realised it may be because I didn't visit constructors... But even
when I visit constructor n try to print out from the VisitConstructor, there
is no difference in the output. Since ctor is actually a mtd, shldn't it
work even I don't visit constructor?

public virtual void VisitConstructorCollection
(ConstructorCollection ctors)
{
foreach (MethodDefinition item in ctors)
{
Console.WriteLine("in ctor of ctors"); //I direct all my
Console.WriteLine() to a file.
item.Accept(this);
}
}
public virtual void VisitConstructor(MethodDefinition ctor)
{
if (ctor.Body != null)
{
Console.WriteLine("in ctor");
ASTCodeVisitor astHelperVisitor = new ASTCodeVisitor();
astHelperVisitor.CurrMethod = ctor.DeclaringType.FullName +
"." + ctor.Name;
ctor.Body.Accept(astHelperVisitor);
}
}


Below is the program I created separately to test this:
The output shows instructions can detect pi2 being assigned in the method
MethodA but not pi1 in the constructor Test.

namespace TestTest
{
class Test
{
public static double pi1;
public static double pi2;

public Test()
{
pi1 = Math.PI;
}

public virtual void MethodA()
{
pi2 = Math.PI;
}

static void Main(string[] args)
{
}
}
}

Here is the output (btn "###" are the instructions detected):

----------------------[assembly] TestTest, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null----------------------
[type_decl] Test
[extends_fr] Object
[method_decl] MethodA
[modifiers] public virtual
###nop ###
###ldc.r8 3.14159265358979###
###stsfld System.Double TestTest.Test::pi2###
[field(currAsm)_used] pi2 (stsfld) (is written)
###ret ###
[return] Void
[method_decl] Main
[modifiers] private static
###nop ###
###ret ###
[return] Void
[parameter] args
[type] String[]
[field_decl] pi1
[modifiers] public static
[type] Double
[field_decl] pi2
[modifiers] public static
[type] Double


Thanks,
LY

--------------------------------------------------
From: "Jb Evain" <j...@nurv.fr>

Sent: Friday, January 15, 2010 8:32 PM


To: <mono-...@googlegroups.com>
Subject: Re: [mono-cecil] Field read and write

> Hey,

> --
> --
> mono-cecil

Wee Li Yen

unread,
Jan 22, 2010, 9:31:18 AM1/22/10
to mono-...@googlegroups.com
Hi,

I know why alr! Careless mistake on my part. My VisitConstructorCollection
and VisitConstructor shld be 'override' not 'virtual'! Cos I copied the
method signature from the docs n forgot to change...

Oh yes! Now those field read n write in declaration, in ctors, and in
methods all can be detected! So initially the problem occurred cos I didn't
visit constructor collection.

Btw, I think VisitConstructor is sort of redundant, since VisitConstructor
accepts a MethodDefintion, so VisitMethodDefinition can do the job of the
VisitConstructor. Cos I managed to print out "in ctor of ctors" but not "in
ctor"...

Thanks,
Li Yen =)

--------------------------------------------------
From: "Wee Li Yen" <weel...@hotmail.com>
Sent: Friday, January 22, 2010 9:49 PM

> --
> --
> mono-cecil
>

Reply all
Reply to author
Forward
0 new messages