• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2017 Julian Seward
11     jseward@acm.org
12  Copyright (C) 2006-2017 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.global VG_(amd64_linux_REDIR_FOR_index)
224.type   VG_(amd64_linux_REDIR_FOR_index), @function
225VG_(amd64_linux_REDIR_FOR_index):
226        movzbl  (%rdi), %eax
227        movl    %esi, %edx
228        cmpb    %sil, %al
229        jne     .L4
230        jmp     .L5
231.L10:
232        addq    $1, %rdi
233        movzbl  (%rdi), %eax
234        cmpb    %dl, %al
235        je      .L5
236.L4:
237        testb   %al, %al
238        jne     .L10
239        xorl    %eax, %eax
240        ret
241.L5:
242        movq    %rdi, %rax
243        ret
244.size VG_(amd64_linux_REDIR_FOR_index), .-VG_(amd64_linux_REDIR_FOR_index)
245
246
247
248/* A CIE for the above four functions, followed by their FDEs */
249	.section .eh_frame,"a",@progbits
250.Lframe1:
251        .long   .LEcie1-.LScie1
252.LScie1:
253        .long   0x0
254        .byte   0x1
255        .string "zR"
256        .uleb128 0x1
257        .sleb128 -8
258        .byte   0x10
259        .uleb128 0x1
260        .byte   0x3
261        .byte   0xc
262        .uleb128 0x7
263        .uleb128 0x8
264        .byte   0x90
265        .uleb128 0x1
266        .align 8
267.LEcie1:
268.LSfde2:
269        .long   .LEfde2-.LASfde2
270.LASfde2:
271        .long   .LASfde2-.Lframe1
272        .long   .LfnB2
273        .long   .LfnE2-.LfnB2
274        .uleb128 0x0
275        .align 8
276.LEfde2:
277.LSfde3:
278        .long   .LEfde3-.LASfde3
279.LASfde3:
280        .long   .LASfde3-.Lframe1
281        .long   .LfnB3
282        .long   .LfnE3-.LfnB3
283        .uleb128 0x0
284        .align 8
285.LEfde3:
286.LSfde4:
287        .long   .LEfde4-.LASfde4
288.LASfde4:
289        .long   .LASfde4-.Lframe1
290        .long   .LfnB4
291        .long   .LfnE4-.LfnB4
292        .uleb128 0x0
293        .align 8
294.LEfde4:
295.LSfde5:
296        .long   .LEfde5-.LASfde5
297.LASfde5:
298        .long   .LASfde5-.Lframe1
299        .long   .LfnB5
300        .long   .LfnE5-.LfnB5
301        .uleb128 0x0
302        .align 8
303.LEfde5:
304	.previous
305
306.global VG_(trampoline_stuff_end)
307VG_(trampoline_stuff_end):
308
309	/* and a trailing page of unexecutable code */
310	UD2_PAGE
311
312#	undef UD2_16
313#	undef UD2_64
314#	undef UD2_256
315#	undef UD2_1024
316#	undef UD2_PAGE
317
318/*---------------- ppc32-linux ----------------*/
319#else
320#if defined(VGP_ppc32_linux)
321
322#	define UD2_16     trap ; trap ; trap; trap
323#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
324#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
325#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
326#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
327
328	/* a leading page of unexecutable code */
329	UD2_PAGE
330
331.global VG_(trampoline_stuff_start)
332VG_(trampoline_stuff_start):
333
334.global VG_(ppc32_linux_SUBST_FOR_sigreturn)
335VG_(ppc32_linux_SUBST_FOR_sigreturn):
336	li 0,__NR_sigreturn
337        sc
338        .long 0	/*illegal insn*/
339
340.global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
341VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
342	li 0,__NR_rt_sigreturn
343        sc
344        .long 0	/*illegal insn*/
345
346/* There's no particular reason that this needs to be handwritten
347   assembly, but since that's what this file contains, here's a
348   simple strlen implementation (written in C and compiled by gcc.)
349*/
350.global VG_(ppc32_linux_REDIR_FOR_strlen)
351.type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
352VG_(ppc32_linux_REDIR_FOR_strlen):
353        lbz 4,0(3)
354        li 9,0
355        cmpwi 0,4,0
356        beq- 0,.L18
357.L19:
358        lbzu 5,1(3)
359        addi 9,9,1
360        cmpwi 0,5,0
361        bne+ 0,.L19
362.L18:
363        mr 3,9
364        blr
365.size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
366
367/* Ditto strcmp */
368.global VG_(ppc32_linux_REDIR_FOR_strcmp)
369.type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
370VG_(ppc32_linux_REDIR_FOR_strcmp):
371.L20:
372        lbz 0,0(3)
373        cmpwi 7,0,0
374        bne- 7,.L21
375        lbz 0,0(4)
376        li 11,0
377        cmpwi 7,0,0
378        beq- 7,.L22
379.L21:
380        lbz 0,0(3)
381        li 11,-1
382        cmpwi 7,0,0
383        beq- 7,.L22
384        lbz 0,0(4)
385        li 11,1
386        cmpwi 7,0,0
387        beq- 7,.L22
388        lbz 9,0(3)
389        lbz 0,0(4)
390        li 11,-1
391        cmplw 7,9,0
392        blt- 7,.L22
393        lbz 9,0(3)
394        lbz 0,0(4)
395        li 11,1
396        addi 3,3,1
397        addi 4,4,1
398        cmplw 7,9,0
399        ble+ 7,.L20
400.L22:
401        mr 3,11
402        blr
403.size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
404
405/* Ditto index/strchr */
406.global VG_(ppc32_linux_REDIR_FOR_strchr)
407.type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
408VG_(ppc32_linux_REDIR_FOR_strchr):
409        lbz 0,0(3)
410        rlwinm 4,4,0,0xff
411        cmpw 7,4,0
412        beqlr 7
413        cmpwi 7,0,0
414        bne 7,.L308
415        b .L304
416.L309:
417        beq 6,.L304
418.L308:
419        lbzu 0,1(3)
420        cmpw 7,4,0
421        cmpwi 6,0,0
422        bne 7,.L309
423        blr
424.L304:
425        li 3,0
426        blr
427.size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
428
429.global VG_(trampoline_stuff_end)
430VG_(trampoline_stuff_end):
431
432	/* and a trailing page of unexecutable code */
433	UD2_PAGE
434
435#	undef UD2_16
436#	undef UD2_64
437#	undef UD2_256
438#	undef UD2_1024
439#	undef UD2_PAGE
440
441/*---------------- ppc64-linux ----------------*/
442#else
443#if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
444
445#	define UD2_16     trap ; trap ; trap; trap
446#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
447#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
448#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
449#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
450
451	/* a leading page of unexecutable code */
452	UD2_PAGE
453
454.global VG_(trampoline_stuff_start)
455VG_(trampoline_stuff_start):
456
457.global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
458VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
459	li 0,__NR_rt_sigreturn
460        sc
461        .long 0	/*illegal insn*/
462
463	/* See comment in pub_core_trampoline.h for what this is for */
464.global VG_(ppctoc_magic_redirect_return_stub)
465VG_(ppctoc_magic_redirect_return_stub):
466	trap
467
468	/* this function is written using the "dotless" ABI convention */
469	.align 2
470	.globl VG_(ppc64_linux_REDIR_FOR_strlen)
471#if !defined VGP_ppc64be_linux || _CALL_ELF == 2
472        /* Little Endian uses ELF version 2 */
473        .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
474VG_(ppc64_linux_REDIR_FOR_strlen):
475#else
476        /* Big Endian uses ELF version 1 */
477	.section        ".opd","aw"
478	.align 3
479VG_(ppc64_linux_REDIR_FOR_strlen):
480	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
481	.previous
482	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
483			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
484	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
485
486.L.VG_(ppc64_linux_REDIR_FOR_strlen):
487#endif
488#if _CALL_ELF == 2
4890:      addis        2,12,.TOC.-0b@ha
490        addi         2,2,.TOC.-0b@l
491        .localentry  VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
492#endif
493        mr 9,3
494        lbz 0,0(3)
495        li 3,0
496        cmpwi 7,0,0
497        beqlr 7
498        li 3,0
499.L01:
500        addi 0,3,1
501        extsw 3,0
502        lbzx 0,9,3
503        cmpwi 7,0,0
504        bne 7,.L01
505        blr
506
507#if !defined VGP_ppc64be_linux || _CALL_ELF == 2
508        .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
509#else
510        .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
511#endif
512        .long 0
513        .byte 0,0,0,0,0,0,0,0
514.L0end:
515
516        /* this function is written using the "dotless" ABI convention */
517        .align 2
518        .globl VG_(ppc64_linux_REDIR_FOR_strchr)
519#if !defined VGP_ppc64be_linux || _CALL_ELF == 2
520        .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
521VG_(ppc64_linux_REDIR_FOR_strchr):
522#else
523	.section        ".opd","aw"
524	.align 3
525VG_(ppc64_linux_REDIR_FOR_strchr):
526        .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
527        .previous
528        .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
529                        .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
530        .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
531
532.L.VG_(ppc64_linux_REDIR_FOR_strchr):
533#endif
534#if  _CALL_ELF == 2
5350:      addis         2,12,.TOC.-0b@ha
536        addi         2,2,.TOC.-0b@l
537        .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
538#endif
539        lbz 0,0(3)
540        rldicl 4,4,0,56
541        cmpw 7,4,0
542        beqlr 7
543        cmpdi 7,0,0
544        bne 7,.L18
545        b .L14
546#if !defined VGP_ppc64be_linux || _CALL_ELF == 2
547        .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
548#else
549        .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
550#endif
551.L19:
552        beq 6,.L14
553.L18:
554        lbzu 0,1(3)
555        cmpw 7,4,0
556        cmpdi 6,0,0
557        bne 7,.L19
558        blr
559.L14:
560        li 3,0
561        blr
562        .long 0
563        .byte 0,0,0,0,0,0,0,0
564.L1end:
565
566
567.global VG_(trampoline_stuff_end)
568VG_(trampoline_stuff_end):
569
570	/* and a trailing page of unexecutable code */
571	UD2_PAGE
572
573#	undef UD2_16
574#	undef UD2_64
575#	undef UD2_256
576#	undef UD2_1024
577#	undef UD2_PAGE
578
579/*---------------- arm-linux ----------------*/
580#else
581#if defined(VGP_arm_linux)
582
583#       define UD2_4      .word 0xFFFFFFFF
584#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
585#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
586#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
587#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
588#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
589
590	/* a leading page of unexecutable code */
591	UD2_PAGE
592
593.global VG_(trampoline_stuff_start)
594VG_(trampoline_stuff_start):
595
596.global VG_(arm_linux_SUBST_FOR_sigreturn)
597.type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
598VG_(arm_linux_SUBST_FOR_sigreturn):
599	mov r7, # __NR_sigreturn
600        svc #0
601        .long 0xFFFFFFFF /*illegal insn*/
602.size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
603
604.global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
605.type   VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
606VG_(arm_linux_SUBST_FOR_rt_sigreturn):
607	mov r7, # __NR_rt_sigreturn
608        svc #0
609        .long 0xFFFFFFFF /*illegal insn*/
610.size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
611
612.global VG_(arm_linux_REDIR_FOR_strlen)
613VG_(arm_linux_REDIR_FOR_strlen):
614	mov	r2, r0
615	ldrb	r0, [r0, #0]	@ zero_extendqisi2
616	@ lr needed for prologue
617	cmp	r0, #0
618	bxeq	lr
619	mov	r0, #0
620.L5:
621	add	r0, r0, #1
622	ldrb	r3, [r0, r2]	@ zero_extendqisi2
623	cmp	r3, #0
624	bne	.L5
625	bx	lr
626	UD2_4
627
628//.global VG_(arm_linux_REDIR_FOR_index)
629//VG_(arm_linux_REDIR_FOR_index):
630//	ldrb	r3, [r0, #0]	@ zero_extendqisi2
631//	and	r1, r1, #255
632//	cmp	r3, r1
633//	@ lr needed for prologue
634//	bne	.L9
635//	bx	lr
636//.L12:
637//	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
638//	cmp	r3, r1
639//	beq	.L11
640//.L9:
641//	cmp	r3, #0
642//	bne	.L12
643//	mov	r0, #0
644//	bx	lr
645//.L11:
646//	bx	lr
647//	UD2_4
648
649.global VG_(arm_linux_REDIR_FOR_memcpy)
650VG_(arm_linux_REDIR_FOR_memcpy):
651	stmfd	sp!, {r4, r5, lr}
652	subs	lr, r2, #0
653	mov	r5, r0
654	beq	.L2
655	cmp	r0, r1
656	bls	.L4
657	add	r3, r0, lr
658	add	r1, lr, r1
659	cmp	lr, #3
660	sub	r4, r3, #1
661	sub	r0, r1, #1
662	ble	.L28
663	sub	ip, r3, #5
664	sub	r1, r1, #5
665.L8:
666	ldrb	r3, [r1, #4]	@ zero_extendqisi2
667	sub	lr, lr, #4
668	strb	r3, [ip, #4]
669	ldrb	r2, [r1, #3]	@ zero_extendqisi2
670	cmp	lr, #3
671	strb	r2, [ip, #3]
672	ldrb	r3, [r1, #2]	@ zero_extendqisi2
673	mov	r4, ip
674	strb	r3, [ip, #2]
675	ldrb	r2, [r1, #1]	@ zero_extendqisi2
676	mov	r0, r1
677	strb	r2, [ip, #1]
678	sub	r1, r1, #4
679	sub	ip, ip, #4
680	bgt	.L8
681	cmp	lr, #0
682	beq	.L2
683.L28:
684	sub	r2, lr, #1
685.L21:
686	sub	r2, r2, #1
687	ldrb	r3, [r0], #-1	@ zero_extendqisi2
688	cmn	r2, #1
689	strb	r3, [r4], #-1
690	bne	.L21
691.L2:
692	mov	r0, r5
693	ldmfd	sp!, {r4, r5, pc}
694.L4:
695	bcs	.L2
696	cmp	lr, #3
697	mov	ip, r0
698	ble	.L29
699.L19:
700	ldrb	r3, [r1, #0]	@ zero_extendqisi2
701	sub	lr, lr, #4
702	strb	r3, [ip, #0]
703	ldrb	r2, [r1, #1]	@ zero_extendqisi2
704	cmp	lr, #3
705	strb	r2, [ip, #1]
706	ldrb	r3, [r1, #2]	@ zero_extendqisi2
707	strb	r3, [ip, #2]
708	ldrb	r2, [r1, #3]	@ zero_extendqisi2
709	add	r1, r1, #4
710	strb	r2, [ip, #3]
711	add	ip, ip, #4
712	bgt	.L19
713	cmp	lr, #0
714	beq	.L2
715.L29:
716	sub	r2, lr, #1
717.L20:
718	sub	r2, r2, #1
719	ldrb	r3, [r1], #1	@ zero_extendqisi2
720	cmn	r2, #1
721	strb	r3, [ip], #1
722	bne	.L20
723	mov	r0, r5
724	ldmfd	sp!, {r4, r5, pc}
725	UD2_4
726
727.global VG_(arm_linux_REDIR_FOR_strcmp)
728VG_(arm_linux_REDIR_FOR_strcmp):
729.L64:
730	ldrb	r3, [r0], #1	@ zero_extendqisi2
731	ldrb	r2, [r1], #1	@ zero_extendqisi2
732	cmp	r3, #0
733	beq	.L67
734	cmp	r3, r2
735	beq	.L64
736	rsb	r0, r2, r3
737	bx	lr
738.L67:
739	rsb	r0, r2, #0
740	bx	lr
741	UD2_4
742
743.global VG_(trampoline_stuff_end)
744VG_(trampoline_stuff_end):
745
746	/* and a trailing page of unexecutable code */
747	UD2_PAGE
748
749#	undef UD2_4
750#	undef UD2_16
751#	undef UD2_64
752#	undef UD2_256
753#	undef UD2_1024
754#	undef UD2_PAGE
755
756/*---------------- arm64-linux ----------------*/
757#else
758#if defined(VGP_arm64_linux)
759
760#       define UD2_4      .word 0xFFFFFFFF
761#	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
762#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
763#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
764#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
765#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
766
767	/* a leading page of unexecutable code */
768	UD2_PAGE
769
770.global VG_(trampoline_stuff_start)
771VG_(trampoline_stuff_start):
772
773.global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
774.type   VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
775VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
776	mov x8, # __NR_rt_sigreturn
777        svc #0
778        .long 0xFFFFFFFF /*illegal insn*/
779.size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
780        .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
781
782.global VG_(arm64_linux_REDIR_FOR_strlen)
783.type   VG_(arm64_linux_REDIR_FOR_strlen),#function
784VG_(arm64_linux_REDIR_FOR_strlen):
785	mov	x2, x0
786	ldrb	w0, [x0]
787	cbz	w0, .L5
788	mov	x0, 0
789.L4:
790	add	x0, x0, 1
791	ldrb	w1, [x2,x0]
792	cbnz	w1, .L4
793	ret
794.L5:
795	mov	x0, 0
796	ret
797.size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
798
799.global VG_(arm64_linux_REDIR_FOR_index)
800.type   VG_(arm64_linux_REDIR_FOR_index),#function
801VG_(arm64_linux_REDIR_FOR_index):
802        ldrb    w2, [x0]
803        uxtb    w1, w1
804        cmp     w2, w1
805        beq     .L11
806.L13:
807        cbz     w2, .L16
808        ldrb    w2, [x0,1]!
809        cmp     w2, w1
810        bne     .L13
811.L11:
812        ret
813.L16:
814        mov     x0, 0
815        ret
816.size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
817
818.global VG_(arm64_linux_REDIR_FOR_strcmp)
819.type   VG_(arm64_linux_REDIR_FOR_strcmp),#function
820VG_(arm64_linux_REDIR_FOR_strcmp):
821        ldrb    w2, [x0]
822        ldrb    w3, [x1]
823        cmp     w2, w3
824        bcc     .L22
825.L21:
826        bhi     .L25
827        cbz     w2, .L26
828        ldrb    w2, [x0,1]!
829        ldrb    w3, [x1,1]!
830        cmp     w2, w3
831        bcs     .L21
832.L22:
833        mov     x0, -1
834        ret
835.L25:
836        mov     x0, 1
837        ret
838.L26:
839        mov     x0, 0
840        ret
841.size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
842
843.global VG_(trampoline_stuff_end)
844VG_(trampoline_stuff_end):
845
846	/* and a trailing page of unexecutable code */
847	UD2_PAGE
848
849#	undef UD2_4
850#	undef UD2_16
851#	undef UD2_64
852#	undef UD2_256
853#	undef UD2_1024
854#	undef UD2_PAGE
855
856/*---------------- x86-darwin ----------------*/
857#else
858#if defined(VGP_x86_darwin)
859
860        /* a leading page of unexecutable code */
861.fill 2048, 2, 0x0b0f /* `ud2` */
862
863.globl VG_(trampoline_stuff_start)
864VG_(trampoline_stuff_start):
865
866.globl VG_(x86_darwin_SUBST_FOR_sigreturn)
867VG_(x86_darwin_SUBST_FOR_sigreturn):
868        /* XXX does this need to have any special form? (cf x86-linux
869	version) */
870        movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
871        int     $0x80
872        ud2
873
874.globl VG_(x86_darwin_REDIR_FOR_strlen)
875VG_(x86_darwin_REDIR_FOR_strlen):
876        movl    4(%esp), %edx
877        movl    %edx, %eax
878        jmp     1f
8790:
880        incl    %eax
8811:
882        cmpb    $0, (%eax)
883        jne     0b
884        subl    %edx, %eax
885        ret
886
887.globl VG_(x86_darwin_REDIR_FOR_strcat)
888VG_(x86_darwin_REDIR_FOR_strcat):
889        pushl   %esi
890        movl    8(%esp), %esi
891        movl    12(%esp), %ecx
892        movl    %esi, %edx
893        jmp     1f
8940:
895        incl    %edx
8961:
897        cmpb    $0, (%edx)
898        jne     0b
8992:
900        movzbl  (%ecx), %eax
901        incl    %ecx
902        movb    %al, (%edx)
903        incl    %edx
904        testb   %al, %al
905        jne     2b
906        movl    %esi, %eax
907        popl    %esi
908        ret
909
910
911.globl VG_(x86_darwin_REDIR_FOR_strcmp)
912VG_(x86_darwin_REDIR_FOR_strcmp):
913        movl    4(%esp), %edx
914        movl    8(%esp), %ecx
915        jmp     1f
9160:
917        incl    %edx
918        incl    %ecx
9191:
920        movzbl  (%edx), %eax
921        testb   %al, %al
922        je      2f
923        cmpb    (%ecx), %al
924        je      0b
9252:
926        movzbl  (%ecx),%edx
927        movzbl  %al,%eax
928        subl    %edx, %eax
929        ret
930
931
932.globl VG_(x86_darwin_REDIR_FOR_strcpy)
933VG_(x86_darwin_REDIR_FOR_strcpy):
934	pushl	%ebp
935	movl	%esp, %ebp
936	pushl	%esi
937	movl	8(%ebp), %esi
938	movl	12(%ebp), %ecx
939	movl	%esi, %edx
940	jmp	1f
9410:
942	incl	%ecx
943	incl	%edx
9441:
945	movzbl	(%ecx), %eax
946	testb	%al, %al
947	movb	%al, (%edx)
948	jne	0b
949	movl	%esi, %eax
950	popl	%esi
951	leave
952	ret
953
954.globl VG_(x86_darwin_REDIR_FOR_strlcat)
955VG_(x86_darwin_REDIR_FOR_strlcat):
956	pushl	%ebp
957	movl	%esp, %ebp
958	pushl	%edi
959	pushl	%esi
960	subl	$16, %esp
961	movl	8(%ebp), %esi
962	movl	16(%ebp), %ecx
963	movl	%esi, %edx
964	leal	(%ecx,%esi), %eax
965	jmp	1f
9660:
967	incl	%edx
9681:
969	cmpl	%edx, %eax
970	je	2f
971	cmpb	$0, (%edx)
972	jne	0b
9732:
974	movl	%edx, %edi
975	subl	%esi, %edi
976	movl	%ecx, %esi
977	subl	%edi, %esi
978	je	3f
979	movl	12(%ebp), %eax
980	jmp	6f
9813:
982	movl	12(%ebp), %eax
983	movl	%eax, (%esp)
984	call	VG_(x86_darwin_REDIR_FOR_strlen)
985	jmp	7f
9864:
987	cmpl	$1, %esi
988	je	5f
989	movb	%cl, (%edx)
990	decl	%esi
991	incl	%edx
9925:
993	incl	%eax
9946:
995	movzbl	(%eax), %ecx
996	testb	%cl, %cl
997	jne	4b
998	movb	$0, (%edx)
999	subl	12(%ebp), %eax
10007:
1001	addl	$16, %esp
1002	leal	(%edi,%eax), %eax
1003	popl	%esi
1004	popl	%edi
1005	leave
1006	ret
1007
1008
1009.globl VG_(trampoline_stuff_end)
1010VG_(trampoline_stuff_end):
1011
1012        /* a trailing page of unexecutable code */
1013.fill 2048, 2, 0x0b0f /* `ud2` */
1014
1015
1016/*---------------- amd64-darwin ----------------*/
1017#else
1018#if defined(VGP_amd64_darwin)
1019
1020        /* a leading page of unexecutable code */
1021.fill 2048, 2, 0x0b0f /* `ud2` */
1022
1023.globl VG_(trampoline_stuff_start)
1024VG_(trampoline_stuff_start):
1025
1026.globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1027VG_(amd64_darwin_SUBST_FOR_sigreturn):
1028        /* XXX does this need to have any special form? (cf x86-linux
1029	version) */
1030        movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1031        syscall
1032        ud2
1033
1034.globl VG_(amd64_darwin_REDIR_FOR_strlen)
1035VG_(amd64_darwin_REDIR_FOR_strlen):
1036        movq    %rdi, %rax
1037        jmp     1f
10380:
1039        incq    %rax
10401:
1041        cmpb    $0, (%rax)
1042        jne     0b
1043        subq    %rdi, %rax
1044        ret
1045
1046.globl VG_(amd64_darwin_REDIR_FOR_strcat)
1047VG_(amd64_darwin_REDIR_FOR_strcat):
1048	movq	%rdi, %rdx
1049	jmp	1f
10500:
1051	incq	%rdx
10521:
1053	cmpb	$0, (%rdx)
1054	jne	0b
10552:
1056	movzbl	(%rsi), %eax
1057	incq	%rsi
1058	movb	%al, (%rdx)
1059	incq	%rdx
1060	testb	%al, %al
1061	jne	2b
1062	movq	%rdi, %rax
1063	ret
1064
1065
1066.globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1067VG_(amd64_darwin_REDIR_FOR_strcmp):
1068	jmp	1f
10690:
1070	incq	%rdi
1071	incq	%rsi
10721:
1073	movzbl	(%rdi), %eax
1074	testb	%al, %al
1075	je	2f
1076	cmpb	(%rsi), %al
1077	je	0b
10782:
1079	movzbl	(%rsi), %edx
1080	movzbl	%al, %eax
1081	subl	%edx, %eax
1082	ret
1083
1084.globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1085VG_(amd64_darwin_REDIR_FOR_strcpy):
1086	pushq	%rbp
1087	movq	%rdi, %rdx
1088	movq	%rsp, %rbp
1089	jmp	1f
10900:
1091	incq	%rsi
1092	incq	%rdx
10931:
1094	movzbl	(%rsi), %eax
1095	testb	%al, %al
1096	movb	%al, (%rdx)
1097	jne	0b
1098	leave
1099	movq	%rdi, %rax
1100	ret
1101
1102.globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1103VG_(amd64_darwin_REDIR_FOR_strlcat):
1104	pushq	%rbp
1105	leaq	(%rdx,%rdi), %rax
1106	movq	%rdi, %rcx
1107	movq	%rsp, %rbp
1108	pushq	%rbx
1109	subq	$8, %rsp
1110	jmp	1f
11110:
1112	incq	%rcx
11131:
1114	cmpq	%rcx, %rax
1115	je	2f
1116	cmpb	$0, (%rcx)
1117	jne	0b
11182:
1119	movq	%rcx, %rbx
1120	subq	%rdi, %rbx
1121	movq	%rdx, %rdi
1122	subq	%rbx, %rdi
1123	je	3f
1124	movq	%rsi, %rax
1125	jmp	6f
11263:
1127	movq	%rsi, %rdi
1128	call	VG_(amd64_darwin_REDIR_FOR_strlen)
1129	jmp	7f
11304:
1131	cmpq	$1, %rdi
1132	je	5f
1133	movb	%dl, (%rcx)
1134	decq	%rdi
1135	incq	%rcx
11365:
1137	incq	%rax
11386:
1139	movzbl	(%rax), %edx
1140	testb	%dl, %dl
1141	jne	4b
1142	movb	$0, (%rcx)
1143	subq	%rsi, %rax
11447:
1145	leaq	(%rbx,%rax), %rax
1146	addq	$8, %rsp
1147	popq	%rbx
1148	leave
1149	ret
1150
1151.globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1152VG_(amd64_darwin_REDIR_FOR_arc4random):
1153	/* not very random, hope dyld won't mind */
1154	movq	$0x76616c6772696e64, %rax
1155	ret
1156
1157.globl VG_(amd64_darwin_REDIR_FOR_strchr)
1158VG_(amd64_darwin_REDIR_FOR_strchr):
1159        pushq   %rbp
1160        movq    %rsp, %rbp
1161        movb    (%rdi), %cl
1162        cmpb    %sil, %cl
1163        jne     1f
1164        movq    %rdi, %rax
1165        popq    %rbp
1166        ret
11671:
1168        testb   %cl, %cl
1169        movl    $0, %eax
1170        je      2f
1171        movb    1(%rdi), %cl
1172        incq    %rdi
1173        cmpb    %sil, %cl
1174        movq    %rdi, %rax
1175        jne     1b
11762:
1177        popq    %rbp
1178        ret
1179
1180.globl VG_(trampoline_stuff_end)
1181VG_(trampoline_stuff_end):
1182
1183        /* a trailing page of unexecutable code */
1184.fill 2048, 2, 0x0b0f /* `ud2` */
1185
1186
1187/*---------------- s390x-linux ----------------*/
1188#else
1189#if defined(VGP_s390x_linux)
1190
1191        /* a leading page of unexecutable code */
1192	.fill 2048, 2, 0x0000
1193
1194.global VG_(trampoline_stuff_start)
1195VG_(trampoline_stuff_start):
1196
1197.global VG_(s390x_linux_SUBST_FOR_sigreturn)
1198VG_(s390x_linux_SUBST_FOR_sigreturn):
1199        svc __NR_sigreturn
1200	.short 0
1201
1202.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1203VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1204        /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1205           for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1206           set ra to this trampoline, but the cfa is still in the stack,
1207           the unwinder thinks, that this is a non-rt frame  and causes a
1208           crash in the gcc unwinder - which is used by the thread library
1209           and others. Therefore we add a lr 1,1 nop, to let the gcc
1210           unwinder bail out gracefully. This might also affect unwinding
1211           across the signal frame - tough luck. fixs390 */
1212        lr 1,1
1213        svc __NR_rt_sigreturn
1214	.short 0
1215
1216.global VG_(s390x_linux_REDIR_FOR_index)
1217.type   VG_(s390x_linux_REDIR_FOR_index),@function
1218VG_(s390x_linux_REDIR_FOR_index):
1219#
1220#   %r2 = address of string
1221#   %r3 = character to find
1222#
1223        lghi    %r0,255
1224        ngr     %r0,%r3        # r0 = (unsigned char)r3
1225        lghi    %r4,0
1226.L1:
1227        llgc    %r1,0(%r2)     # r1 = byte from string
1228        cr      %r1,%r0        # compare
1229        ber     %r14           # return if found
1230        cr      %r1,%r4        # end of string ?
1231        je      .L2
1232        aghi    %r2,1          # increment r2
1233        j       .L1
1234.L2:    lghi    %r2,0          # return value 0
1235        br      %r14
1236.size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1237
1238.globl VG_(trampoline_stuff_end)
1239VG_(trampoline_stuff_end):
1240	.fill 2048, 2, 0x0000
1241
1242/*---------------------- mips32-linux ----------------------*/
1243#else
1244#if defined(VGP_mips32_linux)
1245
1246#	define UD2_16     trap ; trap ; trap; trap
1247#	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1248#	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1249#	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1250#	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1251
1252
1253.global VG_(trampoline_stuff_start)
1254VG_(trampoline_stuff_start):
1255
1256.global VG_(mips32_linux_SUBST_FOR_sigreturn)
1257VG_(mips32_linux_SUBST_FOR_sigreturn):
1258        li $v0,__NR_sigreturn
1259        syscall
1260        nop
1261        .long 0	/*illegal insn*/
1262
1263.global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1264VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1265	li $v0,__NR_rt_sigreturn
1266        syscall
1267        nop
1268        .long 0	/*illegal insn*/
1269
1270/* There's no particular reason that this needs to be handwritten
1271   assembly, but since that's what this file contains, here's a
1272   simple index() and strlen() implementations.
1273*/
1274
1275.set push
1276.set noreorder
1277
1278.global VG_(mips32_linux_REDIR_FOR_index)
1279.type   VG_(mips32_linux_REDIR_FOR_index), @function
1280VG_(mips32_linux_REDIR_FOR_index):
1281      move $v0, $a0
1282   index_loop:
1283      lbu $t0, 0($v0)
1284      beq $t0, $a1, index_end
1285      nop
1286      bne $t0, $zero, index_loop
1287      addiu $v0, $v0, 1
1288      move $v0, $zero
1289   index_end:
1290      jr $ra
1291      nop
1292.size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1293
1294.global VG_(mips32_linux_REDIR_FOR_strlen)
1295.type   VG_(mips32_linux_REDIR_FOR_strlen), @function
1296VG_(mips32_linux_REDIR_FOR_strlen):
1297      move $v0, $a0
1298   strlen_loop:
1299      lbu $t0, 0($a0)
1300      bne $t0, $zero, strlen_loop
1301      addiu $a0, $a0, 1
1302      subu $v0, $a0, $v0
1303      jr $ra
1304      addiu $v0, $v0, -1
1305.size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1306
1307.set pop
1308
1309.global VG_(trampoline_stuff_end)
1310VG_(trampoline_stuff_end):
1311
1312
1313#	undef UD2_16
1314#	undef UD2_64
1315#	undef UD2_256
1316#	undef UD2_1024
1317#	undef UD2_PAGE
1318
1319/*---------------------- mips64-linux ----------------------*/
1320#else
1321#if defined(VGP_mips64_linux)
1322
1323#       define UD2_16     trap ; trap ; trap; trap
1324#       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1325#       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1326#       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1327#       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
1328
1329.global VG_(trampoline_stuff_start)
1330VG_(trampoline_stuff_start):
1331
1332.global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1333VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1334        li $2,__NR_rt_sigreturn
1335        syscall
1336        nop
1337        .long 0	/*illegal insn*/
1338
1339/* There's no particular reason that this needs to be handwritten
1340   assembly, but since that's what this file contains, here's a
1341   simple index() and strlen() implementations.
1342*/
1343
1344.set push
1345.set noreorder
1346
1347.global VG_(mips64_linux_REDIR_FOR_index)
1348.type   VG_(mips64_linux_REDIR_FOR_index), @function
1349VG_(mips64_linux_REDIR_FOR_index):
1350      move $v0, $a0
1351   index_loop:
1352      lbu $t0, 0($v0)
1353      beq $t0, $a1, index_end
1354      nop
1355      bne $t0, $zero, index_loop
1356      daddiu $v0, $v0, 1
1357      move $v0, $zero
1358   index_end:
1359      jr $ra
1360      nop
1361.size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1362
1363.global VG_(mips64_linux_REDIR_FOR_strlen)
1364.type   VG_(mips64_linux_REDIR_FOR_strlen), @function
1365VG_(mips64_linux_REDIR_FOR_strlen):
1366      move $v0, $a0
1367   strlen_loop:
1368      lbu $t0, 0($a0)
1369      bne $t0, $zero, strlen_loop
1370      daddiu $a0, $a0, 1
1371      dsubu $v0, $a0, $v0
1372      jr $ra
1373      daddiu $v0, $v0, -1
1374.size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1375
1376.set pop
1377
1378.global VG_(trampoline_stuff_end)
1379VG_(trampoline_stuff_end):
1380
1381
1382#	undef UD2_16
1383#	undef UD2_64
1384#	undef UD2_256
1385#	undef UD2_1024
1386#	undef UD2_PAGE
1387
1388/*---------------- x86-solaris ----------------*/
1389#else
1390#if defined(VGP_x86_solaris)
1391
1392.global VG_(trampoline_stuff_start)
1393VG_(trampoline_stuff_start):
1394
1395/* int strcmp(const char *s1, const char *s2); */
1396.global VG_(x86_solaris_REDIR_FOR_strcmp)
1397.type   VG_(x86_solaris_REDIR_FOR_strcmp), @function
1398VG_(x86_solaris_REDIR_FOR_strcmp):
1399        pushl   %ebp                    /* establish a stack frame */
1400        movl    %esp, %ebp
1401        movl    8(%ebp), %edx           /* get s1 */
1402        movl    12(%esp), %ecx          /* get s2 */
1403        jmp     2f                      /* go compare the first characters */
14041:
1405        incl    %edx                    /* skip to the next s1 character */
1406        incl    %ecx                    /* skip to the next s2 character */
14072:
1408        movzbl  (%edx), %eax            /* load a character from s1 */
1409        testb   %al, %al                /* is it null? */
1410        jz      3f                      /* yes, exit */
1411        cmpb    (%ecx), %al             /* are the characters equal? */
1412        je      1b                      /* yes, proceed with next characters */
14133:
1414        movzbl  (%ecx), %edx            /* load a character from s2 */
1415        subl    %edx, %eax              /* calculate the return value */
1416        popl    %ebp                    /* destroy the stack frame */
1417        ret                             /* return to the caller */
1418.size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1419
1420/* size_t strlen(const char *s); */
1421.global VG_(x86_solaris_REDIR_FOR_strlen)
1422.type   VG_(x86_solaris_REDIR_FOR_strlen), @function
1423VG_(x86_solaris_REDIR_FOR_strlen):
1424        pushl   %ebp                    /* establish a stack frame */
1425        movl    %esp, %ebp
1426        movl    8(%ebp), %edx           /* get s */
1427        movl    %edx, %eax              /* copy s */
1428        jmp     2f                      /* go handle the first character */
14291:
1430        incl    %eax                    /* skip to the next s character */
14312:
1432        cmpb    $0, (%eax)              /* is the s character null? */
1433        jne     1b                      /* no, go process the next character */
1434        subl    %edx, %eax              /* calculate the return value */
1435        popl    %ebp                    /* destroy the stack frame */
1436        ret                             /* return to the caller */
1437.size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1438
1439.global VG_(trampoline_stuff_end)
1440VG_(trampoline_stuff_end):
1441
1442/*---------------- amd64-solaris ----------------*/
1443#else
1444#if defined(VGP_amd64_solaris)
1445
1446.global VG_(trampoline_stuff_start)
1447VG_(trampoline_stuff_start):
1448
1449/* char *strcpy(char *restrict s1, const char *restrict s2); */
1450.global VG_(amd64_solaris_REDIR_FOR_strcpy)
1451.type   VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1452VG_(amd64_solaris_REDIR_FOR_strcpy):
1453        pushq   %rbp                    /* establish a stack frame */
1454        movq    %rsp, %rbp
1455        movq    %rdi, %rdx              /* copy s1 */
14561:
1457        movzbl  (%rsi), %eax            /* load one input character */
1458        movb    %al, (%rdx)             /* copy to output/s1 */
1459        incq    %rsi                    /* skip to the next output character */
1460        incq    %rdx                    /* skip to the next input character */
1461        testb   %al, %al                /* is the copied character null? */
1462        jnz     1b                      /* no, copy the next character */
1463        leave                           /* destroy the stack frame */
1464        movq    %rdi, %rax              /* set s1 as the return value */
1465        ret                             /* return to the caller */
1466.size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1467
1468/* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1469.global VG_(amd64_solaris_REDIR_FOR_strncpy)
1470.type   VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1471VG_(amd64_solaris_REDIR_FOR_strncpy):
1472        pushq   %rbp                    /* establish a stack frame */
1473        movq    %rsp, %rbp
1474        movq    %rdi, %rcx              /* copy s1 */
14751:
1476        testq   %rdx, %rdx              /* is the remaining size zero? */
1477        jz      3f                      /* yes, all done */
1478        movzbl  (%rsi), %eax            /* load one input character */
1479        movb    %al, (%rcx)             /* copy to output/s1 */
1480        decq    %rdx                    /* decrement the remaining size */
1481        incq    %rsi                    /* skip to the next output character */
1482        incq    %rcx                    /* skip to the next input character */
1483        testb   %al, %al                /* is the copied character null? */
1484        jnz     1b                      /* no, copy the next character */
14852:
1486        testq   %rdx, %rdx              /* is the remaining size zero? */
1487        jz      3f                      /* yes, all done */
1488        movb    $0, (%rdx)              /* copy null to output/s2 */
1489        decq    %rdx                    /* decrement the remaining size */
1490        incq    %rsi                    /* skip to next output character */
1491        jmp     2b                      /* proceed with the next character */
14923:
1493        leave                           /* destroy the stack frame */
1494        movq    %rdi, %rax              /* set s1 as the return value */
1495        ret                             /* return to the caller */
1496.size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1497
1498/* int strcmp(const char *s1, const char *s2); */
1499.global VG_(amd64_solaris_REDIR_FOR_strcmp)
1500.type   VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1501VG_(amd64_solaris_REDIR_FOR_strcmp):
1502        pushq   %rbp                    /* establish a stack frame */
1503        movq    %rsp, %rbp
1504        jmp     2f                      /* go compare the first characters */
15051:
1506        incq    %rdi                    /* skip to the next s1 character */
1507        incq    %rsi                    /* skip to the next s2 character */
15082:
1509        movzbl  (%rdi), %eax            /* load a character from s1 */
1510        testb   %al, %al                /* is it null? */
1511        jz      3f                      /* yes, exit */
1512        cmpb    (%rsi), %al             /* are the characters equal? */
1513        je      1b                      /* yes, proceed with next characters */
15143:
1515        movzbl  (%rsi), %edx            /* load a character from s2 */
1516        subl    %edx, %eax              /* calculate the return value */
1517        leave                           /* destroy the stack frame */
1518        ret                             /* return to the caller */
1519.size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1520
1521/* char *strcat(char *restrict s1, const char *restrict s2); */
1522.global VG_(amd64_solaris_REDIR_FOR_strcat)
1523.type   VG_(amd64_solaris_REDIR_FOR_strcat), @function
1524VG_(amd64_solaris_REDIR_FOR_strcat):
1525        pushq   %rbp                    /* establish a stack frame */
1526        movq    %rsp, %rbp
1527        movq    %rdi, %rdx              /* copy s1 */
1528        jmp     2f                      /* go handle the first character */
15291:
1530        incq    %rdx                    /* skip to the next s1 character */
15312:
1532        cmpb    $0, (%rdx)              /* is the s1 character null? */
1533        jne     1b                      /* no, go check the next character */
15343:
1535        movzbl  (%rsi), %eax            /* load a character from s2 */
1536        movb    %al, (%rdx)             /* copy the s2 character to s1 */
1537        incq    %rdx                    /* skip to the next s1 character */
1538        incq    %rsi                    /* skip to the next s2 character */
1539        testb   %al, %al                /* was the character null? */
1540        jnz     3b                      /* no, go copy the next character */
1541        movq    %rdi, %rax              /* set s1 as the return value */
1542        leave                           /* destroy the stack frame */
1543        ret                             /* return to the caller */
1544.size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1545
1546/* size_t strlen(const char *s); */
1547.global VG_(amd64_solaris_REDIR_FOR_strlen)
1548.type   VG_(amd64_solaris_REDIR_FOR_strlen), @function
1549VG_(amd64_solaris_REDIR_FOR_strlen):
1550        pushq   %rbp                    /* establish a stack frame */
1551        movq    %rsp, %rbp
1552        movq    %rdi, %rax              /* copy s */
1553        jmp     2f                      /* go handle the first character */
15541:
1555        incq    %rax                    /* skip to the next s character */
15562:
1557        cmpb    $0, (%rax)              /* is the s character null? */
1558        jne     1b                      /* no, go process the next character */
1559        subq    %rdi, %rax              /* calculate the return value */
1560        leave                           /* destroy the stack frame */
1561        ret                             /* return to the caller */
1562.size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1563
1564.global VG_(trampoline_stuff_end)
1565VG_(trampoline_stuff_end):
1566
1567/*---------------- unknown ----------------*/
1568#else
1569#  error Unknown platform
1570
1571#endif
1572#endif
1573#endif
1574#endif
1575#endif
1576#endif
1577#endif
1578#endif
1579#endif
1580#endif
1581#endif
1582#endif
1583#endif
1584
1585/* Let the linker know we don't need an executable stack */
1586MARK_STACK_NO_EXEC
1587
1588/*--------------------------------------------------------------------*/
1589/*--- end                                                          ---*/
1590/*--------------------------------------------------------------------*/
1591