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-darwin ----------------*/
856 #if defined(VGP_x86_darwin)
858 /* a leading page of unexecutable code */
859 .fill 2048, 2, 0x0b0f /* `ud2` */
861 .globl VG_(trampoline_stuff_start)
862 VG_(trampoline_stuff_start):
864 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
865 VG_(x86_darwin_SUBST_FOR_sigreturn):
866 /* XXX does this need to have any special form? (cf x86-linux
868 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax
872 .globl VG_(x86_darwin_REDIR_FOR_strlen)
873 VG_(x86_darwin_REDIR_FOR_strlen):
885 .globl VG_(x86_darwin_REDIR_FOR_strcat)
886 VG_(x86_darwin_REDIR_FOR_strcat):
909 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
910 VG_(x86_darwin_REDIR_FOR_strcmp):
930 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
931 VG_(x86_darwin_REDIR_FOR_strcpy):
952 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
953 VG_(x86_darwin_REDIR_FOR_strlcat):
962 leal (%ecx,%esi), %eax
982 call VG_(x86_darwin_REDIR_FOR_strlen)
1000 leal (%edi,%eax), %eax
1007 .globl VG_(trampoline_stuff_end)
1008 VG_(trampoline_stuff_end):
1010 /* a trailing page of unexecutable code */
1011 .fill 2048, 2, 0x0b0f /* `ud2` */
1014 /*---------------- amd64-darwin ----------------*/
1016 #if defined(VGP_amd64_darwin)
1018 /* a leading page of unexecutable code */
1019 .fill 2048, 2, 0x0b0f /* `ud2` */
1021 .globl VG_(trampoline_stuff_start)
1022 VG_(trampoline_stuff_start):
1024 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1025 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1026 /* XXX does this need to have any special form? (cf x86-linux
1028 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1032 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1033 VG_(amd64_darwin_REDIR_FOR_strlen):
1044 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1045 VG_(amd64_darwin_REDIR_FOR_strcat):
1064 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1065 VG_(amd64_darwin_REDIR_FOR_strcmp):
1082 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1083 VG_(amd64_darwin_REDIR_FOR_strcpy):
1100 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1101 VG_(amd64_darwin_REDIR_FOR_strlcat):
1103 leaq (%rdx,%rdi), %rax
1126 call VG_(amd64_darwin_REDIR_FOR_strlen)
1143 leaq (%rbx,%rax), %rax
1149 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1150 VG_(amd64_darwin_REDIR_FOR_arc4random):
1151 /* not very random, hope dyld won't mind */
1152 movq $0x76616c6772696e64, %rax
1155 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1156 VG_(amd64_darwin_REDIR_FOR_strchr):
1178 .globl VG_(trampoline_stuff_end)
1179 VG_(trampoline_stuff_end):
1181 /* a trailing page of unexecutable code */
1182 .fill 2048, 2, 0x0b0f /* `ud2` */
1185 /*---------------- s390x-linux ----------------*/
1187 #if defined(VGP_s390x_linux)
1189 /* a leading page of unexecutable code */
1190 .fill 2048, 2, 0x0000
1192 .global VG_(trampoline_stuff_start)
1193 VG_(trampoline_stuff_start):
1195 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1196 VG_(s390x_linux_SUBST_FOR_sigreturn):
1200 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1201 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1202 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1203 for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1204 set ra to this trampoline, but the cfa is still in the stack,
1205 the unwinder thinks, that this is a non-rt frame and causes a
1206 crash in the gcc unwinder - which is used by the thread library
1207 and others. Therefore we add a lr 1,1 nop, to let the gcc
1208 unwinder bail out gracefully. This might also affect unwinding
1209 across the signal frame - tough luck. fixs390 */
1211 svc __NR_rt_sigreturn
1214 .global VG_(s390x_linux_REDIR_FOR_index)
1215 .type VG_(s390x_linux_REDIR_FOR_index),@function
1216 VG_(s390x_linux_REDIR_FOR_index):
1218 # %r2 = address of string
1219 # %r3 = character to find
1222 ngr %r0,%r3 # r0 = (unsigned char)r3
1225 llgc %r1,0(%r2) # r1 = byte from string
1226 cr %r1,%r0 # compare
1227 ber %r14 # return if found
1228 cr %r1,%r4 # end of string ?
1230 aghi %r2,1 # increment r2
1232 .L2: lghi %r2,0 # return value 0
1234 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1236 .globl VG_(trampoline_stuff_end)
1237 VG_(trampoline_stuff_end):
1238 .fill 2048, 2, 0x0000
1240 /*---------------------- mips32-linux ----------------------*/
1242 #if defined(VGP_mips32_linux)
1244 # define UD2_16 trap ; trap ; trap; trap
1245 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1246 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1247 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1248 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1251 .global VG_(trampoline_stuff_start)
1252 VG_(trampoline_stuff_start):
1254 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1255 VG_(mips32_linux_SUBST_FOR_sigreturn):
1256 li $v0,__NR_sigreturn
1259 .long 0 /*illegal insn*/
1261 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1262 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1263 li $v0,__NR_rt_sigreturn
1266 .long 0 /*illegal insn*/
1268 /* There's no particular reason that this needs to be handwritten
1269 assembly, but since that's what this file contains, here's a
1270 simple index() and strlen() implementations.
1276 .global VG_(mips32_linux_REDIR_FOR_index)
1277 .type VG_(mips32_linux_REDIR_FOR_index), @function
1278 VG_(mips32_linux_REDIR_FOR_index):
1282 beq $t0, $a1, index_end
1284 bne $t0, $zero, index_loop
1290 .size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1292 .global VG_(mips32_linux_REDIR_FOR_strlen)
1293 .type VG_(mips32_linux_REDIR_FOR_strlen), @function
1294 VG_(mips32_linux_REDIR_FOR_strlen):
1298 bne $t0, $zero, strlen_loop
1303 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1307 .global VG_(trampoline_stuff_end)
1308 VG_(trampoline_stuff_end):
1317 /*---------------------- nanomips-linux --------------------*/
1319 #if defined(VGP_nanomips_linux)
1321 .global VG_(trampoline_stuff_start)
1322 VG_(trampoline_stuff_start):
1327 .global VG_(nanomips_linux_SUBST_FOR_rt_sigreturn)
1328 VG_(nanomips_linux_SUBST_FOR_rt_sigreturn):
1329 li $t4, __NR_rt_sigreturn
1333 .global VG_(nanomips_linux_REDIR_FOR_index)
1334 .type VG_(nanomips_linux_REDIR_FOR_index), @function
1335 VG_(nanomips_linux_REDIR_FOR_index):
1338 beqc $t0, $a1, index_end
1340 bnec $t0, $zero, index_loop
1344 .size VG_(nanomips_linux_REDIR_FOR_index), .-VG_(nanomips_linux_REDIR_FOR_index)
1346 .global VG_(nanomips_linux_REDIR_FOR_strlen)
1347 .type VG_(nanomips_linux_REDIR_FOR_strlen), @function
1348 VG_(nanomips_linux_REDIR_FOR_strlen):
1353 bnec $t0, $zero, strlen_loop
1358 .size VG_(nanomips_linux_REDIR_FOR_strlen), .-VG_(nanomips_linux_REDIR_FOR_strlen)
1362 .global VG_(trampoline_stuff_end)
1363 VG_(trampoline_stuff_end):
1366 /*---------------------- mips64-linux ----------------------*/
1368 #if defined(VGP_mips64_linux)
1370 # define UD2_16 trap ; trap ; trap; trap
1371 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16
1372 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64
1373 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256
1374 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1376 .global VG_(trampoline_stuff_start)
1377 VG_(trampoline_stuff_start):
1379 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1380 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1381 li $2,__NR_rt_sigreturn
1384 .long 0 /*illegal insn*/
1386 /* There's no particular reason that this needs to be handwritten
1387 assembly, but since that's what this file contains, here's a
1388 simple index() and strlen() implementations.
1394 .global VG_(mips64_linux_REDIR_FOR_index)
1395 .type VG_(mips64_linux_REDIR_FOR_index), @function
1396 VG_(mips64_linux_REDIR_FOR_index):
1400 beq $t0, $a1, index_end
1402 bne $t0, $zero, index_loop
1408 .size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1410 .global VG_(mips64_linux_REDIR_FOR_strlen)
1411 .type VG_(mips64_linux_REDIR_FOR_strlen), @function
1412 VG_(mips64_linux_REDIR_FOR_strlen):
1416 bne $t0, $zero, strlen_loop
1421 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1425 .global VG_(trampoline_stuff_end)
1426 VG_(trampoline_stuff_end):
1435 /*---------------- x86-solaris ----------------*/
1437 #if defined(VGP_x86_solaris)
1439 .global VG_(trampoline_stuff_start)
1440 VG_(trampoline_stuff_start):
1442 /* int strcmp(const char *s1, const char *s2); */
1443 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1444 .type VG_(x86_solaris_REDIR_FOR_strcmp), @function
1445 VG_(x86_solaris_REDIR_FOR_strcmp):
1446 pushl %ebp /* establish a stack frame */
1448 movl 8(%ebp), %edx /* get s1 */
1449 movl 12(%esp), %ecx /* get s2 */
1450 jmp 2f /* go compare the first characters */
1452 incl %edx /* skip to the next s1 character */
1453 incl %ecx /* skip to the next s2 character */
1455 movzbl (%edx), %eax /* load a character from s1 */
1456 testb %al, %al /* is it null? */
1457 jz 3f /* yes, exit */
1458 cmpb (%ecx), %al /* are the characters equal? */
1459 je 1b /* yes, proceed with next characters */
1461 movzbl (%ecx), %edx /* load a character from s2 */
1462 subl %edx, %eax /* calculate the return value */
1463 popl %ebp /* destroy the stack frame */
1464 ret /* return to the caller */
1465 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1467 /* size_t strlen(const char *s); */
1468 .global VG_(x86_solaris_REDIR_FOR_strlen)
1469 .type VG_(x86_solaris_REDIR_FOR_strlen), @function
1470 VG_(x86_solaris_REDIR_FOR_strlen):
1471 pushl %ebp /* establish a stack frame */
1473 movl 8(%ebp), %edx /* get s */
1474 movl %edx, %eax /* copy s */
1475 jmp 2f /* go handle the first character */
1477 incl %eax /* skip to the next s character */
1479 cmpb $0, (%eax) /* is the s character null? */
1480 jne 1b /* no, go process the next character */
1481 subl %edx, %eax /* calculate the return value */
1482 popl %ebp /* destroy the stack frame */
1483 ret /* return to the caller */
1484 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1486 .global VG_(trampoline_stuff_end)
1487 VG_(trampoline_stuff_end):
1489 /*---------------- amd64-solaris ----------------*/
1491 #if defined(VGP_amd64_solaris)
1493 .global VG_(trampoline_stuff_start)
1494 VG_(trampoline_stuff_start):
1496 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1497 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1498 .type VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1499 VG_(amd64_solaris_REDIR_FOR_strcpy):
1500 pushq %rbp /* establish a stack frame */
1502 movq %rdi, %rdx /* copy s1 */
1504 movzbl (%rsi), %eax /* load one input character */
1505 movb %al, (%rdx) /* copy to output/s1 */
1506 incq %rsi /* skip to the next output character */
1507 incq %rdx /* skip to the next input character */
1508 testb %al, %al /* is the copied character null? */
1509 jnz 1b /* no, copy the next character */
1510 leave /* destroy the stack frame */
1511 movq %rdi, %rax /* set s1 as the return value */
1512 ret /* return to the caller */
1513 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1515 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1516 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1517 .type VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1518 VG_(amd64_solaris_REDIR_FOR_strncpy):
1519 pushq %rbp /* establish a stack frame */
1521 movq %rdi, %rcx /* copy s1 */
1523 testq %rdx, %rdx /* is the remaining size zero? */
1524 jz 3f /* yes, all done */
1525 movzbl (%rsi), %eax /* load one input character */
1526 movb %al, (%rcx) /* copy to output/s1 */
1527 decq %rdx /* decrement the remaining size */
1528 incq %rsi /* skip to the next output character */
1529 incq %rcx /* skip to the next input character */
1530 testb %al, %al /* is the copied character null? */
1531 jnz 1b /* no, copy the next character */
1533 testq %rdx, %rdx /* is the remaining size zero? */
1534 jz 3f /* yes, all done */
1535 movb $0, (%rdx) /* copy null to output/s2 */
1536 decq %rdx /* decrement the remaining size */
1537 incq %rsi /* skip to next output character */
1538 jmp 2b /* proceed with the next character */
1540 leave /* destroy the stack frame */
1541 movq %rdi, %rax /* set s1 as the return value */
1542 ret /* return to the caller */
1543 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1545 /* int strcmp(const char *s1, const char *s2); */
1546 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1547 .type VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1548 VG_(amd64_solaris_REDIR_FOR_strcmp):
1549 pushq %rbp /* establish a stack frame */
1551 jmp 2f /* go compare the first characters */
1553 incq %rdi /* skip to the next s1 character */
1554 incq %rsi /* skip to the next s2 character */
1556 movzbl (%rdi), %eax /* load a character from s1 */
1557 testb %al, %al /* is it null? */
1558 jz 3f /* yes, exit */
1559 cmpb (%rsi), %al /* are the characters equal? */
1560 je 1b /* yes, proceed with next characters */
1562 movzbl (%rsi), %edx /* load a character from s2 */
1563 subl %edx, %eax /* calculate the return value */
1564 leave /* destroy the stack frame */
1565 ret /* return to the caller */
1566 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1568 /* char *strcat(char *restrict s1, const char *restrict s2); */
1569 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1570 .type VG_(amd64_solaris_REDIR_FOR_strcat), @function
1571 VG_(amd64_solaris_REDIR_FOR_strcat):
1572 pushq %rbp /* establish a stack frame */
1574 movq %rdi, %rdx /* copy s1 */
1575 jmp 2f /* go handle the first character */
1577 incq %rdx /* skip to the next s1 character */
1579 cmpb $0, (%rdx) /* is the s1 character null? */
1580 jne 1b /* no, go check the next character */
1582 movzbl (%rsi), %eax /* load a character from s2 */
1583 movb %al, (%rdx) /* copy the s2 character to s1 */
1584 incq %rdx /* skip to the next s1 character */
1585 incq %rsi /* skip to the next s2 character */
1586 testb %al, %al /* was the character null? */
1587 jnz 3b /* no, go copy the next character */
1588 movq %rdi, %rax /* set s1 as the return value */
1589 leave /* destroy the stack frame */
1590 ret /* return to the caller */
1591 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1593 /* size_t strlen(const char *s); */
1594 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1595 .type VG_(amd64_solaris_REDIR_FOR_strlen), @function
1596 VG_(amd64_solaris_REDIR_FOR_strlen):
1597 pushq %rbp /* establish a stack frame */
1599 movq %rdi, %rax /* copy s */
1600 jmp 2f /* go handle the first character */
1602 incq %rax /* skip to the next s character */
1604 cmpb $0, (%rax) /* is the s character null? */
1605 jne 1b /* no, go process the next character */
1606 subq %rdi, %rax /* calculate the return value */
1607 leave /* destroy the stack frame */
1608 ret /* return to the caller */
1609 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1611 .global VG_(trampoline_stuff_end)
1612 VG_(trampoline_stuff_end):
1614 /*---------------- unknown ----------------*/
1616 # error Unknown platform
1633 /* Let the linker know we don't need an executable stack */
1636 /*--------------------------------------------------------------------*/
1638 /*--------------------------------------------------------------------*/