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" <arac= [email protected]><br><b>=C3=80: </b>"Remi Forax" <[email protected]>= <br><b>Cc: </b>"asm" <[email protected]><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 <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:"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:"Times New Roman""><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:"Times New Roman""><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 <<a href=3D"mai= lto:[email protected]" target=3D"_blank">[email protected]</a>> 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" <<a href=3D"mailto= :[email protected]" target=3D"_blank">[email protected]</a>><br><b>=C3= =80: </b>"asm" <<a href=3D"mailto:[email protected]" target=3D"_blank">asm@ow2= .org</a>><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. <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--