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, 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 .global VG_(amd64_linux_REDIR_FOR_vgetcpu)
193 .type VG_(amd64_linux_REDIR_FOR_vgetcpu), @function
194 VG_(amd64_linux_REDIR_FOR_vgetcpu):
196 movq $__NR_getcpu, %rax
200 .size VG_(amd64_linux_REDIR_FOR_vgetcpu), .-.LfnB4
202 /* There's no particular reason that this needs to be handwritten
203 assembly, but since that's what this file contains, here's a
204 simple strlen implementation (written in C and compiled by gcc.)
206 .global VG_(amd64_linux_REDIR_FOR_strlen)
207 .type VG_(amd64_linux_REDIR_FOR_strlen), @function
208 VG_(amd64_linux_REDIR_FOR_strlen):
221 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
223 .global VG_(amd64_linux_REDIR_FOR_index)
224 .type VG_(amd64_linux_REDIR_FOR_index), @function
225 VG_(amd64_linux_REDIR_FOR_index):
244 .size VG_(amd64_linux_REDIR_FOR_index), .-VG_(amd64_linux_REDIR_FOR_index)
248 /* A CIE for the above four functions, followed by their FDEs */
249 .section .eh_frame,"a",@progbits
251 .long .LEcie1-.LScie1
269 .long .LEfde2-.LASfde2
271 .long .LASfde2-.Lframe1
278 .long .LEfde3-.LASfde3
280 .long .LASfde3-.Lframe1
287 .long .LEfde4-.LASfde4
289 .long .LASfde4-.Lframe1
296 .long .LEfde5-.LASfde5
298 .long .LASfde5-.Lframe1
306 .global VG_(trampoline_stuff_end)
307 VG_(trampoline_stuff_end):
309 /* and a trailing page of unexecutable code */
318 /*---------------- ppc32-linux ----------------*/
320 #if defined(VGP_ppc32_linux)
322 # define UD2_16 trap ; trap ; trap; trap
323 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
324 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
325 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
326 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
328 /* a leading page of unexecutable code */
331 .global VG_(trampoline_stuff_start)
332 VG_(trampoline_stuff_start):
334 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
335 VG_(ppc32_linux_SUBST_FOR_sigreturn):
338 .long 0 /*illegal insn*/
340 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
341 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
342 li 0,__NR_rt_sigreturn
344 .long 0 /*illegal insn*/
346 /* There's no particular reason that this needs to be handwritten
347 assembly, but since that's what this file contains, here's a
348 simple strlen implementation (written in C and compiled by gcc.)
350 .global VG_(ppc32_linux_REDIR_FOR_strlen)
351 .type VG_(ppc32_linux_REDIR_FOR_strlen), @function
352 VG_(ppc32_linux_REDIR_FOR_strlen):
365 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
368 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
369 .type VG_(ppc32_linux_REDIR_FOR_strcmp), @function
370 VG_(ppc32_linux_REDIR_FOR_strcmp):
403 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
405 /* Ditto index/strchr */
406 .global VG_(ppc32_linux_REDIR_FOR_strchr)
407 .type VG_(ppc32_linux_REDIR_FOR_strchr), @function
408 VG_(ppc32_linux_REDIR_FOR_strchr):
427 .size VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
429 .global VG_(trampoline_stuff_end)
430 VG_(trampoline_stuff_end):
432 /* and a trailing page of unexecutable code */
441 /*---------------- ppc64-linux ----------------*/
443 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
445 # define UD2_16 trap ; trap ; trap; trap
446 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
447 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
448 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
449 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
451 /* a leading page of unexecutable code */
454 .global VG_(trampoline_stuff_start)
455 VG_(trampoline_stuff_start):
457 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
458 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
459 li 0,__NR_rt_sigreturn
461 .long 0 /*illegal insn*/
463 /* See comment in pub_core_trampoline.h for what this is for */
464 .global VG_(ppctoc_magic_redirect_return_stub)
465 VG_(ppctoc_magic_redirect_return_stub):
468 /* this function is written using the "dotless" ABI convention */
470 .globl VG_(ppc64_linux_REDIR_FOR_strlen)
471 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
472 /* Little Endian uses ELF version 2 */
473 .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
474 VG_(ppc64_linux_REDIR_FOR_strlen):
476 /* Big Endian uses ELF version 1 */
479 VG_(ppc64_linux_REDIR_FOR_strlen):
480 .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
482 .size VG_(ppc64_linux_REDIR_FOR_strlen), \
483 .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
484 .type VG_(ppc64_linux_REDIR_FOR_strlen), @function
486 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
489 0: addis 2,12,.TOC.-0b@ha
491 .localentry VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
507 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
508 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
510 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
513 .byte 0,0,0,0,0,0,0,0
516 /* this function is written using the "dotless" ABI convention */
518 .globl VG_(ppc64_linux_REDIR_FOR_strchr)
519 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
520 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
521 VG_(ppc64_linux_REDIR_FOR_strchr):
525 VG_(ppc64_linux_REDIR_FOR_strchr):
526 .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
528 .size VG_(ppc64_linux_REDIR_FOR_strchr), \
529 .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
530 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
532 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
535 0: addis 2,12,.TOC.-0b@ha
537 .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
546 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
547 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
549 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
563 .byte 0,0,0,0,0,0,0,0
567 .global VG_(trampoline_stuff_end)
568 VG_(trampoline_stuff_end):
570 /* and a trailing page of unexecutable code */
579 /*---------------- arm-linux ----------------*/
581 #if defined(VGP_arm_linux)
583 # define UD2_4 .word 0xFFFFFFFF
584 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
585 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
586 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
587 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
588 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
590 /* a leading page of unexecutable code */
593 .global VG_(trampoline_stuff_start)
594 VG_(trampoline_stuff_start):
596 .global VG_(arm_linux_SUBST_FOR_sigreturn)
597 .type VG_(arm_linux_SUBST_FOR_sigreturn),#function
598 VG_(arm_linux_SUBST_FOR_sigreturn):
599 mov r7, # __NR_sigreturn
601 .long 0xFFFFFFFF /*illegal insn*/
602 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
604 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
605 .type VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
606 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
607 mov r7, # __NR_rt_sigreturn
609 .long 0xFFFFFFFF /*illegal insn*/
610 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
612 .global VG_(arm_linux_REDIR_FOR_strlen)
613 VG_(arm_linux_REDIR_FOR_strlen):
615 ldrb r0, [r0, #0] @ zero_extendqisi2
616 @ lr needed for prologue
622 ldrb r3, [r0, r2] @ zero_extendqisi2
628 .global VG_(arm_linux_REDIR_FOR_index)
629 VG_(arm_linux_REDIR_FOR_index):
630 ldrb r3, [r0, #0] @ zero_extendqisi2
633 @ lr needed for prologue
637 ldrb r3, [r0, #1]! @ zero_extendqisi2
649 .global VG_(arm_linux_REDIR_FOR_memcpy)
650 VG_(arm_linux_REDIR_FOR_memcpy):
651 stmfd sp!, {r4, r5, lr}
666 ldrb r3, [r1, #4] @ zero_extendqisi2
669 ldrb r2, [r1, #3] @ zero_extendqisi2
672 ldrb r3, [r1, #2] @ zero_extendqisi2
675 ldrb r2, [r1, #1] @ zero_extendqisi2
687 ldrb r3, [r0], #-1 @ zero_extendqisi2
693 ldmfd sp!, {r4, r5, pc}
700 ldrb r3, [r1, #0] @ zero_extendqisi2
703 ldrb r2, [r1, #1] @ zero_extendqisi2
706 ldrb r3, [r1, #2] @ zero_extendqisi2
708 ldrb r2, [r1, #3] @ zero_extendqisi2
719 ldrb r3, [r1], #1 @ zero_extendqisi2
724 ldmfd sp!, {r4, r5, pc}
727 .global VG_(arm_linux_REDIR_FOR_strcmp)
728 VG_(arm_linux_REDIR_FOR_strcmp):
730 ldrb r3, [r0], #1 @ zero_extendqisi2
731 ldrb r2, [r1], #1 @ zero_extendqisi2
743 .global VG_(trampoline_stuff_end)
744 VG_(trampoline_stuff_end):
746 /* and a trailing page of unexecutable code */
756 /*---------------- arm64-linux ----------------*/
758 #if defined(VGP_arm64_linux)
760 # define UD2_4 .word 0xFFFFFFFF
761 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
762 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
763 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
764 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
765 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
767 /* a leading page of unexecutable code */
770 .global VG_(trampoline_stuff_start)
771 VG_(trampoline_stuff_start):
773 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
774 .type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
775 VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
776 mov x8, # __NR_rt_sigreturn
778 .long 0xFFFFFFFF /*illegal insn*/
779 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
780 .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
782 .global VG_(arm64_linux_REDIR_FOR_strlen)
783 .type VG_(arm64_linux_REDIR_FOR_strlen),#function
784 VG_(arm64_linux_REDIR_FOR_strlen):
797 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
799 .global VG_(arm64_linux_REDIR_FOR_index)
800 .type VG_(arm64_linux_REDIR_FOR_index),#function
801 VG_(arm64_linux_REDIR_FOR_index):
816 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
818 .global VG_(arm64_linux_REDIR_FOR_strcmp)
819 .type VG_(arm64_linux_REDIR_FOR_strcmp),#function
820 VG_(arm64_linux_REDIR_FOR_strcmp):
841 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
843 .global VG_(trampoline_stuff_end)
844 VG_(trampoline_stuff_end):
846 /* and a trailing page of unexecutable code */
856 /*---------------- x86-darwin ----------------*/
858 #if defined(VGP_x86_darwin)
860 /* a leading page of unexecutable code */
861 .fill 2048, 2, 0x0b0f /* `ud2` */
863 .globl VG_(trampoline_stuff_start)
864 VG_(trampoline_stuff_start):
866 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
867 VG_(x86_darwin_SUBST_FOR_sigreturn):
868 /* XXX does this need to have any special form? (cf x86-linux
870 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax
874 .globl VG_(x86_darwin_REDIR_FOR_strlen)
875 VG_(x86_darwin_REDIR_FOR_strlen):
887 .globl VG_(x86_darwin_REDIR_FOR_strcat)
888 VG_(x86_darwin_REDIR_FOR_strcat):
911 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
912 VG_(x86_darwin_REDIR_FOR_strcmp):
932 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
933 VG_(x86_darwin_REDIR_FOR_strcpy):
954 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
955 VG_(x86_darwin_REDIR_FOR_strlcat):
964 leal (%ecx,%esi), %eax
984 call VG_(x86_darwin_REDIR_FOR_strlen)
1002 leal (%edi,%eax), %eax
1009 .globl VG_(trampoline_stuff_end)
1010 VG_(trampoline_stuff_end):
1012 /* a trailing page of unexecutable code */
1013 .fill 2048, 2, 0x0b0f /* `ud2` */
1016 /*---------------- amd64-darwin ----------------*/
1018 #if defined(VGP_amd64_darwin)
1020 /* a leading page of unexecutable code */
1021 .fill 2048, 2, 0x0b0f /* `ud2` */
1023 .globl VG_(trampoline_stuff_start)
1024 VG_(trampoline_stuff_start):
1026 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1027 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1028 /* XXX does this need to have any special form? (cf x86-linux
1030 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1034 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1035 VG_(amd64_darwin_REDIR_FOR_strlen):
1046 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1047 VG_(amd64_darwin_REDIR_FOR_strcat):
1066 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1067 VG_(amd64_darwin_REDIR_FOR_strcmp):
1084 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1085 VG_(amd64_darwin_REDIR_FOR_strcpy):
1102 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1103 VG_(amd64_darwin_REDIR_FOR_strlcat):
1105 leaq (%rdx,%rdi), %rax
1128 call VG_(amd64_darwin_REDIR_FOR_strlen)
1145 leaq (%rbx,%rax), %rax
1151 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1152 VG_(amd64_darwin_REDIR_FOR_arc4random):
1153 /* not very random, hope dyld won't mind */
1154 movq $0x76616c6772696e64, %rax
1157 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1158 VG_(amd64_darwin_REDIR_FOR_strchr):
1180 .globl VG_(trampoline_stuff_end)
1181 VG_(trampoline_stuff_end):
1183 /* a trailing page of unexecutable code */
1184 .fill 2048, 2, 0x0b0f /* `ud2` */
1187 /*---------------- s390x-linux ----------------*/
1189 #if defined(VGP_s390x_linux)
1191 /* a leading page of unexecutable code */
1192 .fill 2048, 2, 0x0000
1194 .global VG_(trampoline_stuff_start)
1195 VG_(trampoline_stuff_start):
1197 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1198 VG_(s390x_linux_SUBST_FOR_sigreturn):
1202 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1203 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1204 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1205 for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1206 set ra to this trampoline, but the cfa is still in the stack,
1207 the unwinder thinks, that this is a non-rt frame and causes a
1208 crash in the gcc unwinder - which is used by the thread library
1209 and others. Therefore we add a lr 1,1 nop, to let the gcc
1210 unwinder bail out gracefully. This might also affect unwinding
1211 across the signal frame - tough luck. fixs390 */
1213 svc __NR_rt_sigreturn
1216 .global VG_(s390x_linux_REDIR_FOR_index)
1217 .type VG_(s390x_linux_REDIR_FOR_index),@function
1218 VG_(s390x_linux_REDIR_FOR_index):
1220 # %r2 = address of string
1221 # %r3 = character to find
1224 ngr %r0,%r3 # r0 = (unsigned char)r3
1227 llgc %r1,0(%r2) # r1 = byte from string
1228 cr %r1,%r0 # compare
1229 ber %r14 # return if found
1230 cr %r1,%r4 # end of string ?
1232 aghi %r2,1 # increment r2
1234 .L2: lghi %r2,0 # return value 0
1236 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1238 .globl VG_(trampoline_stuff_end)
1239 VG_(trampoline_stuff_end):
1240 .fill 2048, 2, 0x0000
1242 /*---------------------- mips32-linux ----------------------*/
1244 #if defined(VGP_mips32_linux)
1246 # define UD2_16 trap ; trap ; trap; trap
1247 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1248 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1249 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1250 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1253 .global VG_(trampoline_stuff_start)
1254 VG_(trampoline_stuff_start):
1256 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1257 VG_(mips32_linux_SUBST_FOR_sigreturn):
1258 li $v0,__NR_sigreturn
1261 .long 0 /*illegal insn*/
1263 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1264 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1265 li $v0,__NR_rt_sigreturn
1268 .long 0 /*illegal insn*/
1270 /* There's no particular reason that this needs to be handwritten
1271 assembly, but since that's what this file contains, here's a
1272 simple index() and strlen() implementations.
1278 .global VG_(mips32_linux_REDIR_FOR_index)
1279 .type VG_(mips32_linux_REDIR_FOR_index), @function
1280 VG_(mips32_linux_REDIR_FOR_index):
1284 beq $t0, $a1, index_end
1286 bne $t0, $zero, index_loop
1292 .size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1294 .global VG_(mips32_linux_REDIR_FOR_strlen)
1295 .type VG_(mips32_linux_REDIR_FOR_strlen), @function
1296 VG_(mips32_linux_REDIR_FOR_strlen):
1300 bne $t0, $zero, strlen_loop
1305 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1309 .global VG_(trampoline_stuff_end)
1310 VG_(trampoline_stuff_end):
1319 /*---------------------- mips64-linux ----------------------*/
1321 #if defined(VGP_mips64_linux)
1323 # define UD2_16 trap ; trap ; trap; trap
1324 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1325 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1326 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1327 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1329 .global VG_(trampoline_stuff_start)
1330 VG_(trampoline_stuff_start):
1332 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1333 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1334 li $2,__NR_rt_sigreturn
1337 .long 0 /*illegal insn*/
1339 /* There's no particular reason that this needs to be handwritten
1340 assembly, but since that's what this file contains, here's a
1341 simple index() and strlen() implementations.
1347 .global VG_(mips64_linux_REDIR_FOR_index)
1348 .type VG_(mips64_linux_REDIR_FOR_index), @function
1349 VG_(mips64_linux_REDIR_FOR_index):
1353 beq $t0, $a1, index_end
1355 bne $t0, $zero, index_loop
1361 .size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1363 .global VG_(mips64_linux_REDIR_FOR_strlen)
1364 .type VG_(mips64_linux_REDIR_FOR_strlen), @function
1365 VG_(mips64_linux_REDIR_FOR_strlen):
1369 bne $t0, $zero, strlen_loop
1374 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1378 .global VG_(trampoline_stuff_end)
1379 VG_(trampoline_stuff_end):
1388 /*---------------- x86-solaris ----------------*/
1390 #if defined(VGP_x86_solaris)
1392 .global VG_(trampoline_stuff_start)
1393 VG_(trampoline_stuff_start):
1395 /* int strcmp(const char *s1, const char *s2); */
1396 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1397 .type VG_(x86_solaris_REDIR_FOR_strcmp), @function
1398 VG_(x86_solaris_REDIR_FOR_strcmp):
1399 pushl %ebp /* establish a stack frame */
1401 movl 8(%ebp), %edx /* get s1 */
1402 movl 12(%esp), %ecx /* get s2 */
1403 jmp 2f /* go compare the first characters */
1405 incl %edx /* skip to the next s1 character */
1406 incl %ecx /* skip to the next s2 character */
1408 movzbl (%edx), %eax /* load a character from s1 */
1409 testb %al, %al /* is it null? */
1410 jz 3f /* yes, exit */
1411 cmpb (%ecx), %al /* are the characters equal? */
1412 je 1b /* yes, proceed with next characters */
1414 movzbl (%ecx), %edx /* load a character from s2 */
1415 subl %edx, %eax /* calculate the return value */
1416 popl %ebp /* destroy the stack frame */
1417 ret /* return to the caller */
1418 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1420 /* size_t strlen(const char *s); */
1421 .global VG_(x86_solaris_REDIR_FOR_strlen)
1422 .type VG_(x86_solaris_REDIR_FOR_strlen), @function
1423 VG_(x86_solaris_REDIR_FOR_strlen):
1424 pushl %ebp /* establish a stack frame */
1426 movl 8(%ebp), %edx /* get s */
1427 movl %edx, %eax /* copy s */
1428 jmp 2f /* go handle the first character */
1430 incl %eax /* skip to the next s character */
1432 cmpb $0, (%eax) /* is the s character null? */
1433 jne 1b /* no, go process the next character */
1434 subl %edx, %eax /* calculate the return value */
1435 popl %ebp /* destroy the stack frame */
1436 ret /* return to the caller */
1437 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1439 .global VG_(trampoline_stuff_end)
1440 VG_(trampoline_stuff_end):
1442 /*---------------- amd64-solaris ----------------*/
1444 #if defined(VGP_amd64_solaris)
1446 .global VG_(trampoline_stuff_start)
1447 VG_(trampoline_stuff_start):
1449 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1450 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1451 .type VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1452 VG_(amd64_solaris_REDIR_FOR_strcpy):
1453 pushq %rbp /* establish a stack frame */
1455 movq %rdi, %rdx /* copy s1 */
1457 movzbl (%rsi), %eax /* load one input character */
1458 movb %al, (%rdx) /* copy to output/s1 */
1459 incq %rsi /* skip to the next output character */
1460 incq %rdx /* skip to the next input character */
1461 testb %al, %al /* is the copied character null? */
1462 jnz 1b /* no, copy the next character */
1463 leave /* destroy the stack frame */
1464 movq %rdi, %rax /* set s1 as the return value */
1465 ret /* return to the caller */
1466 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1468 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1469 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1470 .type VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1471 VG_(amd64_solaris_REDIR_FOR_strncpy):
1472 pushq %rbp /* establish a stack frame */
1474 movq %rdi, %rcx /* copy s1 */
1476 testq %rdx, %rdx /* is the remaining size zero? */
1477 jz 3f /* yes, all done */
1478 movzbl (%rsi), %eax /* load one input character */
1479 movb %al, (%rcx) /* copy to output/s1 */
1480 decq %rdx /* decrement the remaining size */
1481 incq %rsi /* skip to the next output character */
1482 incq %rcx /* skip to the next input character */
1483 testb %al, %al /* is the copied character null? */
1484 jnz 1b /* no, copy the next character */
1486 testq %rdx, %rdx /* is the remaining size zero? */
1487 jz 3f /* yes, all done */
1488 movb $0, (%rdx) /* copy null to output/s2 */
1489 decq %rdx /* decrement the remaining size */
1490 incq %rsi /* skip to next output character */
1491 jmp 2b /* proceed with the next character */
1493 leave /* destroy the stack frame */
1494 movq %rdi, %rax /* set s1 as the return value */
1495 ret /* return to the caller */
1496 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1498 /* int strcmp(const char *s1, const char *s2); */
1499 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1500 .type VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1501 VG_(amd64_solaris_REDIR_FOR_strcmp):
1502 pushq %rbp /* establish a stack frame */
1504 jmp 2f /* go compare the first characters */
1506 incq %rdi /* skip to the next s1 character */
1507 incq %rsi /* skip to the next s2 character */
1509 movzbl (%rdi), %eax /* load a character from s1 */
1510 testb %al, %al /* is it null? */
1511 jz 3f /* yes, exit */
1512 cmpb (%rsi), %al /* are the characters equal? */
1513 je 1b /* yes, proceed with next characters */
1515 movzbl (%rsi), %edx /* load a character from s2 */
1516 subl %edx, %eax /* calculate the return value */
1517 leave /* destroy the stack frame */
1518 ret /* return to the caller */
1519 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1521 /* char *strcat(char *restrict s1, const char *restrict s2); */
1522 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1523 .type VG_(amd64_solaris_REDIR_FOR_strcat), @function
1524 VG_(amd64_solaris_REDIR_FOR_strcat):
1525 pushq %rbp /* establish a stack frame */
1527 movq %rdi, %rdx /* copy s1 */
1528 jmp 2f /* go handle the first character */
1530 incq %rdx /* skip to the next s1 character */
1532 cmpb $0, (%rdx) /* is the s1 character null? */
1533 jne 1b /* no, go check the next character */
1535 movzbl (%rsi), %eax /* load a character from s2 */
1536 movb %al, (%rdx) /* copy the s2 character to s1 */
1537 incq %rdx /* skip to the next s1 character */
1538 incq %rsi /* skip to the next s2 character */
1539 testb %al, %al /* was the character null? */
1540 jnz 3b /* no, go copy the next character */
1541 movq %rdi, %rax /* set s1 as the return value */
1542 leave /* destroy the stack frame */
1543 ret /* return to the caller */
1544 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1546 /* size_t strlen(const char *s); */
1547 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1548 .type VG_(amd64_solaris_REDIR_FOR_strlen), @function
1549 VG_(amd64_solaris_REDIR_FOR_strlen):
1550 pushq %rbp /* establish a stack frame */
1552 movq %rdi, %rax /* copy s */
1553 jmp 2f /* go handle the first character */
1555 incq %rax /* skip to the next s character */
1557 cmpb $0, (%rax) /* is the s character null? */
1558 jne 1b /* no, go process the next character */
1559 subq %rdi, %rax /* calculate the return value */
1560 leave /* destroy the stack frame */
1561 ret /* return to the caller */
1562 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1564 .global VG_(trampoline_stuff_end)
1565 VG_(trampoline_stuff_end):
1567 /*---------------- unknown ----------------*/
1569 # error Unknown platform
1585 /* Let the linker know we don't need an executable stack */
1588 /*--------------------------------------------------------------------*/
1590 /*--------------------------------------------------------------------*/