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-2015 Julian Seward
12 Copyright (C) 2006-2015 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)
224 /* A CIE for the above four functions, followed by their FDEs */
225 .section .eh_frame,"a",@progbits
227 .long .LEcie1-.LScie1
245 .long .LEfde2-.LASfde2
247 .long .LASfde2-.Lframe1
254 .long .LEfde3-.LASfde3
256 .long .LASfde3-.Lframe1
263 .long .LEfde4-.LASfde4
265 .long .LASfde4-.Lframe1
272 .long .LEfde5-.LASfde5
274 .long .LASfde5-.Lframe1
282 .global VG_(trampoline_stuff_end)
283 VG_(trampoline_stuff_end):
285 /* and a trailing page of unexecutable code */
294 /*---------------- ppc32-linux ----------------*/
296 #if defined(VGP_ppc32_linux)
298 # define UD2_16 trap ; trap ; trap; trap
299 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
300 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
301 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
302 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
304 /* a leading page of unexecutable code */
307 .global VG_(trampoline_stuff_start)
308 VG_(trampoline_stuff_start):
310 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
311 VG_(ppc32_linux_SUBST_FOR_sigreturn):
314 .long 0 /*illegal insn*/
316 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
317 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
318 li 0,__NR_rt_sigreturn
320 .long 0 /*illegal insn*/
322 /* There's no particular reason that this needs to be handwritten
323 assembly, but since that's what this file contains, here's a
324 simple strlen implementation (written in C and compiled by gcc.)
326 .global VG_(ppc32_linux_REDIR_FOR_strlen)
327 .type VG_(ppc32_linux_REDIR_FOR_strlen), @function
328 VG_(ppc32_linux_REDIR_FOR_strlen):
341 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
344 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
345 .type VG_(ppc32_linux_REDIR_FOR_strcmp), @function
346 VG_(ppc32_linux_REDIR_FOR_strcmp):
379 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
381 /* Ditto index/strchr */
382 .global VG_(ppc32_linux_REDIR_FOR_strchr)
383 .type VG_(ppc32_linux_REDIR_FOR_strchr), @function
384 VG_(ppc32_linux_REDIR_FOR_strchr):
403 .size VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
405 .global VG_(trampoline_stuff_end)
406 VG_(trampoline_stuff_end):
408 /* and a trailing page of unexecutable code */
417 /*---------------- ppc64-linux ----------------*/
419 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
421 # define UD2_16 trap ; trap ; trap; trap
422 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
423 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
424 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
425 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
427 /* a leading page of unexecutable code */
430 .global VG_(trampoline_stuff_start)
431 VG_(trampoline_stuff_start):
433 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
434 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
435 li 0,__NR_rt_sigreturn
437 .long 0 /*illegal insn*/
439 /* See comment in pub_core_trampoline.h for what this is for */
440 .global VG_(ppctoc_magic_redirect_return_stub)
441 VG_(ppctoc_magic_redirect_return_stub):
444 /* this function is written using the "dotless" ABI convention */
446 .globl VG_(ppc64_linux_REDIR_FOR_strlen)
447 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
448 /* Little Endian uses ELF version 2 */
449 .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
450 VG_(ppc64_linux_REDIR_FOR_strlen):
452 /* Big Endian uses ELF version 1 */
455 VG_(ppc64_linux_REDIR_FOR_strlen):
456 .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
458 .size VG_(ppc64_linux_REDIR_FOR_strlen), \
459 .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
460 .type VG_(ppc64_linux_REDIR_FOR_strlen), @function
462 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
465 0: addis 2,12,.TOC.-0b@ha
467 .localentry VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
483 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
484 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
486 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
489 .byte 0,0,0,0,0,0,0,0
492 /* this function is written using the "dotless" ABI convention */
494 .globl VG_(ppc64_linux_REDIR_FOR_strchr)
495 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
496 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
497 VG_(ppc64_linux_REDIR_FOR_strchr):
501 VG_(ppc64_linux_REDIR_FOR_strchr):
502 .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
504 .size VG_(ppc64_linux_REDIR_FOR_strchr), \
505 .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
506 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function
508 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
511 0: addis 2,12,.TOC.-0b@ha
513 .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
522 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
523 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
525 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
539 .byte 0,0,0,0,0,0,0,0
543 .global VG_(trampoline_stuff_end)
544 VG_(trampoline_stuff_end):
546 /* and a trailing page of unexecutable code */
555 /*---------------- arm-linux ----------------*/
557 #if defined(VGP_arm_linux)
559 # define UD2_4 .word 0xFFFFFFFF
560 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
561 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
562 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
563 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
564 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
566 /* a leading page of unexecutable code */
569 .global VG_(trampoline_stuff_start)
570 VG_(trampoline_stuff_start):
572 .global VG_(arm_linux_SUBST_FOR_sigreturn)
573 .type VG_(arm_linux_SUBST_FOR_sigreturn),#function
574 VG_(arm_linux_SUBST_FOR_sigreturn):
575 mov r7, # __NR_sigreturn
577 .long 0xFFFFFFFF /*illegal insn*/
578 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
580 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
581 .type VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
582 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
583 mov r7, # __NR_rt_sigreturn
585 .long 0xFFFFFFFF /*illegal insn*/
586 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
588 .global VG_(arm_linux_REDIR_FOR_strlen)
589 VG_(arm_linux_REDIR_FOR_strlen):
591 ldrb r0, [r0, #0] @ zero_extendqisi2
592 @ lr needed for prologue
598 ldrb r3, [r0, r2] @ zero_extendqisi2
604 //.global VG_(arm_linux_REDIR_FOR_index)
605 //VG_(arm_linux_REDIR_FOR_index):
606 // ldrb r3, [r0, #0] @ zero_extendqisi2
609 // @ lr needed for prologue
613 // ldrb r3, [r0, #1]! @ zero_extendqisi2
625 .global VG_(arm_linux_REDIR_FOR_memcpy)
626 VG_(arm_linux_REDIR_FOR_memcpy):
627 stmfd sp!, {r4, r5, lr}
642 ldrb r3, [r1, #4] @ zero_extendqisi2
645 ldrb r2, [r1, #3] @ zero_extendqisi2
648 ldrb r3, [r1, #2] @ zero_extendqisi2
651 ldrb r2, [r1, #1] @ zero_extendqisi2
663 ldrb r3, [r0], #-1 @ zero_extendqisi2
669 ldmfd sp!, {r4, r5, pc}
676 ldrb r3, [r1, #0] @ zero_extendqisi2
679 ldrb r2, [r1, #1] @ zero_extendqisi2
682 ldrb r3, [r1, #2] @ zero_extendqisi2
684 ldrb r2, [r1, #3] @ zero_extendqisi2
695 ldrb r3, [r1], #1 @ zero_extendqisi2
700 ldmfd sp!, {r4, r5, pc}
703 .global VG_(arm_linux_REDIR_FOR_strcmp)
704 VG_(arm_linux_REDIR_FOR_strcmp):
706 ldrb r3, [r0], #1 @ zero_extendqisi2
707 ldrb r2, [r1], #1 @ zero_extendqisi2
719 .global VG_(trampoline_stuff_end)
720 VG_(trampoline_stuff_end):
722 /* and a trailing page of unexecutable code */
732 /*---------------- arm64-linux ----------------*/
734 #if defined(VGP_arm64_linux)
736 # define UD2_4 .word 0xFFFFFFFF
737 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4
738 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
739 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
740 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
741 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
743 /* a leading page of unexecutable code */
746 .global VG_(trampoline_stuff_start)
747 VG_(trampoline_stuff_start):
749 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
750 .type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
751 VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
752 mov x8, # __NR_rt_sigreturn
754 .long 0xFFFFFFFF /*illegal insn*/
755 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
756 .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
758 .global VG_(arm64_linux_REDIR_FOR_strlen)
759 .type VG_(arm64_linux_REDIR_FOR_strlen),#function
760 VG_(arm64_linux_REDIR_FOR_strlen):
773 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
775 .global VG_(arm64_linux_REDIR_FOR_index)
776 .type VG_(arm64_linux_REDIR_FOR_index),#function
777 VG_(arm64_linux_REDIR_FOR_index):
792 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
794 .global VG_(arm64_linux_REDIR_FOR_strcmp)
795 .type VG_(arm64_linux_REDIR_FOR_strcmp),#function
796 VG_(arm64_linux_REDIR_FOR_strcmp):
817 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
819 .global VG_(trampoline_stuff_end)
820 VG_(trampoline_stuff_end):
822 /* and a trailing page of unexecutable code */
832 /*---------------- x86-darwin ----------------*/
834 #if defined(VGP_x86_darwin)
836 /* a leading page of unexecutable code */
837 .fill 2048, 2, 0x0b0f /* `ud2` */
839 .globl VG_(trampoline_stuff_start)
840 VG_(trampoline_stuff_start):
842 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
843 VG_(x86_darwin_SUBST_FOR_sigreturn):
844 /* XXX does this need to have any special form? (cf x86-linux
846 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax
850 .globl VG_(x86_darwin_REDIR_FOR_strlen)
851 VG_(x86_darwin_REDIR_FOR_strlen):
863 .globl VG_(x86_darwin_REDIR_FOR_strcat)
864 VG_(x86_darwin_REDIR_FOR_strcat):
887 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
888 VG_(x86_darwin_REDIR_FOR_strcmp):
908 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
909 VG_(x86_darwin_REDIR_FOR_strcpy):
930 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
931 VG_(x86_darwin_REDIR_FOR_strlcat):
940 leal (%ecx,%esi), %eax
960 call VG_(x86_darwin_REDIR_FOR_strlen)
978 leal (%edi,%eax), %eax
985 .globl VG_(trampoline_stuff_end)
986 VG_(trampoline_stuff_end):
988 /* a trailing page of unexecutable code */
989 .fill 2048, 2, 0x0b0f /* `ud2` */
992 /*---------------- amd64-darwin ----------------*/
994 #if defined(VGP_amd64_darwin)
996 /* a leading page of unexecutable code */
997 .fill 2048, 2, 0x0b0f /* `ud2` */
999 .globl VG_(trampoline_stuff_start)
1000 VG_(trampoline_stuff_start):
1002 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1003 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1004 /* XXX does this need to have any special form? (cf x86-linux
1006 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1010 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1011 VG_(amd64_darwin_REDIR_FOR_strlen):
1022 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1023 VG_(amd64_darwin_REDIR_FOR_strcat):
1042 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1043 VG_(amd64_darwin_REDIR_FOR_strcmp):
1060 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1061 VG_(amd64_darwin_REDIR_FOR_strcpy):
1078 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1079 VG_(amd64_darwin_REDIR_FOR_strlcat):
1081 leaq (%rdx,%rdi), %rax
1104 call VG_(amd64_darwin_REDIR_FOR_strlen)
1121 leaq (%rbx,%rax), %rax
1127 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1128 VG_(amd64_darwin_REDIR_FOR_arc4random):
1129 /* not very random, hope dyld won't mind */
1130 movq $0x76616c6772696e64, %rax
1133 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1134 VG_(amd64_darwin_REDIR_FOR_strchr):
1156 .globl VG_(trampoline_stuff_end)
1157 VG_(trampoline_stuff_end):
1159 /* a trailing page of unexecutable code */
1160 .fill 2048, 2, 0x0b0f /* `ud2` */
1163 /*---------------- s390x-linux ----------------*/
1165 #if defined(VGP_s390x_linux)
1167 /* a leading page of unexecutable code */
1168 .fill 2048, 2, 0x0000
1170 .global VG_(trampoline_stuff_start)
1171 VG_(trampoline_stuff_start):
1173 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1174 VG_(s390x_linux_SUBST_FOR_sigreturn):
1178 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1179 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1180 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1181 for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1182 set ra to this trampoline, but the cfa is still in the stack,
1183 the unwinder thinks, that this is a non-rt frame and causes a
1184 crash in the gcc unwinder - which is used by the thread library
1185 and others. Therefore we add a lr 1,1 nop, to let the gcc
1186 unwinder bail out gracefully. This might also affect unwinding
1187 across the signal frame - tough luck. fixs390 */
1189 svc __NR_rt_sigreturn
1192 .global VG_(s390x_linux_REDIR_FOR_index)
1193 .type VG_(s390x_linux_REDIR_FOR_index),@function
1194 VG_(s390x_linux_REDIR_FOR_index):
1196 # %r2 = addess of string
1197 # %r3 = character to find
1200 ngr %r0,%r3 # r0 = (unsigned char)r3
1203 llgc %r1,0(%r2) # r1 = byte from string
1204 cr %r1,%r0 # compare
1205 ber %r14 # return if found
1206 cr %r1,%r4 # end of string ?
1208 aghi %r2,1 # increment r2
1210 .L2: lghi %r2,0 # return value 0
1212 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1214 .globl VG_(trampoline_stuff_end)
1215 VG_(trampoline_stuff_end):
1216 .fill 2048, 2, 0x0000
1218 /*---------------------- mips32-linux ----------------------*/
1220 #if defined(VGP_mips32_linux)
1222 # define UD2_16 trap ; trap ; trap; trap
1223 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1224 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1225 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1226 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1229 .global VG_(trampoline_stuff_start)
1230 VG_(trampoline_stuff_start):
1232 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1233 VG_(mips32_linux_SUBST_FOR_sigreturn):
1234 li $v0,__NR_sigreturn
1237 .long 0 /*illegal insn*/
1239 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1240 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1241 li $v0,__NR_rt_sigreturn
1244 .long 0 /*illegal insn*/
1246 /* There's no particular reason that this needs to be handwritten
1247 assembly, but since that's what this file contains, here's a
1248 simple strlen implementation (written in C and compiled by gcc.)
1250 .global VG_(mips32_linux_REDIR_FOR_strlen)
1251 .type VG_(mips32_linux_REDIR_FOR_strlen), @function
1252 VG_(mips32_linux_REDIR_FOR_strlen):
1261 bne $t0, $zero, strlen_loop
1264 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1266 .global VG_(trampoline_stuff_end)
1267 VG_(trampoline_stuff_end):
1276 /*---------------------- mips64-linux ----------------------*/
1278 #if defined(VGP_mips64_linux)
1280 # define UD2_16 trap ; trap ; trap; trap
1281 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1282 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1283 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1284 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1286 .global VG_(trampoline_stuff_start)
1287 VG_(trampoline_stuff_start):
1289 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1290 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1291 li $2,__NR_rt_sigreturn
1294 .long 0 /*illegal insn*/
1296 /* There's no particular reason that this needs to be handwritten
1297 assembly, but since that's what this file contains, here's a
1298 simple strlen implementation (written in C and compiled by gcc.)
1300 .global VG_(mips64_linux_REDIR_FOR_strlen)
1301 .type VG_(mips64_linux_REDIR_FOR_strlen), @function
1302 VG_(mips64_linux_REDIR_FOR_strlen):
1320 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1322 .global VG_(trampoline_stuff_end)
1323 VG_(trampoline_stuff_end):
1332 /*---------------------- tilegx-linux ----------------------*/
1334 #if defined(VGP_tilegx_linux)
1336 # define UD2_16 ill ; ill
1337 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1338 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1339 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1340 # define UD2_4K UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1341 # define UD2_16K UD2_4K ; UD2_4K ; UD2_4K ; UD2_4K
1342 # define UD2_PAGE UD2_16K ; UD2_16K ; UD2_16K ; UD2_16K
1343 /* a leading page of unexecutable code */
1346 .global VG_(trampoline_stuff_start)
1347 VG_(trampoline_stuff_start):
1349 .global VG_(tilegx_linux_SUBST_FOR_rt_sigreturn)
1350 VG_(tilegx_linux_SUBST_FOR_rt_sigreturn):
1351 /* This is a very specific sequence which GDB uses to
1352 recognize signal handler frames. */
1353 moveli r10, __NR_rt_sigreturn
1357 .global VG_(tilegx_linux_REDIR_FOR_vgettimeofday)
1358 .type VG_(tilegx_linux_REDIR_FOR_vgettimeofday), @function
1359 VG_(tilegx_linux_REDIR_FOR_vgettimeofday):
1360 moveli r10, __NR_gettimeofday
1363 .size VG_(tilegx_linux_REDIR_FOR_vgettimeofday), .-VG_(tilegx_linux_REDIR_FOR_vgettimeofday)
1365 .global VG_(tilegx_linux_REDIR_FOR_vtime)
1366 .type VG_(tilegx_linux_REDIR_FOR_vtime), @function
1367 VG_(tilegx_linux_REDIR_FOR_vtime):
1368 moveli r10, __NR_gettimeofday
1371 .size VG_(tilegx_linux_REDIR_FOR_vtime), .-VG_(tilegx_linux_REDIR_FOR_vtime)
1373 .global VG_(tilegx_linux_REDIR_FOR_strlen)
1374 .type VG_(tilegx_linux_REDIR_FOR_strlen), @function
1375 VG_(tilegx_linux_REDIR_FOR_strlen):
1388 .size VG_(tilegx_linux_REDIR_FOR_strlen), .-VG_(tilegx_linux_REDIR_FOR_strlen)
1390 .global VG_(trampoline_stuff_end)
1391 VG_(trampoline_stuff_end):
1393 /* and a trailing page of unexecutable code */
1404 /*---------------- x86-solaris ----------------*/
1406 #if defined(VGP_x86_solaris)
1408 .global VG_(trampoline_stuff_start)
1409 VG_(trampoline_stuff_start):
1411 /* int strcmp(const char *s1, const char *s2); */
1412 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1413 .type VG_(x86_solaris_REDIR_FOR_strcmp), @function
1414 VG_(x86_solaris_REDIR_FOR_strcmp):
1415 pushl %ebp /* establish a stack frame */
1417 movl 8(%ebp), %edx /* get s1 */
1418 movl 12(%esp), %ecx /* get s2 */
1419 jmp 2f /* go compare the first characters */
1421 incl %edx /* skip to the next s1 character */
1422 incl %ecx /* skip to the next s2 character */
1424 movzbl (%edx), %eax /* load a character from s1 */
1425 testb %al, %al /* is it null? */
1426 jz 3f /* yes, exit */
1427 cmpb (%ecx), %al /* are the characters equal? */
1428 je 1b /* yes, proceed with next characters */
1430 movzbl (%ecx), %edx /* load a character from s2 */
1431 subl %edx, %eax /* calculate the return value */
1432 popl %ebp /* destroy the stack frame */
1433 ret /* return to the caller */
1434 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1436 /* size_t strlen(const char *s); */
1437 .global VG_(x86_solaris_REDIR_FOR_strlen)
1438 .type VG_(x86_solaris_REDIR_FOR_strlen), @function
1439 VG_(x86_solaris_REDIR_FOR_strlen):
1440 pushl %ebp /* establish a stack frame */
1442 movl 8(%ebp), %edx /* get s */
1443 movl %edx, %eax /* copy s */
1444 jmp 2f /* go handle the first character */
1446 incl %eax /* skip to the next s character */
1448 cmpb $0, (%eax) /* is the s character null? */
1449 jne 1b /* no, go process the next character */
1450 subl %edx, %eax /* calculate the return value */
1451 popl %ebp /* destroy the stack frame */
1452 ret /* return to the caller */
1453 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1455 .global VG_(trampoline_stuff_end)
1456 VG_(trampoline_stuff_end):
1458 /*---------------- amd64-solaris ----------------*/
1460 #if defined(VGP_amd64_solaris)
1462 .global VG_(trampoline_stuff_start)
1463 VG_(trampoline_stuff_start):
1465 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1466 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1467 .type VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1468 VG_(amd64_solaris_REDIR_FOR_strcpy):
1469 pushq %rbp /* establish a stack frame */
1471 movq %rdi, %rdx /* copy s1 */
1473 movzbl (%rsi), %eax /* load one input character */
1474 movb %al, (%rdx) /* copy to output/s2 */
1475 incq %rsi /* skip to the next output character */
1476 incq %rdx /* skip to the next input character */
1477 testb %al, %al /* is the copied character null? */
1478 jnz 1b /* no, copy the next character */
1479 leave /* destroy the stack frame */
1480 movq %rdi, %rax /* set s1 as the return value */
1481 ret /* return to the caller */
1482 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1484 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1485 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1486 .type VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1487 VG_(amd64_solaris_REDIR_FOR_strncpy):
1488 pushq %rbp /* establish a stack frame */
1490 movq %rdi, %rcx /* copy s1 */
1492 testq %rdx, %rdx /* is the remaining size zero? */
1493 jz 3f /* yes, all done */
1494 movzbl (%rsi), %eax /* load one input character */
1495 movb %al, (%rcx) /* copy to output/s2 */
1496 decq %rdx /* decrement the remaining size */
1497 incq %rsi /* skip to the next output character */
1498 incq %rcx /* skip to the next input character */
1499 testb %al, %al /* is the copied character null? */
1500 jnz 1b /* no, copy the next character */
1502 testq %rdx, %rdx /* is the remaining size zero? */
1503 jz 3f /* yes, all done */
1504 movb $0, (%rdx) /* copy null to output/s2 */
1505 decq %rdx /* decrement the remaining size */
1506 incq %rsi /* skip to next output character */
1507 jmp 2b /* proceed with the next character */
1509 leave /* destroy the stack frame */
1510 movq %rdi, %rax /* set s1 as the return value */
1511 ret /* return to the caller */
1512 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1514 /* int strcmp(const char *s1, const char *s2); */
1515 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1516 .type VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1517 VG_(amd64_solaris_REDIR_FOR_strcmp):
1518 pushq %rbp /* establish a stack frame */
1520 jmp 2f /* go compare the first characters */
1522 incq %rdi /* skip to the next s1 character */
1523 incq %rsi /* skip to the next s2 character */
1525 movzbl (%rdi), %eax /* load a character from s1 */
1526 testb %al, %al /* is it null? */
1527 jz 3f /* yes, exit */
1528 cmpb (%rsi), %al /* are the characters equal? */
1529 je 1b /* yes, proceed with next characters */
1531 movzbl (%rsi), %edx /* load a character from s2 */
1532 subl %edx, %eax /* calculate the return value */
1533 leave /* destroy the stack frame */
1534 ret /* return to the caller */
1535 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1537 /* char *strcat(char *restrict s1, const char *restrict s2); */
1538 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1539 .type VG_(amd64_solaris_REDIR_FOR_strcat), @function
1540 VG_(amd64_solaris_REDIR_FOR_strcat):
1541 pushq %rbp /* establish a stack frame */
1543 movq %rdi, %rdx /* copy s1 */
1544 jmp 2f /* go handle the first character */
1546 incq %rdx /* skip to the next s1 character */
1548 cmpb $0, (%rdx) /* is the s1 character null? */
1549 jne 1b /* no, go check the next character */
1551 movzbl (%rsi), %eax /* load a character from s2 */
1552 movb %al, (%rdx) /* copy the s2 character to s1 */
1553 incq %rdx /* skip to the next s1 character */
1554 incq %rsi /* skip to the next s2 character */
1555 testb %al, %al /* was the character null? */
1556 jnz 3b /* no, go copy the next character */
1557 movq %rdi, %rax /* set s1 as the return value */
1558 leave /* destroy the stack frame */
1559 ret /* return to the caller */
1560 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1562 /* size_t strlen(const char *s); */
1563 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1564 .type VG_(amd64_solaris_REDIR_FOR_strlen), @function
1565 VG_(amd64_solaris_REDIR_FOR_strlen):
1566 pushq %rbp /* establish a stack frame */
1568 movq %rdi, %rax /* copy s */
1569 jmp 2f /* go handle the first character */
1571 incq %rax /* skip to the next s character */
1573 cmpb $0, (%rax) /* is the s character null? */
1574 jne 1b /* no, go process the next character */
1575 subq %rdi, %rax /* calculate the return value */
1576 leave /* destroy the stack frame */
1577 ret /* return to the caller */
1578 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1580 .global VG_(trampoline_stuff_end)
1581 VG_(trampoline_stuff_end):
1583 /*---------------- unknown ----------------*/
1585 # error Unknown platform
1602 /* Let the linker know we don't need an executable stack */
1605 /*--------------------------------------------------------------------*/
1607 /*--------------------------------------------------------------------*/