m_trampoline.S revision e739ac0589b4fb43561f801c4faba8c1b89f8680
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-2010 Julian Seward
11     jseward@acm.org
12  Copyright (C) 2006-2010 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.global VG_(trampoline_stuff_end)
116VG_(trampoline_stuff_end):
117
118	/* and a trailing page of unexecutable code */
119	UD2_PAGE
120
121#	undef UD2_16
122#	undef UD2_64
123#	undef UD2_256
124#	undef UD2_1024
125#	undef UD2_PAGE
126
127/*---------------------- amd64-linux ----------------------*/
128#else
129#if defined(VGP_amd64_linux)
130
131#	define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
132#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
133#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
134#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
135#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
136
137	/* a leading page of unexecutable code */
138	UD2_PAGE
139
140.global VG_(trampoline_stuff_start)
141VG_(trampoline_stuff_start):
142
143.global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
144VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
145        /* This is a very specific sequence which GDB uses to
146           recognize signal handler frames. */
147        movq    $__NR_rt_sigreturn, %rax
148        syscall
149        ud2
150
151.global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
152.type   VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
153VG_(amd64_linux_REDIR_FOR_vgettimeofday):
154.LfnB2:
155        movq    $__NR_gettimeofday, %rax
156        syscall
157        ret
158.LfnE2:
159.size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
160
161.global VG_(amd64_linux_REDIR_FOR_vtime)
162.type   VG_(amd64_linux_REDIR_FOR_vtime), @function
163VG_(amd64_linux_REDIR_FOR_vtime):
164.LfnB3:
165        movq    $__NR_time, %rax
166        syscall
167        ret
168.LfnE3:
169.size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
170
171/* There's no particular reason that this needs to be handwritten
172   assembly, but since that's what this file contains, here's a
173   simple strlen implementation (written in C and compiled by gcc.)
174*/
175.global VG_(amd64_linux_REDIR_FOR_strlen)
176.type   VG_(amd64_linux_REDIR_FOR_strlen), @function
177VG_(amd64_linux_REDIR_FOR_strlen):
178.LfnB4:
179	xorl	%eax, %eax
180	cmpb	$0, (%rdi)
181	movq	%rdi, %rdx
182	je	.L41
183.L40:	addq	$1, %rdx
184	cmpb	$0, (%rdx)
185	jne	.L40
186	movq	%rdx, %rax
187	subq	%rdi, %rax
188.L41:	ret
189.LfnE4:
190.size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
191
192
193/* A CIE for the above three functions, followed by their FDEs */
194	.section .eh_frame,"a",@progbits
195.Lframe1:
196        .long   .LEcie1-.LScie1
197.LScie1:
198        .long   0x0
199        .byte   0x1
200        .string "zR"
201        .uleb128 0x1
202        .sleb128 -8
203        .byte   0x10
204        .uleb128 0x1
205        .byte   0x3
206        .byte   0xc
207        .uleb128 0x7
208        .uleb128 0x8
209        .byte   0x90
210        .uleb128 0x1
211        .align 8
212.LEcie1:
213.LSfde2:
214        .long   .LEfde2-.LASfde2
215.LASfde2:
216        .long   .LASfde2-.Lframe1
217        .long   .LfnB2
218        .long   .LfnE2-.LfnB2
219        .uleb128 0x0
220        .align 8
221.LEfde2:
222.LSfde3:
223        .long   .LEfde3-.LASfde3
224.LASfde3:
225        .long   .LASfde3-.Lframe1
226        .long   .LfnB3
227        .long   .LfnE3-.LfnB3
228        .uleb128 0x0
229        .align 8
230.LEfde3:
231.LSfde4:
232        .long   .LEfde4-.LASfde4
233.LASfde4:
234        .long   .LASfde4-.Lframe1
235        .long   .LfnB4
236        .long   .LfnE4-.LfnB4
237        .uleb128 0x0
238        .align 8
239.LEfde4:
240	.previous
241
242.global VG_(trampoline_stuff_end)
243VG_(trampoline_stuff_end):
244
245	/* and a trailing page of unexecutable code */
246	UD2_PAGE
247
248#	undef UD2_16
249#	undef UD2_64
250#	undef UD2_256
251#	undef UD2_1024
252#	undef UD2_PAGE
253
254/*---------------- ppc32-linux ----------------*/
255#else
256#if defined(VGP_ppc32_linux)
257
258#	define UD2_16     trap ; trap ; trap; trap
259#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
260#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
261#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
262#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
263
264	/* a leading page of unexecutable code */
265	UD2_PAGE
266
267.global VG_(trampoline_stuff_start)
268VG_(trampoline_stuff_start):
269
270.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
271VG_(ppc32_linux_SUBST_FOR_sigreturn):
272	li 0,__NR_sigreturn
273        sc
274        .long 0	/*illegal insn*/
275
276.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
277VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
278	li 0,__NR_rt_sigreturn
279        sc
280        .long 0	/*illegal insn*/
281
282/* There's no particular reason that this needs to be handwritten
283   assembly, but since that's what this file contains, here's a
284   simple strlen implementation (written in C and compiled by gcc.)
285*/
286.global VG_(ppc32_linux_REDIR_FOR_strlen)
287.type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
288VG_(ppc32_linux_REDIR_FOR_strlen):
289        lbz 4,0(3)
290        li 9,0
291        cmpwi 0,4,0
292        beq- 0,.L18
293.L19:
294        lbzu 5,1(3)
295        addi 9,9,1
296        cmpwi 0,5,0
297        bne+ 0,.L19
298.L18:
299        mr 3,9
300        blr
301.size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
302
303/* Ditto strcmp */
304.global VG_(ppc32_linux_REDIR_FOR_strcmp)
305.type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
306VG_(ppc32_linux_REDIR_FOR_strcmp):
307.L20:
308        lbz 0,0(3)
309        cmpwi 7,0,0
310        bne- 7,.L21
311        lbz 0,0(4)
312        li 11,0
313        cmpwi 7,0,0
314        beq- 7,.L22
315.L21:
316        lbz 0,0(3)
317        li 11,-1
318        cmpwi 7,0,0
319        beq- 7,.L22
320        lbz 0,0(4)
321        li 11,1
322        cmpwi 7,0,0
323        beq- 7,.L22
324        lbz 9,0(3)
325        lbz 0,0(4)
326        li 11,-1
327        cmplw 7,9,0
328        blt- 7,.L22
329        lbz 9,0(3)
330        lbz 0,0(4)
331        li 11,1
332        addi 3,3,1
333        addi 4,4,1
334        cmplw 7,9,0
335        ble+ 7,.L20
336.L22:
337        mr 3,11
338        blr
339.size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
340
341/* Ditto index/strchr */
342.global VG_(ppc32_linux_REDIR_FOR_strchr)
343.type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
344VG_(ppc32_linux_REDIR_FOR_strchr):
345        lbz 0,0(3)
346        rlwinm 4,4,0,0xff
347        cmpw 7,4,0
348        beqlr 7
349        cmpwi 7,0,0
350        bne 7,.L308
351        b .L304
352.L309:
353        beq 6,.L304
354.L308:
355        lbzu 0,1(3)
356        cmpw 7,4,0
357        cmpwi 6,0,0
358        bne 7,.L309
359        blr
360.L304:
361        li 3,0
362        blr
363.size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
364
365.global VG_(trampoline_stuff_end)
366VG_(trampoline_stuff_end):
367
368	/* and a trailing page of unexecutable code */
369	UD2_PAGE
370
371#	undef UD2_16
372#	undef UD2_64
373#	undef UD2_256
374#	undef UD2_1024
375#	undef UD2_PAGE
376
377/*---------------- ppc64-linux ----------------*/
378#else
379#if defined(VGP_ppc64_linux)
380
381#	define UD2_16     trap ; trap ; trap; trap
382#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
383#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
384#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
385#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
386
387	/* a leading page of unexecutable code */
388	UD2_PAGE
389
390.global VG_(trampoline_stuff_start)
391VG_(trampoline_stuff_start):
392
393.global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
394VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
395	li 0,__NR_rt_sigreturn
396        sc
397        .long 0	/*illegal insn*/
398
399	/* See comment in pub_core_trampoline.h for what this is for */
400.global VG_(ppctoc_magic_redirect_return_stub)
401VG_(ppctoc_magic_redirect_return_stub):
402	trap
403
404	/* this function is written using the "dotless" ABI convention */
405	.align 2
406	.globl VG_(ppc64_linux_REDIR_FOR_strlen)
407	.section        ".opd","aw"
408	.align 3
409VG_(ppc64_linux_REDIR_FOR_strlen):
410	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
411	.previous
412	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
413			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
414	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
415
416.L.VG_(ppc64_linux_REDIR_FOR_strlen):
417        mr 9,3
418        lbz 0,0(3)
419        li 3,0
420        cmpwi 7,0,0
421        beqlr 7
422        li 3,0
423.L01:
424        addi 0,3,1
425        extsw 3,0
426        lbzx 0,9,3
427        cmpwi 7,0,0
428        bne 7,.L01
429        blr
430        .long 0
431        .byte 0,0,0,0,0,0,0,0
432.L0end:
433
434        /* this function is written using the "dotless" ABI convention */
435        .align 2
436        .globl VG_(ppc64_linux_REDIR_FOR_strchr)
437	.section        ".opd","aw"
438	.align 3
439VG_(ppc64_linux_REDIR_FOR_strchr):
440        .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
441        .previous
442        .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
443                        .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
444        .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
445
446.L.VG_(ppc64_linux_REDIR_FOR_strchr):
447        lbz 0,0(3)
448        rldicl 4,4,0,56
449        cmpw 7,4,0
450        beqlr 7
451        cmpdi 7,0,0
452        bne 7,.L18
453        b .L14
454.L19:
455        beq 6,.L14
456.L18:
457        lbzu 0,1(3)
458        cmpw 7,4,0
459        cmpdi 6,0,0
460        bne 7,.L19
461        blr
462.L14:
463        li 3,0
464        blr
465        .long 0
466        .byte 0,0,0,0,0,0,0,0
467.L1end:
468
469
470.global VG_(trampoline_stuff_end)
471VG_(trampoline_stuff_end):
472
473	/* and a trailing page of unexecutable code */
474	UD2_PAGE
475
476#	undef UD2_16
477#	undef UD2_64
478#	undef UD2_256
479#	undef UD2_1024
480#	undef UD2_PAGE
481
482/*---------------- ppc32-linux ----------------*/
483
484#elif defined(VGP_arm_linux)
485
486#       define UD2_4      .word 0xFFFFFFFF
487#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
488#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
489#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
490#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
491#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
492
493	/* a leading page of unexecutable code */
494	UD2_PAGE
495
496.global VG_(trampoline_stuff_start)
497VG_(trampoline_stuff_start):
498
499.global VG_(arm_linux_REDIR_FOR_strlen)
500VG_(arm_linux_REDIR_FOR_strlen):
501	mov	r2, r0
502	ldrb	r0, [r0, #0]	@ zero_extendqisi2
503	@ lr needed for prologue
504	cmp	r0, #0
505	bxeq	lr
506	mov	r0, #0
507.L5:
508	add	r0, r0, #1
509	ldrb	r3, [r0, r2]	@ zero_extendqisi2
510	cmp	r3, #0
511	bne	.L5
512	bx	lr
513	UD2_4
514
515//.global VG_(arm_linux_REDIR_FOR_index)
516//VG_(arm_linux_REDIR_FOR_index):
517//	ldrb	r3, [r0, #0]	@ zero_extendqisi2
518//	and	r1, r1, #255
519//	cmp	r3, r1
520//	@ lr needed for prologue
521//	bne	.L9
522//	bx	lr
523//.L12:
524//	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
525//	cmp	r3, r1
526//	beq	.L11
527//.L9:
528//	cmp	r3, #0
529//	bne	.L12
530//	mov	r0, #0
531//	bx	lr
532//.L11:
533//	bx	lr
534//	UD2_4
535
536.global VG_(arm_linux_REDIR_FOR_memcpy)
537VG_(arm_linux_REDIR_FOR_memcpy):
538	stmfd	sp!, {r4, r5, lr}
539	subs	lr, r2, #0
540	mov	r5, r0
541	beq	.L2
542	cmp	r0, r1
543	bls	.L4
544	add	r3, r0, lr
545	add	r1, lr, r1
546	cmp	lr, #3
547	sub	r4, r3, #1
548	sub	r0, r1, #1
549	ble	.L28
550	sub	ip, r3, #5
551	sub	r1, r1, #5
552.L8:
553	ldrb	r3, [r1, #4]	@ zero_extendqisi2
554	sub	lr, lr, #4
555	strb	r3, [ip, #4]
556	ldrb	r2, [r1, #3]	@ zero_extendqisi2
557	cmp	lr, #3
558	strb	r2, [ip, #3]
559	ldrb	r3, [r1, #2]	@ zero_extendqisi2
560	mov	r4, ip
561	strb	r3, [ip, #2]
562	ldrb	r2, [r1, #1]	@ zero_extendqisi2
563	mov	r0, r1
564	strb	r2, [ip, #1]
565	sub	r1, r1, #4
566	sub	ip, ip, #4
567	bgt	.L8
568	cmp	lr, #0
569	beq	.L2
570.L28:
571	sub	r2, lr, #1
572.L21:
573	sub	r2, r2, #1
574	ldrb	r3, [r0], #-1	@ zero_extendqisi2
575	cmn	r2, #1
576	strb	r3, [r4], #-1
577	bne	.L21
578.L2:
579	mov	r0, r5
580	ldmfd	sp!, {r4, r5, pc}
581.L4:
582	bcs	.L2
583	cmp	lr, #3
584	mov	ip, r0
585	ble	.L29
586.L19:
587	ldrb	r3, [r1, #0]	@ zero_extendqisi2
588	sub	lr, lr, #4
589	strb	r3, [ip, #0]
590	ldrb	r2, [r1, #1]	@ zero_extendqisi2
591	cmp	lr, #3
592	strb	r2, [ip, #1]
593	ldrb	r3, [r1, #2]	@ zero_extendqisi2
594	strb	r3, [ip, #2]
595	ldrb	r2, [r1, #3]	@ zero_extendqisi2
596	add	r1, r1, #4
597	strb	r2, [ip, #3]
598	add	ip, ip, #4
599	bgt	.L19
600	cmp	lr, #0
601	beq	.L2
602.L29:
603	sub	r2, lr, #1
604.L20:
605	sub	r2, r2, #1
606	ldrb	r3, [r1], #1	@ zero_extendqisi2
607	cmn	r2, #1
608	strb	r3, [ip], #1
609	bne	.L20
610	mov	r0, r5
611	ldmfd	sp!, {r4, r5, pc}
612	UD2_4
613
614.global VG_(trampoline_stuff_end)
615VG_(trampoline_stuff_end):
616
617	/* and a trailing page of unexecutable code */
618	UD2_PAGE
619
620#	undef UD2_4
621#	undef UD2_16
622#	undef UD2_64
623#	undef UD2_256
624#	undef UD2_1024
625#	undef UD2_PAGE
626
627/*---------------- ppc32-aix5 ----------------*/
628#else
629#if defined(VGP_ppc32_aix5)
630
631#	define UD2_16     trap ; trap ; trap; trap
632#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
633#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
634#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
635#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
636
637	.csect .text[PR]
638
639	/* a leading page of unexecutable code */
640	UD2_PAGE
641
642.globl VG_(trampoline_stuff_start)
643VG_(trampoline_stuff_start):
644
645/* See pub_core_trampoline.h for an explaination of this.  Also
646   see pub_core_initimg.h, struct AIX5PreloadPage.  On entry, r3
647   points to an AIX5PreloadPage structure.  Note we can only
648   use r2-r10 as scratch registers here since those are the
649   only ones restored from the preload page when finally
650   starting the client. */
651.globl VG_(ppc32_aix5_do_preloads_then_start_client)
652VG_(ppc32_aix5_do_preloads_then_start_client):
653	stwu	1,-1024(1)
654	stw	3,512(1)	/* stash r3 512 bytes up stack */
655
656	/* Try to load .../vgpreload_core.so */
657	lwz	2,0(3)		/* r2 = __NR___loadx */
658	lwz	5,20(3)		/* r5 = off_preloadcorename */
659	add	6,3,5		/* r6 = preloadcorename */
660	addis	1,1,-4
661	bl	do___loadx
662	addis	1,1,4
663	cmpwi	0,3,0
664	beq	.Lfailed
665
666	/* Try to load .../vgpreload_tool.so, if it exists */
667	lwz	3,512(1)	/* restore r3 */
668	lwz	2,0(3)		/* r2 = __NR___loadx */
669	lwz	5,24(3)		/* r5 = off_preloadtoolname */
670	cmpwi	0,5,0		/* skip tool preload if */
671	beq	.Ltry_preload	/* name not present */
672	add	6,3,5		/* r6 = preloadtoolname */
673	addis	1,1,-4
674	bl	do___loadx
675	addis	1,1,4
676	cmpwi	0,3,0
677	beq	.Lfailed
678
679.Ltry_preload:
680	/* Try to load the LD_PRELOAD= file, if it exists */
681	lwz	3,512(1)	/* restore r3 */
682	lwz	2,0(3)		/* r2 = __NR___loadx */
683	lwz	5,28(3)		/* r5 = off_ld_preloadname */
684	cmpwi	0,5,0		/* skip ld_preload if */
685	beq	.Lstart_client	/* name not present */
686	add	6,3,5		/* r6 = ld_preloadname */
687	addis	1,1,-4
688	bl	do___loadx
689	addis	1,1,4
690	cmpwi	0,3,0
691	beq	.Lfailed
692
693.Lstart_client:
694	/* Success.  Restore r2-r10 from preloadpage-> and start
695	the client. */
696	lwz	3,512(1)	/* restore r3 */
697	addi	1,1,1024
698	lwz	2,32+4(3)	/* preloadpage->client_start */
699	mtctr	2
700	lwz	2,40+4(3)	/* preloadpage->r2 */
701	lwz	4,56+4(3)	/* preloadpage->r4 */
702	lwz	5,64+4(3)	/* preloadpage->r5 */
703	lwz	6,72+4(3)	/* preloadpage->r6 */
704	lwz	7,80+4(3)	/* preloadpage->r7 */
705	lwz	8,88+4(3)	/* preloadpage->r8 */
706	lwz	9,96+4(3)	/* preloadpage->r9 */
707	lwz	10,104+4(3)	/* preloadpage->r10 */
708	lwz	3,48+4(3)	/* preloadpage->r3 */
709	bctr
710	/*NOTREACHED*/
711	trap
712
713.Lfailed:
714	/* __loadx barfed for some reason.  Print the error
715	message and get out. */
716	/* First the error msg */
717	lwz	3,512(1)	/* restore r3 */
718	lwz	2,4(3)		/* r2 = __NR_kwrite */
719	lwz	4,12(3)		/* r4 = offset of err msg */
720	add	4,4,3		/* r4 = err msg */
721	lwz	5,16(3)		/* r5 = length err msg */
722	li	3,2		/* r3 = stderr */
723	bl	do_syscall
724	/* now call the diagnosis fn */
725	lwz	3,512(1)	/* restore r3 */
726	lwz	4,112(3)	/* preloadpage->p_diagnose_load_failure */
727	lwz	2,4(4)		/* get its TOC ptr */
728	lwz	4,0(4)		/* get its entry point */
729	mtlr	4
730	blrl
731	/* Now do _exit(1) */
732	lwz	3,512(1)	/* restore r3 */
733	lwz	2,8(3)		/* r2 = __NR_exit */
734	li	3,1		/* doing _exit(1) */
735	addi	1,1,1024	/* fix stack pointer */
736	bl	do_syscall
737	/*NOTREACHED*/
738	trap
739
740do___loadx:
741	/* On entry: r2 = __NR___loadx,	r6 = name of module */
742	li	3,1
743	slwi	3,3,24	/* r3 = 0x1000000 = VKI_DL_LOAD */
744	mr	4,1
745	lis	5,3
746	li	7,0
747	li	8,0
748	li	9,0
749	li	10,0
750do_syscall:
751	crorc	6,6,6
752	sc
753	trap
754	/* sc continues at 'lr', hence this
755	constitutes an automatic return */
756
757
758	/* See comment in pub_core_trampoline.h for what this is for */
759.globl VG_(ppctoc_magic_redirect_return_stub)
760VG_(ppctoc_magic_redirect_return_stub):
761	trap
762
763.globl VG_(trampoline_stuff_end)
764VG_(trampoline_stuff_end):
765
766	/* and a trailing page of unexecutable code */
767	UD2_PAGE
768
769#	undef UD2_16
770#	undef UD2_64
771#	undef UD2_256
772#	undef UD2_1024
773#	undef UD2_PAGE
774
775/*---------------- ppc64-aix5 ----------------*/
776#else
777#if defined(VGP_ppc64_aix5)
778
779#	define UD2_16     trap ; trap ; trap; trap
780#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
781#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
782#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
783#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
784
785.globl VG_(trampoline_stuff_start)
786VG_(trampoline_stuff_start):
787/* See pub_core_trampoline.h for an explaination of this.  Also
788   see pub_core_initimg.h, struct AIX5PreloadPage.  On entry, r3
789   points to an AIX5PreloadPage structure.  Note we can only
790   use r2-r10 as scratch registers here since those are the
791   only ones restored from the preload page when finally
792   starting the client. */
793.globl VG_(ppc64_aix5_do_preloads_then_start_client)
794VG_(ppc64_aix5_do_preloads_then_start_client):
795	stdu	1,-1024(1)
796	std	3,512(1)	/* stash r3 512 bytes up stack */
797
798	/* Try to load .../vgpreload_core.so */
799	lwz	2,0(3)		/* r2 = __NR_kload */
800	lwz	5,20(3)		/* r5 = off_preloadcorename */
801	add	3,3,5		/* r6 = preloadcorename */
802	bl	do_kload
803	cmpdi	0,3,0
804	beq	.Lfailed
805
806	/* Try to load .../vgpreload_tool.so, if it exists */
807	ld	3,512(1)	/* restore r3 */
808	lwz	2,0(3)		/* r2 = __NR_kload */
809	lwz	5,24(3)		/* r5 = off_preloadtoolname */
810	cmpwi	0,5,0		/* skip tool preload if */
811	beq	.Ltry_preload	/* name not present */
812	add	3,3,5		/* r6 = preloadtoolname */
813	bl	do_kload
814	cmpdi	0,3,0
815	beq	.Lfailed
816
817.Ltry_preload:
818	/* Try to load the LD_PRELOAD= file, if it exists */
819	ld	3,512(1)	/* restore r3 */
820	lwz	2,0(3)		/* r2 = __NR_kload */
821	lwz	5,28(3)		/* r5 = off_ld_preloadname */
822	cmpwi	0,5,0		/* skip ld_preload if */
823	beq	.Lstart_client	/* name not present */
824	add	3,3,5		/* r6 = ld_preloadname */
825	bl	do_kload
826	cmpdi	0,3,0
827	beq	.Lfailed
828
829.Lstart_client:
830	/* Success.  Restore r2-r10 from preloadpage-> and start
831	the client. */
832	ld	3,512(1)	/* restore r3 */
833	addi	1,1,1024
834	ld	2,32+0(3)	/* preloadpage->client_start */
835	mtctr	2
836	ld	2,40+0(3)	/* preloadpage->r2 */
837	ld	4,56+0(3)	/* preloadpage->r4 */
838	ld	5,64+0(3)	/* preloadpage->r5 */
839	ld	6,72+0(3)	/* preloadpage->r6 */
840	ld	7,80+0(3)	/* preloadpage->r7 */
841	ld	8,88+0(3)	/* preloadpage->r8 */
842	ld	9,96+0(3)	/* preloadpage->r9 */
843	ld	10,104+0(3)	/* preloadpage->r10 */
844	ld	3,48+0(3)	/* preloadpage->r3 */
845	bctr
846	/*NOTREACHED*/
847	trap
848
849.Lfailed:
850	/* __loadx barfed for some reason.  Print the error
851	message and get out. */
852	/* First the error msg */
853	ld	3,512(1)	/* restore r3 */
854	lwz	2,4(3)		/* r2 = __NR_kwrite */
855	lwz	4,12(3)		/* r4 = offset of err msg */
856	add	4,4,3		/* r4 = err msg */
857	lwz	5,16(3)		/* r5 = length err msg */
858	li	3,2		/* r3 = stderr */
859	bl	do_syscall
860	/* now call the diagnosis fn */
861	ld	3,512(1)	/* restore r3 */
862	ld	4,112(3)	/* preloadpage->p_diagnose_load_failure */
863	ld	11,16(4)
864	ld	2,8(4)		/* get its TOC ptr */
865	ld	4,0(4)		/* get its entry point */
866	mtlr	4
867	blrl
868	/* Now do _exit(1) */
869	lwz	3,512(1)	/* restore r3 */
870	lwz	2,8(3)		/* r2 = __NR_exit */
871	li	3,1		/* doing _exit(1) */
872	addi	1,1,1024	/* fix stack pointer */
873	bl	do_syscall
874	/*NOTREACHED*/
875	trap
876
877do_kload:
878	/* On entry: r2 = __NR_kload,	r3 = name of module */
879	li	4,0
880	li	5,0
881	li	6,0
882	li	7,0
883	li	8,0
884	li	9,0
885	li	10,0
886do_syscall:
887	crorc	6,6,6
888	sc
889	/* sc continues at 'lr', hence this
890	constitutes an automatic return */
891
892	/* See comment in pub_core_trampoline.h for what this is for */
893.globl VG_(ppctoc_magic_redirect_return_stub)
894VG_(ppctoc_magic_redirect_return_stub):
895	trap
896
897.globl VG_(trampoline_stuff_end)
898VG_(trampoline_stuff_end):
899
900	/* and a trailing page of unexecutable code */
901	UD2_PAGE
902
903#	undef UD2_16
904#	undef UD2_64
905#	undef UD2_256
906#	undef UD2_1024
907#	undef UD2_PAGE
908
909/*---------------- x86-darwin ----------------*/
910#else
911#if defined(VGP_x86_darwin)
912
913        /* a leading page of unexecutable code */
914.fill 2048, 2, 0x0b0f /* `ud2` */
915
916.globl VG_(trampoline_stuff_start)
917VG_(trampoline_stuff_start):
918
919.globl VG_(x86_darwin_SUBST_FOR_sigreturn)
920VG_(x86_darwin_SUBST_FOR_sigreturn):
921        /* XXX does this need to have any special form? (cf x86-linux
922	version) */
923        movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
924        int     $0x80
925        ud2
926
927.globl VG_(x86_darwin_REDIR_FOR_strlen)
928VG_(x86_darwin_REDIR_FOR_strlen):
929        movl    4(%esp), %edx
930        movl    %edx, %eax
931        jmp     1f
9320:
933        incl    %eax
9341:
935        cmpb    $0, (%eax)
936        jne     0b
937        subl    %edx, %eax
938        ret
939
940.globl VG_(x86_darwin_REDIR_FOR_strcat)
941VG_(x86_darwin_REDIR_FOR_strcat):
942        pushl   %esi
943        movl    8(%esp), %esi
944        movl    12(%esp), %ecx
945        movl    %esi, %edx
946        jmp     1f
9470:
948        incl    %edx
9491:
950        cmpb    $0, (%edx)
951        jne     0b
9522:
953        movzbl  (%ecx), %eax
954        incl    %ecx
955        movb    %al, (%edx)
956        incl    %edx
957        testb   %al, %al
958        jne     2b
959        movl    %esi, %eax
960        popl    %esi
961        ret
962
963
964.globl VG_(x86_darwin_REDIR_FOR_strcmp)
965VG_(x86_darwin_REDIR_FOR_strcmp):
966        movl    4(%esp), %edx
967        movl    8(%esp), %ecx
968        jmp     1f
9690:
970        incl    %edx
971        incl    %ecx
9721:
973        movzbl  (%edx), %eax
974        testb   %al, %al
975        je      2f
976        cmpb    (%ecx), %al
977        je      0b
9782:
979        movzbl  (%ecx),%edx
980        movzbl  %al,%eax
981        subl    %edx, %eax
982        ret
983
984
985.globl VG_(x86_darwin_REDIR_FOR_strcpy)
986VG_(x86_darwin_REDIR_FOR_strcpy):
987	pushl	%ebp
988	movl	%esp, %ebp
989	pushl	%esi
990	movl	8(%ebp), %esi
991	movl	12(%ebp), %ecx
992	movl	%esi, %edx
993	jmp	1f
9940:
995	incl	%ecx
996	incl	%edx
9971:
998	movzbl	(%ecx), %eax
999	testb	%al, %al
1000	movb	%al, (%edx)
1001	jne	0b
1002	movl	%esi, %eax
1003	popl	%esi
1004	leave
1005	ret
1006
1007.globl VG_(x86_darwin_REDIR_FOR_strlcat)
1008VG_(x86_darwin_REDIR_FOR_strlcat):
1009	pushl	%ebp
1010	movl	%esp, %ebp
1011	pushl	%edi
1012	pushl	%esi
1013	subl	$16, %esp
1014	movl	8(%ebp), %esi
1015	movl	16(%ebp), %ecx
1016	movl	%esi, %edx
1017	leal	(%ecx,%esi), %eax
1018	jmp	1f
10190:
1020	incl	%edx
10211:
1022	cmpl	%edx, %eax
1023	je	2f
1024	cmpb	$0, (%edx)
1025	jne	0b
10262:
1027	movl	%edx, %edi
1028	subl	%esi, %edi
1029	movl	%ecx, %esi
1030	subl	%edi, %esi
1031	je	3f
1032	movl	12(%ebp), %eax
1033	jmp	6f
10343:
1035	movl	12(%ebp), %eax
1036	movl	%eax, (%esp)
1037	call	VG_(x86_darwin_REDIR_FOR_strlen)
1038	jmp	7f
10394:
1040	cmpl	$1, %esi
1041	je	5f
1042	movb	%cl, (%edx)
1043	decl	%esi
1044	incl	%edx
10455:
1046	incl	%eax
10476:
1048	movzbl	(%eax), %ecx
1049	testb	%cl, %cl
1050	jne	4b
1051	movb	$0, (%edx)
1052	subl	12(%ebp), %eax
10537:
1054	addl	$16, %esp
1055	leal	(%edi,%eax), %eax
1056	popl	%esi
1057	popl	%edi
1058	leave
1059	ret
1060
1061
1062.globl VG_(trampoline_stuff_end)
1063VG_(trampoline_stuff_end):
1064
1065        /* a trailing page of unexecutable code */
1066.fill 2048, 2, 0x0b0f /* `ud2` */
1067
1068
1069/*---------------- amd64-darwin ----------------*/
1070#else
1071#if defined(VGP_amd64_darwin)
1072
1073        /* a leading page of unexecutable code */
1074.fill 2048, 2, 0x0b0f /* `ud2` */
1075
1076.globl VG_(trampoline_stuff_start)
1077VG_(trampoline_stuff_start):
1078
1079.globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1080VG_(amd64_darwin_SUBST_FOR_sigreturn):
1081        /* XXX does this need to have any special form? (cf x86-linux
1082	version) */
1083        movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1084        syscall
1085        ud2
1086
1087.globl VG_(amd64_darwin_REDIR_FOR_strlen)
1088VG_(amd64_darwin_REDIR_FOR_strlen):
1089        movq    %rdi, %rax
1090        jmp     1f
10910:
1092        incq    %rax
10931:
1094        cmpb    $0, (%rax)
1095        jne     0b
1096        subq    %rdi, %rax
1097        ret
1098
1099.globl VG_(amd64_darwin_REDIR_FOR_strcat)
1100VG_(amd64_darwin_REDIR_FOR_strcat):
1101	movq	%rdi, %rdx
1102	jmp	1f
11030:
1104	incq	%rdx
11051:
1106	cmpb	$0, (%rdx)
1107	jne	0b
11082:
1109	movzbl	(%rsi), %eax
1110	incq	%rsi
1111	movb	%al, (%rdx)
1112	incq	%rdx
1113	testb	%al, %al
1114	jne	2b
1115	movq	%rdi, %rax
1116	ret
1117
1118
1119.globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1120VG_(amd64_darwin_REDIR_FOR_strcmp):
1121	jmp	1f
11220:
1123	incq	%rdi
1124	incq	%rsi
11251:
1126	movzbl	(%rdi), %eax
1127	testb	%al, %al
1128	je	2f
1129	cmpb	(%rsi), %al
1130	je	0b
11312:
1132	movzbl	(%rsi), %edx
1133	movzbl	%al, %eax
1134	subl	%edx, %eax
1135	ret
1136
1137.globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1138VG_(amd64_darwin_REDIR_FOR_strcpy):
1139	pushq	%rbp
1140	movq	%rdi, %rdx
1141	movq	%rsp, %rbp
1142	jmp	1f
11430:
1144	incq	%rsi
1145	incq	%rdx
11461:
1147	movzbl	(%rsi), %eax
1148	testb	%al, %al
1149	movb	%al, (%rdx)
1150	jne	0b
1151	leave
1152	movq	%rdi, %rax
1153	ret
1154
1155.globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1156VG_(amd64_darwin_REDIR_FOR_strlcat):
1157	pushq	%rbp
1158	leaq	(%rdx,%rdi), %rax
1159	movq	%rdi, %rcx
1160	movq	%rsp, %rbp
1161	pushq	%rbx
1162	subq	$8, %rsp
1163	jmp	1f
11640:
1165	incq	%rcx
11661:
1167	cmpq	%rcx, %rax
1168	je	2f
1169	cmpb	$0, (%rcx)
1170	jne	0b
11712:
1172	movq	%rcx, %rbx
1173	subq	%rdi, %rbx
1174	movq	%rdx, %rdi
1175	subq	%rbx, %rdi
1176	je	3f
1177	movq	%rsi, %rax
1178	jmp	6f
11793:
1180	movq	%rsi, %rdi
1181	call	VG_(amd64_darwin_REDIR_FOR_strlen)
1182	jmp	7f
11834:
1184	cmpq	$1, %rdi
1185	je	5f
1186	movb	%dl, (%rcx)
1187	decq	%rdi
1188	incq	%rcx
11895:
1190	incq	%rax
11916:
1192	movzbl	(%rax), %edx
1193	testb	%dl, %dl
1194	jne	4b
1195	movb	$0, (%rcx)
1196	subq	%rsi, %rax
11977:
1198	leaq	(%rbx,%rax), %rax
1199	addq	$8, %rsp
1200	popq	%rbx
1201	leave
1202	ret
1203
1204.globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1205VG_(amd64_darwin_REDIR_FOR_arc4random):
1206	/* not very random, hope dyld won't mind */
1207	movq	$0x76616c6772696e64, %rax
1208	ret
1209
1210.globl VG_(trampoline_stuff_end)
1211VG_(trampoline_stuff_end):
1212
1213        /* a trailing page of unexecutable code */
1214.fill 2048, 2, 0x0b0f /* `ud2` */
1215
1216
1217/*---------------- unknown ----------------*/
1218#else
1219#  error Unknown platform
1220
1221#endif
1222#endif
1223#endif
1224#endif
1225#endif
1226#endif
1227#endif
1228#endif
1229
1230#if defined(VGO_linux)
1231/* Let the linker know we don't need an executable stack */
1232#  if defined(VGP_arm_linux)
1233   .section .note.GNU-stack,"",%progbits
1234#  else
1235   .section .note.GNU-stack,"",@progbits
1236#  endif
1237#endif
1238
1239/*--------------------------------------------------------------------*/
1240/*--- end                                                          ---*/
1241/*--------------------------------------------------------------------*/
1242