2 /*--------------------------------------------------------------------*/
3 /*--- Trampoline code page stuff. m_trampoline.S ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2010 Julian Seward
12 Copyright (C) 2006-2010 OpenWorks LLP
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30 The GNU General Public License is contained in the file COPYING.
33 #include "pub_core_basics_asm.h"
34 #include "pub_core_vkiscnums_asm.h"
36 /* ------------------ SIMULATED CPU HELPERS ------------------ */
38 Replacements for some functions to do with vsyscalls and signals.
39 This code runs on the simulated CPU.
42 /*---------------------- x86-linux ----------------------*/
43 #if defined(VGP_x86_linux)
45 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
46 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
47 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
48 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
49 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
51 /* a leading page of unexecutable code */
54 .global VG_(trampoline_stuff_start)
55 VG_(trampoline_stuff_start):
57 .global VG_(x86_linux_SUBST_FOR_sigreturn)
58 VG_(x86_linux_SUBST_FOR_sigreturn):
59 /* This is a very specific sequence which GDB uses to
60 recognize signal handler frames. Also gcc: see
61 x86_fallback_frame_state() in
62 gcc-4.1.0/gcc/config/i386/linux-unwind.h */
64 movl $ __NR_sigreturn, %eax
68 .global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
69 VG_(x86_linux_SUBST_FOR_rt_sigreturn):
70 /* Likewise for rt signal frames */
71 movl $ __NR_rt_sigreturn, %eax
75 /* There's no particular reason that this needs to be handwritten
76 assembly, but since that's what this file contains, here's a
77 simple index implementation (written in C and compiled by gcc.)
79 unsigned char* REDIR_FOR_index ( const char* s, int c )
81 unsigned char ch = (unsigned char)((unsigned int)c);
82 unsigned char* p = (unsigned char*)s;
84 if (*p == ch) return p;
85 if (*p == 0) return 0;
90 .global VG_(x86_linux_REDIR_FOR_index)
91 .type VG_(x86_linux_REDIR_FOR_index), @function
92 VG_(x86_linux_REDIR_FOR_index):
113 .size VG_(x86_linux_REDIR_FOR_index), .-VG_(x86_linux_REDIR_FOR_index)
115 /* There's no particular reason that this needs to be handwritten
116 assembly, but since that's what this file contains, here's a
117 simple strlen implementation (written in C and compiled by gcc.)
119 .global VG_(x86_linux_REDIR_FOR_strlen)
120 .type VG_(x86_linux_REDIR_FOR_strlen), @function
121 VG_(x86_linux_REDIR_FOR_strlen):
133 .size VG_(x86_linux_REDIR_FOR_strlen), .-VG_(x86_linux_REDIR_FOR_strlen)
136 .global VG_(trampoline_stuff_end)
137 VG_(trampoline_stuff_end):
139 /* and a trailing page of unexecutable code */
148 /*---------------------- amd64-linux ----------------------*/
150 #if defined(VGP_amd64_linux)
152 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
153 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
154 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
155 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
156 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
158 /* a leading page of unexecutable code */
161 .global VG_(trampoline_stuff_start)
162 VG_(trampoline_stuff_start):
164 .global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
165 VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
166 /* This is a very specific sequence which GDB uses to
167 recognize signal handler frames. */
168 movq $__NR_rt_sigreturn, %rax
172 .global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
173 .type VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
174 VG_(amd64_linux_REDIR_FOR_vgettimeofday):
176 movq $__NR_gettimeofday, %rax
180 .size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
182 .global VG_(amd64_linux_REDIR_FOR_vtime)
183 .type VG_(amd64_linux_REDIR_FOR_vtime), @function
184 VG_(amd64_linux_REDIR_FOR_vtime):
186 movq $__NR_time, %rax
190 .size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
192 /* There's no particular reason that this needs to be handwritten
193 assembly, but since that's what this file contains, here's a
194 simple strlen implementation (written in C and compiled by gcc.)
196 .global VG_(amd64_linux_REDIR_FOR_strlen)
197 .type VG_(amd64_linux_REDIR_FOR_strlen), @function
198 VG_(amd64_linux_REDIR_FOR_strlen):
211 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
214 /* A CIE for the above three functions, followed by their FDEs */
215 .section .eh_frame,"a",@progbits
217 .long .LEcie1-.LScie1
235 .long .LEfde2-.LASfde2
237 .long .LASfde2-.Lframe1
244 .long .LEfde3-.LASfde3
246 .long .LASfde3-.Lframe1
253 .long .LEfde4-.LASfde4
255 .long .LASfde4-.Lframe1
263 .global VG_(trampoline_stuff_end)
264 VG_(trampoline_stuff_end):
266 /* and a trailing page of unexecutable code */
275 /*---------------- ppc32-linux ----------------*/
277 #if defined(VGP_ppc32_linux)
279 # define UD2_16 trap ; trap ; trap; trap
280 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
281 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
282 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
283 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
285 /* a leading page of unexecutable code */
288 .global VG_(trampoline_stuff_start)
289 VG_(trampoline_stuff_start):
291 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
292 VG_(ppc32_linux_SUBST_FOR_sigreturn):
295 .long 0 /*illegal insn*/
297 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
298 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
299 li 0,__NR_rt_sigreturn
301 .long 0 /*illegal insn*/
303 /* There's no particular reason that this needs to be handwritten
304 assembly, but since that's what this file contains, here's a
305 simple strlen implementation (written in C and compiled by gcc.)
307 .global VG_(ppc32_linux_REDIR_FOR_strlen)
308 .type VG_(ppc32_linux_REDIR_FOR_strlen), @function
309 VG_(ppc32_linux_REDIR_FOR_strlen):
322 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
325 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
326 .type VG_(ppc32_linux_REDIR_FOR_strcmp), @function
327 VG_(ppc32_linux_REDIR_FOR_strcmp):
360 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
362 /* Ditto index/strchr */
363 .global VG_(ppc32_linux_REDIR_FOR_strchr)
364 .type VG_(ppc32_linux_REDIR_FOR_strchr), @function
365 VG_(ppc32_linux_REDIR_FOR_strchr):
384 .size VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
386 .global VG_(trampoline_stuff_end)
387 VG_(trampoline_stuff_end):
389 /* and a trailing page of unexecutable code */
398 /*---------------- ppc64-linux ----------------*/
400 #if defined(VGP_ppc64_linux)
402 # define UD2_16 trap ; trap ; trap; trap
403 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
404 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
405 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
406 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
408 /* a leading page of unexecutable code */
411 .global VG_(trampoline_stuff_start)
412 VG_(trampoline_stuff_start):
414 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
415 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
416 li 0,__NR_rt_sigreturn
418 .long 0 /*illegal insn*/
420 /* See comment in pub_core_trampoline.h for what this is for */
421 .global VG_(ppctoc_magic_redirect_return_stub)
422 VG_(ppctoc_magic_redirect_return_stub):
425 /* this function is written using the "dotless" ABI convention */
427 .globl VG_(ppc64_linux_REDIR_FOR_strlen)
430 VG_(ppc64_linux_REDIR_FOR_strlen):
431 .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
433 .size VG_(ppc64_linux_REDIR_FOR_strlen), \
434 .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
435 .type VG_(ppc64_linux_REDIR_FOR_strlen), @function
437 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
452 .byte 0,0,0,0,0,0,0,0
455 /* this function is written using the "dotless" ABI convention */
457 .globl VG_(ppc64_linux_REDIR_FOR_strchr)
460 VG_(ppc64_linux_REDIR_FOR_strchr):
461 .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
463 .size VG_(ppc64_linux_REDIR_FOR_strchr), \
464 .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
465 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
467 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
487 .byte 0,0,0,0,0,0,0,0
491 .global VG_(trampoline_stuff_end)
492 VG_(trampoline_stuff_end):
494 /* and a trailing page of unexecutable code */
503 /*---------------- ppc32-linux ----------------*/
505 #elif defined(VGP_arm_linux)
507 # define UD2_4 .word 0xFFFFFFFF
508 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
509 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
510 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
511 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
512 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
514 /* a leading page of unexecutable code */
517 .global VG_(trampoline_stuff_start)
518 VG_(trampoline_stuff_start):
520 .global VG_(arm_linux_REDIR_FOR_strlen)
521 VG_(arm_linux_REDIR_FOR_strlen):
523 ldrb r0, [r0, #0] @ zero_extendqisi2
524 @ lr needed for prologue
530 ldrb r3, [r0, r2] @ zero_extendqisi2
536 //.global VG_(arm_linux_REDIR_FOR_index)
537 //VG_(arm_linux_REDIR_FOR_index):
538 // ldrb r3, [r0, #0] @ zero_extendqisi2
541 // @ lr needed for prologue
545 // ldrb r3, [r0, #1]! @ zero_extendqisi2
557 .global VG_(arm_linux_REDIR_FOR_memcpy)
558 VG_(arm_linux_REDIR_FOR_memcpy):
559 stmfd sp!, {r4, r5, lr}
574 ldrb r3, [r1, #4] @ zero_extendqisi2
577 ldrb r2, [r1, #3] @ zero_extendqisi2
580 ldrb r3, [r1, #2] @ zero_extendqisi2
583 ldrb r2, [r1, #1] @ zero_extendqisi2
595 ldrb r3, [r0], #-1 @ zero_extendqisi2
601 ldmfd sp!, {r4, r5, pc}
608 ldrb r3, [r1, #0] @ zero_extendqisi2
611 ldrb r2, [r1, #1] @ zero_extendqisi2
614 ldrb r3, [r1, #2] @ zero_extendqisi2
616 ldrb r2, [r1, #3] @ zero_extendqisi2
627 ldrb r3, [r1], #1 @ zero_extendqisi2
632 ldmfd sp!, {r4, r5, pc}
635 .global VG_(trampoline_stuff_end)
636 VG_(trampoline_stuff_end):
638 /* and a trailing page of unexecutable code */
648 /*---------------- ppc32-aix5 ----------------*/
650 #if defined(VGP_ppc32_aix5)
652 # define UD2_16 trap ; trap ; trap; trap
653 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
654 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
655 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
656 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
660 /* a leading page of unexecutable code */
663 .globl VG_(trampoline_stuff_start)
664 VG_(trampoline_stuff_start):
666 /* See pub_core_trampoline.h for an explaination of this. Also
667 see pub_core_initimg.h, struct AIX5PreloadPage. On entry, r3
668 points to an AIX5PreloadPage structure. Note we can only
669 use r2-r10 as scratch registers here since those are the
670 only ones restored from the preload page when finally
671 starting the client. */
672 .globl VG_(ppc32_aix5_do_preloads_then_start_client)
673 VG_(ppc32_aix5_do_preloads_then_start_client):
675 stw 3,512(1) /* stash r3 512 bytes up stack */
677 /* Try to load .../vgpreload_core.so */
678 lwz 2,0(3) /* r2 = __NR___loadx */
679 lwz 5,20(3) /* r5 = off_preloadcorename */
680 add 6,3,5 /* r6 = preloadcorename */
687 /* Try to load .../vgpreload_tool.so, if it exists */
688 lwz 3,512(1) /* restore r3 */
689 lwz 2,0(3) /* r2 = __NR___loadx */
690 lwz 5,24(3) /* r5 = off_preloadtoolname */
691 cmpwi 0,5,0 /* skip tool preload if */
692 beq .Ltry_preload /* name not present */
693 add 6,3,5 /* r6 = preloadtoolname */
701 /* Try to load the LD_PRELOAD= file, if it exists */
702 lwz 3,512(1) /* restore r3 */
703 lwz 2,0(3) /* r2 = __NR___loadx */
704 lwz 5,28(3) /* r5 = off_ld_preloadname */
705 cmpwi 0,5,0 /* skip ld_preload if */
706 beq .Lstart_client /* name not present */
707 add 6,3,5 /* r6 = ld_preloadname */
715 /* Success. Restore r2-r10 from preloadpage-> and start
717 lwz 3,512(1) /* restore r3 */
719 lwz 2,32+4(3) /* preloadpage->client_start */
721 lwz 2,40+4(3) /* preloadpage->r2 */
722 lwz 4,56+4(3) /* preloadpage->r4 */
723 lwz 5,64+4(3) /* preloadpage->r5 */
724 lwz 6,72+4(3) /* preloadpage->r6 */
725 lwz 7,80+4(3) /* preloadpage->r7 */
726 lwz 8,88+4(3) /* preloadpage->r8 */
727 lwz 9,96+4(3) /* preloadpage->r9 */
728 lwz 10,104+4(3) /* preloadpage->r10 */
729 lwz 3,48+4(3) /* preloadpage->r3 */
735 /* __loadx barfed for some reason. Print the error
736 message and get out. */
737 /* First the error msg */
738 lwz 3,512(1) /* restore r3 */
739 lwz 2,4(3) /* r2 = __NR_kwrite */
740 lwz 4,12(3) /* r4 = offset of err msg */
741 add 4,4,3 /* r4 = err msg */
742 lwz 5,16(3) /* r5 = length err msg */
743 li 3,2 /* r3 = stderr */
745 /* now call the diagnosis fn */
746 lwz 3,512(1) /* restore r3 */
747 lwz 4,112(3) /* preloadpage->p_diagnose_load_failure */
748 lwz 2,4(4) /* get its TOC ptr */
749 lwz 4,0(4) /* get its entry point */
752 /* Now do _exit(1) */
753 lwz 3,512(1) /* restore r3 */
754 lwz 2,8(3) /* r2 = __NR_exit */
755 li 3,1 /* doing _exit(1) */
756 addi 1,1,1024 /* fix stack pointer */
762 /* On entry: r2 = __NR___loadx, r6 = name of module */
764 slwi 3,3,24 /* r3 = 0x1000000 = VKI_DL_LOAD */
775 /* sc continues at 'lr', hence this
776 constitutes an automatic return */
779 /* See comment in pub_core_trampoline.h for what this is for */
780 .globl VG_(ppctoc_magic_redirect_return_stub)
781 VG_(ppctoc_magic_redirect_return_stub):
784 .globl VG_(trampoline_stuff_end)
785 VG_(trampoline_stuff_end):
787 /* and a trailing page of unexecutable code */
796 /*---------------- ppc64-aix5 ----------------*/
798 #if defined(VGP_ppc64_aix5)
800 # define UD2_16 trap ; trap ; trap; trap
801 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
802 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
803 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
804 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
806 .globl VG_(trampoline_stuff_start)
807 VG_(trampoline_stuff_start):
808 /* See pub_core_trampoline.h for an explaination of this. Also
809 see pub_core_initimg.h, struct AIX5PreloadPage. On entry, r3
810 points to an AIX5PreloadPage structure. Note we can only
811 use r2-r10 as scratch registers here since those are the
812 only ones restored from the preload page when finally
813 starting the client. */
814 .globl VG_(ppc64_aix5_do_preloads_then_start_client)
815 VG_(ppc64_aix5_do_preloads_then_start_client):
817 std 3,512(1) /* stash r3 512 bytes up stack */
819 /* Try to load .../vgpreload_core.so */
820 lwz 2,0(3) /* r2 = __NR_kload */
821 lwz 5,20(3) /* r5 = off_preloadcorename */
822 add 3,3,5 /* r6 = preloadcorename */
827 /* Try to load .../vgpreload_tool.so, if it exists */
828 ld 3,512(1) /* restore r3 */
829 lwz 2,0(3) /* r2 = __NR_kload */
830 lwz 5,24(3) /* r5 = off_preloadtoolname */
831 cmpwi 0,5,0 /* skip tool preload if */
832 beq .Ltry_preload /* name not present */
833 add 3,3,5 /* r6 = preloadtoolname */
839 /* Try to load the LD_PRELOAD= file, if it exists */
840 ld 3,512(1) /* restore r3 */
841 lwz 2,0(3) /* r2 = __NR_kload */
842 lwz 5,28(3) /* r5 = off_ld_preloadname */
843 cmpwi 0,5,0 /* skip ld_preload if */
844 beq .Lstart_client /* name not present */
845 add 3,3,5 /* r6 = ld_preloadname */
851 /* Success. Restore r2-r10 from preloadpage-> and start
853 ld 3,512(1) /* restore r3 */
855 ld 2,32+0(3) /* preloadpage->client_start */
857 ld 2,40+0(3) /* preloadpage->r2 */
858 ld 4,56+0(3) /* preloadpage->r4 */
859 ld 5,64+0(3) /* preloadpage->r5 */
860 ld 6,72+0(3) /* preloadpage->r6 */
861 ld 7,80+0(3) /* preloadpage->r7 */
862 ld 8,88+0(3) /* preloadpage->r8 */
863 ld 9,96+0(3) /* preloadpage->r9 */
864 ld 10,104+0(3) /* preloadpage->r10 */
865 ld 3,48+0(3) /* preloadpage->r3 */
871 /* __loadx barfed for some reason. Print the error
872 message and get out. */
873 /* First the error msg */
874 ld 3,512(1) /* restore r3 */
875 lwz 2,4(3) /* r2 = __NR_kwrite */
876 lwz 4,12(3) /* r4 = offset of err msg */
877 add 4,4,3 /* r4 = err msg */
878 lwz 5,16(3) /* r5 = length err msg */
879 li 3,2 /* r3 = stderr */
881 /* now call the diagnosis fn */
882 ld 3,512(1) /* restore r3 */
883 ld 4,112(3) /* preloadpage->p_diagnose_load_failure */
885 ld 2,8(4) /* get its TOC ptr */
886 ld 4,0(4) /* get its entry point */
889 /* Now do _exit(1) */
890 lwz 3,512(1) /* restore r3 */
891 lwz 2,8(3) /* r2 = __NR_exit */
892 li 3,1 /* doing _exit(1) */
893 addi 1,1,1024 /* fix stack pointer */
899 /* On entry: r2 = __NR_kload, r3 = name of module */
910 /* sc continues at 'lr', hence this
911 constitutes an automatic return */
913 /* See comment in pub_core_trampoline.h for what this is for */
914 .globl VG_(ppctoc_magic_redirect_return_stub)
915 VG_(ppctoc_magic_redirect_return_stub):
918 .globl VG_(trampoline_stuff_end)
919 VG_(trampoline_stuff_end):
921 /* and a trailing page of unexecutable code */
930 /*---------------- x86-darwin ----------------*/
932 #if defined(VGP_x86_darwin)
934 /* a leading page of unexecutable code */
935 .fill 2048, 2, 0x0b0f /* `ud2` */
937 .globl VG_(trampoline_stuff_start)
938 VG_(trampoline_stuff_start):
940 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
941 VG_(x86_darwin_SUBST_FOR_sigreturn):
942 /* XXX does this need to have any special form? (cf x86-linux
944 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax
948 .globl VG_(x86_darwin_REDIR_FOR_strlen)
949 VG_(x86_darwin_REDIR_FOR_strlen):
961 .globl VG_(x86_darwin_REDIR_FOR_strcat)
962 VG_(x86_darwin_REDIR_FOR_strcat):
985 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
986 VG_(x86_darwin_REDIR_FOR_strcmp):
1006 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
1007 VG_(x86_darwin_REDIR_FOR_strcpy):
1028 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
1029 VG_(x86_darwin_REDIR_FOR_strlcat):
1038 leal (%ecx,%esi), %eax
1058 call VG_(x86_darwin_REDIR_FOR_strlen)
1076 leal (%edi,%eax), %eax
1083 .globl VG_(trampoline_stuff_end)
1084 VG_(trampoline_stuff_end):
1086 /* a trailing page of unexecutable code */
1087 .fill 2048, 2, 0x0b0f /* `ud2` */
1090 /*---------------- amd64-darwin ----------------*/
1092 #if defined(VGP_amd64_darwin)
1094 /* a leading page of unexecutable code */
1095 .fill 2048, 2, 0x0b0f /* `ud2` */
1097 .globl VG_(trampoline_stuff_start)
1098 VG_(trampoline_stuff_start):
1100 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1101 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1102 /* XXX does this need to have any special form? (cf x86-linux
1104 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1108 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1109 VG_(amd64_darwin_REDIR_FOR_strlen):
1120 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1121 VG_(amd64_darwin_REDIR_FOR_strcat):
1140 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1141 VG_(amd64_darwin_REDIR_FOR_strcmp):
1158 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1159 VG_(amd64_darwin_REDIR_FOR_strcpy):
1176 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1177 VG_(amd64_darwin_REDIR_FOR_strlcat):
1179 leaq (%rdx,%rdi), %rax
1202 call VG_(amd64_darwin_REDIR_FOR_strlen)
1219 leaq (%rbx,%rax), %rax
1225 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1226 VG_(amd64_darwin_REDIR_FOR_arc4random):
1227 /* not very random, hope dyld won't mind */
1228 movq $0x76616c6772696e64, %rax
1231 .globl VG_(trampoline_stuff_end)
1232 VG_(trampoline_stuff_end):
1234 /* a trailing page of unexecutable code */
1235 .fill 2048, 2, 0x0b0f /* `ud2` */
1237 /*---------------------- x86-l4re ----------------------*/
1239 #if defined(VGP_x86_l4re)
1241 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
1242 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1243 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1244 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1245 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1247 /* a leading page of unexecutable code */
1250 .global VG_(trampoline_stuff_start)
1251 VG_(trampoline_stuff_start):
1253 .global VG_(x86_l4re_SUBST_FOR_sigreturn)
1254 VG_(x86_l4re_SUBST_FOR_sigreturn):
1255 /* This is a very specific sequence which GDB uses to
1256 recognize signal handler frames. Also gcc: see
1257 x86_fallback_frame_state() in
1258 gcc-4.1.0/gcc/config/i386/linux-unwind.h */
1261 /* movl $ __NR_sigreturn, %eax*/
1265 .global VG_(x86_l4re_SUBST_FOR_rt_sigreturn)
1266 VG_(x86_l4re_SUBST_FOR_rt_sigreturn):
1267 /* Likewise for rt signal frames */
1269 /* movl $ __NR_rt_sigreturn, %eax */
1273 /* There's no particular reason that this needs to be handwritten
1274 assembly, but since that's what this file contains, here's a
1275 simple index implementation (written in C and compiled by gcc.)
1277 unsigned char* REDIR_FOR_index ( const char* s, int c )
1279 unsigned char ch = (unsigned char)((unsigned int)c);
1280 unsigned char* p = (unsigned char*)s;
1282 if (*p == ch) return p;
1283 if (*p == 0) return 0;
1288 .global VG_(x86_l4re_REDIR_FOR_index)
1289 .type VG_(x86_l4re_REDIR_FOR_index), @function
1290 VG_(x86_l4re_REDIR_FOR_index):
1294 movzbl 12(%ebp), %ecx
1311 .size VG_(x86_l4re_REDIR_FOR_index), .-VG_(x86_l4re_REDIR_FOR_index)
1313 .global VG_(trampoline_stuff_end)
1314 VG_(trampoline_stuff_end):
1316 /* and a trailing page of unexecutable code */
1325 /*---------------- s390x-linux ----------------*/
1327 #if defined(VGP_s390x_linux)
1329 /* a leading page of unexecutable code */
1330 .fill 2048, 2, 0x0000
1332 .global VG_(trampoline_stuff_start)
1333 VG_(trampoline_stuff_start):
1335 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1336 VG_(s390x_linux_SUBST_FOR_sigreturn):
1340 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1341 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1342 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1343 for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1344 set ra to this trampoline, but the cfa is still in the stack,
1345 the unwinder thinks, that this is a non-rt frame and causes a
1346 crash in the gcc unwinder - which is used by the thread library
1347 and others. Therefore we add a lr 1,1 nop, to let the gcc
1348 unwinder bail out gracefully. This might also affect unwinding
1349 across the signal frame - tough luck. fixs390 */
1351 svc __NR_rt_sigreturn
1354 .globl VG_(trampoline_stuff_end)
1355 VG_(trampoline_stuff_end):
1356 .fill 2048, 2, 0x0000
1358 /*---------------- unknown ----------------*/
1360 # error Unknown platform
1373 #if defined(VGO_linux)
1374 /* Let the linker know we don't need an executable stack */
1375 # if defined(VGP_arm_linux)
1376 .section .note.GNU-stack,"",%progbits
1378 .section .note.GNU-stack,"",@progbits
1382 /*--------------------------------------------------------------------*/
1384 /*--------------------------------------------------------------------*/