m_trampoline.S revision b32f58018498ea2225959b0ba11c18f0c433deef
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-2011 Julian Seward
11     jseward@acm.org
12  Copyright (C) 2006-2011 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/* There's no particular reason that this needs to be handwritten
193   assembly, but since that's what this file contains, here's a
194   simple strlen implementation (written in C and compiled by gcc.)
195*/
196.global VG_(amd64_linux_REDIR_FOR_strlen)
197.type   VG_(amd64_linux_REDIR_FOR_strlen), @function
198VG_(amd64_linux_REDIR_FOR_strlen):
199.LfnB4:
200	xorl	%eax, %eax
201	cmpb	$0, (%rdi)
202	movq	%rdi, %rdx
203	je	.L41
204.L40:	addq	$1, %rdx
205	cmpb	$0, (%rdx)
206	jne	.L40
207	movq	%rdx, %rax
208	subq	%rdi, %rax
209.L41:	ret
210.LfnE4:
211.size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
212
213
214/* A CIE for the above three functions, followed by their FDEs */
215	.section .eh_frame,"a",@progbits
216.Lframe1:
217        .long   .LEcie1-.LScie1
218.LScie1:
219        .long   0x0
220        .byte   0x1
221        .string "zR"
222        .uleb128 0x1
223        .sleb128 -8
224        .byte   0x10
225        .uleb128 0x1
226        .byte   0x3
227        .byte   0xc
228        .uleb128 0x7
229        .uleb128 0x8
230        .byte   0x90
231        .uleb128 0x1
232        .align 8
233.LEcie1:
234.LSfde2:
235        .long   .LEfde2-.LASfde2
236.LASfde2:
237        .long   .LASfde2-.Lframe1
238        .long   .LfnB2
239        .long   .LfnE2-.LfnB2
240        .uleb128 0x0
241        .align 8
242.LEfde2:
243.LSfde3:
244        .long   .LEfde3-.LASfde3
245.LASfde3:
246        .long   .LASfde3-.Lframe1
247        .long   .LfnB3
248        .long   .LfnE3-.LfnB3
249        .uleb128 0x0
250        .align 8
251.LEfde3:
252.LSfde4:
253        .long   .LEfde4-.LASfde4
254.LASfde4:
255        .long   .LASfde4-.Lframe1
256        .long   .LfnB4
257        .long   .LfnE4-.LfnB4
258        .uleb128 0x0
259        .align 8
260.LEfde4:
261	.previous
262
263.global VG_(trampoline_stuff_end)
264VG_(trampoline_stuff_end):
265
266	/* and a trailing page of unexecutable code */
267	UD2_PAGE
268
269#	undef UD2_16
270#	undef UD2_64
271#	undef UD2_256
272#	undef UD2_1024
273#	undef UD2_PAGE
274
275/*---------------- ppc32-linux ----------------*/
276#else
277#if defined(VGP_ppc32_linux)
278
279#	define UD2_16     trap ; trap ; trap; trap
280#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
281#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
282#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
283#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
284
285	/* a leading page of unexecutable code */
286	UD2_PAGE
287
288.global VG_(trampoline_stuff_start)
289VG_(trampoline_stuff_start):
290
291.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
292VG_(ppc32_linux_SUBST_FOR_sigreturn):
293	li 0,__NR_sigreturn
294        sc
295        .long 0	/*illegal insn*/
296
297.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
298VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
299	li 0,__NR_rt_sigreturn
300        sc
301        .long 0	/*illegal insn*/
302
303/* There's no particular reason that this needs to be handwritten
304   assembly, but since that's what this file contains, here's a
305   simple strlen implementation (written in C and compiled by gcc.)
306*/
307.global VG_(ppc32_linux_REDIR_FOR_strlen)
308.type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
309VG_(ppc32_linux_REDIR_FOR_strlen):
310        lbz 4,0(3)
311        li 9,0
312        cmpwi 0,4,0
313        beq- 0,.L18
314.L19:
315        lbzu 5,1(3)
316        addi 9,9,1
317        cmpwi 0,5,0
318        bne+ 0,.L19
319.L18:
320        mr 3,9
321        blr
322.size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
323
324/* Ditto strcmp */
325.global VG_(ppc32_linux_REDIR_FOR_strcmp)
326.type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
327VG_(ppc32_linux_REDIR_FOR_strcmp):
328.L20:
329        lbz 0,0(3)
330        cmpwi 7,0,0
331        bne- 7,.L21
332        lbz 0,0(4)
333        li 11,0
334        cmpwi 7,0,0
335        beq- 7,.L22
336.L21:
337        lbz 0,0(3)
338        li 11,-1
339        cmpwi 7,0,0
340        beq- 7,.L22
341        lbz 0,0(4)
342        li 11,1
343        cmpwi 7,0,0
344        beq- 7,.L22
345        lbz 9,0(3)
346        lbz 0,0(4)
347        li 11,-1
348        cmplw 7,9,0
349        blt- 7,.L22
350        lbz 9,0(3)
351        lbz 0,0(4)
352        li 11,1
353        addi 3,3,1
354        addi 4,4,1
355        cmplw 7,9,0
356        ble+ 7,.L20
357.L22:
358        mr 3,11
359        blr
360.size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
361
362/* Ditto index/strchr */
363.global VG_(ppc32_linux_REDIR_FOR_strchr)
364.type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
365VG_(ppc32_linux_REDIR_FOR_strchr):
366        lbz 0,0(3)
367        rlwinm 4,4,0,0xff
368        cmpw 7,4,0
369        beqlr 7
370        cmpwi 7,0,0
371        bne 7,.L308
372        b .L304
373.L309:
374        beq 6,.L304
375.L308:
376        lbzu 0,1(3)
377        cmpw 7,4,0
378        cmpwi 6,0,0
379        bne 7,.L309
380        blr
381.L304:
382        li 3,0
383        blr
384.size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
385
386.global VG_(trampoline_stuff_end)
387VG_(trampoline_stuff_end):
388
389	/* and a trailing page of unexecutable code */
390	UD2_PAGE
391
392#	undef UD2_16
393#	undef UD2_64
394#	undef UD2_256
395#	undef UD2_1024
396#	undef UD2_PAGE
397
398/*---------------- ppc64-linux ----------------*/
399#else
400#if defined(VGP_ppc64_linux)
401
402#	define UD2_16     trap ; trap ; trap; trap
403#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
404#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
405#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
406#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
407
408	/* a leading page of unexecutable code */
409	UD2_PAGE
410
411.global VG_(trampoline_stuff_start)
412VG_(trampoline_stuff_start):
413
414.global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
415VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
416	li 0,__NR_rt_sigreturn
417        sc
418        .long 0	/*illegal insn*/
419
420	/* See comment in pub_core_trampoline.h for what this is for */
421.global VG_(ppctoc_magic_redirect_return_stub)
422VG_(ppctoc_magic_redirect_return_stub):
423	trap
424
425	/* this function is written using the "dotless" ABI convention */
426	.align 2
427	.globl VG_(ppc64_linux_REDIR_FOR_strlen)
428	.section        ".opd","aw"
429	.align 3
430VG_(ppc64_linux_REDIR_FOR_strlen):
431	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
432	.previous
433	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
434			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
435	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
436
437.L.VG_(ppc64_linux_REDIR_FOR_strlen):
438        mr 9,3
439        lbz 0,0(3)
440        li 3,0
441        cmpwi 7,0,0
442        beqlr 7
443        li 3,0
444.L01:
445        addi 0,3,1
446        extsw 3,0
447        lbzx 0,9,3
448        cmpwi 7,0,0
449        bne 7,.L01
450        blr
451        .long 0
452        .byte 0,0,0,0,0,0,0,0
453.L0end:
454
455        /* this function is written using the "dotless" ABI convention */
456        .align 2
457        .globl VG_(ppc64_linux_REDIR_FOR_strchr)
458	.section        ".opd","aw"
459	.align 3
460VG_(ppc64_linux_REDIR_FOR_strchr):
461        .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
462        .previous
463        .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
464                        .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
465        .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
466
467.L.VG_(ppc64_linux_REDIR_FOR_strchr):
468        lbz 0,0(3)
469        rldicl 4,4,0,56
470        cmpw 7,4,0
471        beqlr 7
472        cmpdi 7,0,0
473        bne 7,.L18
474        b .L14
475.L19:
476        beq 6,.L14
477.L18:
478        lbzu 0,1(3)
479        cmpw 7,4,0
480        cmpdi 6,0,0
481        bne 7,.L19
482        blr
483.L14:
484        li 3,0
485        blr
486        .long 0
487        .byte 0,0,0,0,0,0,0,0
488.L1end:
489
490
491.global VG_(trampoline_stuff_end)
492VG_(trampoline_stuff_end):
493
494	/* and a trailing page of unexecutable code */
495	UD2_PAGE
496
497#	undef UD2_16
498#	undef UD2_64
499#	undef UD2_256
500#	undef UD2_1024
501#	undef UD2_PAGE
502
503/*---------------- ppc32-linux ----------------*/
504
505#elif defined(VGP_arm_linux)
506
507#       define UD2_4      .word 0xFFFFFFFF
508#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
509#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
510#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
511#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
512#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
513
514	/* a leading page of unexecutable code */
515	UD2_PAGE
516
517.global VG_(trampoline_stuff_start)
518VG_(trampoline_stuff_start):
519
520.global VG_(arm_linux_REDIR_FOR_strlen)
521VG_(arm_linux_REDIR_FOR_strlen):
522	mov	r2, r0
523	ldrb	r0, [r0, #0]	@ zero_extendqisi2
524	@ lr needed for prologue
525	cmp	r0, #0
526	bxeq	lr
527	mov	r0, #0
528.L5:
529	add	r0, r0, #1
530	ldrb	r3, [r0, r2]	@ zero_extendqisi2
531	cmp	r3, #0
532	bne	.L5
533	bx	lr
534	UD2_4
535
536//.global VG_(arm_linux_REDIR_FOR_index)
537//VG_(arm_linux_REDIR_FOR_index):
538//	ldrb	r3, [r0, #0]	@ zero_extendqisi2
539//	and	r1, r1, #255
540//	cmp	r3, r1
541//	@ lr needed for prologue
542//	bne	.L9
543//	bx	lr
544//.L12:
545//	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
546//	cmp	r3, r1
547//	beq	.L11
548//.L9:
549//	cmp	r3, #0
550//	bne	.L12
551//	mov	r0, #0
552//	bx	lr
553//.L11:
554//	bx	lr
555//	UD2_4
556
557.global VG_(arm_linux_REDIR_FOR_memcpy)
558VG_(arm_linux_REDIR_FOR_memcpy):
559	stmfd	sp!, {r4, r5, lr}
560	subs	lr, r2, #0
561	mov	r5, r0
562	beq	.L2
563	cmp	r0, r1
564	bls	.L4
565	add	r3, r0, lr
566	add	r1, lr, r1
567	cmp	lr, #3
568	sub	r4, r3, #1
569	sub	r0, r1, #1
570	ble	.L28
571	sub	ip, r3, #5
572	sub	r1, r1, #5
573.L8:
574	ldrb	r3, [r1, #4]	@ zero_extendqisi2
575	sub	lr, lr, #4
576	strb	r3, [ip, #4]
577	ldrb	r2, [r1, #3]	@ zero_extendqisi2
578	cmp	lr, #3
579	strb	r2, [ip, #3]
580	ldrb	r3, [r1, #2]	@ zero_extendqisi2
581	mov	r4, ip
582	strb	r3, [ip, #2]
583	ldrb	r2, [r1, #1]	@ zero_extendqisi2
584	mov	r0, r1
585	strb	r2, [ip, #1]
586	sub	r1, r1, #4
587	sub	ip, ip, #4
588	bgt	.L8
589	cmp	lr, #0
590	beq	.L2
591.L28:
592	sub	r2, lr, #1
593.L21:
594	sub	r2, r2, #1
595	ldrb	r3, [r0], #-1	@ zero_extendqisi2
596	cmn	r2, #1
597	strb	r3, [r4], #-1
598	bne	.L21
599.L2:
600	mov	r0, r5
601	ldmfd	sp!, {r4, r5, pc}
602.L4:
603	bcs	.L2
604	cmp	lr, #3
605	mov	ip, r0
606	ble	.L29
607.L19:
608	ldrb	r3, [r1, #0]	@ zero_extendqisi2
609	sub	lr, lr, #4
610	strb	r3, [ip, #0]
611	ldrb	r2, [r1, #1]	@ zero_extendqisi2
612	cmp	lr, #3
613	strb	r2, [ip, #1]
614	ldrb	r3, [r1, #2]	@ zero_extendqisi2
615	strb	r3, [ip, #2]
616	ldrb	r2, [r1, #3]	@ zero_extendqisi2
617	add	r1, r1, #4
618	strb	r2, [ip, #3]
619	add	ip, ip, #4
620	bgt	.L19
621	cmp	lr, #0
622	beq	.L2
623.L29:
624	sub	r2, lr, #1
625.L20:
626	sub	r2, r2, #1
627	ldrb	r3, [r1], #1	@ zero_extendqisi2
628	cmn	r2, #1
629	strb	r3, [ip], #1
630	bne	.L20
631	mov	r0, r5
632	ldmfd	sp!, {r4, r5, pc}
633	UD2_4
634
635.global VG_(trampoline_stuff_end)
636VG_(trampoline_stuff_end):
637
638	/* and a trailing page of unexecutable code */
639	UD2_PAGE
640
641#	undef UD2_4
642#	undef UD2_16
643#	undef UD2_64
644#	undef UD2_256
645#	undef UD2_1024
646#	undef UD2_PAGE
647
648/*---------------- x86-darwin ----------------*/
649#else
650#if defined(VGP_x86_darwin)
651
652        /* a leading page of unexecutable code */
653.fill 2048, 2, 0x0b0f /* `ud2` */
654
655.globl VG_(trampoline_stuff_start)
656VG_(trampoline_stuff_start):
657
658.globl VG_(x86_darwin_SUBST_FOR_sigreturn)
659VG_(x86_darwin_SUBST_FOR_sigreturn):
660        /* XXX does this need to have any special form? (cf x86-linux
661	version) */
662        movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
663        int     $0x80
664        ud2
665
666.globl VG_(x86_darwin_REDIR_FOR_strlen)
667VG_(x86_darwin_REDIR_FOR_strlen):
668        movl    4(%esp), %edx
669        movl    %edx, %eax
670        jmp     1f
6710:
672        incl    %eax
6731:
674        cmpb    $0, (%eax)
675        jne     0b
676        subl    %edx, %eax
677        ret
678
679.globl VG_(x86_darwin_REDIR_FOR_strcat)
680VG_(x86_darwin_REDIR_FOR_strcat):
681        pushl   %esi
682        movl    8(%esp), %esi
683        movl    12(%esp), %ecx
684        movl    %esi, %edx
685        jmp     1f
6860:
687        incl    %edx
6881:
689        cmpb    $0, (%edx)
690        jne     0b
6912:
692        movzbl  (%ecx), %eax
693        incl    %ecx
694        movb    %al, (%edx)
695        incl    %edx
696        testb   %al, %al
697        jne     2b
698        movl    %esi, %eax
699        popl    %esi
700        ret
701
702
703.globl VG_(x86_darwin_REDIR_FOR_strcmp)
704VG_(x86_darwin_REDIR_FOR_strcmp):
705        movl    4(%esp), %edx
706        movl    8(%esp), %ecx
707        jmp     1f
7080:
709        incl    %edx
710        incl    %ecx
7111:
712        movzbl  (%edx), %eax
713        testb   %al, %al
714        je      2f
715        cmpb    (%ecx), %al
716        je      0b
7172:
718        movzbl  (%ecx),%edx
719        movzbl  %al,%eax
720        subl    %edx, %eax
721        ret
722
723
724.globl VG_(x86_darwin_REDIR_FOR_strcpy)
725VG_(x86_darwin_REDIR_FOR_strcpy):
726	pushl	%ebp
727	movl	%esp, %ebp
728	pushl	%esi
729	movl	8(%ebp), %esi
730	movl	12(%ebp), %ecx
731	movl	%esi, %edx
732	jmp	1f
7330:
734	incl	%ecx
735	incl	%edx
7361:
737	movzbl	(%ecx), %eax
738	testb	%al, %al
739	movb	%al, (%edx)
740	jne	0b
741	movl	%esi, %eax
742	popl	%esi
743	leave
744	ret
745
746.globl VG_(x86_darwin_REDIR_FOR_strlcat)
747VG_(x86_darwin_REDIR_FOR_strlcat):
748	pushl	%ebp
749	movl	%esp, %ebp
750	pushl	%edi
751	pushl	%esi
752	subl	$16, %esp
753	movl	8(%ebp), %esi
754	movl	16(%ebp), %ecx
755	movl	%esi, %edx
756	leal	(%ecx,%esi), %eax
757	jmp	1f
7580:
759	incl	%edx
7601:
761	cmpl	%edx, %eax
762	je	2f
763	cmpb	$0, (%edx)
764	jne	0b
7652:
766	movl	%edx, %edi
767	subl	%esi, %edi
768	movl	%ecx, %esi
769	subl	%edi, %esi
770	je	3f
771	movl	12(%ebp), %eax
772	jmp	6f
7733:
774	movl	12(%ebp), %eax
775	movl	%eax, (%esp)
776	call	VG_(x86_darwin_REDIR_FOR_strlen)
777	jmp	7f
7784:
779	cmpl	$1, %esi
780	je	5f
781	movb	%cl, (%edx)
782	decl	%esi
783	incl	%edx
7845:
785	incl	%eax
7866:
787	movzbl	(%eax), %ecx
788	testb	%cl, %cl
789	jne	4b
790	movb	$0, (%edx)
791	subl	12(%ebp), %eax
7927:
793	addl	$16, %esp
794	leal	(%edi,%eax), %eax
795	popl	%esi
796	popl	%edi
797	leave
798	ret
799
800
801.globl VG_(trampoline_stuff_end)
802VG_(trampoline_stuff_end):
803
804        /* a trailing page of unexecutable code */
805.fill 2048, 2, 0x0b0f /* `ud2` */
806
807
808/*---------------- amd64-darwin ----------------*/
809#else
810#if defined(VGP_amd64_darwin)
811
812        /* a leading page of unexecutable code */
813.fill 2048, 2, 0x0b0f /* `ud2` */
814
815.globl VG_(trampoline_stuff_start)
816VG_(trampoline_stuff_start):
817
818.globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
819VG_(amd64_darwin_SUBST_FOR_sigreturn):
820        /* XXX does this need to have any special form? (cf x86-linux
821	version) */
822        movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
823        syscall
824        ud2
825
826.globl VG_(amd64_darwin_REDIR_FOR_strlen)
827VG_(amd64_darwin_REDIR_FOR_strlen):
828        movq    %rdi, %rax
829        jmp     1f
8300:
831        incq    %rax
8321:
833        cmpb    $0, (%rax)
834        jne     0b
835        subq    %rdi, %rax
836        ret
837
838.globl VG_(amd64_darwin_REDIR_FOR_strcat)
839VG_(amd64_darwin_REDIR_FOR_strcat):
840	movq	%rdi, %rdx
841	jmp	1f
8420:
843	incq	%rdx
8441:
845	cmpb	$0, (%rdx)
846	jne	0b
8472:
848	movzbl	(%rsi), %eax
849	incq	%rsi
850	movb	%al, (%rdx)
851	incq	%rdx
852	testb	%al, %al
853	jne	2b
854	movq	%rdi, %rax
855	ret
856
857
858.globl VG_(amd64_darwin_REDIR_FOR_strcmp)
859VG_(amd64_darwin_REDIR_FOR_strcmp):
860	jmp	1f
8610:
862	incq	%rdi
863	incq	%rsi
8641:
865	movzbl	(%rdi), %eax
866	testb	%al, %al
867	je	2f
868	cmpb	(%rsi), %al
869	je	0b
8702:
871	movzbl	(%rsi), %edx
872	movzbl	%al, %eax
873	subl	%edx, %eax
874	ret
875
876.globl VG_(amd64_darwin_REDIR_FOR_strcpy)
877VG_(amd64_darwin_REDIR_FOR_strcpy):
878	pushq	%rbp
879	movq	%rdi, %rdx
880	movq	%rsp, %rbp
881	jmp	1f
8820:
883	incq	%rsi
884	incq	%rdx
8851:
886	movzbl	(%rsi), %eax
887	testb	%al, %al
888	movb	%al, (%rdx)
889	jne	0b
890	leave
891	movq	%rdi, %rax
892	ret
893
894.globl VG_(amd64_darwin_REDIR_FOR_strlcat)
895VG_(amd64_darwin_REDIR_FOR_strlcat):
896	pushq	%rbp
897	leaq	(%rdx,%rdi), %rax
898	movq	%rdi, %rcx
899	movq	%rsp, %rbp
900	pushq	%rbx
901	subq	$8, %rsp
902	jmp	1f
9030:
904	incq	%rcx
9051:
906	cmpq	%rcx, %rax
907	je	2f
908	cmpb	$0, (%rcx)
909	jne	0b
9102:
911	movq	%rcx, %rbx
912	subq	%rdi, %rbx
913	movq	%rdx, %rdi
914	subq	%rbx, %rdi
915	je	3f
916	movq	%rsi, %rax
917	jmp	6f
9183:
919	movq	%rsi, %rdi
920	call	VG_(amd64_darwin_REDIR_FOR_strlen)
921	jmp	7f
9224:
923	cmpq	$1, %rdi
924	je	5f
925	movb	%dl, (%rcx)
926	decq	%rdi
927	incq	%rcx
9285:
929	incq	%rax
9306:
931	movzbl	(%rax), %edx
932	testb	%dl, %dl
933	jne	4b
934	movb	$0, (%rcx)
935	subq	%rsi, %rax
9367:
937	leaq	(%rbx,%rax), %rax
938	addq	$8, %rsp
939	popq	%rbx
940	leave
941	ret
942
943.globl VG_(amd64_darwin_REDIR_FOR_arc4random)
944VG_(amd64_darwin_REDIR_FOR_arc4random):
945	/* not very random, hope dyld won't mind */
946	movq	$0x76616c6772696e64, %rax
947	ret
948
949.globl VG_(trampoline_stuff_end)
950VG_(trampoline_stuff_end):
951
952        /* a trailing page of unexecutable code */
953.fill 2048, 2, 0x0b0f /* `ud2` */
954
955
956/*---------------- s390x-linux ----------------*/
957#else
958#if defined(VGP_s390x_linux)
959
960        /* a leading page of unexecutable code */
961	.fill 2048, 2, 0x0000
962
963.global VG_(trampoline_stuff_start)
964VG_(trampoline_stuff_start):
965
966.global VG_(s390x_linux_SUBST_FOR_sigreturn)
967VG_(s390x_linux_SUBST_FOR_sigreturn):
968        svc __NR_sigreturn
969	.short 0
970
971.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
972VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
973        /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
974           for ra = cfa to decide if it is a sig_rt_frame or not. Since we
975           set ra to this trampoline, but the cfa is still in the stack,
976           the unwinder thinks, that this is a non-rt frame  and causes a
977           crash in the gcc unwinder - which is used by the thread library
978           and others. Therefore we add a lr 1,1 nop, to let the gcc
979           unwinder bail out gracefully. This might also affect unwinding
980           across the signal frame - tough luck. fixs390 */
981        lr 1,1
982        svc __NR_rt_sigreturn
983	.short 0
984
985.globl VG_(trampoline_stuff_end)
986VG_(trampoline_stuff_end):
987	.fill 2048, 2, 0x0000
988
989/*---------------- unknown ----------------*/
990#else
991#  error Unknown platform
992
993#endif
994#endif
995#endif
996#endif
997#endif
998#endif
999#endif
1000
1001#if defined(VGO_linux)
1002/* Let the linker know we don't need an executable stack */
1003#  if defined(VGP_arm_linux)
1004   .section .note.GNU-stack,"",%progbits
1005#  else
1006   .section .note.GNU-stack,"",@progbits
1007#  endif
1008#endif
1009
1010/*--------------------------------------------------------------------*/
1011/*--- end                                                          ---*/
1012/*--------------------------------------------------------------------*/
1013