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