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-2013 Julian Seward 11 jseward (at) acm.org 12 Copyright (C) 2006-2013 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 /*---------------- arm-linux ----------------*/ 523 #else 524 #if 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 /*---------------- arm64-linux ----------------*/ 684 #else 685 #if defined(VGP_arm64_linux) 686 687 # define UD2_4 .word 0xFFFFFFFF 688 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4 689 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 690 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 691 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 692 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 693 694 /* a leading page of unexecutable code */ 695 UD2_PAGE 696 697 .global VG_(trampoline_stuff_start) 698 VG_(trampoline_stuff_start): 699 700 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn) 701 .type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function 702 VG_(arm64_linux_SUBST_FOR_rt_sigreturn): 703 mov x8, # __NR_rt_sigreturn 704 svc #0 705 .long 0xFFFFFFFF /*illegal insn*/ 706 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \ 707 .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn) 708 709 .global VG_(arm64_linux_REDIR_FOR_strlen) 710 .type VG_(arm64_linux_REDIR_FOR_strlen),#function 711 VG_(arm64_linux_REDIR_FOR_strlen): 712 mov x2, x0 713 ldrb w0, [x0] 714 cbz w0, .L5 715 mov x0, 0 716 .L4: 717 add x0, x0, 1 718 ldrb w1, [x2,x0] 719 cbnz w1, .L4 720 ret 721 .L5: 722 mov x0, 0 723 ret 724 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen) 725 726 .global VG_(arm64_linux_REDIR_FOR_index) 727 .type VG_(arm64_linux_REDIR_FOR_index),#function 728 VG_(arm64_linux_REDIR_FOR_index): 729 ldrb w2, [x0] 730 uxtb w1, w1 731 cmp w2, w1 732 beq .L11 733 .L13: 734 cbz w2, .L16 735 ldrb w2, [x0,1]! 736 cmp w2, w1 737 bne .L13 738 .L11: 739 ret 740 .L16: 741 mov x0, 0 742 ret 743 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index) 744 745 .global VG_(arm64_linux_REDIR_FOR_strcmp) 746 .type VG_(arm64_linux_REDIR_FOR_strcmp),#function 747 VG_(arm64_linux_REDIR_FOR_strcmp): 748 ldrb w2, [x0] 749 ldrb w3, [x1] 750 cmp w2, w3 751 bcc .L22 752 .L21: 753 bhi .L25 754 cbz w2, .L26 755 ldrb w2, [x0,1]! 756 ldrb w3, [x1,1]! 757 cmp w2, w3 758 bcs .L21 759 .L22: 760 mov x0, -1 761 ret 762 .L25: 763 mov x0, 1 764 ret 765 .L26: 766 mov x0, 0 767 ret 768 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp) 769 770 .global VG_(trampoline_stuff_end) 771 VG_(trampoline_stuff_end): 772 773 /* and a trailing page of unexecutable code */ 774 UD2_PAGE 775 776 # undef UD2_4 777 # undef UD2_16 778 # undef UD2_64 779 # undef UD2_256 780 # undef UD2_1024 781 # undef UD2_PAGE 782 783 /*---------------- x86-darwin ----------------*/ 784 #else 785 #if defined(VGP_x86_darwin) 786 787 /* a leading page of unexecutable code */ 788 .fill 2048, 2, 0x0b0f /* `ud2` */ 789 790 .globl VG_(trampoline_stuff_start) 791 VG_(trampoline_stuff_start): 792 793 .globl VG_(x86_darwin_SUBST_FOR_sigreturn) 794 VG_(x86_darwin_SUBST_FOR_sigreturn): 795 /* XXX does this need to have any special form? (cf x86-linux 796 version) */ 797 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax 798 int $0x80 799 ud2 800 801 .globl VG_(x86_darwin_REDIR_FOR_strlen) 802 VG_(x86_darwin_REDIR_FOR_strlen): 803 movl 4(%esp), %edx 804 movl %edx, %eax 805 jmp 1f 806 0: 807 incl %eax 808 1: 809 cmpb $0, (%eax) 810 jne 0b 811 subl %edx, %eax 812 ret 813 814 .globl VG_(x86_darwin_REDIR_FOR_strcat) 815 VG_(x86_darwin_REDIR_FOR_strcat): 816 pushl %esi 817 movl 8(%esp), %esi 818 movl 12(%esp), %ecx 819 movl %esi, %edx 820 jmp 1f 821 0: 822 incl %edx 823 1: 824 cmpb $0, (%edx) 825 jne 0b 826 2: 827 movzbl (%ecx), %eax 828 incl %ecx 829 movb %al, (%edx) 830 incl %edx 831 testb %al, %al 832 jne 2b 833 movl %esi, %eax 834 popl %esi 835 ret 836 837 838 .globl VG_(x86_darwin_REDIR_FOR_strcmp) 839 VG_(x86_darwin_REDIR_FOR_strcmp): 840 movl 4(%esp), %edx 841 movl 8(%esp), %ecx 842 jmp 1f 843 0: 844 incl %edx 845 incl %ecx 846 1: 847 movzbl (%edx), %eax 848 testb %al, %al 849 je 2f 850 cmpb (%ecx), %al 851 je 0b 852 2: 853 movzbl (%ecx),%edx 854 movzbl %al,%eax 855 subl %edx, %eax 856 ret 857 858 859 .globl VG_(x86_darwin_REDIR_FOR_strcpy) 860 VG_(x86_darwin_REDIR_FOR_strcpy): 861 pushl %ebp 862 movl %esp, %ebp 863 pushl %esi 864 movl 8(%ebp), %esi 865 movl 12(%ebp), %ecx 866 movl %esi, %edx 867 jmp 1f 868 0: 869 incl %ecx 870 incl %edx 871 1: 872 movzbl (%ecx), %eax 873 testb %al, %al 874 movb %al, (%edx) 875 jne 0b 876 movl %esi, %eax 877 popl %esi 878 leave 879 ret 880 881 .globl VG_(x86_darwin_REDIR_FOR_strlcat) 882 VG_(x86_darwin_REDIR_FOR_strlcat): 883 pushl %ebp 884 movl %esp, %ebp 885 pushl %edi 886 pushl %esi 887 subl $16, %esp 888 movl 8(%ebp), %esi 889 movl 16(%ebp), %ecx 890 movl %esi, %edx 891 leal (%ecx,%esi), %eax 892 jmp 1f 893 0: 894 incl %edx 895 1: 896 cmpl %edx, %eax 897 je 2f 898 cmpb $0, (%edx) 899 jne 0b 900 2: 901 movl %edx, %edi 902 subl %esi, %edi 903 movl %ecx, %esi 904 subl %edi, %esi 905 je 3f 906 movl 12(%ebp), %eax 907 jmp 6f 908 3: 909 movl 12(%ebp), %eax 910 movl %eax, (%esp) 911 call VG_(x86_darwin_REDIR_FOR_strlen) 912 jmp 7f 913 4: 914 cmpl $1, %esi 915 je 5f 916 movb %cl, (%edx) 917 decl %esi 918 incl %edx 919 5: 920 incl %eax 921 6: 922 movzbl (%eax), %ecx 923 testb %cl, %cl 924 jne 4b 925 movb $0, (%edx) 926 subl 12(%ebp), %eax 927 7: 928 addl $16, %esp 929 leal (%edi,%eax), %eax 930 popl %esi 931 popl %edi 932 leave 933 ret 934 935 936 .globl VG_(trampoline_stuff_end) 937 VG_(trampoline_stuff_end): 938 939 /* a trailing page of unexecutable code */ 940 .fill 2048, 2, 0x0b0f /* `ud2` */ 941 942 943 /*---------------- amd64-darwin ----------------*/ 944 #else 945 #if defined(VGP_amd64_darwin) 946 947 /* a leading page of unexecutable code */ 948 .fill 2048, 2, 0x0b0f /* `ud2` */ 949 950 .globl VG_(trampoline_stuff_start) 951 VG_(trampoline_stuff_start): 952 953 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn) 954 VG_(amd64_darwin_SUBST_FOR_sigreturn): 955 /* XXX does this need to have any special form? (cf x86-linux 956 version) */ 957 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax 958 syscall 959 ud2 960 961 .globl VG_(amd64_darwin_REDIR_FOR_strlen) 962 VG_(amd64_darwin_REDIR_FOR_strlen): 963 movq %rdi, %rax 964 jmp 1f 965 0: 966 incq %rax 967 1: 968 cmpb $0, (%rax) 969 jne 0b 970 subq %rdi, %rax 971 ret 972 973 .globl VG_(amd64_darwin_REDIR_FOR_strcat) 974 VG_(amd64_darwin_REDIR_FOR_strcat): 975 movq %rdi, %rdx 976 jmp 1f 977 0: 978 incq %rdx 979 1: 980 cmpb $0, (%rdx) 981 jne 0b 982 2: 983 movzbl (%rsi), %eax 984 incq %rsi 985 movb %al, (%rdx) 986 incq %rdx 987 testb %al, %al 988 jne 2b 989 movq %rdi, %rax 990 ret 991 992 993 .globl VG_(amd64_darwin_REDIR_FOR_strcmp) 994 VG_(amd64_darwin_REDIR_FOR_strcmp): 995 jmp 1f 996 0: 997 incq %rdi 998 incq %rsi 999 1: 1000 movzbl (%rdi), %eax 1001 testb %al, %al 1002 je 2f 1003 cmpb (%rsi), %al 1004 je 0b 1005 2: 1006 movzbl (%rsi), %edx 1007 movzbl %al, %eax 1008 subl %edx, %eax 1009 ret 1010 1011 .globl VG_(amd64_darwin_REDIR_FOR_strcpy) 1012 VG_(amd64_darwin_REDIR_FOR_strcpy): 1013 pushq %rbp 1014 movq %rdi, %rdx 1015 movq %rsp, %rbp 1016 jmp 1f 1017 0: 1018 incq %rsi 1019 incq %rdx 1020 1: 1021 movzbl (%rsi), %eax 1022 testb %al, %al 1023 movb %al, (%rdx) 1024 jne 0b 1025 leave 1026 movq %rdi, %rax 1027 ret 1028 1029 .globl VG_(amd64_darwin_REDIR_FOR_strlcat) 1030 VG_(amd64_darwin_REDIR_FOR_strlcat): 1031 pushq %rbp 1032 leaq (%rdx,%rdi), %rax 1033 movq %rdi, %rcx 1034 movq %rsp, %rbp 1035 pushq %rbx 1036 subq $8, %rsp 1037 jmp 1f 1038 0: 1039 incq %rcx 1040 1: 1041 cmpq %rcx, %rax 1042 je 2f 1043 cmpb $0, (%rcx) 1044 jne 0b 1045 2: 1046 movq %rcx, %rbx 1047 subq %rdi, %rbx 1048 movq %rdx, %rdi 1049 subq %rbx, %rdi 1050 je 3f 1051 movq %rsi, %rax 1052 jmp 6f 1053 3: 1054 movq %rsi, %rdi 1055 call VG_(amd64_darwin_REDIR_FOR_strlen) 1056 jmp 7f 1057 4: 1058 cmpq $1, %rdi 1059 je 5f 1060 movb %dl, (%rcx) 1061 decq %rdi 1062 incq %rcx 1063 5: 1064 incq %rax 1065 6: 1066 movzbl (%rax), %edx 1067 testb %dl, %dl 1068 jne 4b 1069 movb $0, (%rcx) 1070 subq %rsi, %rax 1071 7: 1072 leaq (%rbx,%rax), %rax 1073 addq $8, %rsp 1074 popq %rbx 1075 leave 1076 ret 1077 1078 .globl VG_(amd64_darwin_REDIR_FOR_arc4random) 1079 VG_(amd64_darwin_REDIR_FOR_arc4random): 1080 /* not very random, hope dyld won't mind */ 1081 movq $0x76616c6772696e64, %rax 1082 ret 1083 1084 .globl VG_(trampoline_stuff_end) 1085 VG_(trampoline_stuff_end): 1086 1087 /* a trailing page of unexecutable code */ 1088 .fill 2048, 2, 0x0b0f /* `ud2` */ 1089 1090 1091 /*---------------- s390x-linux ----------------*/ 1092 #else 1093 #if defined(VGP_s390x_linux) 1094 1095 /* a leading page of unexecutable code */ 1096 .fill 2048, 2, 0x0000 1097 1098 .global VG_(trampoline_stuff_start) 1099 VG_(trampoline_stuff_start): 1100 1101 .global VG_(s390x_linux_SUBST_FOR_sigreturn) 1102 VG_(s390x_linux_SUBST_FOR_sigreturn): 1103 svc __NR_sigreturn 1104 .short 0 1105 1106 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn) 1107 VG_(s390x_linux_SUBST_FOR_rt_sigreturn): 1108 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then 1109 for ra = cfa to decide if it is a sig_rt_frame or not. Since we 1110 set ra to this trampoline, but the cfa is still in the stack, 1111 the unwinder thinks, that this is a non-rt frame and causes a 1112 crash in the gcc unwinder - which is used by the thread library 1113 and others. Therefore we add a lr 1,1 nop, to let the gcc 1114 unwinder bail out gracefully. This might also affect unwinding 1115 across the signal frame - tough luck. fixs390 */ 1116 lr 1,1 1117 svc __NR_rt_sigreturn 1118 .short 0 1119 1120 .globl VG_(trampoline_stuff_end) 1121 VG_(trampoline_stuff_end): 1122 .fill 2048, 2, 0x0000 1123 1124 /*---------------------- mips32-linux ----------------------*/ 1125 #else 1126 #if defined(VGP_mips32_linux) 1127 1128 # define UD2_16 trap ; trap ; trap; trap 1129 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 1130 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 1131 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 1132 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 1133 1134 1135 .global VG_(trampoline_stuff_start) 1136 VG_(trampoline_stuff_start): 1137 1138 .global VG_(mips32_linux_SUBST_FOR_sigreturn) 1139 VG_(mips32_linux_SUBST_FOR_sigreturn): 1140 li $v0,__NR_sigreturn 1141 syscall 1142 nop 1143 .long 0 /*illegal insn*/ 1144 1145 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn) 1146 VG_(mips32_linux_SUBST_FOR_rt_sigreturn): 1147 li $v0,__NR_rt_sigreturn 1148 syscall 1149 nop 1150 .long 0 /*illegal insn*/ 1151 1152 /* There's no particular reason that this needs to be handwritten 1153 assembly, but since that's what this file contains, here's a 1154 simple strlen implementation (written in C and compiled by gcc.) 1155 */ 1156 .global VG_(mips32_linux_REDIR_FOR_strlen) 1157 .type VG_(mips32_linux_REDIR_FOR_strlen), @function 1158 VG_(mips32_linux_REDIR_FOR_strlen): 1159 li $v0, 0 1160 //la $a0, string 1161 j strlen_cond 1162 strlen_loop: 1163 addi $v0, $v0, 1 1164 addi $a0, $a0, 1 1165 strlen_cond: 1166 lbu $t0, ($a0) 1167 bne $t0, $zero, strlen_loop 1168 jr $ra 1169 1170 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen) 1171 1172 .global VG_(trampoline_stuff_end) 1173 VG_(trampoline_stuff_end): 1174 1175 1176 # undef UD2_16 1177 # undef UD2_64 1178 # undef UD2_256 1179 # undef UD2_1024 1180 # undef UD2_PAGE 1181 1182 /*---------------------- mips64-linux ----------------------*/ 1183 #else 1184 #if defined(VGP_mips64_linux) 1185 1186 # define UD2_16 trap ; trap ; trap; trap 1187 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 1188 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 1189 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 1190 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 1191 1192 .global VG_(trampoline_stuff_start) 1193 VG_(trampoline_stuff_start): 1194 1195 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn) 1196 VG_(mips64_linux_SUBST_FOR_rt_sigreturn): 1197 li $2,__NR_rt_sigreturn 1198 syscall 1199 nop 1200 .long 0 /*illegal insn*/ 1201 1202 /* There's no particular reason that this needs to be handwritten 1203 assembly, but since that's what this file contains, here's a 1204 simple strlen implementation (written in C and compiled by gcc.) 1205 */ 1206 .global VG_(mips64_linux_REDIR_FOR_strlen) 1207 .type VG_(mips64_linux_REDIR_FOR_strlen), @function 1208 VG_(mips64_linux_REDIR_FOR_strlen): 1209 lbu $12, 0($4) 1210 li $13, 0 1211 beq $12, $0, M01 1212 nop 1213 1214 M02: 1215 addiu $13, $13, 1 1216 addiu $4, $4, 1 1217 lbu $12, 0($4) 1218 bne $12, $0, M02 1219 nop 1220 1221 M01: 1222 move $2, $13 1223 jr $31 1224 nop 1225 1226 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen) 1227 1228 .global VG_(trampoline_stuff_end) 1229 VG_(trampoline_stuff_end): 1230 1231 1232 # undef UD2_16 1233 # undef UD2_64 1234 # undef UD2_256 1235 # undef UD2_1024 1236 # undef UD2_PAGE 1237 1238 /*---------------- unknown ----------------*/ 1239 #else 1240 # error Unknown platform 1241 1242 #endif 1243 #endif 1244 #endif 1245 #endif 1246 #endif 1247 #endif 1248 #endif 1249 #endif 1250 #endif 1251 #endif 1252 #endif 1253 1254 #if defined(VGO_linux) 1255 /* Let the linker know we don't need an executable stack */ 1256 # if defined(VGP_arm_linux) 1257 .section .note.GNU-stack,"",%progbits 1258 # else 1259 .section .note.GNU-stack,"",@progbits 1260 # endif 1261 #endif 1262 1263 /*--------------------------------------------------------------------*/ 1264 /*--- end ---*/ 1265 /*--------------------------------------------------------------------*/ 1266