* patcher_get_putfield: only patch back 5-bytes, since the instruction is
[cacao.git] / src / vm / jit / x86_64 / patcher.c
1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 2779 2005-06-22 10:28:54Z twisti $
32
33 */
34
35
36 #include "vm/jit/x86_64/types.h"
37
38 #include "mm/memory.h"
39 #include "native/native.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/field.h"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/references.h"
46 #include "vm/jit/helper.h"
47 #include "vm/jit/patcher.h"
48
49
50 bool helper_initialize_class(void* beginOfJavaStack,classinfo *c,u1 *ra)
51 {
52         if (!c->initialized) {
53                 native_stackframeinfo sfi;
54                 bool init;
55
56                 /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
57                 sfi.returnToFromNative = (functionptr) (ptrint) ra;
58                 sfi.beginOfJavaStackframe = beginOfJavaStack;
59                 sfi.method = NULL; /*internal*/
60                 sfi.addressOfThreadspecificHead = builtin_asm_get_stackframeinfo();
61                 sfi.oldThreadspecificHeadValue = *(sfi.addressOfThreadspecificHead);
62                 *(sfi.addressOfThreadspecificHead) = &sfi;
63
64                 /*printf("calling static initializer (helper_initialize_class), returnaddress=%p for class %s\n",ra,c->name->text);*/
65
66                 init=initialize_class(c);
67
68                 *(sfi.addressOfThreadspecificHead) = sfi.oldThreadspecificHeadValue;
69
70                 return init;
71         }
72
73         return true;
74 }
75
76
77
78 /* patcher_get_putstatic *******************************************************
79
80    Machine code:
81
82    <patched call position>
83    4d 8b 15 86 fe ff ff             mov    -378(%rip),%r10
84    49 8b 32                         mov    (%r10),%rsi
85
86 *******************************************************************************/
87
88 bool patcher_get_putstatic(u1 *sp)
89 {
90         u1                *ra;
91         java_objectheader *o;
92         u8                 mcode;
93         unresolved_field  *uf;
94         fieldinfo         *fi;
95         s4                 offset;
96         void              *beginJavaStack;
97
98         /* get stuff from the stack */
99
100         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
101         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
102         mcode =                       *((u8 *)     (sp + 1 * 8));
103         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 8));
104
105         beginJavaStack=              (void*)(sp + 3 * 8);
106
107         /* calculate and set the new return address */
108
109         ra = ra - 5;
110         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
111
112         PATCHER_MONITORENTER;
113
114         /* get the fieldinfo */
115
116         if (!(fi = helper_resolve_fieldinfo(uf))) {
117                 PATCHER_MONITOREXIT;
118
119                 return false;
120         }
121
122         /* check if the field's class is initialized */
123
124         if (!helper_initialize_class(beginJavaStack, fi->class, ra + 5)) {
125                 PATCHER_MONITOREXIT;
126
127                 return false;
128         }
129
130         /* patch back original code */
131
132         *((u8 *) ra) = mcode;
133
134         /* if we show disassembly, we have to skip the nop's */
135
136         if (showdisassemble)
137                 ra = ra + 5;
138
139         /* get RIP offset from machine instruction */
140
141         offset = *((u4 *) (ra + 3));
142
143         /* patch the field value's address (+ 7: is the size of the RIP move) */
144
145         *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
146
147         PATCHER_MARK_PATCHED_MONITOREXIT;
148
149         return true;
150 }
151
152
153 /* patcher_get_putfield ********************************************************
154
155    Machine code:
156
157    <patched call position>
158    45 8b 8f 00 00 00 00             mov    0x0(%r15),%r9d
159
160 *******************************************************************************/
161
162 bool patcher_get_putfield(u1 *sp)
163 {
164         u1                *ra;
165         java_objectheader *o;
166         u8                 mcode;
167         unresolved_field  *uf;
168         fieldinfo         *fi;
169         u1                 byte;
170
171         /* get stuff from the stack */
172
173         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
174         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
175         mcode =                       *((u8 *)     (sp + 1 * 8));
176         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 8));
177
178         /* calculate and set the new return address */
179
180         ra = ra - 5;
181         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
182
183         PATCHER_MONITORENTER;
184
185         /* get the fieldinfo */
186
187         if (!(fi = helper_resolve_fieldinfo(uf))) {
188                 PATCHER_MONITOREXIT;
189
190                 return false;
191         }
192
193         /* patch back original code (instruction code is smaller than 8 bytes) */
194
195         *((u4 *) (ra + 0)) = (u4) mcode;
196         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
197
198         /* if we show disassembly, we have to skip the nop's */
199
200         if (showdisassemble)
201                 ra = ra + 5;
202
203         /* patch the field's offset: we check for the field type, because the     */
204         /* instructions have different lengths                                    */
205
206         if (IS_INT_LNG_TYPE(fi->type)) {
207                 /* check for special case: %rsp or %r12 as base register */
208
209                 byte = *(ra + 3);
210
211                 if (byte == 0x24)
212                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
213                 else
214                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
215
216         } else {
217                 /* check for special case: %rsp or %r12 as base register */
218
219                 byte = *(ra + 5);
220
221                 if (byte == 0x24)
222                         *((u4 *) (ra + 6)) = (u4) (fi->offset);
223                 else
224                         *((u4 *) (ra + 5)) = (u4) (fi->offset);
225         }
226
227         PATCHER_MARK_PATCHED_MONITOREXIT;
228
229         return true;
230 }
231
232
233 /* patcher_putfieldconst *******************************************************
234
235    Machine code:
236
237    <patched call position>
238    41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
239
240 *******************************************************************************/
241
242 bool patcher_putfieldconst(u1 *sp)
243 {
244         u1                *ra;
245         java_objectheader *o;
246         u8                 mcode;
247         unresolved_field  *uf;
248         fieldinfo         *fi;
249
250         /* get stuff from the stack */
251
252         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
253         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
254         mcode =                       *((u8 *)     (sp + 1 * 8));
255         uf    = (unresolved_field *)  *((ptrint *) (sp + 0 * 8));
256
257         /* calculate and set the new return address */
258
259         ra = ra - 5;
260         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
261
262         PATCHER_MONITORENTER;
263
264         /* get the fieldinfo */
265
266         if (!(fi = helper_resolve_fieldinfo(uf))) {
267                 PATCHER_MONITOREXIT;
268
269                 return false;
270         }
271
272         /* patch back original code */
273
274         *((u8 *) ra) = mcode;
275
276         /* if we show disassembly, we have to skip the nop's */
277
278         if (showdisassemble)
279                 ra = ra + 5;
280
281         /* patch the field's offset */
282
283         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
284                 /* handle special case when the base register is %r12 */
285
286                 if (*(ra + 2) == 0x84) {
287                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
288                         *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
289
290                 } else {
291                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
292                         *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
293                 }
294
295         } else {
296                 /* handle special case when the base register is %r12 */
297
298                 if (*(ra + 2) == 0x84)
299                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
300                 else
301                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
302         }
303
304         PATCHER_MARK_PATCHED_MONITOREXIT;
305
306         return true;
307 }
308
309
310 /* patcher_builtin_new *********************************************************
311
312    Machine code:
313
314    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
315    <patched call position>
316    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
317    48 ff d0                         callq  *%rax
318
319 *******************************************************************************/
320
321 bool patcher_builtin_new(u1 *sp)
322 {
323         u1                *ra;
324         java_objectheader *o;
325         u8                 mcode;
326         constant_classref *cr;
327         classinfo         *c;
328         void              *beginJavaStack;
329         /* get stuff from the stack */
330
331         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
332         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
333         mcode =                       *((u8 *)     (sp + 1 * 8));
334         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
335         beginJavaStack =              (void*) (sp+3*8);
336
337         /* calculate and set the new return address */
338
339         ra = ra - (10 + 5);
340         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
341
342         PATCHER_MONITORENTER;
343
344         /* get the classinfo */
345
346         if (!(c = helper_resolve_classinfo(cr))) {
347                 PATCHER_MONITOREXIT;
348
349                 return false;
350         }
351
352         if (!helper_initialize_class(beginJavaStack, c, ra + 5)) {
353                 PATCHER_MONITOREXIT;
354
355                 return false;
356         }
357
358         /* patch back original code */
359
360         *((u8 *) (ra + 10)) = mcode;
361
362         /* patch the classinfo pointer */
363
364         *((ptrint *) (ra + 2)) = (ptrint) c;
365
366         /* if we show disassembly, we have to skip the nop's */
367
368         if (showdisassemble)
369                 ra = ra + 5;
370
371         /* patch new function address */
372
373         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
374
375         PATCHER_MARK_PATCHED_MONITOREXIT;
376
377         return true;
378 }
379
380
381 /* patcher_builtin_newarray ****************************************************
382
383    Machine code:
384
385    48 be 88 13 9b 00 00 00 00 00    mov    $0x9b1388,%rsi
386    <patched call position>
387    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
388    48 ff d0                         callq  *%rax
389
390 *******************************************************************************/
391
392 bool patcher_builtin_newarray(u1 *sp)
393 {
394         u1                *ra;
395         java_objectheader *o;
396         u8                 mcode;
397         constant_classref *cr;
398         classinfo         *c;
399
400         /* get stuff from the stack */
401
402         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
403         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
404         mcode =                       *((u8 *)     (sp + 1 * 8));
405         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
406
407         /* calculate and set the new return address */
408
409         ra = ra - (10 + 5);
410         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
411
412         PATCHER_MONITORENTER;
413
414         /* get the classinfo */
415
416         if (!(c = helper_resolve_classinfo(cr))) {
417                 PATCHER_MONITOREXIT;
418
419                 return false;
420         }
421
422         /* patch back original code */
423
424         *((u8 *) (ra + 10)) = mcode;
425
426         /* patch the class' vftbl pointer */
427
428         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
429
430         /* if we show disassembly, we have to skip the nop's */
431
432         if (showdisassemble)
433                 ra = ra + 5;
434
435         /* patch new function address */
436
437         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
438
439         PATCHER_MARK_PATCHED_MONITOREXIT;
440
441         return true;
442 }
443
444
445 /* patcher_builtin_multianewarray **********************************************
446
447    Machine code:
448
449    <patched call position>
450    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
451    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
452    48 89 e2                         mov    %rsp,%rdx
453    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
454    48 ff d0                         callq  *%rax
455
456 *******************************************************************************/
457
458 bool patcher_builtin_multianewarray(u1 *sp)
459 {
460         u1                *ra;
461         java_objectheader *o;
462         u8                 mcode;
463         constant_classref *cr;
464         classinfo         *c;
465
466         /* get stuff from the stack */
467
468         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
469         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
470         mcode =                       *((u8 *)     (sp + 1 * 8));
471         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
472
473         /* calculate and set the new return address */
474
475         ra = ra - 5;
476         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
477
478         PATCHER_MONITORENTER;
479
480         /* get the classinfo */
481
482         if (!(c = helper_resolve_classinfo(cr))) {
483                 PATCHER_MONITOREXIT;
484
485                 return false;
486         }
487
488         /* patch back original code */
489
490         *((u8 *) ra) = mcode;
491
492         /* if we show disassembly, we have to skip the nop's */
493
494         if (showdisassemble)
495                 ra = ra + 5;
496
497         /* patch the class' vftbl pointer */
498
499         *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
500
501         /* patch new function address */
502
503         *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
504
505         PATCHER_MARK_PATCHED_MONITOREXIT;
506
507         return true;
508 }
509
510
511 /* patcher_builtin_arraycheckcast **********************************************
512
513    Machine code:
514
515    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
516    <patched call position>
517    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
518    48 ff d0                         callq  *%rax
519
520 *******************************************************************************/
521
522 bool patcher_builtin_arraycheckcast(u1 *sp)
523 {
524         u1                *ra;
525         java_objectheader *o;
526         u8                 mcode;
527         constant_classref *cr;
528         classinfo         *c;
529
530         /* get stuff from the stack */
531
532         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
533         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
534         mcode =                       *((u8 *)     (sp + 1 * 8));
535         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
536
537         /* calculate and set the new return address */
538
539         ra = ra - (10 + 5);
540         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
541
542         PATCHER_MONITORENTER;
543
544         /* get the classinfo */
545
546         if (!(c = helper_resolve_classinfo(cr))) {
547                 PATCHER_MONITOREXIT;
548
549                 return false;
550         }
551
552         /* patch back original code */
553
554         *((u8 *) (ra + 10)) = mcode;
555
556         /* patch the class' vftbl pointer */
557
558         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
559
560         /* if we show disassembly, we have to skip the nop's */
561
562         if (showdisassemble)
563                 ra = ra + 5;
564
565         /* patch new function address */
566
567         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arraycheckcast;
568
569         PATCHER_MARK_PATCHED_MONITOREXIT;
570
571         return true;
572 }
573
574
575 /* patcher_builtin_arrayinstanceof *********************************************
576
577    Machine code:
578
579    48 be 30 3c b2 00 00 00 00 00    mov    $0xb23c30,%rsi
580    <patched call position>
581    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
582    48 ff d0                         callq  *%rax
583
584 *******************************************************************************/
585
586 bool patcher_builtin_arrayinstanceof(u1 *sp)
587 {
588         u1                *ra;
589         java_objectheader *o;
590         u8                 mcode;
591         constant_classref *cr;
592         classinfo         *c;
593
594         /* get stuff from the stack */
595
596         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
597         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
598         mcode =                       *((u8 *)     (sp + 1 * 8));
599         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
600
601         /* calculate and set the new return address */
602
603         ra = ra - (10 + 5);
604         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
605
606         PATCHER_MONITORENTER;
607
608         /* get the classinfo */
609
610         if (!(c = helper_resolve_classinfo(cr))) {
611                 PATCHER_MONITOREXIT;
612
613                 return false;
614         }
615
616         /* patch back original code */
617
618         *((u8 *) (ra + 10)) = mcode;
619
620         /* patch the class' vftbl pointer */
621
622         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
623
624         /* if we show disassembly, we have to skip the nop's */
625
626         if (showdisassemble)
627                 ra = ra + 5;
628
629         /* patch new function address */
630
631         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
632
633         PATCHER_MARK_PATCHED_MONITOREXIT;
634
635         return true;
636 }
637
638
639 /* patcher_invokestatic_special ************************************************
640
641    Machine code:
642
643    <patched call position>
644    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
645    49 ff d2                         callq  *%r10
646
647 *******************************************************************************/
648
649 bool patcher_invokestatic_special(u1 *sp)
650 {
651         u1                *ra;
652         java_objectheader *o;
653         u8                 mcode;
654         unresolved_method *um;
655         methodinfo        *m;
656
657         /* get stuff from the stack */
658
659         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
660         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
661         mcode =                       *((u8 *)     (sp + 1 * 8));
662         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
663
664         /* calculate and set the new return address */
665
666         ra = ra - 5;
667         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
668
669         PATCHER_MONITORENTER;
670
671         /* get the fieldinfo */
672
673         if (!(m = helper_resolve_methodinfo(um))) {
674                 PATCHER_MONITOREXIT;
675
676                 return false;
677         }
678         /* patch back original code */
679
680         *((u8 *) ra) = mcode;
681
682         /* if we show disassembly, we have to skip the nop's */
683
684         if (showdisassemble)
685                 ra = ra + 5;
686
687         /* patch stubroutine */
688
689         *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
690
691         PATCHER_MARK_PATCHED_MONITOREXIT;
692
693         return true;
694 }
695
696
697 /* patcher_invokevirtual *******************************************************
698
699    Machine code:
700
701    <patched call position>
702    4c 8b 17                         mov    (%rdi),%r10
703    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
704    48 ff d0                         callq  *%rax
705
706 *******************************************************************************/
707
708 bool patcher_invokevirtual(u1 *sp)
709 {
710         u1                *ra;
711         java_objectheader *o;
712         u8                 mcode;
713         unresolved_method *um;
714         methodinfo        *m;
715
716         /* get stuff from the stack */
717
718         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
719         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
720         mcode =                       *((u8 *)     (sp + 1 * 8));
721         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
722
723         /* calculate and set the new return address */
724
725         ra = ra - 5;
726         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
727
728         PATCHER_MONITORENTER;
729
730         /* get the fieldinfo */
731
732         if (!(m = helper_resolve_methodinfo(um))) {
733                 PATCHER_MONITOREXIT;
734
735                 return false;
736         }
737
738         /* patch back original code */
739
740         *((u8 *) ra) = mcode;
741
742         /* if we show disassembly, we have to skip the nop's */
743
744         if (showdisassemble)
745                 ra = ra + 5;
746
747         /* patch vftbl index */
748
749         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
750                                                                    sizeof(methodptr) * m->vftblindex);
751
752         PATCHER_MARK_PATCHED_MONITOREXIT;
753
754         return true;
755 }
756
757
758 /* patcher_invokeinterface *****************************************************
759
760    Machine code:
761
762    <patched call position>
763    4c 8b 17                         mov    (%rdi),%r10
764    4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
765    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
766    48 ff d0                         callq  *%rax
767
768 *******************************************************************************/
769
770 bool patcher_invokeinterface(u1 *sp)
771 {
772         u1                *ra;
773         java_objectheader *o;
774         u8                 mcode;
775         unresolved_method *um;
776         methodinfo        *m;
777
778         /* get stuff from the stack */
779
780         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
781         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
782         mcode =                       *((u8 *)     (sp + 1 * 8));
783         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
784
785         /* calculate and set the new return address */
786
787         ra = ra - 5;
788         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
789
790         PATCHER_MONITORENTER;
791
792         /* get the fieldinfo */
793
794         if (!(m = helper_resolve_methodinfo(um))) {
795                 PATCHER_MONITOREXIT;
796
797                 return false;
798         }
799
800         /* patch back original code */
801
802         *((u8 *) ra) = mcode;
803
804         /* if we show disassembly, we have to skip the nop's */
805
806         if (showdisassemble)
807                 ra = ra + 5;
808
809         /* patch interfacetable index */
810
811         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
812                                                                    sizeof(methodptr) * m->class->index);
813
814         /* patch method offset */
815
816         *((s4 *) (ra + 3 + 7 + 3)) =
817                 (s4) (sizeof(methodptr) * (m - m->class->methods));
818
819         PATCHER_MARK_PATCHED_MONITOREXIT;
820
821         return true;
822 }
823
824
825 /* patcher_checkcast_instanceof_flags ******************************************
826
827    Machine code:
828
829    <patched call position>
830    41 ba 00 00 00 00                mov    $0x0,%r10d
831    41 81 e2 00 02 00 00             and    $0x200,%r10d
832    0f 84 35 00 00 00                je     0x00002aaaaab01479
833
834 *******************************************************************************/
835
836 bool patcher_checkcast_instanceof_flags(u1 *sp)
837 {
838         u1                *ra;
839         java_objectheader *o;
840         u8                 mcode;
841         constant_classref *cr;
842         classinfo         *c;
843
844         /* get stuff from the stack */
845
846         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
847         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
848         mcode =                       *((u8 *)     (sp + 1 * 8));
849         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
850
851         /* calculate and set the new return address */
852
853         ra = ra - 5;
854         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
855
856         PATCHER_MONITORENTER;
857
858         /* get the fieldinfo */
859
860         if (!(c = helper_resolve_classinfo(cr))) {
861                 PATCHER_MONITOREXIT;
862
863                 return false;
864         }
865
866         /* patch back original code */
867
868         *((u8 *) ra) = mcode;
869
870         /* if we show disassembly, we have to skip the nop's */
871
872         if (showdisassemble)
873                 ra = ra + 5;
874
875         /* patch class flags */
876
877         *((s4 *) (ra + 2)) = (s4) c->flags;
878
879         PATCHER_MARK_PATCHED_MONITOREXIT;
880
881         return true;
882 }
883
884
885 /* patcher_checkcast_instanceof_interface **************************************
886
887    Machine code:
888
889    <patched call position>
890    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
891    49 81 eb 00 00 00 00             sub    $0x0,%r11
892    4d 85 db                         test   %r11,%r11
893    0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
894    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
895
896 *******************************************************************************/
897
898 bool patcher_checkcast_instanceof_interface(u1 *sp)
899 {
900         u1                *ra;
901         java_objectheader *o;
902         u8                 mcode;
903         constant_classref *cr;
904         classinfo         *c;
905
906         /* get stuff from the stack */
907
908         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
909         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
910         mcode =                       *((u8 *)     (sp + 1 * 8));
911         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
912
913         /* calculate and set the new return address */
914
915         ra = ra - 5;
916         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
917
918         PATCHER_MONITORENTER;
919
920         /* get the fieldinfo */
921
922         if (!(c = helper_resolve_classinfo(cr))) {
923                 PATCHER_MONITOREXIT;
924
925                 return false;
926         }
927
928         /* patch back original code */
929
930         *((u8 *) ra) = mcode;
931
932         /* if we show disassembly, we have to skip the nop's */
933
934         if (showdisassemble)
935                 ra = ra + 5;
936
937         /* patch super class index */
938
939         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
940
941         *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
942                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
943                           c->index * sizeof(methodptr*));
944
945         PATCHER_MARK_PATCHED_MONITOREXIT;
946
947         return true;
948 }
949
950
951 /* patcher_checkcast_class *****************************************************
952
953    Machine code:
954
955    <patched call position>
956    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
957    45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
958    45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
959    4d 29 da                         sub    %r11,%r10
960    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
961
962 *******************************************************************************/
963
964 bool patcher_checkcast_class(u1 *sp)
965 {
966         u1                *ra;
967         java_objectheader *o;
968         u8                 mcode;
969         constant_classref *cr;
970         classinfo         *c;
971
972         /* get stuff from the stack */
973
974         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
975         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
976         mcode =                       *((u8 *)     (sp + 1 * 8));
977         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
978
979         /* calculate and set the new return address */
980
981         ra = ra - 5;
982         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
983
984         PATCHER_MONITORENTER;
985
986         /* get the fieldinfo */
987
988         if (!(c = helper_resolve_classinfo(cr))) {
989                 PATCHER_MONITOREXIT;
990
991                 return false;
992         }
993
994         /* patch back original code */
995
996         *((u8 *) ra) = mcode;
997
998         /* if we show disassembly, we have to skip the nop's */
999
1000         if (showdisassemble)
1001                 ra = ra + 5;
1002
1003         /* patch super class' vftbl */
1004
1005         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1006         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
1007
1008         PATCHER_MARK_PATCHED_MONITOREXIT;
1009
1010         return true;
1011 }
1012
1013
1014 /* patcher_instanceof_class ****************************************************
1015
1016    Machine code:
1017
1018    <patched call position>
1019    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
1020
1021 *******************************************************************************/
1022
1023 bool patcher_instanceof_class(u1 *sp)
1024 {
1025         u1                *ra;
1026         java_objectheader *o;
1027         u8                 mcode;
1028         constant_classref *cr;
1029         classinfo         *c;
1030
1031         /* get stuff from the stack */
1032
1033         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1034         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1035         mcode =                       *((u8 *)     (sp + 1 * 8));
1036         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
1037
1038         /* calculate and set the new return address */
1039
1040         ra = ra - 5;
1041         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1042
1043         PATCHER_MONITORENTER;
1044
1045         /* get the fieldinfo */
1046
1047         if (!(c = helper_resolve_classinfo(cr))) {
1048                 PATCHER_MONITOREXIT;
1049
1050                 return false;
1051         }
1052
1053         /* patch back original code */
1054
1055         *((u8 *) ra) = mcode;
1056
1057         /* if we show disassembly, we have to skip the nop's */
1058
1059         if (showdisassemble)
1060                 ra = ra + 5;
1061
1062         /* patch super class' vftbl */
1063
1064         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1065
1066         PATCHER_MARK_PATCHED_MONITOREXIT;
1067
1068         return true;
1069 }
1070
1071
1072 /* patcher_clinit **************************************************************
1073
1074    May be used for GET/PUTSTATIC and in native stub.
1075
1076    Machine code:
1077
1078    <patched call position>
1079    4d 8b 15 92 ff ff ff             mov    -110(%rip),%r10
1080    49 89 1a                         mov    %rbx,(%r10)
1081
1082 *******************************************************************************/
1083
1084 bool patcher_clinit(u1 *sp)
1085 {
1086         u1                *ra;
1087         java_objectheader *o;
1088         u8                 mcode;
1089         classinfo         *c;
1090         void              *beginJavaStack;
1091
1092         /* get stuff from the stack */
1093
1094         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1095         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1096         mcode =                       *((u8 *)     (sp + 1 * 8));
1097         c     = (classinfo *)         *((ptrint *) (sp + 0 * 8));
1098
1099         beginJavaStack =      (void*) (sp + 3 * 8);
1100
1101         /* calculate and set the new return address */
1102
1103         ra = ra - 5;
1104         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1105
1106         PATCHER_MONITORENTER;
1107
1108         /* check if the class is initialized */
1109
1110         if (!helper_initialize_class(beginJavaStack, c, ra + 5)) {
1111                 PATCHER_MONITOREXIT;
1112
1113                 return false;
1114         }
1115
1116         /* patch back original code */
1117
1118         *((u8 *) ra) = mcode;
1119
1120         PATCHER_MARK_PATCHED_MONITOREXIT;
1121
1122         return true;
1123 }
1124
1125
1126 /* patcher_resolve_native ******************************************************
1127
1128    Machine code:
1129
1130    <patched call position>
1131    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
1132    48 ff d0                         callq  *%rax
1133
1134 *******************************************************************************/
1135
1136 bool patcher_resolve_native(u1 *sp)
1137 {
1138         u1                *ra;
1139         java_objectheader *o;
1140         u8                 mcode;
1141         methodinfo        *m;
1142         functionptr        f;
1143         void              *beginJavaStack;
1144
1145         /* get stuff from the stack */
1146
1147         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1148         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1149         mcode =                       *((u8 *)     (sp + 1 * 8));
1150         m     = (methodinfo *)        *((ptrint *) (sp + 0 * 8));
1151
1152         beginJavaStack =      (void*) (sp + 3 * 8);
1153
1154         /* calculate and set the new return address */
1155
1156         ra = ra - 5;
1157         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1158
1159         PATCHER_MONITORENTER;
1160
1161         /* resolve native function */
1162
1163         if (!(f = native_resolve_function(m))) {
1164                 PATCHER_MONITOREXIT;
1165
1166                 return false;
1167         }
1168
1169         /* patch back original code */
1170
1171         *((u8 *) ra) = mcode;
1172
1173         /* if we show disassembly, we have to skip the nop's */
1174
1175         if (showdisassemble)
1176                 ra = ra + 5;
1177
1178         /* patch native function pointer */
1179
1180         *((ptrint *) (ra + 2)) = (ptrint) f;
1181
1182         PATCHER_MARK_PATCHED_MONITOREXIT;
1183
1184         return true;
1185 }
1186
1187
1188 /*
1189  * These are local overrides for various environment variables in Emacs.
1190  * Please do not remove this and leave it at the end of the file, where
1191  * Emacs will automagically detect them.
1192  * ---------------------------------------------------------------------
1193  * Local variables:
1194  * mode: c
1195  * indent-tabs-mode: t
1196  * c-basic-offset: 4
1197  * tab-width: 4
1198  * End:
1199  * vim:noexpandtab:sw=4:ts=4:
1200  */