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-2017 Julian Seward
12 Copyright (C) 2006-2017 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, see <http://www.gnu.org/licenses/>.
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics_asm.h"
32 #include "pub_core_vkiscnums_asm.h"
34 /* ------------------ SIMULATED CPU HELPERS ------------------ */
36 Replacements for some functions to do with vsyscalls and signals.
37 This code runs on the simulated CPU.
40 /*---------------------- x86-linux ----------------------*/
41 #if defined(VGP_x86_linux)
43 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
44 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
45 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
46 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
47 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
49 /* a leading page of unexecutable code */
52 .global VG_(trampoline_stuff_start)
53 VG_(trampoline_stuff_start):
55 .global VG_(x86_linux_SUBST_FOR_sigreturn)
56 VG_(x86_linux_SUBST_FOR_sigreturn):
57 /* This is a very specific sequence which GDB uses to
58 recognize signal handler frames. Also gcc: see
59 x86_fallback_frame_state() in
60 gcc-4.1.0/gcc/config/i386/linux-unwind.h */
62 movl $ __NR_sigreturn, %eax
66 .global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
67 VG_(x86_linux_SUBST_FOR_rt_sigreturn):
68 /* Likewise for rt signal frames */
69 movl $ __NR_rt_sigreturn, %eax
73 /* There's no particular reason that this needs to be handwritten
74 assembly, but since that's what this file contains, here's a
75 simple index implementation (written in C and compiled by gcc.)
77 unsigned char* REDIR_FOR_index ( const char* s, int c )
79 unsigned char ch = (unsigned char)((unsigned int)c);
80 unsigned char* p = (unsigned char*)s;
82 if (*p == ch) return p;
83 if (*p == 0) return 0;
88 .global VG_(x86_linux_REDIR_FOR_index)
89 .type VG_(x86_linux_REDIR_FOR_index), @function
90 VG_(x86_linux_REDIR_FOR_index):
111 .size VG_(x86_linux_REDIR_FOR_index), .-VG_(x86_linux_REDIR_FOR_index)
113 /* There's no particular reason that this needs to be handwritten
114 assembly, but since that's what this file contains, here's a
115 simple strlen implementation (written in C and compiled by gcc.)
117 .global VG_(x86_linux_REDIR_FOR_strlen)
118 .type VG_(x86_linux_REDIR_FOR_strlen), @function
119 VG_(x86_linux_REDIR_FOR_strlen):
131 .size VG_(x86_linux_REDIR_FOR_strlen), .-VG_(x86_linux_REDIR_FOR_strlen)
134 .global VG_(trampoline_stuff_end)
135 VG_(trampoline_stuff_end):
137 /* and a trailing page of unexecutable code */
146 /*---------------------- amd64-linux ----------------------*/
148 #if defined(VGP_amd64_linux)
150 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
151 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
152 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
153 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
154 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
156 /* a leading page of unexecutable code */
159 .global VG_(trampoline_stuff_start)
160 VG_(trampoline_stuff_start):
162 .global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
163 VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
164 /* This is a very specific sequence which GDB uses to
165 recognize signal handler frames. */
166 movq $__NR_rt_sigreturn, %rax
170 .global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
171 .type VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
172 VG_(amd64_linux_REDIR_FOR_vgettimeofday):
174 movq $__NR_gettimeofday, %rax
178 .size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
180 .global VG_(amd64_linux_REDIR_FOR_vtime)
181 .type VG_(amd64_linux_REDIR_FOR_vtime), @function
182 VG_(amd64_linux_REDIR_FOR_vtime):
184 movq $__NR_time, %rax
188 .size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
190 .global VG_(amd64_linux_REDIR_FOR_vgetcpu)
191 .type VG_(amd64_linux_REDIR_FOR_vgetcpu), @function
192 VG_(amd64_linux_REDIR_FOR_vgetcpu):
194 movq $__NR_getcpu, %rax
198 .size VG_(amd64_linux_REDIR_FOR_vgetcpu), .-.LfnB4
200 /* There's no particular reason that this needs to be handwritten
201 assembly, but since that's what this file contains, here's a
202 simple strlen implementation (written in C and compiled by gcc.)
204 .global VG_(amd64_linux_REDIR_FOR_strlen)
205 .type VG_(amd64_linux_REDIR_FOR_strlen), @function
206 VG_(amd64_linux_REDIR_FOR_strlen):
219 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
221 .global VG_(amd64_linux_REDIR_FOR_index)
222 .type VG_(amd64_linux_REDIR_FOR_index), @function
223 VG_(amd64_linux_REDIR_FOR_index):
242 .size VG_(amd64_linux_REDIR_FOR_index), .-VG_(amd64_linux_REDIR_FOR_index)
246 /* A CIE for the above four functions, followed by their FDEs */
247 .section .eh_frame,"a",@progbits
249 .long .LEcie1-.LScie1
267 .long .LEfde2-.LASfde2
269 .long .LASfde2-.Lframe1
276 .long .LEfde3-.LASfde3
278 .long .LASfde3-.Lframe1
285 .long .LEfde4-.LASfde4
287 .long .LASfde4-.Lframe1
294 .long .LEfde5-.LASfde5
296 .long .LASfde5-.Lframe1
304 .global VG_(trampoline_stuff_end)
305 VG_(trampoline_stuff_end):
307 /* and a trailing page of unexecutable code */
316 /*---------------- ppc32-linux ----------------*/
318 #if defined(VGP_ppc32_linux)
320 # define UD2_16 trap ; trap ; trap; trap
321 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
322 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
323 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
324 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
326 /* a leading page of unexecutable code */
329 .global VG_(trampoline_stuff_start)
330 VG_(trampoline_stuff_start):
332 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
333 VG_(ppc32_linux_SUBST_FOR_sigreturn):
336 .long 0 /*illegal insn*/
338 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
339 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
340 li 0,__NR_rt_sigreturn
342 .long 0 /*illegal insn*/
344 /* There's no particular reason that this needs to be handwritten
345 assembly, but since that's what this file contains, here's a
346 simple strlen implementation (written in C and compiled by gcc.)
348 .global VG_(ppc32_linux_REDIR_FOR_strlen)
349 .type VG_(ppc32_linux_REDIR_FOR_strlen), @function
350 VG_(ppc32_linux_REDIR_FOR_strlen):
363 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
366 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
367 .type VG_(ppc32_linux_REDIR_FOR_strcmp), @function
368 VG_(ppc32_linux_REDIR_FOR_strcmp):
401 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
403 /* Ditto index/strchr */
404 .global VG_(ppc32_linux_REDIR_FOR_strchr)
405 .type VG_(ppc32_linux_REDIR_FOR_strchr), @function
406 VG_(ppc32_linux_REDIR_FOR_strchr):
425 .size VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
427 .global VG_(trampoline_stuff_end)
428 VG_(trampoline_stuff_end):
430 /* and a trailing page of unexecutable code */
439 /*---------------- ppc64-linux ----------------*/
441 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
443 # define UD2_16 trap ; trap ; trap; trap
444 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
445 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
446 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
447 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
449 /* a leading page of unexecutable code */
452 .global VG_(trampoline_stuff_start)
453 VG_(trampoline_stuff_start):
455 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
456 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
457 li 0,__NR_rt_sigreturn
459 .long 0 /*illegal insn*/
461 /* See comment in pub_core_trampoline.h for what this is for */
462 .global VG_(ppctoc_magic_redirect_return_stub)
463 VG_(ppctoc_magic_redirect_return_stub):
466 /* this function is written using the "dotless" ABI convention */
468 .globl VG_(ppc64_linux_REDIR_FOR_strlen)
469 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
470 /* Little Endian uses ELF version 2 */
471 .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
472 VG_(ppc64_linux_REDIR_FOR_strlen):
474 /* Big Endian uses ELF version 1 */
477 VG_(ppc64_linux_REDIR_FOR_strlen):
478 .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
480 .size VG_(ppc64_linux_REDIR_FOR_strlen), \
481 .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
482 .type VG_(ppc64_linux_REDIR_FOR_strlen), @function
484 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
487 0: addis 2,12,.TOC.-0b@ha
489 .localentry VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
505 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
506 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
508 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
511 .byte 0,0,0,0,0,0,0,0
514 /* this function is written using the "dotless" ABI convention */
516 .globl VG_(ppc64_linux_REDIR_FOR_strchr)
517 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
518 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
519 VG_(ppc64_linux_REDIR_FOR_strchr):
523 VG_(ppc64_linux_REDIR_FOR_strchr):
524 .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
526 .size VG_(ppc64_linux_REDIR_FOR_strchr), \
527 .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
528 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
530 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
533 0: addis 2,12,.TOC.-0b@ha
535 .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
544 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
545 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
547 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
561 .byte 0,0,0,0,0,0,0,0
565 .global VG_(trampoline_stuff_end)
566 VG_(trampoline_stuff_end):
568 /* and a trailing page of unexecutable code */
577 /*---------------- arm-linux ----------------*/
579 #if defined(VGP_arm_linux)
581 # define UD2_4 .word 0xFFFFFFFF
582 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
583 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
584 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
585 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
586 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
588 /* a leading page of unexecutable code */
591 .global VG_(trampoline_stuff_start)
592 VG_(trampoline_stuff_start):
594 .global VG_(arm_linux_SUBST_FOR_sigreturn)
595 .type VG_(arm_linux_SUBST_FOR_sigreturn),#function
596 VG_(arm_linux_SUBST_FOR_sigreturn):
597 mov r7, # __NR_sigreturn
599 .long 0xFFFFFFFF /*illegal insn*/
600 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
602 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
603 .type VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
604 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
605 mov r7, # __NR_rt_sigreturn
607 .long 0xFFFFFFFF /*illegal insn*/
608 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
610 .global VG_(arm_linux_REDIR_FOR_strlen)
611 VG_(arm_linux_REDIR_FOR_strlen):
613 ldrb r0, [r0, #0] @ zero_extendqisi2
614 @ lr needed for prologue
620 ldrb r3, [r0, r2] @ zero_extendqisi2
626 .global VG_(arm_linux_REDIR_FOR_index)
627 VG_(arm_linux_REDIR_FOR_index):
628 ldrb r3, [r0, #0] @ zero_extendqisi2
631 @ lr needed for prologue
635 ldrb r3, [r0, #1]! @ zero_extendqisi2
647 .global VG_(arm_linux_REDIR_FOR_memcpy)
648 VG_(arm_linux_REDIR_FOR_memcpy):
649 stmfd sp!, {r4, r5, lr}
664 ldrb r3, [r1, #4] @ zero_extendqisi2
667 ldrb r2, [r1, #3] @ zero_extendqisi2
670 ldrb r3, [r1, #2] @ zero_extendqisi2
673 ldrb r2, [r1, #1] @ zero_extendqisi2
685 ldrb r3, [r0], #-1 @ zero_extendqisi2
691 ldmfd sp!, {r4, r5, pc}
698 ldrb r3, [r1, #0] @ zero_extendqisi2
701 ldrb r2, [r1, #1] @ zero_extendqisi2
704 ldrb r3, [r1, #2] @ zero_extendqisi2
706 ldrb r2, [r1, #3] @ zero_extendqisi2
717 ldrb r3, [r1], #1 @ zero_extendqisi2
722 ldmfd sp!, {r4, r5, pc}
725 .global VG_(arm_linux_REDIR_FOR_strcmp)
726 VG_(arm_linux_REDIR_FOR_strcmp):
728 ldrb r3, [r0], #1 @ zero_extendqisi2
729 ldrb r2, [r1], #1 @ zero_extendqisi2
741 .global VG_(trampoline_stuff_end)
742 VG_(trampoline_stuff_end):
744 /* and a trailing page of unexecutable code */
754 /*---------------- arm64-linux ----------------*/
756 #if defined(VGP_arm64_linux)
758 # define UD2_4 .word 0xFFFFFFFF
759 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
760 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
761 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
762 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
763 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
765 /* a leading page of unexecutable code */
768 .global VG_(trampoline_stuff_start)
769 VG_(trampoline_stuff_start):
771 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
772 .type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
773 VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
774 mov x8, # __NR_rt_sigreturn
776 .long 0xFFFFFFFF /*illegal insn*/
777 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
778 .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
780 .global VG_(arm64_linux_REDIR_FOR_strlen)
781 .type VG_(arm64_linux_REDIR_FOR_strlen),#function
782 VG_(arm64_linux_REDIR_FOR_strlen):
795 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
797 .global VG_(arm64_linux_REDIR_FOR_index)
798 .type VG_(arm64_linux_REDIR_FOR_index),#function
799 VG_(arm64_linux_REDIR_FOR_index):
814 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
816 .global VG_(arm64_linux_REDIR_FOR_strcmp)
817 .type VG_(arm64_linux_REDIR_FOR_strcmp),#function
818 VG_(arm64_linux_REDIR_FOR_strcmp):
839 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
841 .global VG_(trampoline_stuff_end)
842 VG_(trampoline_stuff_end):
844 /* and a trailing page of unexecutable code */
854 /*---------------- x86-freebsd ----------------*/
856 #if defined(VGP_x86_freebsd)
858 .global VG_(trampoline_stuff_start)
859 VG_(trampoline_stuff_start):
861 .global VG_(x86_freebsd_SUBST_FOR_sigreturn)
862 VG_(x86_freebsd_SUBST_FOR_sigreturn):
864 * PJF this magic number is fairly flakey
865 * If ever it is wrong sys_fake_sigreturn will fail
866 * the sigreturn will be to some bogus EIP address and
867 * the client will likely terminate with a SIGILL
868 * In this case adding some printfs to sigframe_create
869 * and sys_fake_sigreturn should help debugging to
870 * find the right offset
872 lea 0x1c(%esp), %eax /* args to sigreturn(ucontext_t *) */
874 pushl %eax /* fake return addr */
875 /* movl 0x44(%eax), %gs ; restore %gs, not done by sigreturn */
876 movl $__NR_fake_sigreturn, %eax
880 .global VG_(trampoline_stuff_end)
881 VG_(trampoline_stuff_end):
884 #if defined(VGP_amd64_freebsd)
886 # define UD2_16 ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
887 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
888 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
889 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
890 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
892 /* a leading page of unexecutable code */
895 .global VG_(trampoline_stuff_start)
896 VG_(trampoline_stuff_start):
898 .global VG_(amd64_freebsd_SUBST_FOR_sigreturn)
899 VG_(amd64_freebsd_SUBST_FOR_sigreturn):
900 /* This is a very specific sequence which GDB uses to
901 recognize signal handler frames. */
903 movq $__NR_fake_sigreturn, %rax
905 /* running the preprocessor on
906 * src/amd64.amd64/lib/libc/sigreturn.S
908 * .text; .p2align 4,0x90; .globl __sys_sigreturn;
909 * .type __sys_sigreturn,@function; __sys_sigreturn:;
910 * .cfi_startproc; .weak sigreturn; .equ sigreturn,__sys_sigreturn;
911 * .weak _sigreturn; .equ _sigreturn,__sys_sigreturn;
914 * syscall; jb .cerror; ret; .size __sys_sigreturn, . - __sys_sigreturn;
919 * sigframe in sigframe-amd64-freebsd.c
920 * differs from sigframe in /usr/include/x86/sigframe.h
921 * by having the address to this trampoline first
922 * so I assume that the +8 is to get back to the
930 .global VG_(trampoline_stuff_end)
931 VG_(trampoline_stuff_end):
933 /* and a trailing page of unexecutable code */
942 /*---------------- x86-darwin ----------------*/
944 #if defined(VGP_x86_darwin)
946 /* a leading page of unexecutable code */
947 .fill 2048, 2, 0x0b0f /* `ud2` */
949 .globl VG_(trampoline_stuff_start)
950 VG_(trampoline_stuff_start):
952 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
953 VG_(x86_darwin_SUBST_FOR_sigreturn):
954 /* XXX does this need to have any special form? (cf x86-linux
956 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax
960 .globl VG_(x86_darwin_REDIR_FOR_strlen)
961 VG_(x86_darwin_REDIR_FOR_strlen):
973 .globl VG_(x86_darwin_REDIR_FOR_strcat)
974 VG_(x86_darwin_REDIR_FOR_strcat):
997 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
998 VG_(x86_darwin_REDIR_FOR_strcmp):
1018 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
1019 VG_(x86_darwin_REDIR_FOR_strcpy):
1040 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
1041 VG_(x86_darwin_REDIR_FOR_strlcat):
1050 leal (%ecx,%esi), %eax
1070 call VG_(x86_darwin_REDIR_FOR_strlen)
1088 leal (%edi,%eax), %eax
1095 .globl VG_(trampoline_stuff_end)
1096 VG_(trampoline_stuff_end):
1098 /* a trailing page of unexecutable code */
1099 .fill 2048, 2, 0x0b0f /* `ud2` */
1102 /*---------------- amd64-darwin ----------------*/
1104 #if defined(VGP_amd64_darwin)
1106 /* a leading page of unexecutable code */
1107 .fill 2048, 2, 0x0b0f /* `ud2` */
1109 .globl VG_(trampoline_stuff_start)
1110 VG_(trampoline_stuff_start):
1112 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1113 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1114 /* XXX does this need to have any special form? (cf x86-linux
1116 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1120 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1121 VG_(amd64_darwin_REDIR_FOR_strlen):
1132 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1133 VG_(amd64_darwin_REDIR_FOR_strcat):
1152 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1153 VG_(amd64_darwin_REDIR_FOR_strcmp):
1170 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1171 VG_(amd64_darwin_REDIR_FOR_strcpy):
1188 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1189 VG_(amd64_darwin_REDIR_FOR_strlcat):
1191 leaq (%rdx,%rdi), %rax
1214 call VG_(amd64_darwin_REDIR_FOR_strlen)
1231 leaq (%rbx,%rax), %rax
1237 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1238 VG_(amd64_darwin_REDIR_FOR_arc4random):
1239 /* not very random, hope dyld won't mind */
1240 movq $0x76616c6772696e64, %rax
1243 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1244 VG_(amd64_darwin_REDIR_FOR_strchr):
1266 .globl VG_(trampoline_stuff_end)
1267 VG_(trampoline_stuff_end):
1269 /* a trailing page of unexecutable code */
1270 .fill 2048, 2, 0x0b0f /* `ud2` */
1273 /*---------------- s390x-linux ----------------*/
1275 #if defined(VGP_s390x_linux)
1277 /* a leading page of unexecutable code */
1278 .fill 2048, 2, 0x0000
1280 .global VG_(trampoline_stuff_start)
1281 VG_(trampoline_stuff_start):
1283 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1284 VG_(s390x_linux_SUBST_FOR_sigreturn):
1288 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1289 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1290 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1291 for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1292 set ra to this trampoline, but the cfa is still in the stack,
1293 the unwinder thinks, that this is a non-rt frame and causes a
1294 crash in the gcc unwinder - which is used by the thread library
1295 and others. Therefore we add a lr 1,1 nop, to let the gcc
1296 unwinder bail out gracefully. This might also affect unwinding
1297 across the signal frame - tough luck. fixs390 */
1299 svc __NR_rt_sigreturn
1302 .global VG_(s390x_linux_REDIR_FOR_index)
1303 .type VG_(s390x_linux_REDIR_FOR_index),@function
1304 VG_(s390x_linux_REDIR_FOR_index):
1306 # %r2 = address of string
1307 # %r3 = character to find
1310 ngr %r0,%r3 # r0 = (unsigned char)r3
1313 llgc %r1,0(%r2) # r1 = byte from string
1314 cr %r1,%r0 # compare
1315 ber %r14 # return if found
1316 cr %r1,%r4 # end of string ?
1318 aghi %r2,1 # increment r2
1320 .L2: lghi %r2,0 # return value 0
1322 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1324 .globl VG_(trampoline_stuff_end)
1325 VG_(trampoline_stuff_end):
1326 .fill 2048, 2, 0x0000
1328 /*---------------------- mips32-linux ----------------------*/
1330 #if defined(VGP_mips32_linux)
1332 # define UD2_16 trap ; trap ; trap; trap
1333 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1334 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1335 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1336 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1339 .global VG_(trampoline_stuff_start)
1340 VG_(trampoline_stuff_start):
1342 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1343 VG_(mips32_linux_SUBST_FOR_sigreturn):
1344 li $v0,__NR_sigreturn
1347 .long 0 /*illegal insn*/
1349 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1350 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1351 li $v0,__NR_rt_sigreturn
1354 .long 0 /*illegal insn*/
1356 /* There's no particular reason that this needs to be handwritten
1357 assembly, but since that's what this file contains, here's a
1358 simple index() and strlen() implementations.
1364 .global VG_(mips32_linux_REDIR_FOR_index)
1365 .type VG_(mips32_linux_REDIR_FOR_index), @function
1366 VG_(mips32_linux_REDIR_FOR_index):
1370 beq $t0, $a1, index_end
1372 bne $t0, $zero, index_loop
1378 .size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1380 .global VG_(mips32_linux_REDIR_FOR_strlen)
1381 .type VG_(mips32_linux_REDIR_FOR_strlen), @function
1382 VG_(mips32_linux_REDIR_FOR_strlen):
1386 bne $t0, $zero, strlen_loop
1391 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1395 .global VG_(trampoline_stuff_end)
1396 VG_(trampoline_stuff_end):
1405 /*---------------------- nanomips-linux --------------------*/
1407 #if defined(VGP_nanomips_linux)
1409 .global VG_(trampoline_stuff_start)
1410 VG_(trampoline_stuff_start):
1415 .global VG_(nanomips_linux_SUBST_FOR_rt_sigreturn)
1416 VG_(nanomips_linux_SUBST_FOR_rt_sigreturn):
1417 li $t4, __NR_rt_sigreturn
1421 .global VG_(nanomips_linux_REDIR_FOR_index)
1422 .type VG_(nanomips_linux_REDIR_FOR_index), @function
1423 VG_(nanomips_linux_REDIR_FOR_index):
1426 beqc $t0, $a1, index_end
1428 bnec $t0, $zero, index_loop
1432 .size VG_(nanomips_linux_REDIR_FOR_index), .-VG_(nanomips_linux_REDIR_FOR_index)
1434 .global VG_(nanomips_linux_REDIR_FOR_strlen)
1435 .type VG_(nanomips_linux_REDIR_FOR_strlen), @function
1436 VG_(nanomips_linux_REDIR_FOR_strlen):
1441 bnec $t0, $zero, strlen_loop
1446 .size VG_(nanomips_linux_REDIR_FOR_strlen), .-VG_(nanomips_linux_REDIR_FOR_strlen)
1450 .global VG_(trampoline_stuff_end)
1451 VG_(trampoline_stuff_end):
1454 /*---------------------- mips64-linux ----------------------*/
1456 #if defined(VGP_mips64_linux)
1458 # define UD2_16 trap ; trap ; trap; trap
1459 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1460 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1461 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1462 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1464 .global VG_(trampoline_stuff_start)
1465 VG_(trampoline_stuff_start):
1467 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1468 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1469 li $2,__NR_rt_sigreturn
1472 .long 0 /*illegal insn*/
1474 /* There's no particular reason that this needs to be handwritten
1475 assembly, but since that's what this file contains, here's a
1476 simple index() and strlen() implementations.
1482 .global VG_(mips64_linux_REDIR_FOR_index)
1483 .type VG_(mips64_linux_REDIR_FOR_index), @function
1484 VG_(mips64_linux_REDIR_FOR_index):
1488 beq $t0, $a1, index_end
1490 bne $t0, $zero, index_loop
1496 .size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1498 .global VG_(mips64_linux_REDIR_FOR_strlen)
1499 .type VG_(mips64_linux_REDIR_FOR_strlen), @function
1500 VG_(mips64_linux_REDIR_FOR_strlen):
1504 bne $t0, $zero, strlen_loop
1509 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1513 .global VG_(trampoline_stuff_end)
1514 VG_(trampoline_stuff_end):
1523 /*---------------- x86-solaris ----------------*/
1525 #if defined(VGP_x86_solaris)
1527 .global VG_(trampoline_stuff_start)
1528 VG_(trampoline_stuff_start):
1530 /* int strcmp(const char *s1, const char *s2); */
1531 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1532 .type VG_(x86_solaris_REDIR_FOR_strcmp), @function
1533 VG_(x86_solaris_REDIR_FOR_strcmp):
1534 pushl %ebp /* establish a stack frame */
1536 movl 8(%ebp), %edx /* get s1 */
1537 movl 12(%esp), %ecx /* get s2 */
1538 jmp 2f /* go compare the first characters */
1540 incl %edx /* skip to the next s1 character */
1541 incl %ecx /* skip to the next s2 character */
1543 movzbl (%edx), %eax /* load a character from s1 */
1544 testb %al, %al /* is it null? */
1545 jz 3f /* yes, exit */
1546 cmpb (%ecx), %al /* are the characters equal? */
1547 je 1b /* yes, proceed with next characters */
1549 movzbl (%ecx), %edx /* load a character from s2 */
1550 subl %edx, %eax /* calculate the return value */
1551 popl %ebp /* destroy the stack frame */
1552 ret /* return to the caller */
1553 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1555 /* size_t strlen(const char *s); */
1556 .global VG_(x86_solaris_REDIR_FOR_strlen)
1557 .type VG_(x86_solaris_REDIR_FOR_strlen), @function
1558 VG_(x86_solaris_REDIR_FOR_strlen):
1559 pushl %ebp /* establish a stack frame */
1561 movl 8(%ebp), %edx /* get s */
1562 movl %edx, %eax /* copy s */
1563 jmp 2f /* go handle the first character */
1565 incl %eax /* skip to the next s character */
1567 cmpb $0, (%eax) /* is the s character null? */
1568 jne 1b /* no, go process the next character */
1569 subl %edx, %eax /* calculate the return value */
1570 popl %ebp /* destroy the stack frame */
1571 ret /* return to the caller */
1572 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1574 .global VG_(trampoline_stuff_end)
1575 VG_(trampoline_stuff_end):
1577 /*---------------- amd64-solaris ----------------*/
1579 #if defined(VGP_amd64_solaris)
1581 .global VG_(trampoline_stuff_start)
1582 VG_(trampoline_stuff_start):
1584 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1585 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1586 .type VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1587 VG_(amd64_solaris_REDIR_FOR_strcpy):
1588 pushq %rbp /* establish a stack frame */
1590 movq %rdi, %rdx /* copy s1 */
1592 movzbl (%rsi), %eax /* load one input character */
1593 movb %al, (%rdx) /* copy to output/s1 */
1594 incq %rsi /* skip to the next output character */
1595 incq %rdx /* skip to the next input character */
1596 testb %al, %al /* is the copied character null? */
1597 jnz 1b /* no, copy the next character */
1598 leave /* destroy the stack frame */
1599 movq %rdi, %rax /* set s1 as the return value */
1600 ret /* return to the caller */
1601 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1603 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1604 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1605 .type VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1606 VG_(amd64_solaris_REDIR_FOR_strncpy):
1607 pushq %rbp /* establish a stack frame */
1609 movq %rdi, %rcx /* copy s1 */
1611 testq %rdx, %rdx /* is the remaining size zero? */
1612 jz 3f /* yes, all done */
1613 movzbl (%rsi), %eax /* load one input character */
1614 movb %al, (%rcx) /* copy to output/s1 */
1615 decq %rdx /* decrement the remaining size */
1616 incq %rsi /* skip to the next output character */
1617 incq %rcx /* skip to the next input character */
1618 testb %al, %al /* is the copied character null? */
1619 jnz 1b /* no, copy the next character */
1621 testq %rdx, %rdx /* is the remaining size zero? */
1622 jz 3f /* yes, all done */
1623 movb $0, (%rdx) /* copy null to output/s2 */
1624 decq %rdx /* decrement the remaining size */
1625 incq %rsi /* skip to next output character */
1626 jmp 2b /* proceed with the next character */
1628 leave /* destroy the stack frame */
1629 movq %rdi, %rax /* set s1 as the return value */
1630 ret /* return to the caller */
1631 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1633 /* int strcmp(const char *s1, const char *s2); */
1634 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1635 .type VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1636 VG_(amd64_solaris_REDIR_FOR_strcmp):
1637 pushq %rbp /* establish a stack frame */
1639 jmp 2f /* go compare the first characters */
1641 incq %rdi /* skip to the next s1 character */
1642 incq %rsi /* skip to the next s2 character */
1644 movzbl (%rdi), %eax /* load a character from s1 */
1645 testb %al, %al /* is it null? */
1646 jz 3f /* yes, exit */
1647 cmpb (%rsi), %al /* are the characters equal? */
1648 je 1b /* yes, proceed with next characters */
1650 movzbl (%rsi), %edx /* load a character from s2 */
1651 subl %edx, %eax /* calculate the return value */
1652 leave /* destroy the stack frame */
1653 ret /* return to the caller */
1654 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1656 /* char *strcat(char *restrict s1, const char *restrict s2); */
1657 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1658 .type VG_(amd64_solaris_REDIR_FOR_strcat), @function
1659 VG_(amd64_solaris_REDIR_FOR_strcat):
1660 pushq %rbp /* establish a stack frame */
1662 movq %rdi, %rdx /* copy s1 */
1663 jmp 2f /* go handle the first character */
1665 incq %rdx /* skip to the next s1 character */
1667 cmpb $0, (%rdx) /* is the s1 character null? */
1668 jne 1b /* no, go check the next character */
1670 movzbl (%rsi), %eax /* load a character from s2 */
1671 movb %al, (%rdx) /* copy the s2 character to s1 */
1672 incq %rdx /* skip to the next s1 character */
1673 incq %rsi /* skip to the next s2 character */
1674 testb %al, %al /* was the character null? */
1675 jnz 3b /* no, go copy the next character */
1676 movq %rdi, %rax /* set s1 as the return value */
1677 leave /* destroy the stack frame */
1678 ret /* return to the caller */
1679 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1681 /* size_t strlen(const char *s); */
1682 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1683 .type VG_(amd64_solaris_REDIR_FOR_strlen), @function
1684 VG_(amd64_solaris_REDIR_FOR_strlen):
1685 pushq %rbp /* establish a stack frame */
1687 movq %rdi, %rax /* copy s */
1688 jmp 2f /* go handle the first character */
1690 incq %rax /* skip to the next s character */
1692 cmpb $0, (%rax) /* is the s character null? */
1693 jne 1b /* no, go process the next character */
1694 subq %rdi, %rax /* calculate the return value */
1695 leave /* destroy the stack frame */
1696 ret /* return to the caller */
1697 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1699 .global VG_(trampoline_stuff_end)
1700 VG_(trampoline_stuff_end):
1702 /*---------------- unknown ----------------*/
1704 # error Unknown platform
1723 /* Let the linker know we don't need an executable stack */
1726 /*--------------------------------------------------------------------*/
1728 /*--------------------------------------------------------------------*/