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-2011 Julian Seward
     11      jseward (at) acm.org
     12   Copyright (C) 2006-2011 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 /* There's no particular reason that this needs to be handwritten
    193    assembly, but since that's what this file contains, here's a
    194    simple strlen implementation (written in C and compiled by gcc.)
    195 */
    196 .global VG_(amd64_linux_REDIR_FOR_strlen)
    197 .type   VG_(amd64_linux_REDIR_FOR_strlen), @function
    198 VG_(amd64_linux_REDIR_FOR_strlen):
    199 .LfnB4:
    200 	xorl	%eax, %eax
    201 	cmpb	$0, (%rdi)
    202 	movq	%rdi, %rdx
    203 	je	.L41
    204 .L40:	addq	$1, %rdx
    205 	cmpb	$0, (%rdx)
    206 	jne	.L40
    207 	movq	%rdx, %rax
    208 	subq	%rdi, %rax
    209 .L41:	ret
    210 .LfnE4:
    211 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
    212 
    213 
    214 /* A CIE for the above three functions, followed by their FDEs */
    215 	.section .eh_frame,"a",@progbits
    216 .Lframe1:
    217         .long   .LEcie1-.LScie1
    218 .LScie1:
    219         .long   0x0
    220         .byte   0x1
    221         .string "zR"
    222         .uleb128 0x1
    223         .sleb128 -8
    224         .byte   0x10
    225         .uleb128 0x1
    226         .byte   0x3
    227         .byte   0xc
    228         .uleb128 0x7
    229         .uleb128 0x8
    230         .byte   0x90
    231         .uleb128 0x1
    232         .align 8
    233 .LEcie1:
    234 .LSfde2:
    235         .long   .LEfde2-.LASfde2
    236 .LASfde2:
    237         .long   .LASfde2-.Lframe1
    238         .long   .LfnB2
    239         .long   .LfnE2-.LfnB2
    240         .uleb128 0x0
    241         .align 8
    242 .LEfde2:
    243 .LSfde3:
    244         .long   .LEfde3-.LASfde3
    245 .LASfde3:
    246         .long   .LASfde3-.Lframe1
    247         .long   .LfnB3
    248         .long   .LfnE3-.LfnB3
    249         .uleb128 0x0
    250         .align 8
    251 .LEfde3:
    252 .LSfde4:
    253         .long   .LEfde4-.LASfde4
    254 .LASfde4:
    255         .long   .LASfde4-.Lframe1
    256         .long   .LfnB4
    257         .long   .LfnE4-.LfnB4
    258         .uleb128 0x0
    259         .align 8
    260 .LEfde4:
    261 	.previous
    262 
    263 .global VG_(trampoline_stuff_end)
    264 VG_(trampoline_stuff_end):
    265 
    266 	/* and a trailing page of unexecutable code */
    267 	UD2_PAGE
    268 
    269 #	undef UD2_16
    270 #	undef UD2_64
    271 #	undef UD2_256
    272 #	undef UD2_1024
    273 #	undef UD2_PAGE
    274 
    275 /*---------------- ppc32-linux ----------------*/
    276 #else
    277 #if defined(VGP_ppc32_linux)
    278 
    279 #	define UD2_16     trap ; trap ; trap; trap
    280 #	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
    281 #	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
    282 #	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
    283 #	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
    284 
    285 	/* a leading page of unexecutable code */
    286 	UD2_PAGE
    287 
    288 .global VG_(trampoline_stuff_start)
    289 VG_(trampoline_stuff_start):
    290 
    291 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
    292 VG_(ppc32_linux_SUBST_FOR_sigreturn):
    293 	li 0,__NR_sigreturn
    294         sc
    295         .long 0	/*illegal insn*/
    296 
    297 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
    298 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
    299 	li 0,__NR_rt_sigreturn
    300         sc
    301         .long 0	/*illegal insn*/
    302 
    303 /* There's no particular reason that this needs to be handwritten
    304    assembly, but since that's what this file contains, here's a
    305    simple strlen implementation (written in C and compiled by gcc.)
    306 */
    307 .global VG_(ppc32_linux_REDIR_FOR_strlen)
    308 .type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
    309 VG_(ppc32_linux_REDIR_FOR_strlen):
    310         lbz 4,0(3)
    311         li 9,0
    312         cmpwi 0,4,0
    313         beq- 0,.L18
    314 .L19:
    315         lbzu 5,1(3)
    316         addi 9,9,1
    317         cmpwi 0,5,0
    318         bne+ 0,.L19
    319 .L18:
    320         mr 3,9
    321         blr
    322 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
    323 
    324 /* Ditto strcmp */
    325 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
    326 .type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
    327 VG_(ppc32_linux_REDIR_FOR_strcmp):
    328 .L20:
    329         lbz 0,0(3)
    330         cmpwi 7,0,0
    331         bne- 7,.L21
    332         lbz 0,0(4)
    333         li 11,0
    334         cmpwi 7,0,0
    335         beq- 7,.L22
    336 .L21:
    337         lbz 0,0(3)
    338         li 11,-1
    339         cmpwi 7,0,0
    340         beq- 7,.L22
    341         lbz 0,0(4)
    342         li 11,1
    343         cmpwi 7,0,0
    344         beq- 7,.L22
    345         lbz 9,0(3)
    346         lbz 0,0(4)
    347         li 11,-1
    348         cmplw 7,9,0
    349         blt- 7,.L22
    350         lbz 9,0(3)
    351         lbz 0,0(4)
    352         li 11,1
    353         addi 3,3,1
    354         addi 4,4,1
    355         cmplw 7,9,0
    356         ble+ 7,.L20
    357 .L22:
    358         mr 3,11
    359         blr
    360 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
    361 
    362 /* Ditto index/strchr */
    363 .global VG_(ppc32_linux_REDIR_FOR_strchr)
    364 .type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
    365 VG_(ppc32_linux_REDIR_FOR_strchr):
    366         lbz 0,0(3)
    367         rlwinm 4,4,0,0xff
    368         cmpw 7,4,0
    369         beqlr 7
    370         cmpwi 7,0,0
    371         bne 7,.L308
    372         b .L304
    373 .L309:
    374         beq 6,.L304
    375 .L308:
    376         lbzu 0,1(3)
    377         cmpw 7,4,0
    378         cmpwi 6,0,0
    379         bne 7,.L309
    380         blr
    381 .L304:
    382         li 3,0
    383         blr
    384 .size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
    385 
    386 .global VG_(trampoline_stuff_end)
    387 VG_(trampoline_stuff_end):
    388 
    389 	/* and a trailing page of unexecutable code */
    390 	UD2_PAGE
    391 
    392 #	undef UD2_16
    393 #	undef UD2_64
    394 #	undef UD2_256
    395 #	undef UD2_1024
    396 #	undef UD2_PAGE
    397 
    398 /*---------------- ppc64-linux ----------------*/
    399 #else
    400 #if defined(VGP_ppc64_linux)
    401 
    402 #	define UD2_16     trap ; trap ; trap; trap
    403 #	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
    404 #	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
    405 #	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
    406 #	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
    407 
    408 	/* a leading page of unexecutable code */
    409 	UD2_PAGE
    410 
    411 .global VG_(trampoline_stuff_start)
    412 VG_(trampoline_stuff_start):
    413 
    414 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
    415 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
    416 	li 0,__NR_rt_sigreturn
    417         sc
    418         .long 0	/*illegal insn*/
    419 
    420 	/* See comment in pub_core_trampoline.h for what this is for */
    421 .global VG_(ppctoc_magic_redirect_return_stub)
    422 VG_(ppctoc_magic_redirect_return_stub):
    423 	trap
    424 
    425 	/* this function is written using the "dotless" ABI convention */
    426 	.align 2
    427 	.globl VG_(ppc64_linux_REDIR_FOR_strlen)
    428 	.section        ".opd","aw"
    429 	.align 3
    430 VG_(ppc64_linux_REDIR_FOR_strlen):
    431 	.quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
    432 	.previous
    433 	.size	VG_(ppc64_linux_REDIR_FOR_strlen), \
    434 			.L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
    435 	.type	VG_(ppc64_linux_REDIR_FOR_strlen), @function
    436 
    437 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
    438         mr 9,3
    439         lbz 0,0(3)
    440         li 3,0
    441         cmpwi 7,0,0
    442         beqlr 7
    443         li 3,0
    444 .L01:
    445         addi 0,3,1
    446         extsw 3,0
    447         lbzx 0,9,3
    448         cmpwi 7,0,0
    449         bne 7,.L01
    450         blr
    451         .long 0
    452         .byte 0,0,0,0,0,0,0,0
    453 .L0end:
    454 
    455         /* this function is written using the "dotless" ABI convention */
    456         .align 2
    457         .globl VG_(ppc64_linux_REDIR_FOR_strchr)
    458 	.section        ".opd","aw"
    459 	.align 3
    460 VG_(ppc64_linux_REDIR_FOR_strchr):
    461         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
    462         .previous
    463         .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
    464                         .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
    465         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
    466 
    467 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
    468         lbz 0,0(3)
    469         rldicl 4,4,0,56
    470         cmpw 7,4,0
    471         beqlr 7
    472         cmpdi 7,0,0
    473         bne 7,.L18
    474         b .L14
    475 .L19:
    476         beq 6,.L14
    477 .L18:
    478         lbzu 0,1(3)
    479         cmpw 7,4,0
    480         cmpdi 6,0,0
    481         bne 7,.L19
    482         blr
    483 .L14:
    484         li 3,0
    485         blr
    486         .long 0
    487         .byte 0,0,0,0,0,0,0,0
    488 .L1end:
    489 
    490 
    491 .global VG_(trampoline_stuff_end)
    492 VG_(trampoline_stuff_end):
    493 
    494 	/* and a trailing page of unexecutable code */
    495 	UD2_PAGE
    496 
    497 #	undef UD2_16
    498 #	undef UD2_64
    499 #	undef UD2_256
    500 #	undef UD2_1024
    501 #	undef UD2_PAGE
    502 
    503 /*---------------- ppc32-linux ----------------*/
    504 
    505 #elif defined(VGP_arm_linux)
    506 
    507 #       define UD2_4      .word 0xFFFFFFFF
    508 #	define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
    509 #	define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
    510 #	define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
    511 #	define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
    512 #	define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
    513 
    514 	/* a leading page of unexecutable code */
    515 	UD2_PAGE
    516 
    517 .global VG_(trampoline_stuff_start)
    518 VG_(trampoline_stuff_start):
    519 
    520 .global VG_(arm_linux_REDIR_FOR_strlen)
    521 VG_(arm_linux_REDIR_FOR_strlen):
    522 	mov	r2, r0
    523 	ldrb	r0, [r0, #0]	@ zero_extendqisi2
    524 	@ lr needed for prologue
    525 	cmp	r0, #0
    526 	bxeq	lr
    527 	mov	r0, #0
    528 .L5:
    529 	add	r0, r0, #1
    530 	ldrb	r3, [r0, r2]	@ zero_extendqisi2
    531 	cmp	r3, #0
    532 	bne	.L5
    533 	bx	lr
    534 	UD2_4
    535 
    536 //.global VG_(arm_linux_REDIR_FOR_index)
    537 //VG_(arm_linux_REDIR_FOR_index):
    538 //	ldrb	r3, [r0, #0]	@ zero_extendqisi2
    539 //	and	r1, r1, #255
    540 //	cmp	r3, r1
    541 //	@ lr needed for prologue
    542 //	bne	.L9
    543 //	bx	lr
    544 //.L12:
    545 //	ldrb	r3, [r0, #1]!	@ zero_extendqisi2
    546 //	cmp	r3, r1
    547 //	beq	.L11
    548 //.L9:
    549 //	cmp	r3, #0
    550 //	bne	.L12
    551 //	mov	r0, #0
    552 //	bx	lr
    553 //.L11:
    554 //	bx	lr
    555 //	UD2_4
    556 
    557 .global VG_(arm_linux_REDIR_FOR_memcpy)
    558 VG_(arm_linux_REDIR_FOR_memcpy):
    559 	stmfd	sp!, {r4, r5, lr}
    560 	subs	lr, r2, #0
    561 	mov	r5, r0
    562 	beq	.L2
    563 	cmp	r0, r1
    564 	bls	.L4
    565 	add	r3, r0, lr
    566 	add	r1, lr, r1
    567 	cmp	lr, #3
    568 	sub	r4, r3, #1
    569 	sub	r0, r1, #1
    570 	ble	.L28
    571 	sub	ip, r3, #5
    572 	sub	r1, r1, #5
    573 .L8:
    574 	ldrb	r3, [r1, #4]	@ zero_extendqisi2
    575 	sub	lr, lr, #4
    576 	strb	r3, [ip, #4]
    577 	ldrb	r2, [r1, #3]	@ zero_extendqisi2
    578 	cmp	lr, #3
    579 	strb	r2, [ip, #3]
    580 	ldrb	r3, [r1, #2]	@ zero_extendqisi2
    581 	mov	r4, ip
    582 	strb	r3, [ip, #2]
    583 	ldrb	r2, [r1, #1]	@ zero_extendqisi2
    584 	mov	r0, r1
    585 	strb	r2, [ip, #1]
    586 	sub	r1, r1, #4
    587 	sub	ip, ip, #4
    588 	bgt	.L8
    589 	cmp	lr, #0
    590 	beq	.L2
    591 .L28:
    592 	sub	r2, lr, #1
    593 .L21:
    594 	sub	r2, r2, #1
    595 	ldrb	r3, [r0], #-1	@ zero_extendqisi2
    596 	cmn	r2, #1
    597 	strb	r3, [r4], #-1
    598 	bne	.L21
    599 .L2:
    600 	mov	r0, r5
    601 	ldmfd	sp!, {r4, r5, pc}
    602 .L4:
    603 	bcs	.L2
    604 	cmp	lr, #3
    605 	mov	ip, r0
    606 	ble	.L29
    607 .L19:
    608 	ldrb	r3, [r1, #0]	@ zero_extendqisi2
    609 	sub	lr, lr, #4
    610 	strb	r3, [ip, #0]
    611 	ldrb	r2, [r1, #1]	@ zero_extendqisi2
    612 	cmp	lr, #3
    613 	strb	r2, [ip, #1]
    614 	ldrb	r3, [r1, #2]	@ zero_extendqisi2
    615 	strb	r3, [ip, #2]
    616 	ldrb	r2, [r1, #3]	@ zero_extendqisi2
    617 	add	r1, r1, #4
    618 	strb	r2, [ip, #3]
    619 	add	ip, ip, #4
    620 	bgt	.L19
    621 	cmp	lr, #0
    622 	beq	.L2
    623 .L29:
    624 	sub	r2, lr, #1
    625 .L20:
    626 	sub	r2, r2, #1
    627 	ldrb	r3, [r1], #1	@ zero_extendqisi2
    628 	cmn	r2, #1
    629 	strb	r3, [ip], #1
    630 	bne	.L20
    631 	mov	r0, r5
    632 	ldmfd	sp!, {r4, r5, pc}
    633 	UD2_4
    634 
    635 .global VG_(trampoline_stuff_end)
    636 VG_(trampoline_stuff_end):
    637 
    638 	/* and a trailing page of unexecutable code */
    639 	UD2_PAGE
    640 
    641 #	undef UD2_4
    642 #	undef UD2_16
    643 #	undef UD2_64
    644 #	undef UD2_256
    645 #	undef UD2_1024
    646 #	undef UD2_PAGE
    647 
    648 /*---------------- x86-darwin ----------------*/
    649 #else
    650 #if defined(VGP_x86_darwin)
    651 
    652         /* a leading page of unexecutable code */
    653 .fill 2048, 2, 0x0b0f /* `ud2` */
    654 
    655 .globl VG_(trampoline_stuff_start)
    656 VG_(trampoline_stuff_start):
    657 
    658 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
    659 VG_(x86_darwin_SUBST_FOR_sigreturn):
    660         /* XXX does this need to have any special form? (cf x86-linux
    661 	version) */
    662         movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
    663         int     $0x80
    664         ud2
    665 
    666 .globl VG_(x86_darwin_REDIR_FOR_strlen)
    667 VG_(x86_darwin_REDIR_FOR_strlen):
    668         movl    4(%esp), %edx
    669         movl    %edx, %eax
    670         jmp     1f
    671 0:
    672         incl    %eax
    673 1:
    674         cmpb    $0, (%eax)
    675         jne     0b
    676         subl    %edx, %eax
    677         ret
    678 
    679 .globl VG_(x86_darwin_REDIR_FOR_strcat)
    680 VG_(x86_darwin_REDIR_FOR_strcat):
    681         pushl   %esi
    682         movl    8(%esp), %esi
    683         movl    12(%esp), %ecx
    684         movl    %esi, %edx
    685         jmp     1f
    686 0:
    687         incl    %edx
    688 1:
    689         cmpb    $0, (%edx)
    690         jne     0b
    691 2:
    692         movzbl  (%ecx), %eax
    693         incl    %ecx
    694         movb    %al, (%edx)
    695         incl    %edx
    696         testb   %al, %al
    697         jne     2b
    698         movl    %esi, %eax
    699         popl    %esi
    700         ret
    701 
    702 
    703 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
    704 VG_(x86_darwin_REDIR_FOR_strcmp):
    705         movl    4(%esp), %edx
    706         movl    8(%esp), %ecx
    707         jmp     1f
    708 0:
    709         incl    %edx
    710         incl    %ecx
    711 1:
    712         movzbl  (%edx), %eax
    713         testb   %al, %al
    714         je      2f
    715         cmpb    (%ecx), %al
    716         je      0b
    717 2:
    718         movzbl  (%ecx),%edx
    719         movzbl  %al,%eax
    720         subl    %edx, %eax
    721         ret
    722 
    723 
    724 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
    725 VG_(x86_darwin_REDIR_FOR_strcpy):
    726 	pushl	%ebp
    727 	movl	%esp, %ebp
    728 	pushl	%esi
    729 	movl	8(%ebp), %esi
    730 	movl	12(%ebp), %ecx
    731 	movl	%esi, %edx
    732 	jmp	1f
    733 0:
    734 	incl	%ecx
    735 	incl	%edx
    736 1:
    737 	movzbl	(%ecx), %eax
    738 	testb	%al, %al
    739 	movb	%al, (%edx)
    740 	jne	0b
    741 	movl	%esi, %eax
    742 	popl	%esi
    743 	leave
    744 	ret
    745 
    746 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
    747 VG_(x86_darwin_REDIR_FOR_strlcat):
    748 	pushl	%ebp
    749 	movl	%esp, %ebp
    750 	pushl	%edi
    751 	pushl	%esi
    752 	subl	$16, %esp
    753 	movl	8(%ebp), %esi
    754 	movl	16(%ebp), %ecx
    755 	movl	%esi, %edx
    756 	leal	(%ecx,%esi), %eax
    757 	jmp	1f
    758 0:
    759 	incl	%edx
    760 1:
    761 	cmpl	%edx, %eax
    762 	je	2f
    763 	cmpb	$0, (%edx)
    764 	jne	0b
    765 2:
    766 	movl	%edx, %edi
    767 	subl	%esi, %edi
    768 	movl	%ecx, %esi
    769 	subl	%edi, %esi
    770 	je	3f
    771 	movl	12(%ebp), %eax
    772 	jmp	6f
    773 3:
    774 	movl	12(%ebp), %eax
    775 	movl	%eax, (%esp)
    776 	call	VG_(x86_darwin_REDIR_FOR_strlen)
    777 	jmp	7f
    778 4:
    779 	cmpl	$1, %esi
    780 	je	5f
    781 	movb	%cl, (%edx)
    782 	decl	%esi
    783 	incl	%edx
    784 5:
    785 	incl	%eax
    786 6:
    787 	movzbl	(%eax), %ecx
    788 	testb	%cl, %cl
    789 	jne	4b
    790 	movb	$0, (%edx)
    791 	subl	12(%ebp), %eax
    792 7:
    793 	addl	$16, %esp
    794 	leal	(%edi,%eax), %eax
    795 	popl	%esi
    796 	popl	%edi
    797 	leave
    798 	ret
    799 
    800 
    801 .globl VG_(trampoline_stuff_end)
    802 VG_(trampoline_stuff_end):
    803 
    804         /* a trailing page of unexecutable code */
    805 .fill 2048, 2, 0x0b0f /* `ud2` */
    806 
    807 
    808 /*---------------- amd64-darwin ----------------*/
    809 #else
    810 #if defined(VGP_amd64_darwin)
    811 
    812         /* a leading page of unexecutable code */
    813 .fill 2048, 2, 0x0b0f /* `ud2` */
    814 
    815 .globl VG_(trampoline_stuff_start)
    816 VG_(trampoline_stuff_start):
    817 
    818 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
    819 VG_(amd64_darwin_SUBST_FOR_sigreturn):
    820         /* XXX does this need to have any special form? (cf x86-linux
    821 	version) */
    822         movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
    823         syscall
    824         ud2
    825 
    826 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
    827 VG_(amd64_darwin_REDIR_FOR_strlen):
    828         movq    %rdi, %rax
    829         jmp     1f
    830 0:
    831         incq    %rax
    832 1:
    833         cmpb    $0, (%rax)
    834         jne     0b
    835         subq    %rdi, %rax
    836         ret
    837 
    838 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
    839 VG_(amd64_darwin_REDIR_FOR_strcat):
    840 	movq	%rdi, %rdx
    841 	jmp	1f
    842 0:
    843 	incq	%rdx
    844 1:
    845 	cmpb	$0, (%rdx)
    846 	jne	0b
    847 2:
    848 	movzbl	(%rsi), %eax
    849 	incq	%rsi
    850 	movb	%al, (%rdx)
    851 	incq	%rdx
    852 	testb	%al, %al
    853 	jne	2b
    854 	movq	%rdi, %rax
    855 	ret
    856 
    857 
    858 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
    859 VG_(amd64_darwin_REDIR_FOR_strcmp):
    860 	jmp	1f
    861 0:
    862 	incq	%rdi
    863 	incq	%rsi
    864 1:
    865 	movzbl	(%rdi), %eax
    866 	testb	%al, %al
    867 	je	2f
    868 	cmpb	(%rsi), %al
    869 	je	0b
    870 2:
    871 	movzbl	(%rsi), %edx
    872 	movzbl	%al, %eax
    873 	subl	%edx, %eax
    874 	ret
    875 
    876 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
    877 VG_(amd64_darwin_REDIR_FOR_strcpy):
    878 	pushq	%rbp
    879 	movq	%rdi, %rdx
    880 	movq	%rsp, %rbp
    881 	jmp	1f
    882 0:
    883 	incq	%rsi
    884 	incq	%rdx
    885 1:
    886 	movzbl	(%rsi), %eax
    887 	testb	%al, %al
    888 	movb	%al, (%rdx)
    889 	jne	0b
    890 	leave
    891 	movq	%rdi, %rax
    892 	ret
    893 
    894 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
    895 VG_(amd64_darwin_REDIR_FOR_strlcat):
    896 	pushq	%rbp
    897 	leaq	(%rdx,%rdi), %rax
    898 	movq	%rdi, %rcx
    899 	movq	%rsp, %rbp
    900 	pushq	%rbx
    901 	subq	$8, %rsp
    902 	jmp	1f
    903 0:
    904 	incq	%rcx
    905 1:
    906 	cmpq	%rcx, %rax
    907 	je	2f
    908 	cmpb	$0, (%rcx)
    909 	jne	0b
    910 2:
    911 	movq	%rcx, %rbx
    912 	subq	%rdi, %rbx
    913 	movq	%rdx, %rdi
    914 	subq	%rbx, %rdi
    915 	je	3f
    916 	movq	%rsi, %rax
    917 	jmp	6f
    918 3:
    919 	movq	%rsi, %rdi
    920 	call	VG_(amd64_darwin_REDIR_FOR_strlen)
    921 	jmp	7f
    922 4:
    923 	cmpq	$1, %rdi
    924 	je	5f
    925 	movb	%dl, (%rcx)
    926 	decq	%rdi
    927 	incq	%rcx
    928 5:
    929 	incq	%rax
    930 6:
    931 	movzbl	(%rax), %edx
    932 	testb	%dl, %dl
    933 	jne	4b
    934 	movb	$0, (%rcx)
    935 	subq	%rsi, %rax
    936 7:
    937 	leaq	(%rbx,%rax), %rax
    938 	addq	$8, %rsp
    939 	popq	%rbx
    940 	leave
    941 	ret
    942 
    943 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
    944 VG_(amd64_darwin_REDIR_FOR_arc4random):
    945 	/* not very random, hope dyld won't mind */
    946 	movq	$0x76616c6772696e64, %rax
    947 	ret
    948 
    949 .globl VG_(trampoline_stuff_end)
    950 VG_(trampoline_stuff_end):
    951 
    952         /* a trailing page of unexecutable code */
    953 .fill 2048, 2, 0x0b0f /* `ud2` */
    954 
    955 
    956 /*---------------- s390x-linux ----------------*/
    957 #else
    958 #if defined(VGP_s390x_linux)
    959 
    960         /* a leading page of unexecutable code */
    961 	.fill 2048, 2, 0x0000
    962 
    963 .global VG_(trampoline_stuff_start)
    964 VG_(trampoline_stuff_start):
    965 
    966 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
    967 VG_(s390x_linux_SUBST_FOR_sigreturn):
    968         svc __NR_sigreturn
    969 	.short 0
    970 
    971 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
    972 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
    973         /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
    974            for ra = cfa to decide if it is a sig_rt_frame or not. Since we
    975            set ra to this trampoline, but the cfa is still in the stack,
    976            the unwinder thinks, that this is a non-rt frame  and causes a
    977            crash in the gcc unwinder - which is used by the thread library
    978            and others. Therefore we add a lr 1,1 nop, to let the gcc
    979            unwinder bail out gracefully. This might also affect unwinding
    980            across the signal frame - tough luck. fixs390 */
    981         lr 1,1
    982         svc __NR_rt_sigreturn
    983 	.short 0
    984 
    985 .globl VG_(trampoline_stuff_end)
    986 VG_(trampoline_stuff_end):
    987 	.fill 2048, 2, 0x0000
    988 
    989 /*---------------- unknown ----------------*/
    990 #else
    991 #  error Unknown platform
    992 
    993 #endif
    994 #endif
    995 #endif
    996 #endif
    997 #endif
    998 #endif
    999 #endif
   1000 
   1001 #if defined(VGO_linux)
   1002 /* Let the linker know we don't need an executable stack */
   1003 #  if defined(VGP_arm_linux)
   1004    .section .note.GNU-stack,"",%progbits
   1005 #  else
   1006    .section .note.GNU-stack,"",@progbits
   1007 #  endif
   1008 #endif
   1009 
   1010 /*--------------------------------------------------------------------*/
   1011 /*--- end                                                          ---*/
   1012 /*--------------------------------------------------------------------*/
   1013