m_trampoline.S revision 663860b1408516d02ebfcb3a9999a134e6cfb223
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-2012 Julian Seward
11     jseward@acm.org
12  Copyright (C) 2006-2012 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/*---------------- ppc32-linux ----------------*/
523
524#elif 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/*---------------- x86-darwin ----------------*/
684#else
685#if defined(VGP_x86_darwin)
686
687        /* a leading page of unexecutable code */
688.fill 2048, 2, 0x0b0f /* `ud2` */
689
690.globl VG_(trampoline_stuff_start)
691VG_(trampoline_stuff_start):
692
693.globl VG_(x86_darwin_SUBST_FOR_sigreturn)
694VG_(x86_darwin_SUBST_FOR_sigreturn):
695        /* XXX does this need to have any special form? (cf x86-linux
696	version) */
697        movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
698        int     $0x80
699        ud2
700
701.globl VG_(x86_darwin_REDIR_FOR_strlen)
702VG_(x86_darwin_REDIR_FOR_strlen):
703        movl    4(%esp), %edx
704        movl    %edx, %eax
705        jmp     1f
7060:
707        incl    %eax
7081:
709        cmpb    $0, (%eax)
710        jne     0b
711        subl    %edx, %eax
712        ret
713
714.globl VG_(x86_darwin_REDIR_FOR_strcat)
715VG_(x86_darwin_REDIR_FOR_strcat):
716        pushl   %esi
717        movl    8(%esp), %esi
718        movl    12(%esp), %ecx
719        movl    %esi, %edx
720        jmp     1f
7210:
722        incl    %edx
7231:
724        cmpb    $0, (%edx)
725        jne     0b
7262:
727        movzbl  (%ecx), %eax
728        incl    %ecx
729        movb    %al, (%edx)
730        incl    %edx
731        testb   %al, %al
732        jne     2b
733        movl    %esi, %eax
734        popl    %esi
735        ret
736
737
738.globl VG_(x86_darwin_REDIR_FOR_strcmp)
739VG_(x86_darwin_REDIR_FOR_strcmp):
740        movl    4(%esp), %edx
741        movl    8(%esp), %ecx
742        jmp     1f
7430:
744        incl    %edx
745        incl    %ecx
7461:
747        movzbl  (%edx), %eax
748        testb   %al, %al
749        je      2f
750        cmpb    (%ecx), %al
751        je      0b
7522:
753        movzbl  (%ecx),%edx
754        movzbl  %al,%eax
755        subl    %edx, %eax
756        ret
757
758
759.globl VG_(x86_darwin_REDIR_FOR_strcpy)
760VG_(x86_darwin_REDIR_FOR_strcpy):
761	pushl	%ebp
762	movl	%esp, %ebp
763	pushl	%esi
764	movl	8(%ebp), %esi
765	movl	12(%ebp), %ecx
766	movl	%esi, %edx
767	jmp	1f
7680:
769	incl	%ecx
770	incl	%edx
7711:
772	movzbl	(%ecx), %eax
773	testb	%al, %al
774	movb	%al, (%edx)
775	jne	0b
776	movl	%esi, %eax
777	popl	%esi
778	leave
779	ret
780
781.globl VG_(x86_darwin_REDIR_FOR_strlcat)
782VG_(x86_darwin_REDIR_FOR_strlcat):
783	pushl	%ebp
784	movl	%esp, %ebp
785	pushl	%edi
786	pushl	%esi
787	subl	$16, %esp
788	movl	8(%ebp), %esi
789	movl	16(%ebp), %ecx
790	movl	%esi, %edx
791	leal	(%ecx,%esi), %eax
792	jmp	1f
7930:
794	incl	%edx
7951:
796	cmpl	%edx, %eax
797	je	2f
798	cmpb	$0, (%edx)
799	jne	0b
8002:
801	movl	%edx, %edi
802	subl	%esi, %edi
803	movl	%ecx, %esi
804	subl	%edi, %esi
805	je	3f
806	movl	12(%ebp), %eax
807	jmp	6f
8083:
809	movl	12(%ebp), %eax
810	movl	%eax, (%esp)
811	call	VG_(x86_darwin_REDIR_FOR_strlen)
812	jmp	7f
8134:
814	cmpl	$1, %esi
815	je	5f
816	movb	%cl, (%edx)
817	decl	%esi
818	incl	%edx
8195:
820	incl	%eax
8216:
822	movzbl	(%eax), %ecx
823	testb	%cl, %cl
824	jne	4b
825	movb	$0, (%edx)
826	subl	12(%ebp), %eax
8277:
828	addl	$16, %esp
829	leal	(%edi,%eax), %eax
830	popl	%esi
831	popl	%edi
832	leave
833	ret
834
835
836.globl VG_(trampoline_stuff_end)
837VG_(trampoline_stuff_end):
838
839        /* a trailing page of unexecutable code */
840.fill 2048, 2, 0x0b0f /* `ud2` */
841
842
843/*---------------- amd64-darwin ----------------*/
844#else
845#if defined(VGP_amd64_darwin)
846
847        /* a leading page of unexecutable code */
848.fill 2048, 2, 0x0b0f /* `ud2` */
849
850.globl VG_(trampoline_stuff_start)
851VG_(trampoline_stuff_start):
852
853.globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
854VG_(amd64_darwin_SUBST_FOR_sigreturn):
855        /* XXX does this need to have any special form? (cf x86-linux
856	version) */
857        movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
858        syscall
859        ud2
860
861.globl VG_(amd64_darwin_REDIR_FOR_strlen)
862VG_(amd64_darwin_REDIR_FOR_strlen):
863        movq    %rdi, %rax
864        jmp     1f
8650:
866        incq    %rax
8671:
868        cmpb    $0, (%rax)
869        jne     0b
870        subq    %rdi, %rax
871        ret
872
873.globl VG_(amd64_darwin_REDIR_FOR_strcat)
874VG_(amd64_darwin_REDIR_FOR_strcat):
875	movq	%rdi, %rdx
876	jmp	1f
8770:
878	incq	%rdx
8791:
880	cmpb	$0, (%rdx)
881	jne	0b
8822:
883	movzbl	(%rsi), %eax
884	incq	%rsi
885	movb	%al, (%rdx)
886	incq	%rdx
887	testb	%al, %al
888	jne	2b
889	movq	%rdi, %rax
890	ret
891
892
893.globl VG_(amd64_darwin_REDIR_FOR_strcmp)
894VG_(amd64_darwin_REDIR_FOR_strcmp):
895	jmp	1f
8960:
897	incq	%rdi
898	incq	%rsi
8991:
900	movzbl	(%rdi), %eax
901	testb	%al, %al
902	je	2f
903	cmpb	(%rsi), %al
904	je	0b
9052:
906	movzbl	(%rsi), %edx
907	movzbl	%al, %eax
908	subl	%edx, %eax
909	ret
910
911.globl VG_(amd64_darwin_REDIR_FOR_strcpy)
912VG_(amd64_darwin_REDIR_FOR_strcpy):
913	pushq	%rbp
914	movq	%rdi, %rdx
915	movq	%rsp, %rbp
916	jmp	1f
9170:
918	incq	%rsi
919	incq	%rdx
9201:
921	movzbl	(%rsi), %eax
922	testb	%al, %al
923	movb	%al, (%rdx)
924	jne	0b
925	leave
926	movq	%rdi, %rax
927	ret
928
929.globl VG_(amd64_darwin_REDIR_FOR_strlcat)
930VG_(amd64_darwin_REDIR_FOR_strlcat):
931	pushq	%rbp
932	leaq	(%rdx,%rdi), %rax
933	movq	%rdi, %rcx
934	movq	%rsp, %rbp
935	pushq	%rbx
936	subq	$8, %rsp
937	jmp	1f
9380:
939	incq	%rcx
9401:
941	cmpq	%rcx, %rax
942	je	2f
943	cmpb	$0, (%rcx)
944	jne	0b
9452:
946	movq	%rcx, %rbx
947	subq	%rdi, %rbx
948	movq	%rdx, %rdi
949	subq	%rbx, %rdi
950	je	3f
951	movq	%rsi, %rax
952	jmp	6f
9533:
954	movq	%rsi, %rdi
955	call	VG_(amd64_darwin_REDIR_FOR_strlen)
956	jmp	7f
9574:
958	cmpq	$1, %rdi
959	je	5f
960	movb	%dl, (%rcx)
961	decq	%rdi
962	incq	%rcx
9635:
964	incq	%rax
9656:
966	movzbl	(%rax), %edx
967	testb	%dl, %dl
968	jne	4b
969	movb	$0, (%rcx)
970	subq	%rsi, %rax
9717:
972	leaq	(%rbx,%rax), %rax
973	addq	$8, %rsp
974	popq	%rbx
975	leave
976	ret
977
978.globl VG_(amd64_darwin_REDIR_FOR_arc4random)
979VG_(amd64_darwin_REDIR_FOR_arc4random):
980	/* not very random, hope dyld won't mind */
981	movq	$0x76616c6772696e64, %rax
982	ret
983
984.globl VG_(trampoline_stuff_end)
985VG_(trampoline_stuff_end):
986
987        /* a trailing page of unexecutable code */
988.fill 2048, 2, 0x0b0f /* `ud2` */
989
990
991/*---------------- s390x-linux ----------------*/
992#else
993#if defined(VGP_s390x_linux)
994
995        /* a leading page of unexecutable code */
996	.fill 2048, 2, 0x0000
997
998.global VG_(trampoline_stuff_start)
999VG_(trampoline_stuff_start):
1000
1001.global VG_(s390x_linux_SUBST_FOR_sigreturn)
1002VG_(s390x_linux_SUBST_FOR_sigreturn):
1003        svc __NR_sigreturn
1004	.short 0
1005
1006.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1007VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1008        /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1009           for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1010           set ra to this trampoline, but the cfa is still in the stack,
1011           the unwinder thinks, that this is a non-rt frame  and causes a
1012           crash in the gcc unwinder - which is used by the thread library
1013           and others. Therefore we add a lr 1,1 nop, to let the gcc
1014           unwinder bail out gracefully. This might also affect unwinding
1015           across the signal frame - tough luck. fixs390 */
1016        lr 1,1
1017        svc __NR_rt_sigreturn
1018	.short 0
1019
1020.globl VG_(trampoline_stuff_end)
1021VG_(trampoline_stuff_end):
1022	.fill 2048, 2, 0x0000
1023
1024/*---------------------- mips32-linux ----------------------*/
1025#else
1026#if defined(VGP_mips32_linux)
1027
1028#	define UD2_16     trap ; trap ; trap; trap
1029#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1030#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1031#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1032#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1033
1034
1035.global VG_(trampoline_stuff_start)
1036VG_(trampoline_stuff_start):
1037
1038.global VG_(mips32_linux_SUBST_FOR_sigreturn)
1039VG_(mips32_linux_SUBST_FOR_sigreturn):
1040        li $v0,__NR_sigreturn
1041        syscall
1042        nop
1043        .long 0	/*illegal insn*/
1044
1045.global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1046VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1047	li $v0,__NR_rt_sigreturn
1048        syscall
1049        nop
1050        .long 0	/*illegal insn*/
1051
1052/* There's no particular reason that this needs to be handwritten
1053   assembly, but since that's what this file contains, here's a
1054   simple strlen implementation (written in C and compiled by gcc.)
1055*/
1056.global VG_(mips32_linux_REDIR_FOR_strlen)
1057.type   VG_(mips32_linux_REDIR_FOR_strlen), @function
1058VG_(mips32_linux_REDIR_FOR_strlen):
1059      li $v0, 0
1060      //la $a0, string
1061      j strlen_cond
1062   strlen_loop:
1063      addi $v0, $v0, 1
1064      addi $a0, $a0, 1
1065   strlen_cond:
1066      lbu $t0, ($a0)
1067      bne $t0, $zero, strlen_loop
1068    jr $ra
1069
1070.size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1071
1072.global VG_(trampoline_stuff_end)
1073VG_(trampoline_stuff_end):
1074
1075
1076#	undef UD2_16
1077#	undef UD2_64
1078#	undef UD2_256
1079#	undef UD2_1024
1080#	undef UD2_PAGE
1081
1082/*---------------- unknown ----------------*/
1083#else
1084#  error Unknown platform
1085
1086#endif
1087#endif
1088#endif
1089#endif
1090#endif
1091#endif
1092#endif
1093#endif
1094
1095#if defined(VGO_linux)
1096/* Let the linker know we don't need an executable stack */
1097#  if defined(VGP_arm_linux)
1098   .section .note.GNU-stack,"",%progbits
1099#  else
1100   .section .note.GNU-stack,"",@progbits
1101#  endif
1102#endif
1103
1104/*--------------------------------------------------------------------*/
1105/*--- end                                                          ---*/
1106/*--------------------------------------------------------------------*/
1107