709cc5a031c5306283ca66d91c55df1fae806762
[cacao.git] / src / vm / jit / i386 / patcher.c
1 /* src/vm/jit/i386/patcher.c - i386 code patching functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: patcher.c 8295 2007-08-11 17:57:24Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdint.h>
33
34 #include "vm/types.h"
35
36 #include "vm/jit/i386/codegen.h"
37
38 #include "mm/memory.h"
39
40 #include "native/native.h"
41
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
45
46 #include "vm/jit/patcher.h"
47 #include "vm/jit/stacktrace.h"
48
49 #include "vmcore/class.h"
50 #include "vmcore/field.h"
51 #include "vmcore/options.h"
52 #include "vm/resolve.h"
53 #include "vmcore/references.h"
54
55
56 /* patcher_wrapper *************************************************************
57
58    Wrapper for all patchers.  It also creates the stackframe info
59    structure.
60
61    If the return value of the patcher function is false, it gets the
62    exception object, clears the exception pointer and returns the
63    exception.
64
65 *******************************************************************************/
66
67 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
68 {
69         stackframeinfo     sfi;
70         u1                *xpc;
71         java_object_t     *o;
72         functionptr        f;
73         bool               result;
74         java_handle_t     *e;
75
76         /* define the patcher function */
77
78         bool (*patcher_function)(u1 *);
79
80         /* get stuff from the stack */
81
82         xpc = (u1 *)                *((ptrint *) (sp + 6 * 4));
83         o   = (java_object_t *)     *((ptrint *) (sp + 4 * 4));
84         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
85
86         /* calculate and set the new return address */
87
88         xpc = xpc - PATCHER_CALL_SIZE;
89
90         *((ptrint *) (sp + 6 * 4)) = (ptrint) xpc;
91
92         /* cast the passed function to a patcher function */
93
94         patcher_function = (bool (*)(u1 *)) (ptrint) f;
95
96         /* enter a monitor on the patching position */
97
98         PATCHER_MONITORENTER;
99
100         /* create the stackframeinfo */
101
102         /* RA is passed as NULL, but the XPC is correct and can be used in
103            stacktrace_create_extern_stackframeinfo for
104            md_codegen_get_pv_from_pc. */
105
106         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 7 * 4, xpc, xpc);
107
108         /* call the proper patcher function */
109
110         result = (patcher_function)(sp);
111
112         /* remove the stackframeinfo */
113
114         stacktrace_remove_stackframeinfo(&sfi);
115
116         /* check for return value and exit accordingly */
117
118         if (result == false) {
119                 e = exceptions_get_and_clear_exception();
120
121                 PATCHER_MONITOREXIT;
122
123                 return e;
124         }
125
126         PATCHER_MARK_PATCHED_MONITOREXIT;
127
128         return NULL;
129 }
130
131
132 /* patcher_get_putstatic *******************************************************
133
134    Machine code:
135
136    <patched call position>
137    b8 00 00 00 00             mov    $0x00000000,%eax
138
139 *******************************************************************************/
140
141 bool patcher_get_putstatic(u1 *sp)
142 {
143         u1               *ra;
144         u8                mcode;
145         unresolved_field *uf;
146         fieldinfo        *fi;
147
148         /* get stuff from the stack */
149
150         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
151         mcode =                      *((u8 *)     (sp + 2 * 4));
152         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
153
154         /* get the fieldinfo */
155
156         if (!(fi = resolve_field_eager(uf)))
157                 return false;
158
159         /* check if the field's class is initialized */
160
161         if (!(fi->class->state & CLASS_INITIALIZED))
162                 if (!initialize_class(fi->class))
163                         return false;
164
165         /* patch back original code */
166
167         *((u4 *) (ra + 0)) = (u4) mcode;
168         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
169
170         /* if we show disassembly, we have to skip the nop's */
171
172         if (opt_shownops)
173                 ra = ra + 5;
174
175         /* patch the field value's address */
176
177         *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
178
179         return true;
180 }
181
182
183 /* patcher_getfield ************************************************************
184
185    Machine code:
186
187    <patched call position>
188    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
189
190 *******************************************************************************/
191
192 bool patcher_getfield(u1 *sp)
193 {
194         u1               *ra;
195         u8                mcode;
196         unresolved_field *uf;
197         fieldinfo        *fi;
198
199         /* get stuff from the stack */
200
201         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
202         mcode =                      *((u8 *)     (sp + 2 * 4));
203         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
204
205         /* get the fieldinfo */
206
207         if (!(fi = resolve_field_eager(uf)))
208                 return false;
209
210         /* patch back original code */
211
212         *((u4 *) (ra + 0)) = (u4) mcode;
213         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
214
215         /* if we show disassembly, we have to skip the nop's */
216
217         if (opt_shownops)
218                 ra = ra + 5;
219
220         /* patch the field's offset */
221
222         *((u4 *) (ra + 2)) = (u4) (fi->offset);
223
224         /* if the field has type long, we need to patch the second move too */
225
226         if (fi->type == TYPE_LNG)
227                 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
228
229         return true;
230 }
231
232
233 /* patcher_putfield ************************************************************
234
235    Machine code:
236
237    <patched call position>
238    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
239
240 *******************************************************************************/
241
242 bool patcher_putfield(u1 *sp)
243 {
244         u1               *ra;
245         u8                mcode;
246         unresolved_field *uf;
247         fieldinfo        *fi;
248
249         /* get stuff from the stack */
250
251         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
252         mcode =                      *((u8 *)     (sp + 2 * 4));
253         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
254
255         /* get the fieldinfo */
256
257         if (!(fi = resolve_field_eager(uf)))
258                 return false;
259
260         /* patch back original code */
261
262         *((u4 *) (ra + 0)) = (u4) mcode;
263         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
264
265         /* if we show disassembly, we have to skip the nop's */
266
267         if (opt_shownops)
268                 ra = ra + 5;
269
270         /* patch the field's offset */
271
272         if (fi->type != TYPE_LNG) {
273                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
274         }
275         else {
276                 /* The long code is special:
277                  *
278                  * 89 8d 00 00 00 00          mov    %ecx,0x00000000(%ebp)
279                  * 89 95 00 00 00 00          mov    %edx,0x00000000(%ebp)
280                  */
281
282                 *((u4 *) (ra + 2))     = (u4) (fi->offset);
283                 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
284         }
285
286         return true;
287 }
288
289
290 /* patcher_putfieldconst *******************************************************
291
292    Machine code:
293
294    <patched call position>
295    c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%ebp)
296
297 *******************************************************************************/
298
299 bool patcher_putfieldconst(u1 *sp)
300 {
301         u1               *ra;
302         u8                mcode;
303         unresolved_field *uf;
304         fieldinfo        *fi;
305
306         /* get stuff from the stack */
307
308         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
309         mcode =                      *((u8 *)     (sp + 2 * 4));
310         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
311
312         /* get the fieldinfo */
313
314         if (!(fi = resolve_field_eager(uf)))
315                 return false;
316
317         /* patch back original code */
318
319         *((u4 *) (ra + 0)) = (u4) mcode;
320         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
321
322         /* if we show disassembly, we have to skip the nop's */
323
324         if (opt_shownops)
325                 ra = ra + 5;
326
327         /* patch the field's offset */
328
329         if (!IS_2_WORD_TYPE(fi->type)) {
330                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
331         }
332         else {
333                 /* long/double code is different:
334                  *
335                  * c7 80 00 00 00 00 c8 01 00 00    movl   $0x1c8,0x0(%eax)
336                  * c7 80 04 00 00 00 00 00 00 00    movl   $0x0,0x4(%eax)
337                  */
338
339                 *((u4 *) (ra + 2))      = (u4) (fi->offset);
340                 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
341         }
342
343         return true;
344 }
345
346
347 /* patcher_aconst **************************************************************
348
349    Machine code:
350
351    <patched call postition>
352    c7 04 24 00 00 00 00       movl   $0x0000000,(%esp)
353    b8 00 00 00 00             mov    $0x0000000,%eax
354
355 *******************************************************************************/
356
357 bool patcher_aconst(u1 *sp)
358 {
359         u1                *ra;
360         u8                 mcode;
361         constant_classref *cr;
362         classinfo         *c;
363
364         /* get stuff from the stack */
365
366         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
367         mcode =                       *((u8 *)     (sp + 2 * 4));
368         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
369
370         /* get the classinfo */
371
372         if (!(c = resolve_classref_eager(cr)))
373                 return false;
374
375         /* patch back original code */
376
377         *((u4 *) (ra + 0)) = (u4) mcode;
378         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
379
380         /* if we show disassembly, we have to skip the nop's */
381
382         if (opt_shownops)
383                 ra = ra + 5;
384
385         /* patch the classinfo pointer */
386
387         *((ptrint *) (ra + 1)) = (ptrint) c;
388
389         return true;
390 }
391
392
393 /* patcher_builtin_multianewarray **********************************************
394
395    Machine code:
396
397    <patched call position>
398    c7 04 24 02 00 00 00       movl   $0x2,(%esp)
399    c7 44 24 04 00 00 00 00    movl   $0x00000000,0x4(%esp)
400    89 e0                      mov    %esp,%eax
401    83 c0 0c                   add    $0xc,%eax
402    89 44 24 08                mov    %eax,0x8(%esp)
403    b8 00 00 00 00             mov    $0x00000000,%eax
404    ff d0                      call   *%eax
405
406 *******************************************************************************/
407
408 bool patcher_builtin_multianewarray(u1 *sp)
409 {
410         u1                *ra;
411         u8                 mcode;
412         constant_classref *cr;
413         classinfo         *c;
414
415         /* get stuff from the stack */
416
417         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
418         mcode =                       *((u8 *)     (sp + 2 * 4));
419         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
420
421         /* get the classinfo */
422
423         if (!(c = resolve_classref_eager(cr)))
424                 return false;
425
426         /* patch back original code */
427
428         *((u4 *) (ra + 0)) = (u4) mcode;
429         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
430
431         /* if we show disassembly, we have to skip the nop's */
432
433         if (opt_shownops)
434                 ra = ra + 5;
435
436         /* patch the classinfo pointer */
437
438         *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
439
440         return true;
441 }
442
443
444 /* patcher_builtin_arraycheckcast **********************************************
445
446    Machine code:
447
448    <patched call position>
449    c7 44 24 04 00 00 00 00    movl   $0x00000000,0x4(%esp)
450    ba 00 00 00 00             mov    $0x00000000,%edx
451    ff d2                      call   *%edx
452
453 *******************************************************************************/
454
455 bool patcher_builtin_arraycheckcast(u1 *sp)
456 {
457         u1                *ra;
458         u8                 mcode;
459         constant_classref *cr;
460         classinfo         *c;
461
462         /* get stuff from the stack */
463
464         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
465         mcode =                       *((u8 *)     (sp + 2 * 4));
466         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
467
468         /* get the classinfo */
469
470         if (!(c = resolve_classref_eager(cr)))
471                 return false;
472
473         /* patch back original code */
474
475         *((u4 *) (ra + 0)) = (u4) mcode;
476         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
477
478         /* if we show disassembly, we have to skip the nop's */
479
480         if (opt_shownops)
481                 ra = ra + 5;
482
483         /* patch the classinfo pointer */
484
485         *((ptrint *) (ra + 4)) = (ptrint) c;
486
487         /* patch new function address */
488
489         *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
490
491         return true;
492 }
493
494
495 /* patcher_invokestatic_special ************************************************
496
497    Machine code:
498
499    <patched call position>
500    b9 00 00 00 00             mov    $0x00000000,%ecx
501    ff d1                      call   *%ecx
502
503 *******************************************************************************/
504
505 bool patcher_invokestatic_special(u1 *sp)
506 {
507         u1                *ra;
508         u8                 mcode;
509         unresolved_method *um;
510         methodinfo        *m;
511
512         /* get stuff from the stack */
513
514         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
515         mcode =                       *((u8 *)     (sp + 2 * 4));
516         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
517
518         /* get the fieldinfo */
519
520         if (!(m = resolve_method_eager(um)))
521                 return false;
522
523         /* patch back original code */
524
525         *((u4 *) (ra + 0)) = (u4) mcode;
526         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
527
528         /* if we show disassembly, we have to skip the nop's */
529
530         if (opt_shownops)
531                 ra = ra + 5;
532
533         /* patch stubroutine */
534
535         *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
536
537         return true;
538 }
539
540
541 /* patcher_invokevirtual *******************************************************
542
543    Machine code:
544
545    <patched call position>
546    8b 08                      mov    (%eax),%ecx
547    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
548    ff d0                      call   *%eax
549
550 *******************************************************************************/
551
552 bool patcher_invokevirtual(u1 *sp)
553 {
554         u1                *ra;
555         u8                 mcode;
556         unresolved_method *um;
557         methodinfo        *m;
558
559         /* get stuff from the stack */
560
561         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
562         mcode =                       *((u8 *)     (sp + 2 * 4));
563         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
564
565         /* get the fieldinfo */
566
567         if (!(m = resolve_method_eager(um)))
568                 return false;
569
570         /* patch back original code */
571
572         *((u4 *) (ra + 0)) = (u4) mcode;
573         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
574
575         /* if we show disassembly, we have to skip the nop's */
576
577         if (opt_shownops)
578                 ra = ra + 5;
579
580         /* patch vftbl index */
581
582         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
583                                                                    sizeof(methodptr) * m->vftblindex);
584
585         return true;
586 }
587
588
589 /* patcher_invokeinterface *****************************************************
590
591    Machine code:
592
593    <patched call position>
594    8b 00                      mov    (%eax),%eax
595    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
596    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
597    ff d0                      call   *%eax
598
599 *******************************************************************************/
600
601 bool patcher_invokeinterface(u1 *sp)
602 {
603         u1                *ra;
604         u8                 mcode;
605         unresolved_method *um;
606         methodinfo        *m;
607
608         /* get stuff from the stack */
609
610         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
611         mcode =                       *((u8 *)     (sp + 2 * 4));
612         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
613
614         /* get the fieldinfo */
615
616         if (!(m = resolve_method_eager(um)))
617                 return false;
618
619         /* patch back original code */
620
621         *((u4 *) (ra + 0)) = (u4) mcode;
622         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
623
624         /* if we show disassembly, we have to skip the nop's */
625
626         if (opt_shownops)
627                 ra = ra + 5;
628
629         /* patch interfacetable index */
630
631         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
632                                                                    sizeof(methodptr) * m->class->index);
633
634         /* patch method offset */
635
636         *((s4 *) (ra + 2 + 6 + 2)) =
637                 (s4) (sizeof(methodptr) * (m - m->class->methods));
638
639         return true;
640 }
641
642
643 /* patcher_checkcast_instanceof_flags ******************************************
644
645    Machine code:
646
647    <patched call position>
648    b9 00 00 00 00             mov    $0x00000000,%ecx
649
650 *******************************************************************************/
651
652 bool patcher_checkcast_instanceof_flags(u1 *sp)
653 {
654         u1                *ra;
655         u8                 mcode;
656         constant_classref *cr;
657         classinfo         *c;
658
659         /* get stuff from the stack */
660
661         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
662         mcode =                       *((u8 *)     (sp + 2 * 4));
663         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
664
665         /* get the fieldinfo */
666
667         if (!(c = resolve_classref_eager(cr)))
668                 return false;
669
670         /* patch back original code */
671
672         *((u4 *) (ra + 0)) = (u4) mcode;
673         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
674
675         /* if we show disassembly, we have to skip the nop's */
676
677         if (opt_shownops)
678                 ra = ra + 5;
679
680         /* patch class flags */
681
682         *((s4 *) (ra + 1)) = (s4) c->flags;
683
684         return true;
685 }
686
687
688 /* patcher_checkcast_interface *************************************************
689
690    Machine code:
691
692    <patched call position>
693    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
694    81 ea 00 00 00 00          sub    $0x00000000,%edx
695    85 d2                      test   %edx,%edx
696    0f 8f 06 00 00 00          jg     0x00000000
697    8b 35 03 00 00 00          mov    0x3,%esi
698    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
699
700 *******************************************************************************/
701
702 bool patcher_checkcast_interface(u1 *sp)
703 {
704         u1                *ra;
705         u8                 mcode;
706         constant_classref *cr;
707         classinfo         *c;
708
709         /* get stuff from the stack */
710
711         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
712         mcode =                       *((u8 *)     (sp + 2 * 4));
713         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
714
715         /* get the fieldinfo */
716
717         if (!(c = resolve_classref_eager(cr)))
718                 return false;
719
720         /* patch back original code */
721
722         *((u4 *) (ra + 0)) = (u4) mcode;
723         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
724
725         /* if we show disassembly, we have to skip the nop's */
726
727         if (opt_shownops)
728                 ra = ra + 5;
729
730         /* patch super class index */
731
732         *((s4 *) (ra + 6 + 2)) = (s4) c->index;
733
734         *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
735                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
736                           c->index * sizeof(methodptr*));
737
738         return true;
739 }
740
741
742 /* patcher_instanceof_interface ************************************************
743
744    Machine code:
745
746    <patched call position>
747    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
748    81 ea 00 00 00 00          sub    $0x00000000,%edx
749    85 d2                      test   %edx,%edx
750    0f 8e 13 00 00 00          jle    0x00000000
751    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
752
753 *******************************************************************************/
754
755 bool patcher_instanceof_interface(u1 *sp)
756 {
757         u1                *ra;
758         u8                 mcode;
759         constant_classref *cr;
760         classinfo         *c;
761
762         /* get stuff from the stack */
763
764         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
765         mcode =                       *((u8 *)     (sp + 2 * 4));
766         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
767
768         /* get the fieldinfo */
769
770         if (!(c = resolve_classref_eager(cr)))
771                 return false;
772
773         /* patch back original code */
774
775         *((u4 *) (ra + 0)) = (u4) mcode;
776         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
777
778         /* if we show disassembly, we have to skip the nop's */
779
780         if (opt_shownops)
781                 ra = ra + 5;
782
783         /* patch super class index */
784
785         *((s4 *) (ra + 6 + 2)) = (s4) c->index;
786
787         *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
788                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
789                           c->index * sizeof(methodptr*));
790
791         return true;
792 }
793
794
795 /* patcher_checkcast_class *****************************************************
796
797    Machine code:
798
799    <patched call position>
800    ba 00 00 00 00             mov    $0x00000000,%edx
801    8b 89 00 00 00 00          mov    0x00000000(%ecx),%ecx
802    8b 92 00 00 00 00          mov    0x00000000(%edx),%edx
803    29 d1                      sub    %edx,%ecx
804    ba 00 00 00 00             mov    $0x00000000,%edx
805
806 *******************************************************************************/
807
808 bool patcher_checkcast_class(u1 *sp)
809 {
810         u1                *ra;
811         u8                 mcode;
812         constant_classref *cr;
813         classinfo         *c;
814
815         /* get stuff from the stack */
816
817         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
818         mcode =                       *((u8 *)     (sp + 2 * 4));
819         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
820
821         /* get the fieldinfo */
822
823         if (!(c = resolve_classref_eager(cr)))
824                 return false;
825
826         /* patch back original code */
827
828         *((u4 *) (ra + 0)) = (u4) mcode;
829         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
830
831         /* if we show disassembly, we have to skip the nop's */
832
833         if (opt_shownops)
834                 ra = ra + 5;
835
836         /* patch super class' vftbl */
837
838         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
839         *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
840
841         return true;
842 }
843
844
845 /* patcher_instanceof_class ****************************************************
846
847    Machine code:
848
849    <patched call position>
850    b9 00 00 00 00             mov    $0x0,%ecx
851    8b 40 14                   mov    0x14(%eax),%eax
852    8b 51 18                   mov    0x18(%ecx),%edx
853    8b 49 14                   mov    0x14(%ecx),%ecx
854
855 *******************************************************************************/
856
857 bool patcher_instanceof_class(u1 *sp)
858 {
859         u1                *ra;
860         u8                 mcode;
861         constant_classref *cr;
862         classinfo         *c;
863
864         /* get stuff from the stack */
865
866         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
867         mcode =                       *((u8 *)     (sp + 2 * 4));
868         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
869
870         /* get the fieldinfo */
871
872         if (!(c = resolve_classref_eager(cr)))
873                 return false;
874
875         /* patch back original code */
876
877         *((u4 *) (ra + 0)) = (u4) mcode;
878         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
879
880         /* if we show disassembly, we have to skip the nop's */
881
882         if (opt_shownops)
883                 ra = ra + 5;
884
885         /* patch super class' vftbl */
886
887         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
888
889         return true;
890 }
891
892
893 /* patcher_clinit **************************************************************
894
895    Is used int PUT/GETSTATIC and native stub.
896
897    Machine code:
898
899    <patched call position>
900
901 *******************************************************************************/
902
903 bool patcher_clinit(u1 *sp)
904 {
905         u1        *ra;
906         u8         mcode;
907         classinfo *c;
908
909         /* get stuff from the stack */
910
911         ra    = (u1 *)        *((ptrint *) (sp + 6 * 4));
912         mcode =               *((u8 *)     (sp + 2 * 4));
913         c     = (classinfo *) *((ptrint *) (sp + 1 * 4));
914
915         /* check if the class is initialized */
916
917         if (!(c->state & CLASS_INITIALIZED))
918                 if (!initialize_class(c))
919                         return false;
920
921         /* patch back original code */
922
923         *((u4 *) (ra + 0)) = (u4) mcode;
924         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
925
926         return true;
927 }
928
929
930 /* patcher_athrow_areturn ******************************************************
931
932    Machine code:
933
934    <patched call position>
935
936 *******************************************************************************/
937
938 #ifdef ENABLE_VERIFIER
939 bool patcher_athrow_areturn(u1 *sp)
940 {
941         u1               *ra;
942         u8                mcode;
943         unresolved_class *uc;
944
945         /* get stuff from the stack */
946
947         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
948         mcode =                      *((u8 *)     (sp + 2 * 4));
949         uc    = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
950
951         /* resolve the class and check subtype constraints */
952
953         if (!resolve_class_eager_no_access_check(uc))
954                 return false;
955
956         /* patch back original code */
957
958         *((u4 *) (ra + 0)) = (u4) mcode;
959         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
960
961         return true;
962 }
963 #endif /* ENABLE_VERIFIER */
964
965
966 /* patcher_resolve_native ******************************************************
967
968    Is used in native stub.
969
970    Machine code:
971
972    <patched call position>
973    c7 44 24 04 28 90 01 40    movl   $0x40019028,0x4(%esp)
974
975 *******************************************************************************/
976
977 #if !defined(WITH_STATIC_CLASSPATH)
978 bool patcher_resolve_native(u1 *sp)
979 {
980         u1          *ra;
981         u8           mcode;
982         methodinfo  *m;
983         functionptr  f;
984
985         /* get stuff from the stack */
986
987         ra    = (u1 *)         *((ptrint *) (sp + 6 * 4));
988         mcode =                *((u8 *)     (sp + 2 * 4));
989         m     = (methodinfo *) *((ptrint *) (sp + 1 * 4));
990
991         /* resolve native function */
992
993         if (!(f = native_resolve_function(m)))
994                 return false;
995
996         /* patch back original code */
997
998         *((u4 *) (ra + 0)) = (u4) mcode;
999         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1000
1001         /* if we show disassembly, we have to skip the nop's */
1002
1003         if (opt_shownops)
1004                 ra = ra + 5;
1005
1006         /* patch native function pointer */
1007
1008         *((ptrint *) (ra + 4)) = (ptrint) f;
1009
1010         return true;
1011 }
1012 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1013
1014
1015 /*
1016  * These are local overrides for various environment variables in Emacs.
1017  * Please do not remove this and leave it at the end of the file, where
1018  * Emacs will automagically detect them.
1019  * ---------------------------------------------------------------------
1020  * Local variables:
1021  * mode: c
1022  * indent-tabs-mode: t
1023  * c-basic-offset: 4
1024  * tab-width: 4
1025  * End:
1026  * vim:noexpandtab:sw=4:ts=4:
1027  */