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