Re: Learning ASM

[email protected] Wed, 3 Oct 2018 15:09:29 +0200 (CEST)
Newsgroups gmane.comp.java.objectweb.asm
Message-ID <[email protected]>
This is a multi-part message in MIME format...

------------=_1538572703-4637-18
Content-Type: multipart/alternative; 
	boundary="=_b626fb9b-eb50-458f-b02f-af6f713e71f6"

--=_b626fb9b-eb50-458f-b02f-af6f713e71f6
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

> De: "Paul Bell" <[email protected]>
> =C3=80: "Remi Forax" <[email protected]>
> Cc: "asm" <[email protected]>
> Envoy=C3=A9: Mercredi 3 Octobre 2018 12:58:09
> Objet: Re: [asm] Learning ASM

> Hi R=C3=A9mi,

> Thank you for getting back to me about this and apologies for my tardy re=
ply.

> When you say "...if you put a breakpoint in one of the
> MethodVisitor.visit*Insn", are you talking about a breakpoint instruction
> (0xCA, I think)? If so, it's my understanding that, absent a JVMTI agent,=
 or
> the Eclipse debug perspective, this won't work. Please note that I am usi=
ng
> only the -javaagent from the command line, i.e., no Eclipse, no JVMTI age=
nt. It
> would be great if a breakpoint "event" (to use the JVMTI terminology) cou=
ld be
> caught by ASM, but I don't think that's possible (again, I know very litt=
le
> about ASM).

no, i was talking about debugging the code of the agent itself, at least th=
e part that calls ASM.=20

> With respect to intercepting INVOKEVIRTUAL calls, how can my Java agent c=
ode
> obtain the name of the method being called by INVOKEVIRTUAL? This example,
> taken from one of the jasmin pages, shows Java code that calls method "eq=
uals"
> on some object and the resulting bytecode:
> Object x;
>     ...
>     x.equals("hello")

> aload_1       ; push local variable 1 (i.e. 'x') onto stack
>     ldc "hello"   ; push the string "hello" onto stack

>     ; invoke the equals method
>     invokevirtual java/lang/Object/equals(Ljava/lang/Object;)Z
>     ; the boolean result is now on the stack

> How can my Java agent code obtain the 'x' variable (at stack location 1),=
 the
> 'hello' argument (at stack location 0), and the fully-qualified method na=
me
> (java/lang/Object/equals)?

The agent can intercept the bytecode as an array of bytes, then you can use=
 ASM to read the bytecode using the ClassReader, transform it into a ClassW=
riter and regenerate a byte new byte array with the code you want inserted =
whenever you want.=20
An agent has no API to directly influence the bytecode executed by a VM bec=
ause most VMs do consume the bytecode directly but rewrite it to a form tha=
t suit them more.=20

The agent API is in java.lang.instrument=20
https://docs.oracle.com/en/java/javase/11/docs/api/java.instrument/java/lan=
g/instrument/package-summary.html=20

An agent can change the bytecode by registrering a ClassTransformer using=20
[ https://docs.oracle.com/en/java/javase/11/docs/api/java.instrument/java/l=
ang/instrument/Instrumentation.html#addTransformer(java.lang.instrument.Cla=
ssFileTransformer,boolean) | https://docs.oracle.com/en/java/javase/11/docs=
/api/java.instrument/java/lang/instrument/Instrumentation.html#addTransform=
er(java.lang.instrument.ClassFileTransformer,boolean) ]=20

And how to rewrite the bytecode using the a ClassReader ClassVisitor ClassW=
riter is described in the guide, i have linked in my previous message.=20

> Thanks again!
> -Paul

R=C3=A9mi=20

> On Tue, Oct 2, 2018 at 9:16 AM Remi Forax < [ mailto:[email protected] |
> [email protected] ] > wrote:

>> Hi Paul,

>>> De: "Paul Bell" < [ mailto:[email protected] | [email protected] ] >
>>> =C3=80: "asm" < [ mailto:[email protected] | [email protected] ] >
>>> Envoy=C3=A9: Mardi 2 Octobre 2018 14:40:18
>>> Objet: [asm] Learning ASM

>>> Hello,

>>> I am just now learning ASM and this is my first post.

>>> I've cobbled together a working Java agent that uses ASM to modify meth=
ods in
>>> the code I want to trace/debug/monitor. Specifically, I modify static m=
ethods,
>>> instance methods, and constructors. These modifications, inserted at me=
thods'
>>> entry, call into my tracing program.

>>> There's an awful lot I don't know about ASM and I would be grateful for=
 help
>>> with a few things (for now):

>>>    * How can ASM be used to "single step" through program execution? By=
 "single
>>>    step" I mean similar to the Eclipse debug breakpoint facility where =
pressing F5
>>>     allows you to step into the next instruction.

>> ASM do bytecode transformation by transforming the bytecode in a series =
of
>> visitor calls, if you put a breakpoint in one of the MethodVisitor.visit=
*Insn
>> you override, you will see the method been called for each bytecode mana=
ged by
>> this method.

>>>    * How can I "hook" INVOKEVIRTUAL calls? I would like to know when a =
method calls
>>>     another method.

>> override MethodVisitor.visitMethodInsn et check if the opcode is
>> Opcodes.INVOKEVIRTUAL

>>>     * What are "labels" and how are they used?

>> labels are target of gotos, catch blocks, etc.
>> You can create one with new Label(), insert it in the bytecode flow with
>> visitLabel() and use it as parameter of any visit* methods.

>> Eric has written a nice guide that explain how to use ASM and how ASM wo=
rks
>> under the cover,
>> [ https://asm.ow2.io/asm4-guide.pdf | https://asm.ow2.io/asm4-guide.pdf ]

>>> Thanks very much.

>>> -Paul

>> R=C3=A9mi

--=_b626fb9b-eb50-458f-b02f-af6f713e71f6
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<html><body><div style=3D"font-family: arial, helvetica, sans-serif; font-s=
ize: 12pt; color: #000000"><div><br></div><div><br></div><hr id=3D"zwchr" d=
ata-marker=3D"__DIVIDER__"><div data-marker=3D"__HEADERS__"><blockquote sty=
le=3D"border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:=
#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:=
Helvetica,Arial,sans-serif;font-size:12pt;"><b>De: </b>"Paul Bell" &lt;arac=
[email protected]&gt;<br><b>=C3=80: </b>"Remi Forax" &lt;[email protected]&gt;=
<br><b>Cc: </b>"asm" &lt;[email protected]&gt;<br><b>Envoy=C3=A9: </b>Mercredi 3 =
Octobre 2018 12:58:09<br><b>Objet: </b>Re: [asm] Learning ASM<br></blockquo=
te></div><div data-marker=3D"__QUOTED_TEXT__"><blockquote style=3D"border-l=
eft:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weig=
ht:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Aria=
l,sans-serif;font-size:12pt;"><div dir=3D"ltr">Hi&nbsp;

<span style=3D"color:rgb(0,0,0);font-family:arial,helvetica,sans-serif">R=
=C3=A9mi,</span><div><span style=3D"color:rgb(0,0,0);font-family:arial,helv=
etica,sans-serif"><br></span></div><div><span style=3D"color:rgb(0,0,0);fon=
t-family:arial,helvetica,sans-serif">Thank you for getting back to me about=
 this and apologies for my tardy reply.</span></div><div><span style=3D"col=
or:rgb(0,0,0);font-family:arial,helvetica,sans-serif"><br></span></div><div=
><span style=3D"color:rgb(0,0,0);font-family:arial,helvetica,sans-serif">Wh=
en you say "...if you put a <i>breakpoint </i>in one of the MethodVisitor.v=
isit*Insn", are you talking about a breakpoint instruction (0xCA, I think)?=
 If so, it's my understanding that, absent a JVMTI agent, or the Eclipse de=
bug perspective, this won't work. Please note that I am using only the -jav=
aagent from the command line, i.e., no Eclipse, no JVMTI agent. It would be=
 great if a breakpoint "event" (to use the JVMTI terminology) could be caug=
ht by ASM, but I don't think that's possible (again, I know very little abo=
ut ASM).</span></div></div></blockquote><div><br></div><div>no, i was talki=
ng about debugging the code of the agent itself, at least the part that cal=
ls ASM.<br data-mce-bogus=3D"1"></div><div><br data-mce-bogus=3D"1"></div><=
blockquote style=3D"border-left:2px solid #1010FF;margin-left:5px;padding-l=
eft:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:non=
e;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir=3D"ltr">=
<div><span style=3D"color:rgb(0,0,0);font-family:arial,helvetica,sans-serif=
"><br></span></div><div><span style=3D"color:rgb(0,0,0);font-family:arial,h=
elvetica,sans-serif">With respect to intercepting INVOKEVIRTUAL calls, how =
can my Java agent code obtain the name of the method being called by INVOKE=
VIRTUAL? This example, taken from one of the jasmin pages, shows Java code =
that calls method "equals" on some object and the resulting bytecode:</span=
></div><div><b style=3D"color:rgb(0,0,0);font-family:&quot;Times New Roman&=
quot;;font-size:medium"><pre><font size=3D"-1">    Object x;
    ...
    x.equals("hello")</font></pre></b></div><div><span style=3D"color:rgb(0=
,0,0);font-family:arial,helvetica,sans-serif"><br></span></div><div><span s=
tyle=3D"color:rgb(0,0,0)"><pre style=3D"font-weight:bold;font-size:medium;f=
ont-family:&quot;Times New Roman&quot;"><font size=3D"-1">    aload_1      =
 ; push local variable 1 (i.e. 'x') onto stack
    ldc "hello"   ; push the string "hello" onto stack

    ; invoke the equals method
    invokevirtual java/lang/Object/equals(Ljava/lang/Object;)Z
    ; the boolean result is now on the stack</font></pre><pre style=3D"font=
-weight:bold;font-size:medium;font-family:&quot;Times New Roman&quot;"><fon=
t size=3D"-1"><br></font></pre><pre style=3D""><font style=3D"" face=3D"ari=
al, helvetica, sans-serif">How can my Java agent code obtain the 'x' variab=
le (at stack location 1), the 'hello' argument (at stack location 0), and t=
he fully-qualified method name (java/lang/Object/equals)?</font></pre></spa=
n></div></div></blockquote><div><br></div><div>The agent can intercept the =
bytecode as an array of bytes, then you can use ASM to read the bytecode us=
ing the ClassReader, transform it into a ClassWriter and regenerate a byte =
new byte array with the code you want inserted whenever you want.<br data-m=
ce-bogus=3D"1"></div><div>An agent has no API to directly influence the byt=
ecode executed by a VM because most VMs do consume the bytecode directly bu=
t rewrite it to a form that suit them more.<br data-mce-bogus=3D"1"></div><=
div><br data-mce-bogus=3D"1"></div><div>The agent API is in java.lang.instr=
ument<br data-mce-bogus=3D"1"></div><div>https://docs.oracle.com/en/java/ja=
vase/11/docs/api/java.instrument/java/lang/instrument/package-summary.html<=
br data-mce-bogus=3D"1"></div><div><br data-mce-bogus=3D"1"></div><div>An a=
gent can change the bytecode by registrering a ClassTransformer using<br da=
ta-mce-bogus=3D"1"></div><div><a href=3D"https://docs.oracle.com/en/java/ja=
vase/11/docs/api/java.instrument/java/lang/instrument/Instrumentation.html#=
addTransformer(java.lang.instrument.ClassFileTransformer,boolean)">https://=
docs.oracle.com/en/java/javase/11/docs/api/java.instrument/java/lang/instru=
ment/Instrumentation.html#addTransformer(java.lang.instrument.ClassFileTran=
sformer,boolean)</a><br data-mce-bogus=3D"1"></div><div><br data-mce-bogus=
=3D"1"></div><div>And how to rewrite the bytecode using the a ClassReader C=
lassVisitor ClassWriter is described in the guide, i have linked in my prev=
ious message.<br data-mce-bogus=3D"1"></div><div><br data-mce-bogus=3D"1"><=
/div><blockquote style=3D"border-left:2px solid #1010FF;margin-left:5px;pad=
ding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decorati=
on:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><div dir=3D=
"ltr"><div><span style=3D"color:rgb(0,0,0)"><pre style=3D""><font style=3D"=
" face=3D"arial, helvetica, sans-serif">Thanks again!</font></pre><pre styl=
e=3D""><font style=3D"" face=3D"arial, helvetica, sans-serif">-Paul</font><=
/pre></span></div></div></blockquote><div><br></div><div>R=C3=A9mi<br data-=
mce-bogus=3D"1"></div><div><br data-mce-bogus=3D"1"></div><blockquote style=
=3D"border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#0=
00;font-weight:normal;font-style:normal;text-decoration:none;font-family:He=
lvetica,Arial,sans-serif;font-size:12pt;"><br><div class=3D"gmail_quote"><d=
iv dir=3D"ltr">On Tue, Oct 2, 2018 at 9:16 AM Remi Forax &lt;<a href=3D"mai=
lto:[email protected]" target=3D"_blank">[email protected]</a>&gt; wrote:<b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div><div style=3D"font-family:arial=
,helvetica,sans-serif;font-size:12pt;color:#000000"><div>Hi Paul,<br></div>=
<br><hr id=3D"m_-8970503987493700044zwchr"><div><blockquote style=3D"border=
-left:2px solid #1010ff;margin-left:5px;padding-left:5px;color:#000;font-we=
ight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Ar=
ial,sans-serif;font-size:12pt"><b>De: </b>"Paul Bell" &lt;<a href=3D"mailto=
:[email protected]" target=3D"_blank">[email protected]</a>&gt;<br><b>=C3=
=80: </b>"asm" &lt;<a href=3D"mailto:[email protected]" target=3D"_blank">asm@ow2=
.org</a>&gt;<br><b>Envoy=C3=A9: </b>Mardi 2 Octobre 2018 14:40:18<br><b>Obj=
et: </b>[asm] Learning ASM<br></blockquote></div><div><blockquote style=3D"=
border-left:2px solid #1010ff;margin-left:5px;padding-left:5px;color:#000;f=
ont-weight:normal;font-style:normal;text-decoration:none;font-family:Helvet=
ica,Arial,sans-serif;font-size:12pt"><div dir=3D"ltr"><div dir=3D"ltr">Hell=
o,<br></div><br><div>I am just now learning ASM and this is my first post.<=
/div><br><div>I've cobbled together a working Java agent that uses ASM to m=
odify methods in the code I want to trace/debug/monitor. Specifically, I mo=
dify static methods, instance methods, and constructors. These modification=
s, inserted at methods' entry, call into my tracing program.</div><br><div>=
There's an awful lot I don't know about ASM and I would be grateful for hel=
p with a few things (for now):</div><div><ul><li>How can ASM be used to "si=
ngle step" through program execution? By "single step" I mean similar to th=
e Eclipse debug breakpoint facility where pressing F5 allows you to step in=
to the next instruction.</li></ul></div></div></blockquote><br><div>ASM do =
bytecode transformation by transforming the bytecode in a series of visitor=
 calls, if you put a breakpoint in one of the MethodVisitor.visit*Insn you =
override, you will see the method been called for each bytecode managed by =
this method.&nbsp; <br></div><br><blockquote style=3D"border-left:2px solid=
 #1010ff;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;fon=
t-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;=
font-size:12pt"><div dir=3D"ltr"><div><ul><li>How can I "hook" INVOKEVIRTUA=
L calls? I would like to know when a method calls another method.</li></ul>=
</div></div></blockquote><br><div>override MethodVisitor.visitMethodInsn et=
 check if the opcode is Opcodes.INVOKEVIRTUAL<br></div><br><blockquote styl=
e=3D"border-left:2px solid #1010ff;margin-left:5px;padding-left:5px;color:#=
000;font-weight:normal;font-style:normal;text-decoration:none;font-family:H=
elvetica,Arial,sans-serif;font-size:12pt"><div dir=3D"ltr"><div><ul><li>Wha=
t are "labels" and how are they used?</li></ul></div></div></blockquote><br=
><div>labels are target of gotos, catch blocks, etc.<br></div><div>You can =
create one with new Label(), insert it in the bytecode flow with visitLabel=
() and use it as parameter of any visit* methods.<br></div><br><div>Eric ha=
s written a nice guide that explain how to use ASM and how ASM works under =
the cover,<br></div><div><a href=3D"https://asm.ow2.io/asm4-guide.pdf" targ=
et=3D"_blank">https://asm.ow2.io/asm4-guide.pdf</a><br></div><br><br><block=
quote style=3D"border-left:2px solid #1010ff;margin-left:5px;padding-left:5=
px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;fon=
t-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir=3D"ltr"><div>T=
hanks very much.</div><br><div>-Paul</div></div></blockquote><br><div>R=C3=
=A9mi<br></div><br>
</div></div></div></blockquote></div><br></blockquote></div></div></body></=
html>=

--=_b626fb9b-eb50-458f-b02f-af6f713e71f6--

------------=_1538572703-4637-18
Content-Type: text/plain; charset="UTF-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit


-- 
You receive this message as a subscriber of the [email protected] mailing list.
To unsubscribe: mailto:[email protected]
For general help: mailto:[email protected]?subject=help
OW2 mailing lists service home page: http://www.ow2.org/wws

------------=_1538572703-4637-18--