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@acm.org 12 Copyright (C) 2006-2013 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/*---------------- 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) 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/*---------------- 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) 698VG_(trampoline_stuff_start): 699 700.global VG_(arm64_linux_SUBST_FOR_rt_sigreturn) 701.type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function 702VG_(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 711VG_(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 728VG_(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 747VG_(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) 771VG_(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) 791VG_(trampoline_stuff_start): 792 793.globl VG_(x86_darwin_SUBST_FOR_sigreturn) 794VG_(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) 802VG_(x86_darwin_REDIR_FOR_strlen): 803 movl 4(%esp), %edx 804 movl %edx, %eax 805 jmp 1f 8060: 807 incl %eax 8081: 809 cmpb $0, (%eax) 810 jne 0b 811 subl %edx, %eax 812 ret 813 814.globl VG_(x86_darwin_REDIR_FOR_strcat) 815VG_(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 8210: 822 incl %edx 8231: 824 cmpb $0, (%edx) 825 jne 0b 8262: 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) 839VG_(x86_darwin_REDIR_FOR_strcmp): 840 movl 4(%esp), %edx 841 movl 8(%esp), %ecx 842 jmp 1f 8430: 844 incl %edx 845 incl %ecx 8461: 847 movzbl (%edx), %eax 848 testb %al, %al 849 je 2f 850 cmpb (%ecx), %al 851 je 0b 8522: 853 movzbl (%ecx),%edx 854 movzbl %al,%eax 855 subl %edx, %eax 856 ret 857 858 859.globl VG_(x86_darwin_REDIR_FOR_strcpy) 860VG_(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 8680: 869 incl %ecx 870 incl %edx 8711: 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) 882VG_(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 8930: 894 incl %edx 8951: 896 cmpl %edx, %eax 897 je 2f 898 cmpb $0, (%edx) 899 jne 0b 9002: 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 9083: 909 movl 12(%ebp), %eax 910 movl %eax, (%esp) 911 call VG_(x86_darwin_REDIR_FOR_strlen) 912 jmp 7f 9134: 914 cmpl $1, %esi 915 je 5f 916 movb %cl, (%edx) 917 decl %esi 918 incl %edx 9195: 920 incl %eax 9216: 922 movzbl (%eax), %ecx 923 testb %cl, %cl 924 jne 4b 925 movb $0, (%edx) 926 subl 12(%ebp), %eax 9277: 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) 937VG_(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) 951VG_(trampoline_stuff_start): 952 953.globl VG_(amd64_darwin_SUBST_FOR_sigreturn) 954VG_(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) 962VG_(amd64_darwin_REDIR_FOR_strlen): 963 movq %rdi, %rax 964 jmp 1f 9650: 966 incq %rax 9671: 968 cmpb $0, (%rax) 969 jne 0b 970 subq %rdi, %rax 971 ret 972 973.globl VG_(amd64_darwin_REDIR_FOR_strcat) 974VG_(amd64_darwin_REDIR_FOR_strcat): 975 movq %rdi, %rdx 976 jmp 1f 9770: 978 incq %rdx 9791: 980 cmpb $0, (%rdx) 981 jne 0b 9822: 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) 994VG_(amd64_darwin_REDIR_FOR_strcmp): 995 jmp 1f 9960: 997 incq %rdi 998 incq %rsi 9991: 1000 movzbl (%rdi), %eax 1001 testb %al, %al 1002 je 2f 1003 cmpb (%rsi), %al 1004 je 0b 10052: 1006 movzbl (%rsi), %edx 1007 movzbl %al, %eax 1008 subl %edx, %eax 1009 ret 1010 1011.globl VG_(amd64_darwin_REDIR_FOR_strcpy) 1012VG_(amd64_darwin_REDIR_FOR_strcpy): 1013 pushq %rbp 1014 movq %rdi, %rdx 1015 movq %rsp, %rbp 1016 jmp 1f 10170: 1018 incq %rsi 1019 incq %rdx 10201: 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) 1030VG_(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 10380: 1039 incq %rcx 10401: 1041 cmpq %rcx, %rax 1042 je 2f 1043 cmpb $0, (%rcx) 1044 jne 0b 10452: 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 10533: 1054 movq %rsi, %rdi 1055 call VG_(amd64_darwin_REDIR_FOR_strlen) 1056 jmp 7f 10574: 1058 cmpq $1, %rdi 1059 je 5f 1060 movb %dl, (%rcx) 1061 decq %rdi 1062 incq %rcx 10635: 1064 incq %rax 10656: 1066 movzbl (%rax), %edx 1067 testb %dl, %dl 1068 jne 4b 1069 movb $0, (%rcx) 1070 subq %rsi, %rax 10717: 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) 1079VG_(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) 1085VG_(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) 1099VG_(trampoline_stuff_start): 1100 1101.global VG_(s390x_linux_SUBST_FOR_sigreturn) 1102VG_(s390x_linux_SUBST_FOR_sigreturn): 1103 svc __NR_sigreturn 1104 .short 0 1105 1106.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn) 1107VG_(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) 1121VG_(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) 1136VG_(trampoline_stuff_start): 1137 1138.global VG_(mips32_linux_SUBST_FOR_sigreturn) 1139VG_(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) 1146VG_(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 1158VG_(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) 1173VG_(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) 1193VG_(trampoline_stuff_start): 1194 1195.global VG_(mips64_linux_SUBST_FOR_rt_sigreturn) 1196VG_(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 1208VG_(mips64_linux_REDIR_FOR_strlen): 1209 lbu $12, 0($4) 1210 li $13, 0 1211 beq $12, $0, M01 1212 nop 1213 1214M02: 1215 addiu $13, $13, 1 1216 addiu $4, $4, 1 1217 lbu $12, 0($4) 1218 bne $12, $0, M02 1219 nop 1220 1221M01: 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) 1229VG_(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