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@acm.org 12 Copyright (C) 2006-2012 OpenWorks LLP 13 info@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) 55VG_(trampoline_stuff_start): 56 57.global VG_(x86_linux_SUBST_FOR_sigreturn) 58VG_(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) 69VG_(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 92VG_(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 121VG_(x86_linux_REDIR_FOR_strlen): 122 pushl %ebp 123 movl %esp, %ebp 124 movl 8(%ebp), %edx 125 movl %edx, %eax 126 jmp 2f 1271: incl %eax 1282: 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) 137VG_(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) 162VG_(trampoline_stuff_start): 163 164.global VG_(amd64_linux_SUBST_FOR_rt_sigreturn) 165VG_(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 174VG_(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 184VG_(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 194VG_(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 208VG_(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) 283VG_(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) 308VG_(trampoline_stuff_start): 309 310.global VG_(ppc32_linux_SUBST_FOR_sigreturn) 311VG_(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) 317VG_(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 328VG_(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 346VG_(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 384VG_(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) 406VG_(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) 431VG_(trampoline_stuff_start): 432 433.global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn) 434VG_(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) 441VG_(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 449VG_(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 479VG_(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) 511VG_(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) 537VG_(trampoline_stuff_start): 538 539.global VG_(arm_linux_SUBST_FOR_sigreturn) 540.type VG_(arm_linux_SUBST_FOR_sigreturn),#function 541VG_(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 549VG_(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) 556VG_(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) 593VG_(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) 671VG_(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) 691VG_(trampoline_stuff_start): 692 693.globl VG_(x86_darwin_SUBST_FOR_sigreturn) 694VG_(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) 702VG_(x86_darwin_REDIR_FOR_strlen): 703 movl 4(%esp), %edx 704 movl %edx, %eax 705 jmp 1f 7060: 707 incl %eax 7081: 709 cmpb $0, (%eax) 710 jne 0b 711 subl %edx, %eax 712 ret 713 714.globl VG_(x86_darwin_REDIR_FOR_strcat) 715VG_(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 7210: 722 incl %edx 7231: 724 cmpb $0, (%edx) 725 jne 0b 7262: 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) 739VG_(x86_darwin_REDIR_FOR_strcmp): 740 movl 4(%esp), %edx 741 movl 8(%esp), %ecx 742 jmp 1f 7430: 744 incl %edx 745 incl %ecx 7461: 747 movzbl (%edx), %eax 748 testb %al, %al 749 je 2f 750 cmpb (%ecx), %al 751 je 0b 7522: 753 movzbl (%ecx),%edx 754 movzbl %al,%eax 755 subl %edx, %eax 756 ret 757 758 759.globl VG_(x86_darwin_REDIR_FOR_strcpy) 760VG_(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 7680: 769 incl %ecx 770 incl %edx 7711: 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) 782VG_(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 7930: 794 incl %edx 7951: 796 cmpl %edx, %eax 797 je 2f 798 cmpb $0, (%edx) 799 jne 0b 8002: 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 8083: 809 movl 12(%ebp), %eax 810 movl %eax, (%esp) 811 call VG_(x86_darwin_REDIR_FOR_strlen) 812 jmp 7f 8134: 814 cmpl $1, %esi 815 je 5f 816 movb %cl, (%edx) 817 decl %esi 818 incl %edx 8195: 820 incl %eax 8216: 822 movzbl (%eax), %ecx 823 testb %cl, %cl 824 jne 4b 825 movb $0, (%edx) 826 subl 12(%ebp), %eax 8277: 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) 837VG_(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) 851VG_(trampoline_stuff_start): 852 853.globl VG_(amd64_darwin_SUBST_FOR_sigreturn) 854VG_(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) 862VG_(amd64_darwin_REDIR_FOR_strlen): 863 movq %rdi, %rax 864 jmp 1f 8650: 866 incq %rax 8671: 868 cmpb $0, (%rax) 869 jne 0b 870 subq %rdi, %rax 871 ret 872 873.globl VG_(amd64_darwin_REDIR_FOR_strcat) 874VG_(amd64_darwin_REDIR_FOR_strcat): 875 movq %rdi, %rdx 876 jmp 1f 8770: 878 incq %rdx 8791: 880 cmpb $0, (%rdx) 881 jne 0b 8822: 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) 894VG_(amd64_darwin_REDIR_FOR_strcmp): 895 jmp 1f 8960: 897 incq %rdi 898 incq %rsi 8991: 900 movzbl (%rdi), %eax 901 testb %al, %al 902 je 2f 903 cmpb (%rsi), %al 904 je 0b 9052: 906 movzbl (%rsi), %edx 907 movzbl %al, %eax 908 subl %edx, %eax 909 ret 910 911.globl VG_(amd64_darwin_REDIR_FOR_strcpy) 912VG_(amd64_darwin_REDIR_FOR_strcpy): 913 pushq %rbp 914 movq %rdi, %rdx 915 movq %rsp, %rbp 916 jmp 1f 9170: 918 incq %rsi 919 incq %rdx 9201: 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) 930VG_(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 9380: 939 incq %rcx 9401: 941 cmpq %rcx, %rax 942 je 2f 943 cmpb $0, (%rcx) 944 jne 0b 9452: 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 9533: 954 movq %rsi, %rdi 955 call VG_(amd64_darwin_REDIR_FOR_strlen) 956 jmp 7f 9574: 958 cmpq $1, %rdi 959 je 5f 960 movb %dl, (%rcx) 961 decq %rdi 962 incq %rcx 9635: 964 incq %rax 9656: 966 movzbl (%rax), %edx 967 testb %dl, %dl 968 jne 4b 969 movb $0, (%rcx) 970 subq %rsi, %rax 9717: 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) 979VG_(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) 985VG_(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) 999VG_(trampoline_stuff_start): 1000 1001.global VG_(s390x_linux_SUBST_FOR_sigreturn) 1002VG_(s390x_linux_SUBST_FOR_sigreturn): 1003 svc __NR_sigreturn 1004 .short 0 1005 1006.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn) 1007VG_(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) 1021VG_(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) 1036VG_(trampoline_stuff_start): 1037 1038.global VG_(mips32_linux_SUBST_FOR_sigreturn) 1039VG_(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) 1046VG_(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 1058VG_(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) 1073VG_(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