Home | History | Annotate | Download | only in coregrind
      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 (at) acm.org
     12   Copyright (C) 2006-2017 OpenWorks LLP
     13      info (at) 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)
     55 VG_(trampoline_stuff_start):
     56 
     57 .global VG_(x86_linux_SUBST_FOR_sigreturn)
     58 VG_(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)
     69 VG_(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
     92 VG_(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
    121 VG_(x86_linux_REDIR_FOR_strlen):
    122         pushl   %ebp
    123         movl    %esp, %ebp
    124         movl    8(%ebp), %edx
    125         movl    %edx, %eax
    126         jmp     2f
    127 1:      incl    %eax
    128 2:      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)
    137 VG_(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)
    162 VG_(trampoline_stuff_start):
    163 
    164 .global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
    165 VG_(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
    174 VG_(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
    184 VG_(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
    194 VG_(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
    208 VG_(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
    225 VG_(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)
    307 VG_(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)
    332 VG_(trampoline_stuff_start):
    333 
    334 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
    335 VG_(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)
    341 VG_(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
    352 VG_(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
    370 VG_(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
    408 VG_(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)
    430 VG_(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)
    455 VG_(trampoline_stuff_start):
    456 
    457 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
    458 VG_(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)
    465 VG_(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
    474 VG_(ppc64_linux_REDIR_FOR_strlen):
    475 #else
    476         /* Big Endian uses ELF version 1 */
    477 	.section        ".opd","aw"
    478 	.align 3
    479 VG_(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
    489 0:      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
    521 VG_(ppc64_linux_REDIR_FOR_strchr):
    522 #else
    523 	.section        ".opd","aw"
    524 	.align 3
    525 VG_(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
    535 0:      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)
    568 VG_(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)
    594 VG_(trampoline_stuff_start):
    595 
    596 .global VG_(arm_linux_SUBST_FOR_sigreturn)
    597 .type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
    598 VG_(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
    606 VG_(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)
    613 VG_(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)
    650 VG_(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)
    728 VG_(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)
    744 VG_(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)
    771 VG_(trampoline_stuff_start):
    772 
    773 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
    774 .type   VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
    775 VG_(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
    784 VG_(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
    801 VG_(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
    820 VG_(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)
    844 VG_(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)
    864 VG_(trampoline_stuff_start):
    865 
    866 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
    867 VG_(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)
    875 VG_(x86_darwin_REDIR_FOR_strlen):
    876         movl    4(%esp), %edx
    877         movl    %edx, %eax
    878         jmp     1f
    879 0:
    880         incl    %eax
    881 1:
    882         cmpb    $0, (%eax)
    883         jne     0b
    884         subl    %edx, %eax
    885         ret
    886 
    887 .globl VG_(x86_darwin_REDIR_FOR_strcat)
    888 VG_(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
    894 0:
    895         incl    %edx
    896 1:
    897         cmpb    $0, (%edx)
    898         jne     0b
    899 2:
    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)
    912 VG_(x86_darwin_REDIR_FOR_strcmp):
    913         movl    4(%esp), %edx
    914         movl    8(%esp), %ecx
    915         jmp     1f
    916 0:
    917         incl    %edx
    918         incl    %ecx
    919 1:
    920         movzbl  (%edx), %eax
    921         testb   %al, %al
    922         je      2f
    923         cmpb    (%ecx), %al
    924         je      0b
    925 2:
    926         movzbl  (%ecx),%edx
    927         movzbl  %al,%eax
    928         subl    %edx, %eax
    929         ret
    930 
    931 
    932 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
    933 VG_(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
    941 0:
    942 	incl	%ecx
    943 	incl	%edx
    944 1:
    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)
    955 VG_(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
    966 0:
    967 	incl	%edx
    968 1:
    969 	cmpl	%edx, %eax
    970 	je	2f
    971 	cmpb	$0, (%edx)
    972 	jne	0b
    973 2:
    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
    981 3:
    982 	movl	12(%ebp), %eax
    983 	movl	%eax, (%esp)
    984 	call	VG_(x86_darwin_REDIR_FOR_strlen)
    985 	jmp	7f
    986 4:
    987 	cmpl	$1, %esi
    988 	je	5f
    989 	movb	%cl, (%edx)
    990 	decl	%esi
    991 	incl	%edx
    992 5:
    993 	incl	%eax
    994 6:
    995 	movzbl	(%eax), %ecx
    996 	testb	%cl, %cl
    997 	jne	4b
    998 	movb	$0, (%edx)
    999 	subl	12(%ebp), %eax
   1000 7:
   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)
   1010 VG_(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)
   1024 VG_(trampoline_stuff_start):
   1025 
   1026 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
   1027 VG_(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)
   1035 VG_(amd64_darwin_REDIR_FOR_strlen):
   1036         movq    %rdi, %rax
   1037         jmp     1f
   1038 0:
   1039         incq    %rax
   1040 1:
   1041         cmpb    $0, (%rax)
   1042         jne     0b
   1043         subq    %rdi, %rax
   1044         ret
   1045 
   1046 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
   1047 VG_(amd64_darwin_REDIR_FOR_strcat):
   1048 	movq	%rdi, %rdx
   1049 	jmp	1f
   1050 0:
   1051 	incq	%rdx
   1052 1:
   1053 	cmpb	$0, (%rdx)
   1054 	jne	0b
   1055 2:
   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)
   1067 VG_(amd64_darwin_REDIR_FOR_strcmp):
   1068 	jmp	1f
   1069 0:
   1070 	incq	%rdi
   1071 	incq	%rsi
   1072 1:
   1073 	movzbl	(%rdi), %eax
   1074 	testb	%al, %al
   1075 	je	2f
   1076 	cmpb	(%rsi), %al
   1077 	je	0b
   1078 2:
   1079 	movzbl	(%rsi), %edx
   1080 	movzbl	%al, %eax
   1081 	subl	%edx, %eax
   1082 	ret
   1083 
   1084 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
   1085 VG_(amd64_darwin_REDIR_FOR_strcpy):
   1086 	pushq	%rbp
   1087 	movq	%rdi, %rdx
   1088 	movq	%rsp, %rbp
   1089 	jmp	1f
   1090 0:
   1091 	incq	%rsi
   1092 	incq	%rdx
   1093 1:
   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)
   1103 VG_(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
   1111 0:
   1112 	incq	%rcx
   1113 1:
   1114 	cmpq	%rcx, %rax
   1115 	je	2f
   1116 	cmpb	$0, (%rcx)
   1117 	jne	0b
   1118 2:
   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
   1126 3:
   1127 	movq	%rsi, %rdi
   1128 	call	VG_(amd64_darwin_REDIR_FOR_strlen)
   1129 	jmp	7f
   1130 4:
   1131 	cmpq	$1, %rdi
   1132 	je	5f
   1133 	movb	%dl, (%rcx)
   1134 	decq	%rdi
   1135 	incq	%rcx
   1136 5:
   1137 	incq	%rax
   1138 6:
   1139 	movzbl	(%rax), %edx
   1140 	testb	%dl, %dl
   1141 	jne	4b
   1142 	movb	$0, (%rcx)
   1143 	subq	%rsi, %rax
   1144 7:
   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)
   1152 VG_(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)
   1158 VG_(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
   1167 1:
   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
   1176 2:
   1177         popq    %rbp
   1178         ret
   1179 
   1180 .globl VG_(trampoline_stuff_end)
   1181 VG_(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)
   1195 VG_(trampoline_stuff_start):
   1196 
   1197 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
   1198 VG_(s390x_linux_SUBST_FOR_sigreturn):
   1199         svc __NR_sigreturn
   1200 	.short 0
   1201 
   1202 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
   1203 VG_(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
   1218 VG_(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)
   1239 VG_(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)
   1254 VG_(trampoline_stuff_start):
   1255 
   1256 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
   1257 VG_(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)
   1264 VG_(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
   1280 VG_(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
   1296 VG_(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)
   1310 VG_(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)
   1330 VG_(trampoline_stuff_start):
   1331 
   1332 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
   1333 VG_(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
   1349 VG_(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
   1365 VG_(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)
   1379 VG_(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)
   1393 VG_(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
   1398 VG_(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 */
   1404 1:
   1405         incl    %edx                    /* skip to the next s1 character */
   1406         incl    %ecx                    /* skip to the next s2 character */
   1407 2:
   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 */
   1413 3:
   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
   1423 VG_(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 */
   1429 1:
   1430         incl    %eax                    /* skip to the next s character */
   1431 2:
   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)
   1440 VG_(trampoline_stuff_end):
   1441 
   1442 /*---------------- amd64-solaris ----------------*/
   1443 #else
   1444 #if defined(VGP_amd64_solaris)
   1445 
   1446 .global VG_(trampoline_stuff_start)
   1447 VG_(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
   1452 VG_(amd64_solaris_REDIR_FOR_strcpy):
   1453         pushq   %rbp                    /* establish a stack frame */
   1454         movq    %rsp, %rbp
   1455         movq    %rdi, %rdx              /* copy s1 */
   1456 1:
   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
   1471 VG_(amd64_solaris_REDIR_FOR_strncpy):
   1472         pushq   %rbp                    /* establish a stack frame */
   1473         movq    %rsp, %rbp
   1474         movq    %rdi, %rcx              /* copy s1 */
   1475 1:
   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 */
   1485 2:
   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 */
   1492 3:
   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
   1501 VG_(amd64_solaris_REDIR_FOR_strcmp):
   1502         pushq   %rbp                    /* establish a stack frame */
   1503         movq    %rsp, %rbp
   1504         jmp     2f                      /* go compare the first characters */
   1505 1:
   1506         incq    %rdi                    /* skip to the next s1 character */
   1507         incq    %rsi                    /* skip to the next s2 character */
   1508 2:
   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 */
   1514 3:
   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
   1524 VG_(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 */
   1529 1:
   1530         incq    %rdx                    /* skip to the next s1 character */
   1531 2:
   1532         cmpb    $0, (%rdx)              /* is the s1 character null? */
   1533         jne     1b                      /* no, go check the next character */
   1534 3:
   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
   1549 VG_(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 */
   1554 1:
   1555         incq    %rax                    /* skip to the next s character */
   1556 2:
   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)
   1565 VG_(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 */
   1586 MARK_STACK_NO_EXEC
   1587 
   1588 /*--------------------------------------------------------------------*/
   1589 /*--- end                                                          ---*/
   1590 /*--------------------------------------------------------------------*/
   1591