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-2012 Julian Seward
     11      jseward (at) acm.org
     12   Copyright (C) 2006-2012 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_ppc64_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 	.section        ".opd","aw"
    448 	.align 3
    449 VG_(ppc64_linux_REDIR_FOR_strlen):
    450 	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
    451 	.previous
    452 	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
    453 			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
    454 	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
    455 
    456 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
    457         mr 9,3
    458         lbz 0,0(3)
    459         li 3,0
    460         cmpwi 7,0,0
    461         beqlr 7
    462         li 3,0
    463 .L01:
    464         addi 0,3,1
    465         extsw 3,0
    466         lbzx 0,9,3
    467         cmpwi 7,0,0
    468         bne 7,.L01
    469         blr
    470         .long 0
    471         .byte 0,0,0,0,0,0,0,0
    472 .L0end:
    473 
    474         /* this function is written using the "dotless" ABI convention */
    475         .align 2
    476         .globl VG_(ppc64_linux_REDIR_FOR_strchr)
    477 	.section        ".opd","aw"
    478 	.align 3
    479 VG_(ppc64_linux_REDIR_FOR_strchr):
    480         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
    481         .previous
    482         .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
    483                         .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
    484         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
    485 
    486 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
    487         lbz 0,0(3)
    488         rldicl 4,4,0,56
    489         cmpw 7,4,0
    490         beqlr 7
    491         cmpdi 7,0,0
    492         bne 7,.L18
    493         b .L14
    494 .L19:
    495         beq 6,.L14
    496 .L18:
    497         lbzu 0,1(3)
    498         cmpw 7,4,0
    499         cmpdi 6,0,0
    500         bne 7,.L19
    501         blr
    502 .L14:
    503         li 3,0
    504         blr
    505         .long 0
    506         .byte 0,0,0,0,0,0,0,0
    507 .L1end:
    508 
    509 
    510 .global VG_(trampoline_stuff_end)
    511 VG_(trampoline_stuff_end):
    512 
    513 	/* and a trailing page of unexecutable code */
    514 	UD2_PAGE
    515 
    516 #	undef UD2_16
    517 #	undef UD2_64
    518 #	undef UD2_256
    519 #	undef UD2_1024
    520 #	undef UD2_PAGE
    521 
    522 /*---------------- ppc32-linux ----------------*/
    523 
    524 #elif defined(VGP_arm_linux)
    525 
    526 #       define UD2_4      .word 0xFFFFFFFF
    527 #	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
    528 #	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
    529 #	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
    530 #	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
    531 #	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
    532 
    533 	/* a leading page of unexecutable code */
    534 	UD2_PAGE
    535 
    536 .global VG_(trampoline_stuff_start)
    537 VG_(trampoline_stuff_start):
    538 
    539 .global VG_(arm_linux_SUBST_FOR_sigreturn)
    540 .type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
    541 VG_(arm_linux_SUBST_FOR_sigreturn):
    542 	mov r7, # __NR_sigreturn
    543         svc #0
    544         .long 0xFFFFFFFF /*illegal insn*/
    545 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
    546 
    547 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
    548 .type   VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
    549 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
    550 	mov r7, # __NR_rt_sigreturn
    551         svc #0
    552         .long 0xFFFFFFFF /*illegal insn*/
    553 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
    554 
    555 .global VG_(arm_linux_REDIR_FOR_strlen)
    556 VG_(arm_linux_REDIR_FOR_strlen):
    557 	mov	r2, r0
    558 	ldrb	r0, [r0, #0]	@ zero_extendqisi2
    559 	@ lr needed for prologue
    560 	cmp	r0, #0
    561 	bxeq	lr
    562 	mov	r0, #0
    563 .L5:
    564 	add	r0, r0, #1
    565 	ldrb	r3, [r0, r2]	@ zero_extendqisi2
    566 	cmp	r3, #0
    567 	bne	.L5
    568 	bx	lr
    569 	UD2_4
    570 
    571 //.global VG_(arm_linux_REDIR_FOR_index)
    572 //VG_(arm_linux_REDIR_FOR_index):
    573 //	ldrb	r3, [r0, #0]	@ zero_extendqisi2
    574 //	and	r1, r1, #255
    575 //	cmp	r3, r1
    576 //	@ lr needed for prologue
    577 //	bne	.L9
    578 //	bx	lr
    579 //.L12:
    580 //	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
    581 //	cmp	r3, r1
    582 //	beq	.L11
    583 //.L9:
    584 //	cmp	r3, #0
    585 //	bne	.L12
    586 //	mov	r0, #0
    587 //	bx	lr
    588 //.L11:
    589 //	bx	lr
    590 //	UD2_4
    591 
    592 .global VG_(arm_linux_REDIR_FOR_memcpy)
    593 VG_(arm_linux_REDIR_FOR_memcpy):
    594 	stmfd	sp!, {r4, r5, lr}
    595 	subs	lr, r2, #0
    596 	mov	r5, r0
    597 	beq	.L2
    598 	cmp	r0, r1
    599 	bls	.L4
    600 	add	r3, r0, lr
    601 	add	r1, lr, r1
    602 	cmp	lr, #3
    603 	sub	r4, r3, #1
    604 	sub	r0, r1, #1
    605 	ble	.L28
    606 	sub	ip, r3, #5
    607 	sub	r1, r1, #5
    608 .L8:
    609 	ldrb	r3, [r1, #4]	@ zero_extendqisi2
    610 	sub	lr, lr, #4
    611 	strb	r3, [ip, #4]
    612 	ldrb	r2, [r1, #3]	@ zero_extendqisi2
    613 	cmp	lr, #3
    614 	strb	r2, [ip, #3]
    615 	ldrb	r3, [r1, #2]	@ zero_extendqisi2
    616 	mov	r4, ip
    617 	strb	r3, [ip, #2]
    618 	ldrb	r2, [r1, #1]	@ zero_extendqisi2
    619 	mov	r0, r1
    620 	strb	r2, [ip, #1]
    621 	sub	r1, r1, #4
    622 	sub	ip, ip, #4
    623 	bgt	.L8
    624 	cmp	lr, #0
    625 	beq	.L2
    626 .L28:
    627 	sub	r2, lr, #1
    628 .L21:
    629 	sub	r2, r2, #1
    630 	ldrb	r3, [r0], #-1	@ zero_extendqisi2
    631 	cmn	r2, #1
    632 	strb	r3, [r4], #-1
    633 	bne	.L21
    634 .L2:
    635 	mov	r0, r5
    636 	ldmfd	sp!, {r4, r5, pc}
    637 .L4:
    638 	bcs	.L2
    639 	cmp	lr, #3
    640 	mov	ip, r0
    641 	ble	.L29
    642 .L19:
    643 	ldrb	r3, [r1, #0]	@ zero_extendqisi2
    644 	sub	lr, lr, #4
    645 	strb	r3, [ip, #0]
    646 	ldrb	r2, [r1, #1]	@ zero_extendqisi2
    647 	cmp	lr, #3
    648 	strb	r2, [ip, #1]
    649 	ldrb	r3, [r1, #2]	@ zero_extendqisi2
    650 	strb	r3, [ip, #2]
    651 	ldrb	r2, [r1, #3]	@ zero_extendqisi2
    652 	add	r1, r1, #4
    653 	strb	r2, [ip, #3]
    654 	add	ip, ip, #4
    655 	bgt	.L19
    656 	cmp	lr, #0
    657 	beq	.L2
    658 .L29:
    659 	sub	r2, lr, #1
    660 .L20:
    661 	sub	r2, r2, #1
    662 	ldrb	r3, [r1], #1	@ zero_extendqisi2
    663 	cmn	r2, #1
    664 	strb	r3, [ip], #1
    665 	bne	.L20
    666 	mov	r0, r5
    667 	ldmfd	sp!, {r4, r5, pc}
    668 	UD2_4
    669 
    670 .global VG_(trampoline_stuff_end)
    671 VG_(trampoline_stuff_end):
    672 
    673 	/* and a trailing page of unexecutable code */
    674 	UD2_PAGE
    675 
    676 #	undef UD2_4
    677 #	undef UD2_16
    678 #	undef UD2_64
    679 #	undef UD2_256
    680 #	undef UD2_1024
    681 #	undef UD2_PAGE
    682 
    683 /*---------------- x86-darwin ----------------*/
    684 #else
    685 #if defined(VGP_x86_darwin)
    686 
    687         /* a leading page of unexecutable code */
    688 .fill 2048, 2, 0x0b0f /* `ud2` */
    689 
    690 .globl VG_(trampoline_stuff_start)
    691 VG_(trampoline_stuff_start):
    692 
    693 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
    694 VG_(x86_darwin_SUBST_FOR_sigreturn):
    695         /* XXX does this need to have any special form? (cf x86-linux
    696 	version) */
    697         movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
    698         int     $0x80
    699         ud2
    700 
    701 .globl VG_(x86_darwin_REDIR_FOR_strlen)
    702 VG_(x86_darwin_REDIR_FOR_strlen):
    703         movl    4(%esp), %edx
    704         movl    %edx, %eax
    705         jmp     1f
    706 0:
    707         incl    %eax
    708 1:
    709         cmpb    $0, (%eax)
    710         jne     0b
    711         subl    %edx, %eax
    712         ret
    713 
    714 .globl VG_(x86_darwin_REDIR_FOR_strcat)
    715 VG_(x86_darwin_REDIR_FOR_strcat):
    716         pushl   %esi
    717         movl    8(%esp), %esi
    718         movl    12(%esp), %ecx
    719         movl    %esi, %edx
    720         jmp     1f
    721 0:
    722         incl    %edx
    723 1:
    724         cmpb    $0, (%edx)
    725         jne     0b
    726 2:
    727         movzbl  (%ecx), %eax
    728         incl    %ecx
    729         movb    %al, (%edx)
    730         incl    %edx
    731         testb   %al, %al
    732         jne     2b
    733         movl    %esi, %eax
    734         popl    %esi
    735         ret
    736 
    737 
    738 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
    739 VG_(x86_darwin_REDIR_FOR_strcmp):
    740         movl    4(%esp), %edx
    741         movl    8(%esp), %ecx
    742         jmp     1f
    743 0:
    744         incl    %edx
    745         incl    %ecx
    746 1:
    747         movzbl  (%edx), %eax
    748         testb   %al, %al
    749         je      2f
    750         cmpb    (%ecx), %al
    751         je      0b
    752 2:
    753         movzbl  (%ecx),%edx
    754         movzbl  %al,%eax
    755         subl    %edx, %eax
    756         ret
    757 
    758 
    759 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
    760 VG_(x86_darwin_REDIR_FOR_strcpy):
    761 	pushl	%ebp
    762 	movl	%esp, %ebp
    763 	pushl	%esi
    764 	movl	8(%ebp), %esi
    765 	movl	12(%ebp), %ecx
    766 	movl	%esi, %edx
    767 	jmp	1f
    768 0:
    769 	incl	%ecx
    770 	incl	%edx
    771 1:
    772 	movzbl	(%ecx), %eax
    773 	testb	%al, %al
    774 	movb	%al, (%edx)
    775 	jne	0b
    776 	movl	%esi, %eax
    777 	popl	%esi
    778 	leave
    779 	ret
    780 
    781 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
    782 VG_(x86_darwin_REDIR_FOR_strlcat):
    783 	pushl	%ebp
    784 	movl	%esp, %ebp
    785 	pushl	%edi
    786 	pushl	%esi
    787 	subl	$16, %esp
    788 	movl	8(%ebp), %esi
    789 	movl	16(%ebp), %ecx
    790 	movl	%esi, %edx
    791 	leal	(%ecx,%esi), %eax
    792 	jmp	1f
    793 0:
    794 	incl	%edx
    795 1:
    796 	cmpl	%edx, %eax
    797 	je	2f
    798 	cmpb	$0, (%edx)
    799 	jne	0b
    800 2:
    801 	movl	%edx, %edi
    802 	subl	%esi, %edi
    803 	movl	%ecx, %esi
    804 	subl	%edi, %esi
    805 	je	3f
    806 	movl	12(%ebp), %eax
    807 	jmp	6f
    808 3:
    809 	movl	12(%ebp), %eax
    810 	movl	%eax, (%esp)
    811 	call	VG_(x86_darwin_REDIR_FOR_strlen)
    812 	jmp	7f
    813 4:
    814 	cmpl	$1, %esi
    815 	je	5f
    816 	movb	%cl, (%edx)
    817 	decl	%esi
    818 	incl	%edx
    819 5:
    820 	incl	%eax
    821 6:
    822 	movzbl	(%eax), %ecx
    823 	testb	%cl, %cl
    824 	jne	4b
    825 	movb	$0, (%edx)
    826 	subl	12(%ebp), %eax
    827 7:
    828 	addl	$16, %esp
    829 	leal	(%edi,%eax), %eax
    830 	popl	%esi
    831 	popl	%edi
    832 	leave
    833 	ret
    834 
    835 
    836 .globl VG_(trampoline_stuff_end)
    837 VG_(trampoline_stuff_end):
    838 
    839         /* a trailing page of unexecutable code */
    840 .fill 2048, 2, 0x0b0f /* `ud2` */
    841 
    842 
    843 /*---------------- amd64-darwin ----------------*/
    844 #else
    845 #if defined(VGP_amd64_darwin)
    846 
    847         /* a leading page of unexecutable code */
    848 .fill 2048, 2, 0x0b0f /* `ud2` */
    849 
    850 .globl VG_(trampoline_stuff_start)
    851 VG_(trampoline_stuff_start):
    852 
    853 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
    854 VG_(amd64_darwin_SUBST_FOR_sigreturn):
    855         /* XXX does this need to have any special form? (cf x86-linux
    856 	version) */
    857         movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
    858         syscall
    859         ud2
    860 
    861 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
    862 VG_(amd64_darwin_REDIR_FOR_strlen):
    863         movq    %rdi, %rax
    864         jmp     1f
    865 0:
    866         incq    %rax
    867 1:
    868         cmpb    $0, (%rax)
    869         jne     0b
    870         subq    %rdi, %rax
    871         ret
    872 
    873 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
    874 VG_(amd64_darwin_REDIR_FOR_strcat):
    875 	movq	%rdi, %rdx
    876 	jmp	1f
    877 0:
    878 	incq	%rdx
    879 1:
    880 	cmpb	$0, (%rdx)
    881 	jne	0b
    882 2:
    883 	movzbl	(%rsi), %eax
    884 	incq	%rsi
    885 	movb	%al, (%rdx)
    886 	incq	%rdx
    887 	testb	%al, %al
    888 	jne	2b
    889 	movq	%rdi, %rax
    890 	ret
    891 
    892 
    893 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
    894 VG_(amd64_darwin_REDIR_FOR_strcmp):
    895 	jmp	1f
    896 0:
    897 	incq	%rdi
    898 	incq	%rsi
    899 1:
    900 	movzbl	(%rdi), %eax
    901 	testb	%al, %al
    902 	je	2f
    903 	cmpb	(%rsi), %al
    904 	je	0b
    905 2:
    906 	movzbl	(%rsi), %edx
    907 	movzbl	%al, %eax
    908 	subl	%edx, %eax
    909 	ret
    910 
    911 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
    912 VG_(amd64_darwin_REDIR_FOR_strcpy):
    913 	pushq	%rbp
    914 	movq	%rdi, %rdx
    915 	movq	%rsp, %rbp
    916 	jmp	1f
    917 0:
    918 	incq	%rsi
    919 	incq	%rdx
    920 1:
    921 	movzbl	(%rsi), %eax
    922 	testb	%al, %al
    923 	movb	%al, (%rdx)
    924 	jne	0b
    925 	leave
    926 	movq	%rdi, %rax
    927 	ret
    928 
    929 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
    930 VG_(amd64_darwin_REDIR_FOR_strlcat):
    931 	pushq	%rbp
    932 	leaq	(%rdx,%rdi), %rax
    933 	movq	%rdi, %rcx
    934 	movq	%rsp, %rbp
    935 	pushq	%rbx
    936 	subq	$8, %rsp
    937 	jmp	1f
    938 0:
    939 	incq	%rcx
    940 1:
    941 	cmpq	%rcx, %rax
    942 	je	2f
    943 	cmpb	$0, (%rcx)
    944 	jne	0b
    945 2:
    946 	movq	%rcx, %rbx
    947 	subq	%rdi, %rbx
    948 	movq	%rdx, %rdi
    949 	subq	%rbx, %rdi
    950 	je	3f
    951 	movq	%rsi, %rax
    952 	jmp	6f
    953 3:
    954 	movq	%rsi, %rdi
    955 	call	VG_(amd64_darwin_REDIR_FOR_strlen)
    956 	jmp	7f
    957 4:
    958 	cmpq	$1, %rdi
    959 	je	5f
    960 	movb	%dl, (%rcx)
    961 	decq	%rdi
    962 	incq	%rcx
    963 5:
    964 	incq	%rax
    965 6:
    966 	movzbl	(%rax), %edx
    967 	testb	%dl, %dl
    968 	jne	4b
    969 	movb	$0, (%rcx)
    970 	subq	%rsi, %rax
    971 7:
    972 	leaq	(%rbx,%rax), %rax
    973 	addq	$8, %rsp
    974 	popq	%rbx
    975 	leave
    976 	ret
    977 
    978 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
    979 VG_(amd64_darwin_REDIR_FOR_arc4random):
    980 	/* not very random, hope dyld won't mind */
    981 	movq	$0x76616c6772696e64, %rax
    982 	ret
    983 
    984 .globl VG_(trampoline_stuff_end)
    985 VG_(trampoline_stuff_end):
    986 
    987         /* a trailing page of unexecutable code */
    988 .fill 2048, 2, 0x0b0f /* `ud2` */
    989 
    990 
    991 /*---------------- s390x-linux ----------------*/
    992 #else
    993 #if defined(VGP_s390x_linux)
    994 
    995         /* a leading page of unexecutable code */
    996 	.fill 2048, 2, 0x0000
    997 
    998 .global VG_(trampoline_stuff_start)
    999 VG_(trampoline_stuff_start):
   1000 
   1001 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
   1002 VG_(s390x_linux_SUBST_FOR_sigreturn):
   1003         svc __NR_sigreturn
   1004 	.short 0
   1005 
   1006 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
   1007 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
   1008         /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
   1009            for ra = cfa to decide if it is a sig_rt_frame or not. Since we
   1010            set ra to this trampoline, but the cfa is still in the stack,
   1011            the unwinder thinks, that this is a non-rt frame  and causes a
   1012            crash in the gcc unwinder - which is used by the thread library
   1013            and others. Therefore we add a lr 1,1 nop, to let the gcc
   1014            unwinder bail out gracefully. This might also affect unwinding
   1015            across the signal frame - tough luck. fixs390 */
   1016         lr 1,1
   1017         svc __NR_rt_sigreturn
   1018 	.short 0
   1019 
   1020 .globl VG_(trampoline_stuff_end)
   1021 VG_(trampoline_stuff_end):
   1022 	.fill 2048, 2, 0x0000
   1023 
   1024 /*---------------------- mips32-linux ----------------------*/
   1025 #else
   1026 #if defined(VGP_mips32_linux)
   1027 
   1028 #	define UD2_16     trap ; trap ; trap; trap
   1029 #	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
   1030 #	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
   1031 #	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
   1032 #	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
   1033 
   1034 
   1035 .global VG_(trampoline_stuff_start)
   1036 VG_(trampoline_stuff_start):
   1037 
   1038 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
   1039 VG_(mips32_linux_SUBST_FOR_sigreturn):
   1040         li $v0,__NR_sigreturn
   1041         syscall
   1042         nop
   1043         .long 0	/*illegal insn*/
   1044 
   1045 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
   1046 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
   1047 	li $v0,__NR_rt_sigreturn
   1048         syscall
   1049         nop
   1050         .long 0	/*illegal insn*/
   1051 
   1052 /* There's no particular reason that this needs to be handwritten
   1053    assembly, but since that's what this file contains, here's a
   1054    simple strlen implementation (written in C and compiled by gcc.)
   1055 */
   1056 .global VG_(mips32_linux_REDIR_FOR_strlen)
   1057 .type   VG_(mips32_linux_REDIR_FOR_strlen), @function
   1058 VG_(mips32_linux_REDIR_FOR_strlen):
   1059       li $v0, 0
   1060       //la $a0, string
   1061       j strlen_cond
   1062    strlen_loop:
   1063       addi $v0, $v0, 1
   1064       addi $a0, $a0, 1
   1065    strlen_cond:
   1066       lbu $t0, ($a0)
   1067       bne $t0, $zero, strlen_loop
   1068     jr $ra
   1069 
   1070 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
   1071 
   1072 .global VG_(trampoline_stuff_end)
   1073 VG_(trampoline_stuff_end):
   1074 
   1075 
   1076 #	undef UD2_16
   1077 #	undef UD2_64
   1078 #	undef UD2_256
   1079 #	undef UD2_1024
   1080 #	undef UD2_PAGE
   1081 
   1082 /*---------------- unknown ----------------*/
   1083 #else
   1084 #  error Unknown platform
   1085 
   1086 #endif
   1087 #endif
   1088 #endif
   1089 #endif
   1090 #endif
   1091 #endif
   1092 #endif
   1093 #endif
   1094 
   1095 #if defined(VGO_linux)
   1096 /* Let the linker know we don't need an executable stack */
   1097 #  if defined(VGP_arm_linux)
   1098    .section .note.GNU-stack,"",%progbits
   1099 #  else
   1100    .section .note.GNU-stack,"",@progbits
   1101 #  endif
   1102 #endif
   1103 
   1104 /*--------------------------------------------------------------------*/
   1105 /*--- end                                                          ---*/
   1106 /*--------------------------------------------------------------------*/
   1107