1
2/*--------------------------------------------------------------------*/
3/*--- Trampoline code page stuff.                   m_trampoline.S ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7  This file is part of Valgrind, a dynamic binary instrumentation
8  framework.
9
10  Copyright (C) 2000-2013 Julian Seward
11     jseward@acm.org
12  Copyright (C) 2006-2013 OpenWorks LLP
13     info@open-works.co.uk
14
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.
19
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.
24
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
28  02111-1307, USA.
29
30  The GNU General Public License is contained in the file COPYING.
31*/
32
33#include "pub_core_basics_asm.h"
34#include "pub_core_vkiscnums_asm.h"
35
36/* ------------------ SIMULATED CPU HELPERS ------------------ */
37/*
38   Replacements for some functions to do with vsyscalls and signals.
39   This code runs on the simulated CPU.
40*/
41
42/*---------------------- x86-linux ----------------------*/
43#if defined(VGP_x86_linux)
44
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
50
51	/* a leading page of unexecutable code */
52	UD2_PAGE
53
54.global VG_(trampoline_stuff_start)
55VG_(trampoline_stuff_start):
56
57.global VG_(x86_linux_SUBST_FOR_sigreturn)
58VG_(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 */
63        popl    %eax
64        movl    $ __NR_sigreturn, %eax
65        int     $0x80
66        ud2
67
68.global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
69VG_(x86_linux_SUBST_FOR_rt_sigreturn):
70        /* Likewise for rt signal frames */
71        movl    $ __NR_rt_sigreturn, %eax
72        int     $0x80
73        ud2
74
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.)
78
79   unsigned char* REDIR_FOR_index ( const char* s, int c )
80   {
81      unsigned char  ch = (unsigned char)((unsigned int)c);
82      unsigned char* p  = (unsigned char*)s;
83      while (1) {
84         if (*p == ch) return p;
85         if (*p == 0)  return 0;
86         p++;
87      }
88   }
89*/
90.global VG_(x86_linux_REDIR_FOR_index)
91.type   VG_(x86_linux_REDIR_FOR_index), @function
92VG_(x86_linux_REDIR_FOR_index):
93        pushl   %ebp
94        movl    %esp, %ebp
95        movl    8(%ebp), %eax
96        movzbl  12(%ebp), %ecx
97        movzbl  (%eax), %edx
98        cmpb    %dl, %cl
99        jne     .L9
100        jmp     .L2
101.L11:
102        addl    $1, %eax
103        movzbl  (%eax), %edx
104        cmpb    %dl, %cl
105        je      .L2
106.L9:
107        testb   %dl, %dl
108        jne     .L11
109        xorl    %eax, %eax
110.L2:
111        popl    %ebp
112        ret
113.size VG_(x86_linux_REDIR_FOR_index), .-VG_(x86_linux_REDIR_FOR_index)
114
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.)
118*/
119.global VG_(x86_linux_REDIR_FOR_strlen)
120.type   VG_(x86_linux_REDIR_FOR_strlen), @function
121VG_(x86_linux_REDIR_FOR_strlen):
122        pushl   %ebp
123        movl    %esp, %ebp
124        movl    8(%ebp), %edx
125        movl    %edx, %eax
126        jmp     2f
1271:      incl    %eax
1282:      cmpb    $0, (%eax)
129        jne     1b
130        subl    %edx, %eax
131        popl    %ebp
132        ret
133.size VG_(x86_linux_REDIR_FOR_strlen), .-VG_(x86_linux_REDIR_FOR_strlen)
134
135
136.global VG_(trampoline_stuff_end)
137VG_(trampoline_stuff_end):
138
139	/* and a trailing page of unexecutable code */
140	UD2_PAGE
141
142#	undef UD2_16
143#	undef UD2_64
144#	undef UD2_256
145#	undef UD2_1024
146#	undef UD2_PAGE
147
148/*---------------------- amd64-linux ----------------------*/
149#else
150#if defined(VGP_amd64_linux)
151
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
157
158	/* a leading page of unexecutable code */
159	UD2_PAGE
160
161.global VG_(trampoline_stuff_start)
162VG_(trampoline_stuff_start):
163
164.global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
165VG_(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
169        syscall
170        ud2
171
172.global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
173.type   VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
174VG_(amd64_linux_REDIR_FOR_vgettimeofday):
175.LfnB2:
176        movq    $__NR_gettimeofday, %rax
177        syscall
178        ret
179.LfnE2:
180.size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
181
182.global VG_(amd64_linux_REDIR_FOR_vtime)
183.type   VG_(amd64_linux_REDIR_FOR_vtime), @function
184VG_(amd64_linux_REDIR_FOR_vtime):
185.LfnB3:
186        movq    $__NR_time, %rax
187        syscall
188        ret
189.LfnE3:
190.size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
191
192.global VG_(amd64_linux_REDIR_FOR_vgetcpu)
193.type   VG_(amd64_linux_REDIR_FOR_vgetcpu), @function
194VG_(amd64_linux_REDIR_FOR_vgetcpu):
195.LfnB4:
196        movq    $__NR_getcpu, %rax
197        syscall
198        ret
199.LfnE4:
200.size VG_(amd64_linux_REDIR_FOR_vgetcpu), .-.LfnB4
201
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.)
205*/
206.global VG_(amd64_linux_REDIR_FOR_strlen)
207.type   VG_(amd64_linux_REDIR_FOR_strlen), @function
208VG_(amd64_linux_REDIR_FOR_strlen):
209.LfnB5:
210	xorl	%eax, %eax
211	cmpb	$0, (%rdi)
212	movq	%rdi, %rdx
213	je	.L41
214.L40:	addq	$1, %rdx
215	cmpb	$0, (%rdx)
216	jne	.L40
217	movq	%rdx, %rax
218	subq	%rdi, %rax
219.L41:	ret
220.LfnE5:
221.size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
222
223
224/* A CIE for the above four functions, followed by their FDEs */
225	.section .eh_frame,"a",@progbits
226.Lframe1:
227        .long   .LEcie1-.LScie1
228.LScie1:
229        .long   0x0
230        .byte   0x1
231        .string "zR"
232        .uleb128 0x1
233        .sleb128 -8
234        .byte   0x10
235        .uleb128 0x1
236        .byte   0x3
237        .byte   0xc
238        .uleb128 0x7
239        .uleb128 0x8
240        .byte   0x90
241        .uleb128 0x1
242        .align 8
243.LEcie1:
244.LSfde2:
245        .long   .LEfde2-.LASfde2
246.LASfde2:
247        .long   .LASfde2-.Lframe1
248        .long   .LfnB2
249        .long   .LfnE2-.LfnB2
250        .uleb128 0x0
251        .align 8
252.LEfde2:
253.LSfde3:
254        .long   .LEfde3-.LASfde3
255.LASfde3:
256        .long   .LASfde3-.Lframe1
257        .long   .LfnB3
258        .long   .LfnE3-.LfnB3
259        .uleb128 0x0
260        .align 8
261.LEfde3:
262.LSfde4:
263        .long   .LEfde4-.LASfde4
264.LASfde4:
265        .long   .LASfde4-.Lframe1
266        .long   .LfnB4
267        .long   .LfnE4-.LfnB4
268        .uleb128 0x0
269        .align 8
270.LEfde4:
271.LSfde5:
272        .long   .LEfde5-.LASfde5
273.LASfde5:
274        .long   .LASfde5-.Lframe1
275        .long   .LfnB5
276        .long   .LfnE5-.LfnB5
277        .uleb128 0x0
278        .align 8
279.LEfde5:
280	.previous
281
282.global VG_(trampoline_stuff_end)
283VG_(trampoline_stuff_end):
284
285	/* and a trailing page of unexecutable code */
286	UD2_PAGE
287
288#	undef UD2_16
289#	undef UD2_64
290#	undef UD2_256
291#	undef UD2_1024
292#	undef UD2_PAGE
293
294/*---------------- ppc32-linux ----------------*/
295#else
296#if defined(VGP_ppc32_linux)
297
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
303
304	/* a leading page of unexecutable code */
305	UD2_PAGE
306
307.global VG_(trampoline_stuff_start)
308VG_(trampoline_stuff_start):
309
310.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
311VG_(ppc32_linux_SUBST_FOR_sigreturn):
312	li 0,__NR_sigreturn
313        sc
314        .long 0	/*illegal insn*/
315
316.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
317VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
318	li 0,__NR_rt_sigreturn
319        sc
320        .long 0	/*illegal insn*/
321
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.)
325*/
326.global VG_(ppc32_linux_REDIR_FOR_strlen)
327.type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
328VG_(ppc32_linux_REDIR_FOR_strlen):
329        lbz 4,0(3)
330        li 9,0
331        cmpwi 0,4,0
332        beq- 0,.L18
333.L19:
334        lbzu 5,1(3)
335        addi 9,9,1
336        cmpwi 0,5,0
337        bne+ 0,.L19
338.L18:
339        mr 3,9
340        blr
341.size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
342
343/* Ditto strcmp */
344.global VG_(ppc32_linux_REDIR_FOR_strcmp)
345.type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
346VG_(ppc32_linux_REDIR_FOR_strcmp):
347.L20:
348        lbz 0,0(3)
349        cmpwi 7,0,0
350        bne- 7,.L21
351        lbz 0,0(4)
352        li 11,0
353        cmpwi 7,0,0
354        beq- 7,.L22
355.L21:
356        lbz 0,0(3)
357        li 11,-1
358        cmpwi 7,0,0
359        beq- 7,.L22
360        lbz 0,0(4)
361        li 11,1
362        cmpwi 7,0,0
363        beq- 7,.L22
364        lbz 9,0(3)
365        lbz 0,0(4)
366        li 11,-1
367        cmplw 7,9,0
368        blt- 7,.L22
369        lbz 9,0(3)
370        lbz 0,0(4)
371        li 11,1
372        addi 3,3,1
373        addi 4,4,1
374        cmplw 7,9,0
375        ble+ 7,.L20
376.L22:
377        mr 3,11
378        blr
379.size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
380
381/* Ditto index/strchr */
382.global VG_(ppc32_linux_REDIR_FOR_strchr)
383.type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
384VG_(ppc32_linux_REDIR_FOR_strchr):
385        lbz 0,0(3)
386        rlwinm 4,4,0,0xff
387        cmpw 7,4,0
388        beqlr 7
389        cmpwi 7,0,0
390        bne 7,.L308
391        b .L304
392.L309:
393        beq 6,.L304
394.L308:
395        lbzu 0,1(3)
396        cmpw 7,4,0
397        cmpwi 6,0,0
398        bne 7,.L309
399        blr
400.L304:
401        li 3,0
402        blr
403.size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
404
405.global VG_(trampoline_stuff_end)
406VG_(trampoline_stuff_end):
407
408	/* and a trailing page of unexecutable code */
409	UD2_PAGE
410
411#	undef UD2_16
412#	undef UD2_64
413#	undef UD2_256
414#	undef UD2_1024
415#	undef UD2_PAGE
416
417/*---------------- ppc64-linux ----------------*/
418#else
419#if defined(VGP_ppc64_linux)
420
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
426
427	/* a leading page of unexecutable code */
428	UD2_PAGE
429
430.global VG_(trampoline_stuff_start)
431VG_(trampoline_stuff_start):
432
433.global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
434VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
435	li 0,__NR_rt_sigreturn
436        sc
437        .long 0	/*illegal insn*/
438
439	/* See comment in pub_core_trampoline.h for what this is for */
440.global VG_(ppctoc_magic_redirect_return_stub)
441VG_(ppctoc_magic_redirect_return_stub):
442	trap
443
444	/* this function is written using the "dotless" ABI convention */
445	.align 2
446	.globl VG_(ppc64_linux_REDIR_FOR_strlen)
447	.section        ".opd","aw"
448	.align 3
449VG_(ppc64_linux_REDIR_FOR_strlen):
450	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
451	.previous
452	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
453			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
454	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
455
456.L.VG_(ppc64_linux_REDIR_FOR_strlen):
457        mr 9,3
458        lbz 0,0(3)
459        li 3,0
460        cmpwi 7,0,0
461        beqlr 7
462        li 3,0
463.L01:
464        addi 0,3,1
465        extsw 3,0
466        lbzx 0,9,3
467        cmpwi 7,0,0
468        bne 7,.L01
469        blr
470        .long 0
471        .byte 0,0,0,0,0,0,0,0
472.L0end:
473
474        /* this function is written using the "dotless" ABI convention */
475        .align 2
476        .globl VG_(ppc64_linux_REDIR_FOR_strchr)
477	.section        ".opd","aw"
478	.align 3
479VG_(ppc64_linux_REDIR_FOR_strchr):
480        .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
481        .previous
482        .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
483                        .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
484        .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
485
486.L.VG_(ppc64_linux_REDIR_FOR_strchr):
487        lbz 0,0(3)
488        rldicl 4,4,0,56
489        cmpw 7,4,0
490        beqlr 7
491        cmpdi 7,0,0
492        bne 7,.L18
493        b .L14
494.L19:
495        beq 6,.L14
496.L18:
497        lbzu 0,1(3)
498        cmpw 7,4,0
499        cmpdi 6,0,0
500        bne 7,.L19
501        blr
502.L14:
503        li 3,0
504        blr
505        .long 0
506        .byte 0,0,0,0,0,0,0,0
507.L1end:
508
509
510.global VG_(trampoline_stuff_end)
511VG_(trampoline_stuff_end):
512
513	/* and a trailing page of unexecutable code */
514	UD2_PAGE
515
516#	undef UD2_16
517#	undef UD2_64
518#	undef UD2_256
519#	undef UD2_1024
520#	undef UD2_PAGE
521
522/*---------------- arm-linux ----------------*/
523#else
524#if defined(VGP_arm_linux)
525
526#       define UD2_4      .word 0xFFFFFFFF
527#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
528#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
529#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
530#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
531#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
532
533	/* a leading page of unexecutable code */
534	UD2_PAGE
535
536.global VG_(trampoline_stuff_start)
537VG_(trampoline_stuff_start):
538
539.global VG_(arm_linux_SUBST_FOR_sigreturn)
540.type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
541VG_(arm_linux_SUBST_FOR_sigreturn):
542	mov r7, # __NR_sigreturn
543        svc #0
544        .long 0xFFFFFFFF /*illegal insn*/
545.size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
546
547.global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
548.type   VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
549VG_(arm_linux_SUBST_FOR_rt_sigreturn):
550	mov r7, # __NR_rt_sigreturn
551        svc #0
552        .long 0xFFFFFFFF /*illegal insn*/
553.size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
554
555.global VG_(arm_linux_REDIR_FOR_strlen)
556VG_(arm_linux_REDIR_FOR_strlen):
557	mov	r2, r0
558	ldrb	r0, [r0, #0]	@ zero_extendqisi2
559	@ lr needed for prologue
560	cmp	r0, #0
561	bxeq	lr
562	mov	r0, #0
563.L5:
564	add	r0, r0, #1
565	ldrb	r3, [r0, r2]	@ zero_extendqisi2
566	cmp	r3, #0
567	bne	.L5
568	bx	lr
569	UD2_4
570
571//.global VG_(arm_linux_REDIR_FOR_index)
572//VG_(arm_linux_REDIR_FOR_index):
573//	ldrb	r3, [r0, #0]	@ zero_extendqisi2
574//	and	r1, r1, #255
575//	cmp	r3, r1
576//	@ lr needed for prologue
577//	bne	.L9
578//	bx	lr
579//.L12:
580//	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
581//	cmp	r3, r1
582//	beq	.L11
583//.L9:
584//	cmp	r3, #0
585//	bne	.L12
586//	mov	r0, #0
587//	bx	lr
588//.L11:
589//	bx	lr
590//	UD2_4
591
592.global VG_(arm_linux_REDIR_FOR_memcpy)
593VG_(arm_linux_REDIR_FOR_memcpy):
594	stmfd	sp!, {r4, r5, lr}
595	subs	lr, r2, #0
596	mov	r5, r0
597	beq	.L2
598	cmp	r0, r1
599	bls	.L4
600	add	r3, r0, lr
601	add	r1, lr, r1
602	cmp	lr, #3
603	sub	r4, r3, #1
604	sub	r0, r1, #1
605	ble	.L28
606	sub	ip, r3, #5
607	sub	r1, r1, #5
608.L8:
609	ldrb	r3, [r1, #4]	@ zero_extendqisi2
610	sub	lr, lr, #4
611	strb	r3, [ip, #4]
612	ldrb	r2, [r1, #3]	@ zero_extendqisi2
613	cmp	lr, #3
614	strb	r2, [ip, #3]
615	ldrb	r3, [r1, #2]	@ zero_extendqisi2
616	mov	r4, ip
617	strb	r3, [ip, #2]
618	ldrb	r2, [r1, #1]	@ zero_extendqisi2
619	mov	r0, r1
620	strb	r2, [ip, #1]
621	sub	r1, r1, #4
622	sub	ip, ip, #4
623	bgt	.L8
624	cmp	lr, #0
625	beq	.L2
626.L28:
627	sub	r2, lr, #1
628.L21:
629	sub	r2, r2, #1
630	ldrb	r3, [r0], #-1	@ zero_extendqisi2
631	cmn	r2, #1
632	strb	r3, [r4], #-1
633	bne	.L21
634.L2:
635	mov	r0, r5
636	ldmfd	sp!, {r4, r5, pc}
637.L4:
638	bcs	.L2
639	cmp	lr, #3
640	mov	ip, r0
641	ble	.L29
642.L19:
643	ldrb	r3, [r1, #0]	@ zero_extendqisi2
644	sub	lr, lr, #4
645	strb	r3, [ip, #0]
646	ldrb	r2, [r1, #1]	@ zero_extendqisi2
647	cmp	lr, #3
648	strb	r2, [ip, #1]
649	ldrb	r3, [r1, #2]	@ zero_extendqisi2
650	strb	r3, [ip, #2]
651	ldrb	r2, [r1, #3]	@ zero_extendqisi2
652	add	r1, r1, #4
653	strb	r2, [ip, #3]
654	add	ip, ip, #4
655	bgt	.L19
656	cmp	lr, #0
657	beq	.L2
658.L29:
659	sub	r2, lr, #1
660.L20:
661	sub	r2, r2, #1
662	ldrb	r3, [r1], #1	@ zero_extendqisi2
663	cmn	r2, #1
664	strb	r3, [ip], #1
665	bne	.L20
666	mov	r0, r5
667	ldmfd	sp!, {r4, r5, pc}
668	UD2_4
669
670.global VG_(trampoline_stuff_end)
671VG_(trampoline_stuff_end):
672
673	/* and a trailing page of unexecutable code */
674	UD2_PAGE
675
676#	undef UD2_4
677#	undef UD2_16
678#	undef UD2_64
679#	undef UD2_256
680#	undef UD2_1024
681#	undef UD2_PAGE
682
683/*---------------- arm64-linux ----------------*/
684#else
685#if defined(VGP_arm64_linux)
686
687#       define UD2_4      .word 0xFFFFFFFF
688#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
689#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
690#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
691#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
692#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
693
694	/* a leading page of unexecutable code */
695	UD2_PAGE
696
697.global VG_(trampoline_stuff_start)
698VG_(trampoline_stuff_start):
699
700.global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
701.type   VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
702VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
703	mov x8, # __NR_rt_sigreturn
704        svc #0
705        .long 0xFFFFFFFF /*illegal insn*/
706.size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
707        .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
708
709.global VG_(arm64_linux_REDIR_FOR_strlen)
710.type   VG_(arm64_linux_REDIR_FOR_strlen),#function
711VG_(arm64_linux_REDIR_FOR_strlen):
712	mov	x2, x0
713	ldrb	w0, [x0]
714	cbz	w0, .L5
715	mov	x0, 0
716.L4:
717	add	x0, x0, 1
718	ldrb	w1, [x2,x0]
719	cbnz	w1, .L4
720	ret
721.L5:
722	mov	x0, 0
723	ret
724.size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
725
726.global VG_(arm64_linux_REDIR_FOR_index)
727.type   VG_(arm64_linux_REDIR_FOR_index),#function
728VG_(arm64_linux_REDIR_FOR_index):
729        ldrb    w2, [x0]
730        uxtb    w1, w1
731        cmp     w2, w1
732        beq     .L11
733.L13:
734        cbz     w2, .L16
735        ldrb    w2, [x0,1]!
736        cmp     w2, w1
737        bne     .L13
738.L11:
739        ret
740.L16:
741        mov     x0, 0
742        ret
743.size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
744
745.global VG_(arm64_linux_REDIR_FOR_strcmp)
746.type   VG_(arm64_linux_REDIR_FOR_strcmp),#function
747VG_(arm64_linux_REDIR_FOR_strcmp):
748        ldrb    w2, [x0]
749        ldrb    w3, [x1]
750        cmp     w2, w3
751        bcc     .L22
752.L21:
753        bhi     .L25
754        cbz     w2, .L26
755        ldrb    w2, [x0,1]!
756        ldrb    w3, [x1,1]!
757        cmp     w2, w3
758        bcs     .L21
759.L22:
760        mov     x0, -1
761        ret
762.L25:
763        mov     x0, 1
764        ret
765.L26:
766        mov     x0, 0
767        ret
768.size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
769
770.global VG_(trampoline_stuff_end)
771VG_(trampoline_stuff_end):
772
773	/* and a trailing page of unexecutable code */
774	UD2_PAGE
775
776#	undef UD2_4
777#	undef UD2_16
778#	undef UD2_64
779#	undef UD2_256
780#	undef UD2_1024
781#	undef UD2_PAGE
782
783/*---------------- x86-darwin ----------------*/
784#else
785#if defined(VGP_x86_darwin)
786
787        /* a leading page of unexecutable code */
788.fill 2048, 2, 0x0b0f /* `ud2` */
789
790.globl VG_(trampoline_stuff_start)
791VG_(trampoline_stuff_start):
792
793.globl VG_(x86_darwin_SUBST_FOR_sigreturn)
794VG_(x86_darwin_SUBST_FOR_sigreturn):
795        /* XXX does this need to have any special form? (cf x86-linux
796	version) */
797        movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
798        int     $0x80
799        ud2
800
801.globl VG_(x86_darwin_REDIR_FOR_strlen)
802VG_(x86_darwin_REDIR_FOR_strlen):
803        movl    4(%esp), %edx
804        movl    %edx, %eax
805        jmp     1f
8060:
807        incl    %eax
8081:
809        cmpb    $0, (%eax)
810        jne     0b
811        subl    %edx, %eax
812        ret
813
814.globl VG_(x86_darwin_REDIR_FOR_strcat)
815VG_(x86_darwin_REDIR_FOR_strcat):
816        pushl   %esi
817        movl    8(%esp), %esi
818        movl    12(%esp), %ecx
819        movl    %esi, %edx
820        jmp     1f
8210:
822        incl    %edx
8231:
824        cmpb    $0, (%edx)
825        jne     0b
8262:
827        movzbl  (%ecx), %eax
828        incl    %ecx
829        movb    %al, (%edx)
830        incl    %edx
831        testb   %al, %al
832        jne     2b
833        movl    %esi, %eax
834        popl    %esi
835        ret
836
837
838.globl VG_(x86_darwin_REDIR_FOR_strcmp)
839VG_(x86_darwin_REDIR_FOR_strcmp):
840        movl    4(%esp), %edx
841        movl    8(%esp), %ecx
842        jmp     1f
8430:
844        incl    %edx
845        incl    %ecx
8461:
847        movzbl  (%edx), %eax
848        testb   %al, %al
849        je      2f
850        cmpb    (%ecx), %al
851        je      0b
8522:
853        movzbl  (%ecx),%edx
854        movzbl  %al,%eax
855        subl    %edx, %eax
856        ret
857
858
859.globl VG_(x86_darwin_REDIR_FOR_strcpy)
860VG_(x86_darwin_REDIR_FOR_strcpy):
861	pushl	%ebp
862	movl	%esp, %ebp
863	pushl	%esi
864	movl	8(%ebp), %esi
865	movl	12(%ebp), %ecx
866	movl	%esi, %edx
867	jmp	1f
8680:
869	incl	%ecx
870	incl	%edx
8711:
872	movzbl	(%ecx), %eax
873	testb	%al, %al
874	movb	%al, (%edx)
875	jne	0b
876	movl	%esi, %eax
877	popl	%esi
878	leave
879	ret
880
881.globl VG_(x86_darwin_REDIR_FOR_strlcat)
882VG_(x86_darwin_REDIR_FOR_strlcat):
883	pushl	%ebp
884	movl	%esp, %ebp
885	pushl	%edi
886	pushl	%esi
887	subl	$16, %esp
888	movl	8(%ebp), %esi
889	movl	16(%ebp), %ecx
890	movl	%esi, %edx
891	leal	(%ecx,%esi), %eax
892	jmp	1f
8930:
894	incl	%edx
8951:
896	cmpl	%edx, %eax
897	je	2f
898	cmpb	$0, (%edx)
899	jne	0b
9002:
901	movl	%edx, %edi
902	subl	%esi, %edi
903	movl	%ecx, %esi
904	subl	%edi, %esi
905	je	3f
906	movl	12(%ebp), %eax
907	jmp	6f
9083:
909	movl	12(%ebp), %eax
910	movl	%eax, (%esp)
911	call	VG_(x86_darwin_REDIR_FOR_strlen)
912	jmp	7f
9134:
914	cmpl	$1, %esi
915	je	5f
916	movb	%cl, (%edx)
917	decl	%esi
918	incl	%edx
9195:
920	incl	%eax
9216:
922	movzbl	(%eax), %ecx
923	testb	%cl, %cl
924	jne	4b
925	movb	$0, (%edx)
926	subl	12(%ebp), %eax
9277:
928	addl	$16, %esp
929	leal	(%edi,%eax), %eax
930	popl	%esi
931	popl	%edi
932	leave
933	ret
934
935
936.globl VG_(trampoline_stuff_end)
937VG_(trampoline_stuff_end):
938
939        /* a trailing page of unexecutable code */
940.fill 2048, 2, 0x0b0f /* `ud2` */
941
942
943/*---------------- amd64-darwin ----------------*/
944#else
945#if defined(VGP_amd64_darwin)
946
947        /* a leading page of unexecutable code */
948.fill 2048, 2, 0x0b0f /* `ud2` */
949
950.globl VG_(trampoline_stuff_start)
951VG_(trampoline_stuff_start):
952
953.globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
954VG_(amd64_darwin_SUBST_FOR_sigreturn):
955        /* XXX does this need to have any special form? (cf x86-linux
956	version) */
957        movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
958        syscall
959        ud2
960
961.globl VG_(amd64_darwin_REDIR_FOR_strlen)
962VG_(amd64_darwin_REDIR_FOR_strlen):
963        movq    %rdi, %rax
964        jmp     1f
9650:
966        incq    %rax
9671:
968        cmpb    $0, (%rax)
969        jne     0b
970        subq    %rdi, %rax
971        ret
972
973.globl VG_(amd64_darwin_REDIR_FOR_strcat)
974VG_(amd64_darwin_REDIR_FOR_strcat):
975	movq	%rdi, %rdx
976	jmp	1f
9770:
978	incq	%rdx
9791:
980	cmpb	$0, (%rdx)
981	jne	0b
9822:
983	movzbl	(%rsi), %eax
984	incq	%rsi
985	movb	%al, (%rdx)
986	incq	%rdx
987	testb	%al, %al
988	jne	2b
989	movq	%rdi, %rax
990	ret
991
992
993.globl VG_(amd64_darwin_REDIR_FOR_strcmp)
994VG_(amd64_darwin_REDIR_FOR_strcmp):
995	jmp	1f
9960:
997	incq	%rdi
998	incq	%rsi
9991:
1000	movzbl	(%rdi), %eax
1001	testb	%al, %al
1002	je	2f
1003	cmpb	(%rsi), %al
1004	je	0b
10052:
1006	movzbl	(%rsi), %edx
1007	movzbl	%al, %eax
1008	subl	%edx, %eax
1009	ret
1010
1011.globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1012VG_(amd64_darwin_REDIR_FOR_strcpy):
1013	pushq	%rbp
1014	movq	%rdi, %rdx
1015	movq	%rsp, %rbp
1016	jmp	1f
10170:
1018	incq	%rsi
1019	incq	%rdx
10201:
1021	movzbl	(%rsi), %eax
1022	testb	%al, %al
1023	movb	%al, (%rdx)
1024	jne	0b
1025	leave
1026	movq	%rdi, %rax
1027	ret
1028
1029.globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1030VG_(amd64_darwin_REDIR_FOR_strlcat):
1031	pushq	%rbp
1032	leaq	(%rdx,%rdi), %rax
1033	movq	%rdi, %rcx
1034	movq	%rsp, %rbp
1035	pushq	%rbx
1036	subq	$8, %rsp
1037	jmp	1f
10380:
1039	incq	%rcx
10401:
1041	cmpq	%rcx, %rax
1042	je	2f
1043	cmpb	$0, (%rcx)
1044	jne	0b
10452:
1046	movq	%rcx, %rbx
1047	subq	%rdi, %rbx
1048	movq	%rdx, %rdi
1049	subq	%rbx, %rdi
1050	je	3f
1051	movq	%rsi, %rax
1052	jmp	6f
10533:
1054	movq	%rsi, %rdi
1055	call	VG_(amd64_darwin_REDIR_FOR_strlen)
1056	jmp	7f
10574:
1058	cmpq	$1, %rdi
1059	je	5f
1060	movb	%dl, (%rcx)
1061	decq	%rdi
1062	incq	%rcx
10635:
1064	incq	%rax
10656:
1066	movzbl	(%rax), %edx
1067	testb	%dl, %dl
1068	jne	4b
1069	movb	$0, (%rcx)
1070	subq	%rsi, %rax
10717:
1072	leaq	(%rbx,%rax), %rax
1073	addq	$8, %rsp
1074	popq	%rbx
1075	leave
1076	ret
1077
1078.globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1079VG_(amd64_darwin_REDIR_FOR_arc4random):
1080	/* not very random, hope dyld won't mind */
1081	movq	$0x76616c6772696e64, %rax
1082	ret
1083
1084.globl VG_(trampoline_stuff_end)
1085VG_(trampoline_stuff_end):
1086
1087        /* a trailing page of unexecutable code */
1088.fill 2048, 2, 0x0b0f /* `ud2` */
1089
1090
1091/*---------------- s390x-linux ----------------*/
1092#else
1093#if defined(VGP_s390x_linux)
1094
1095        /* a leading page of unexecutable code */
1096	.fill 2048, 2, 0x0000
1097
1098.global VG_(trampoline_stuff_start)
1099VG_(trampoline_stuff_start):
1100
1101.global VG_(s390x_linux_SUBST_FOR_sigreturn)
1102VG_(s390x_linux_SUBST_FOR_sigreturn):
1103        svc __NR_sigreturn
1104	.short 0
1105
1106.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1107VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1108        /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1109           for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1110           set ra to this trampoline, but the cfa is still in the stack,
1111           the unwinder thinks, that this is a non-rt frame  and causes a
1112           crash in the gcc unwinder - which is used by the thread library
1113           and others. Therefore we add a lr 1,1 nop, to let the gcc
1114           unwinder bail out gracefully. This might also affect unwinding
1115           across the signal frame - tough luck. fixs390 */
1116        lr 1,1
1117        svc __NR_rt_sigreturn
1118	.short 0
1119
1120.globl VG_(trampoline_stuff_end)
1121VG_(trampoline_stuff_end):
1122	.fill 2048, 2, 0x0000
1123
1124/*---------------------- mips32-linux ----------------------*/
1125#else
1126#if defined(VGP_mips32_linux)
1127
1128#	define UD2_16     trap ; trap ; trap; trap
1129#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1130#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1131#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1132#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1133
1134
1135.global VG_(trampoline_stuff_start)
1136VG_(trampoline_stuff_start):
1137
1138.global VG_(mips32_linux_SUBST_FOR_sigreturn)
1139VG_(mips32_linux_SUBST_FOR_sigreturn):
1140        li $v0,__NR_sigreturn
1141        syscall
1142        nop
1143        .long 0	/*illegal insn*/
1144
1145.global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1146VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1147	li $v0,__NR_rt_sigreturn
1148        syscall
1149        nop
1150        .long 0	/*illegal insn*/
1151
1152/* There's no particular reason that this needs to be handwritten
1153   assembly, but since that's what this file contains, here's a
1154   simple strlen implementation (written in C and compiled by gcc.)
1155*/
1156.global VG_(mips32_linux_REDIR_FOR_strlen)
1157.type   VG_(mips32_linux_REDIR_FOR_strlen), @function
1158VG_(mips32_linux_REDIR_FOR_strlen):
1159      li $v0, 0
1160      //la $a0, string
1161      j strlen_cond
1162   strlen_loop:
1163      addi $v0, $v0, 1
1164      addi $a0, $a0, 1
1165   strlen_cond:
1166      lbu $t0, ($a0)
1167      bne $t0, $zero, strlen_loop
1168    jr $ra
1169
1170.size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1171
1172.global VG_(trampoline_stuff_end)
1173VG_(trampoline_stuff_end):
1174
1175
1176#	undef UD2_16
1177#	undef UD2_64
1178#	undef UD2_256
1179#	undef UD2_1024
1180#	undef UD2_PAGE
1181
1182/*---------------------- mips64-linux ----------------------*/
1183#else
1184#if defined(VGP_mips64_linux)
1185
1186#       define UD2_16     trap ; trap ; trap; trap
1187#       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1188#       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1189#       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1190#       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1191
1192.global VG_(trampoline_stuff_start)
1193VG_(trampoline_stuff_start):
1194
1195.global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1196VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1197        li $2,__NR_rt_sigreturn
1198        syscall
1199        nop
1200        .long 0	/*illegal insn*/
1201
1202/* There's no particular reason that this needs to be handwritten
1203   assembly, but since that's what this file contains, here's a
1204   simple strlen implementation (written in C and compiled by gcc.)
1205*/
1206.global VG_(mips64_linux_REDIR_FOR_strlen)
1207.type   VG_(mips64_linux_REDIR_FOR_strlen), @function
1208VG_(mips64_linux_REDIR_FOR_strlen):
1209        lbu $12, 0($4)
1210        li  $13, 0
1211        beq $12, $0, M01
1212        nop
1213
1214M02:
1215        addiu $13, $13, 1
1216        addiu $4, $4, 1
1217        lbu $12, 0($4)
1218        bne $12, $0, M02
1219        nop
1220
1221M01:
1222        move $2, $13
1223        jr $31
1224        nop
1225
1226.size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1227
1228.global VG_(trampoline_stuff_end)
1229VG_(trampoline_stuff_end):
1230
1231
1232#	undef UD2_16
1233#	undef UD2_64
1234#	undef UD2_256
1235#	undef UD2_1024
1236#	undef UD2_PAGE
1237
1238/*---------------- unknown ----------------*/
1239#else
1240#  error Unknown platform
1241
1242#endif
1243#endif
1244#endif
1245#endif
1246#endif
1247#endif
1248#endif
1249#endif
1250#endif
1251#endif
1252#endif
1253
1254#if defined(VGO_linux)
1255/* Let the linker know we don't need an executable stack */
1256#  if defined(VGP_arm_linux)
1257   .section .note.GNU-stack,"",%progbits
1258#  else
1259   .section .note.GNU-stack,"",@progbits
1260#  endif
1261#endif
1262
1263/*--------------------------------------------------------------------*/
1264/*--- end                                                          ---*/
1265/*--------------------------------------------------------------------*/
1266