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-2015 Julian Seward 11 jseward (at) acm.org 12 Copyright (C) 2006-2015 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_ppc64be_linux) || defined(VGP_ppc64le_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 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2 448 /* Little Endian uses ELF version 2 */ 449 .type VG_(ppc64_linux_REDIR_FOR_strlen),@function 450 VG_(ppc64_linux_REDIR_FOR_strlen): 451 #else 452 /* Big Endian uses ELF version 1 */ 453 .section ".opd","aw" 454 .align 3 455 VG_(ppc64_linux_REDIR_FOR_strlen): 456 .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0 457 .previous 458 .size VG_(ppc64_linux_REDIR_FOR_strlen), \ 459 .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen) 460 .type VG_(ppc64_linux_REDIR_FOR_strlen), @function 461 462 .L.VG_(ppc64_linux_REDIR_FOR_strlen): 463 #endif 464 #if _CALL_ELF == 2 465 0: addis 2,12,.TOC.-0b@ha 466 addi 2,2,.TOC.-0b@l 467 .localentry VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen) 468 #endif 469 mr 9,3 470 lbz 0,0(3) 471 li 3,0 472 cmpwi 7,0,0 473 beqlr 7 474 li 3,0 475 .L01: 476 addi 0,3,1 477 extsw 3,0 478 lbzx 0,9,3 479 cmpwi 7,0,0 480 bne 7,.L01 481 blr 482 483 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2 484 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen) 485 #else 486 .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen) 487 #endif 488 .long 0 489 .byte 0,0,0,0,0,0,0,0 490 .L0end: 491 492 /* this function is written using the "dotless" ABI convention */ 493 .align 2 494 .globl VG_(ppc64_linux_REDIR_FOR_strchr) 495 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2 496 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function 497 VG_(ppc64_linux_REDIR_FOR_strchr): 498 #else 499 .section ".opd","aw" 500 .align 3 501 VG_(ppc64_linux_REDIR_FOR_strchr): 502 .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0 503 .previous 504 .size VG_(ppc64_linux_REDIR_FOR_strchr), \ 505 .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr) 506 .type VG_(ppc64_linux_REDIR_FOR_strchr),@function 507 508 .L.VG_(ppc64_linux_REDIR_FOR_strchr): 509 #endif 510 #if _CALL_ELF == 2 511 0: addis 2,12,.TOC.-0b@ha 512 addi 2,2,.TOC.-0b@l 513 .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr) 514 #endif 515 lbz 0,0(3) 516 rldicl 4,4,0,56 517 cmpw 7,4,0 518 beqlr 7 519 cmpdi 7,0,0 520 bne 7,.L18 521 b .L14 522 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2 523 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr) 524 #else 525 .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr) 526 #endif 527 .L19: 528 beq 6,.L14 529 .L18: 530 lbzu 0,1(3) 531 cmpw 7,4,0 532 cmpdi 6,0,0 533 bne 7,.L19 534 blr 535 .L14: 536 li 3,0 537 blr 538 .long 0 539 .byte 0,0,0,0,0,0,0,0 540 .L1end: 541 542 543 .global VG_(trampoline_stuff_end) 544 VG_(trampoline_stuff_end): 545 546 /* and a trailing page of unexecutable code */ 547 UD2_PAGE 548 549 # undef UD2_16 550 # undef UD2_64 551 # undef UD2_256 552 # undef UD2_1024 553 # undef UD2_PAGE 554 555 /*---------------- arm-linux ----------------*/ 556 #else 557 #if defined(VGP_arm_linux) 558 559 # define UD2_4 .word 0xFFFFFFFF 560 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4 561 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 562 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 563 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 564 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 565 566 /* a leading page of unexecutable code */ 567 UD2_PAGE 568 569 .global VG_(trampoline_stuff_start) 570 VG_(trampoline_stuff_start): 571 572 .global VG_(arm_linux_SUBST_FOR_sigreturn) 573 .type VG_(arm_linux_SUBST_FOR_sigreturn),#function 574 VG_(arm_linux_SUBST_FOR_sigreturn): 575 mov r7, # __NR_sigreturn 576 svc #0 577 .long 0xFFFFFFFF /*illegal insn*/ 578 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn) 579 580 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn) 581 .type VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function 582 VG_(arm_linux_SUBST_FOR_rt_sigreturn): 583 mov r7, # __NR_rt_sigreturn 584 svc #0 585 .long 0xFFFFFFFF /*illegal insn*/ 586 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn) 587 588 .global VG_(arm_linux_REDIR_FOR_strlen) 589 VG_(arm_linux_REDIR_FOR_strlen): 590 mov r2, r0 591 ldrb r0, [r0, #0] @ zero_extendqisi2 592 @ lr needed for prologue 593 cmp r0, #0 594 bxeq lr 595 mov r0, #0 596 .L5: 597 add r0, r0, #1 598 ldrb r3, [r0, r2] @ zero_extendqisi2 599 cmp r3, #0 600 bne .L5 601 bx lr 602 UD2_4 603 604 //.global VG_(arm_linux_REDIR_FOR_index) 605 //VG_(arm_linux_REDIR_FOR_index): 606 // ldrb r3, [r0, #0] @ zero_extendqisi2 607 // and r1, r1, #255 608 // cmp r3, r1 609 // @ lr needed for prologue 610 // bne .L9 611 // bx lr 612 //.L12: 613 // ldrb r3, [r0, #1]! @ zero_extendqisi2 614 // cmp r3, r1 615 // beq .L11 616 //.L9: 617 // cmp r3, #0 618 // bne .L12 619 // mov r0, #0 620 // bx lr 621 //.L11: 622 // bx lr 623 // UD2_4 624 625 .global VG_(arm_linux_REDIR_FOR_memcpy) 626 VG_(arm_linux_REDIR_FOR_memcpy): 627 stmfd sp!, {r4, r5, lr} 628 subs lr, r2, #0 629 mov r5, r0 630 beq .L2 631 cmp r0, r1 632 bls .L4 633 add r3, r0, lr 634 add r1, lr, r1 635 cmp lr, #3 636 sub r4, r3, #1 637 sub r0, r1, #1 638 ble .L28 639 sub ip, r3, #5 640 sub r1, r1, #5 641 .L8: 642 ldrb r3, [r1, #4] @ zero_extendqisi2 643 sub lr, lr, #4 644 strb r3, [ip, #4] 645 ldrb r2, [r1, #3] @ zero_extendqisi2 646 cmp lr, #3 647 strb r2, [ip, #3] 648 ldrb r3, [r1, #2] @ zero_extendqisi2 649 mov r4, ip 650 strb r3, [ip, #2] 651 ldrb r2, [r1, #1] @ zero_extendqisi2 652 mov r0, r1 653 strb r2, [ip, #1] 654 sub r1, r1, #4 655 sub ip, ip, #4 656 bgt .L8 657 cmp lr, #0 658 beq .L2 659 .L28: 660 sub r2, lr, #1 661 .L21: 662 sub r2, r2, #1 663 ldrb r3, [r0], #-1 @ zero_extendqisi2 664 cmn r2, #1 665 strb r3, [r4], #-1 666 bne .L21 667 .L2: 668 mov r0, r5 669 ldmfd sp!, {r4, r5, pc} 670 .L4: 671 bcs .L2 672 cmp lr, #3 673 mov ip, r0 674 ble .L29 675 .L19: 676 ldrb r3, [r1, #0] @ zero_extendqisi2 677 sub lr, lr, #4 678 strb r3, [ip, #0] 679 ldrb r2, [r1, #1] @ zero_extendqisi2 680 cmp lr, #3 681 strb r2, [ip, #1] 682 ldrb r3, [r1, #2] @ zero_extendqisi2 683 strb r3, [ip, #2] 684 ldrb r2, [r1, #3] @ zero_extendqisi2 685 add r1, r1, #4 686 strb r2, [ip, #3] 687 add ip, ip, #4 688 bgt .L19 689 cmp lr, #0 690 beq .L2 691 .L29: 692 sub r2, lr, #1 693 .L20: 694 sub r2, r2, #1 695 ldrb r3, [r1], #1 @ zero_extendqisi2 696 cmn r2, #1 697 strb r3, [ip], #1 698 bne .L20 699 mov r0, r5 700 ldmfd sp!, {r4, r5, pc} 701 UD2_4 702 703 .global VG_(arm_linux_REDIR_FOR_strcmp) 704 VG_(arm_linux_REDIR_FOR_strcmp): 705 .L64: 706 ldrb r3, [r0], #1 @ zero_extendqisi2 707 ldrb r2, [r1], #1 @ zero_extendqisi2 708 cmp r3, #0 709 beq .L67 710 cmp r3, r2 711 beq .L64 712 rsb r0, r2, r3 713 bx lr 714 .L67: 715 rsb r0, r2, #0 716 bx lr 717 UD2_4 718 719 .global VG_(trampoline_stuff_end) 720 VG_(trampoline_stuff_end): 721 722 /* and a trailing page of unexecutable code */ 723 UD2_PAGE 724 725 # undef UD2_4 726 # undef UD2_16 727 # undef UD2_64 728 # undef UD2_256 729 # undef UD2_1024 730 # undef UD2_PAGE 731 732 /*---------------- arm64-linux ----------------*/ 733 #else 734 #if defined(VGP_arm64_linux) 735 736 # define UD2_4 .word 0xFFFFFFFF 737 # define UD2_16 UD2_4 ; UD2_4 ; UD2_4 ; UD2_4 738 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 739 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 740 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 741 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 742 743 /* a leading page of unexecutable code */ 744 UD2_PAGE 745 746 .global VG_(trampoline_stuff_start) 747 VG_(trampoline_stuff_start): 748 749 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn) 750 .type VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function 751 VG_(arm64_linux_SUBST_FOR_rt_sigreturn): 752 mov x8, # __NR_rt_sigreturn 753 svc #0 754 .long 0xFFFFFFFF /*illegal insn*/ 755 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \ 756 .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn) 757 758 .global VG_(arm64_linux_REDIR_FOR_strlen) 759 .type VG_(arm64_linux_REDIR_FOR_strlen),#function 760 VG_(arm64_linux_REDIR_FOR_strlen): 761 mov x2, x0 762 ldrb w0, [x0] 763 cbz w0, .L5 764 mov x0, 0 765 .L4: 766 add x0, x0, 1 767 ldrb w1, [x2,x0] 768 cbnz w1, .L4 769 ret 770 .L5: 771 mov x0, 0 772 ret 773 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen) 774 775 .global VG_(arm64_linux_REDIR_FOR_index) 776 .type VG_(arm64_linux_REDIR_FOR_index),#function 777 VG_(arm64_linux_REDIR_FOR_index): 778 ldrb w2, [x0] 779 uxtb w1, w1 780 cmp w2, w1 781 beq .L11 782 .L13: 783 cbz w2, .L16 784 ldrb w2, [x0,1]! 785 cmp w2, w1 786 bne .L13 787 .L11: 788 ret 789 .L16: 790 mov x0, 0 791 ret 792 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index) 793 794 .global VG_(arm64_linux_REDIR_FOR_strcmp) 795 .type VG_(arm64_linux_REDIR_FOR_strcmp),#function 796 VG_(arm64_linux_REDIR_FOR_strcmp): 797 ldrb w2, [x0] 798 ldrb w3, [x1] 799 cmp w2, w3 800 bcc .L22 801 .L21: 802 bhi .L25 803 cbz w2, .L26 804 ldrb w2, [x0,1]! 805 ldrb w3, [x1,1]! 806 cmp w2, w3 807 bcs .L21 808 .L22: 809 mov x0, -1 810 ret 811 .L25: 812 mov x0, 1 813 ret 814 .L26: 815 mov x0, 0 816 ret 817 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp) 818 819 .global VG_(trampoline_stuff_end) 820 VG_(trampoline_stuff_end): 821 822 /* and a trailing page of unexecutable code */ 823 UD2_PAGE 824 825 # undef UD2_4 826 # undef UD2_16 827 # undef UD2_64 828 # undef UD2_256 829 # undef UD2_1024 830 # undef UD2_PAGE 831 832 /*---------------- x86-darwin ----------------*/ 833 #else 834 #if defined(VGP_x86_darwin) 835 836 /* a leading page of unexecutable code */ 837 .fill 2048, 2, 0x0b0f /* `ud2` */ 838 839 .globl VG_(trampoline_stuff_start) 840 VG_(trampoline_stuff_start): 841 842 .globl VG_(x86_darwin_SUBST_FOR_sigreturn) 843 VG_(x86_darwin_SUBST_FOR_sigreturn): 844 /* XXX does this need to have any special form? (cf x86-linux 845 version) */ 846 movl $ __NR_DARWIN_FAKE_SIGRETURN, %eax 847 int $0x80 848 ud2 849 850 .globl VG_(x86_darwin_REDIR_FOR_strlen) 851 VG_(x86_darwin_REDIR_FOR_strlen): 852 movl 4(%esp), %edx 853 movl %edx, %eax 854 jmp 1f 855 0: 856 incl %eax 857 1: 858 cmpb $0, (%eax) 859 jne 0b 860 subl %edx, %eax 861 ret 862 863 .globl VG_(x86_darwin_REDIR_FOR_strcat) 864 VG_(x86_darwin_REDIR_FOR_strcat): 865 pushl %esi 866 movl 8(%esp), %esi 867 movl 12(%esp), %ecx 868 movl %esi, %edx 869 jmp 1f 870 0: 871 incl %edx 872 1: 873 cmpb $0, (%edx) 874 jne 0b 875 2: 876 movzbl (%ecx), %eax 877 incl %ecx 878 movb %al, (%edx) 879 incl %edx 880 testb %al, %al 881 jne 2b 882 movl %esi, %eax 883 popl %esi 884 ret 885 886 887 .globl VG_(x86_darwin_REDIR_FOR_strcmp) 888 VG_(x86_darwin_REDIR_FOR_strcmp): 889 movl 4(%esp), %edx 890 movl 8(%esp), %ecx 891 jmp 1f 892 0: 893 incl %edx 894 incl %ecx 895 1: 896 movzbl (%edx), %eax 897 testb %al, %al 898 je 2f 899 cmpb (%ecx), %al 900 je 0b 901 2: 902 movzbl (%ecx),%edx 903 movzbl %al,%eax 904 subl %edx, %eax 905 ret 906 907 908 .globl VG_(x86_darwin_REDIR_FOR_strcpy) 909 VG_(x86_darwin_REDIR_FOR_strcpy): 910 pushl %ebp 911 movl %esp, %ebp 912 pushl %esi 913 movl 8(%ebp), %esi 914 movl 12(%ebp), %ecx 915 movl %esi, %edx 916 jmp 1f 917 0: 918 incl %ecx 919 incl %edx 920 1: 921 movzbl (%ecx), %eax 922 testb %al, %al 923 movb %al, (%edx) 924 jne 0b 925 movl %esi, %eax 926 popl %esi 927 leave 928 ret 929 930 .globl VG_(x86_darwin_REDIR_FOR_strlcat) 931 VG_(x86_darwin_REDIR_FOR_strlcat): 932 pushl %ebp 933 movl %esp, %ebp 934 pushl %edi 935 pushl %esi 936 subl $16, %esp 937 movl 8(%ebp), %esi 938 movl 16(%ebp), %ecx 939 movl %esi, %edx 940 leal (%ecx,%esi), %eax 941 jmp 1f 942 0: 943 incl %edx 944 1: 945 cmpl %edx, %eax 946 je 2f 947 cmpb $0, (%edx) 948 jne 0b 949 2: 950 movl %edx, %edi 951 subl %esi, %edi 952 movl %ecx, %esi 953 subl %edi, %esi 954 je 3f 955 movl 12(%ebp), %eax 956 jmp 6f 957 3: 958 movl 12(%ebp), %eax 959 movl %eax, (%esp) 960 call VG_(x86_darwin_REDIR_FOR_strlen) 961 jmp 7f 962 4: 963 cmpl $1, %esi 964 je 5f 965 movb %cl, (%edx) 966 decl %esi 967 incl %edx 968 5: 969 incl %eax 970 6: 971 movzbl (%eax), %ecx 972 testb %cl, %cl 973 jne 4b 974 movb $0, (%edx) 975 subl 12(%ebp), %eax 976 7: 977 addl $16, %esp 978 leal (%edi,%eax), %eax 979 popl %esi 980 popl %edi 981 leave 982 ret 983 984 985 .globl VG_(trampoline_stuff_end) 986 VG_(trampoline_stuff_end): 987 988 /* a trailing page of unexecutable code */ 989 .fill 2048, 2, 0x0b0f /* `ud2` */ 990 991 992 /*---------------- amd64-darwin ----------------*/ 993 #else 994 #if defined(VGP_amd64_darwin) 995 996 /* a leading page of unexecutable code */ 997 .fill 2048, 2, 0x0b0f /* `ud2` */ 998 999 .globl VG_(trampoline_stuff_start) 1000 VG_(trampoline_stuff_start): 1001 1002 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn) 1003 VG_(amd64_darwin_SUBST_FOR_sigreturn): 1004 /* XXX does this need to have any special form? (cf x86-linux 1005 version) */ 1006 movq $ __NR_DARWIN_FAKE_SIGRETURN, %rax 1007 syscall 1008 ud2 1009 1010 .globl VG_(amd64_darwin_REDIR_FOR_strlen) 1011 VG_(amd64_darwin_REDIR_FOR_strlen): 1012 movq %rdi, %rax 1013 jmp 1f 1014 0: 1015 incq %rax 1016 1: 1017 cmpb $0, (%rax) 1018 jne 0b 1019 subq %rdi, %rax 1020 ret 1021 1022 .globl VG_(amd64_darwin_REDIR_FOR_strcat) 1023 VG_(amd64_darwin_REDIR_FOR_strcat): 1024 movq %rdi, %rdx 1025 jmp 1f 1026 0: 1027 incq %rdx 1028 1: 1029 cmpb $0, (%rdx) 1030 jne 0b 1031 2: 1032 movzbl (%rsi), %eax 1033 incq %rsi 1034 movb %al, (%rdx) 1035 incq %rdx 1036 testb %al, %al 1037 jne 2b 1038 movq %rdi, %rax 1039 ret 1040 1041 1042 .globl VG_(amd64_darwin_REDIR_FOR_strcmp) 1043 VG_(amd64_darwin_REDIR_FOR_strcmp): 1044 jmp 1f 1045 0: 1046 incq %rdi 1047 incq %rsi 1048 1: 1049 movzbl (%rdi), %eax 1050 testb %al, %al 1051 je 2f 1052 cmpb (%rsi), %al 1053 je 0b 1054 2: 1055 movzbl (%rsi), %edx 1056 movzbl %al, %eax 1057 subl %edx, %eax 1058 ret 1059 1060 .globl VG_(amd64_darwin_REDIR_FOR_strcpy) 1061 VG_(amd64_darwin_REDIR_FOR_strcpy): 1062 pushq %rbp 1063 movq %rdi, %rdx 1064 movq %rsp, %rbp 1065 jmp 1f 1066 0: 1067 incq %rsi 1068 incq %rdx 1069 1: 1070 movzbl (%rsi), %eax 1071 testb %al, %al 1072 movb %al, (%rdx) 1073 jne 0b 1074 leave 1075 movq %rdi, %rax 1076 ret 1077 1078 .globl VG_(amd64_darwin_REDIR_FOR_strlcat) 1079 VG_(amd64_darwin_REDIR_FOR_strlcat): 1080 pushq %rbp 1081 leaq (%rdx,%rdi), %rax 1082 movq %rdi, %rcx 1083 movq %rsp, %rbp 1084 pushq %rbx 1085 subq $8, %rsp 1086 jmp 1f 1087 0: 1088 incq %rcx 1089 1: 1090 cmpq %rcx, %rax 1091 je 2f 1092 cmpb $0, (%rcx) 1093 jne 0b 1094 2: 1095 movq %rcx, %rbx 1096 subq %rdi, %rbx 1097 movq %rdx, %rdi 1098 subq %rbx, %rdi 1099 je 3f 1100 movq %rsi, %rax 1101 jmp 6f 1102 3: 1103 movq %rsi, %rdi 1104 call VG_(amd64_darwin_REDIR_FOR_strlen) 1105 jmp 7f 1106 4: 1107 cmpq $1, %rdi 1108 je 5f 1109 movb %dl, (%rcx) 1110 decq %rdi 1111 incq %rcx 1112 5: 1113 incq %rax 1114 6: 1115 movzbl (%rax), %edx 1116 testb %dl, %dl 1117 jne 4b 1118 movb $0, (%rcx) 1119 subq %rsi, %rax 1120 7: 1121 leaq (%rbx,%rax), %rax 1122 addq $8, %rsp 1123 popq %rbx 1124 leave 1125 ret 1126 1127 .globl VG_(amd64_darwin_REDIR_FOR_arc4random) 1128 VG_(amd64_darwin_REDIR_FOR_arc4random): 1129 /* not very random, hope dyld won't mind */ 1130 movq $0x76616c6772696e64, %rax 1131 ret 1132 1133 .globl VG_(amd64_darwin_REDIR_FOR_strchr) 1134 VG_(amd64_darwin_REDIR_FOR_strchr): 1135 pushq %rbp 1136 movq %rsp, %rbp 1137 movb (%rdi), %cl 1138 cmpb %sil, %cl 1139 jne 1f 1140 movq %rdi, %rax 1141 popq %rbp 1142 ret 1143 1: 1144 testb %cl, %cl 1145 movl $0, %eax 1146 je 2f 1147 movb 1(%rdi), %cl 1148 incq %rdi 1149 cmpb %sil, %cl 1150 movq %rdi, %rax 1151 jne 1b 1152 2: 1153 popq %rbp 1154 ret 1155 1156 .globl VG_(trampoline_stuff_end) 1157 VG_(trampoline_stuff_end): 1158 1159 /* a trailing page of unexecutable code */ 1160 .fill 2048, 2, 0x0b0f /* `ud2` */ 1161 1162 1163 /*---------------- s390x-linux ----------------*/ 1164 #else 1165 #if defined(VGP_s390x_linux) 1166 1167 /* a leading page of unexecutable code */ 1168 .fill 2048, 2, 0x0000 1169 1170 .global VG_(trampoline_stuff_start) 1171 VG_(trampoline_stuff_start): 1172 1173 .global VG_(s390x_linux_SUBST_FOR_sigreturn) 1174 VG_(s390x_linux_SUBST_FOR_sigreturn): 1175 svc __NR_sigreturn 1176 .short 0 1177 1178 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn) 1179 VG_(s390x_linux_SUBST_FOR_rt_sigreturn): 1180 /* Old gcc unwinding code checks for a sig(_rt)_return svc and then 1181 for ra = cfa to decide if it is a sig_rt_frame or not. Since we 1182 set ra to this trampoline, but the cfa is still in the stack, 1183 the unwinder thinks, that this is a non-rt frame and causes a 1184 crash in the gcc unwinder - which is used by the thread library 1185 and others. Therefore we add a lr 1,1 nop, to let the gcc 1186 unwinder bail out gracefully. This might also affect unwinding 1187 across the signal frame - tough luck. fixs390 */ 1188 lr 1,1 1189 svc __NR_rt_sigreturn 1190 .short 0 1191 1192 .global VG_(s390x_linux_REDIR_FOR_index) 1193 .type VG_(s390x_linux_REDIR_FOR_index),@function 1194 VG_(s390x_linux_REDIR_FOR_index): 1195 # 1196 # %r2 = addess of string 1197 # %r3 = character to find 1198 # 1199 lghi %r0,255 1200 ngr %r0,%r3 # r0 = (unsigned char)r3 1201 lghi %r4,0 1202 .L1: 1203 llgc %r1,0(%r2) # r1 = byte from string 1204 cr %r1,%r0 # compare 1205 ber %r14 # return if found 1206 cr %r1,%r4 # end of string ? 1207 je .L2 1208 aghi %r2,1 # increment r2 1209 j .L1 1210 .L2: lghi %r2,0 # return value 0 1211 br %r14 1212 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index) 1213 1214 .globl VG_(trampoline_stuff_end) 1215 VG_(trampoline_stuff_end): 1216 .fill 2048, 2, 0x0000 1217 1218 /*---------------------- mips32-linux ----------------------*/ 1219 #else 1220 #if defined(VGP_mips32_linux) 1221 1222 # define UD2_16 trap ; trap ; trap; trap 1223 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 1224 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 1225 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 1226 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 1227 1228 1229 .global VG_(trampoline_stuff_start) 1230 VG_(trampoline_stuff_start): 1231 1232 .global VG_(mips32_linux_SUBST_FOR_sigreturn) 1233 VG_(mips32_linux_SUBST_FOR_sigreturn): 1234 li $v0,__NR_sigreturn 1235 syscall 1236 nop 1237 .long 0 /*illegal insn*/ 1238 1239 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn) 1240 VG_(mips32_linux_SUBST_FOR_rt_sigreturn): 1241 li $v0,__NR_rt_sigreturn 1242 syscall 1243 nop 1244 .long 0 /*illegal insn*/ 1245 1246 /* There's no particular reason that this needs to be handwritten 1247 assembly, but since that's what this file contains, here's a 1248 simple strlen implementation (written in C and compiled by gcc.) 1249 */ 1250 .global VG_(mips32_linux_REDIR_FOR_strlen) 1251 .type VG_(mips32_linux_REDIR_FOR_strlen), @function 1252 VG_(mips32_linux_REDIR_FOR_strlen): 1253 li $v0, 0 1254 //la $a0, string 1255 j strlen_cond 1256 strlen_loop: 1257 addi $v0, $v0, 1 1258 addi $a0, $a0, 1 1259 strlen_cond: 1260 lbu $t0, ($a0) 1261 bne $t0, $zero, strlen_loop 1262 jr $ra 1263 1264 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen) 1265 1266 .global VG_(trampoline_stuff_end) 1267 VG_(trampoline_stuff_end): 1268 1269 1270 # undef UD2_16 1271 # undef UD2_64 1272 # undef UD2_256 1273 # undef UD2_1024 1274 # undef UD2_PAGE 1275 1276 /*---------------------- mips64-linux ----------------------*/ 1277 #else 1278 #if defined(VGP_mips64_linux) 1279 1280 # define UD2_16 trap ; trap ; trap; trap 1281 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 1282 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 1283 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 1284 # define UD2_PAGE UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 1285 1286 .global VG_(trampoline_stuff_start) 1287 VG_(trampoline_stuff_start): 1288 1289 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn) 1290 VG_(mips64_linux_SUBST_FOR_rt_sigreturn): 1291 li $2,__NR_rt_sigreturn 1292 syscall 1293 nop 1294 .long 0 /*illegal insn*/ 1295 1296 /* There's no particular reason that this needs to be handwritten 1297 assembly, but since that's what this file contains, here's a 1298 simple strlen implementation (written in C and compiled by gcc.) 1299 */ 1300 .global VG_(mips64_linux_REDIR_FOR_strlen) 1301 .type VG_(mips64_linux_REDIR_FOR_strlen), @function 1302 VG_(mips64_linux_REDIR_FOR_strlen): 1303 lbu $12, 0($4) 1304 li $13, 0 1305 beq $12, $0, M01 1306 nop 1307 1308 M02: 1309 addiu $13, $13, 1 1310 addiu $4, $4, 1 1311 lbu $12, 0($4) 1312 bne $12, $0, M02 1313 nop 1314 1315 M01: 1316 move $2, $13 1317 jr $31 1318 nop 1319 1320 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen) 1321 1322 .global VG_(trampoline_stuff_end) 1323 VG_(trampoline_stuff_end): 1324 1325 1326 # undef UD2_16 1327 # undef UD2_64 1328 # undef UD2_256 1329 # undef UD2_1024 1330 # undef UD2_PAGE 1331 1332 /*---------------------- tilegx-linux ----------------------*/ 1333 #else 1334 #if defined(VGP_tilegx_linux) 1335 1336 # define UD2_16 ill ; ill 1337 # define UD2_64 UD2_16 ; UD2_16 ; UD2_16 ; UD2_16 1338 # define UD2_256 UD2_64 ; UD2_64 ; UD2_64 ; UD2_64 1339 # define UD2_1024 UD2_256 ; UD2_256 ; UD2_256 ; UD2_256 1340 # define UD2_4K UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024 1341 # define UD2_16K UD2_4K ; UD2_4K ; UD2_4K ; UD2_4K 1342 # define UD2_PAGE UD2_16K ; UD2_16K ; UD2_16K ; UD2_16K 1343 /* a leading page of unexecutable code */ 1344 UD2_PAGE 1345 1346 .global VG_(trampoline_stuff_start) 1347 VG_(trampoline_stuff_start): 1348 1349 .global VG_(tilegx_linux_SUBST_FOR_rt_sigreturn) 1350 VG_(tilegx_linux_SUBST_FOR_rt_sigreturn): 1351 /* This is a very specific sequence which GDB uses to 1352 recognize signal handler frames. */ 1353 moveli r10, __NR_rt_sigreturn 1354 swint1 1355 ill 1356 1357 .global VG_(tilegx_linux_REDIR_FOR_vgettimeofday) 1358 .type VG_(tilegx_linux_REDIR_FOR_vgettimeofday), @function 1359 VG_(tilegx_linux_REDIR_FOR_vgettimeofday): 1360 moveli r10, __NR_gettimeofday 1361 swint1 1362 jrp lr 1363 .size VG_(tilegx_linux_REDIR_FOR_vgettimeofday), .-VG_(tilegx_linux_REDIR_FOR_vgettimeofday) 1364 1365 .global VG_(tilegx_linux_REDIR_FOR_vtime) 1366 .type VG_(tilegx_linux_REDIR_FOR_vtime), @function 1367 VG_(tilegx_linux_REDIR_FOR_vtime): 1368 moveli r10, __NR_gettimeofday 1369 swint1 1370 jrp lr 1371 .size VG_(tilegx_linux_REDIR_FOR_vtime), .-VG_(tilegx_linux_REDIR_FOR_vtime) 1372 1373 .global VG_(tilegx_linux_REDIR_FOR_strlen) 1374 .type VG_(tilegx_linux_REDIR_FOR_strlen), @function 1375 VG_(tilegx_linux_REDIR_FOR_strlen): 1376 { 1377 movei r1, 0 1378 beqz r0, 2f 1379 } 1380 1: { 1381 addi r1, r1, 1 1382 ld1s_add r2, r0, 1 1383 } 1384 bnezt r2, 1b 1385 addi r1, r1, -1 1386 2: move r0, r1 1387 jrp lr 1388 .size VG_(tilegx_linux_REDIR_FOR_strlen), .-VG_(tilegx_linux_REDIR_FOR_strlen) 1389 1390 .global VG_(trampoline_stuff_end) 1391 VG_(trampoline_stuff_end): 1392 1393 /* and a trailing page of unexecutable code */ 1394 UD2_PAGE 1395 1396 # undef UD2_16 1397 # undef UD2_64 1398 # undef UD2_256 1399 # undef UD2_1024 1400 # undef UD2_4K 1401 # undef UD2_16K 1402 # undef UD2_PAGE 1403 1404 /*---------------- x86-solaris ----------------*/ 1405 #else 1406 #if defined(VGP_x86_solaris) 1407 1408 .global VG_(trampoline_stuff_start) 1409 VG_(trampoline_stuff_start): 1410 1411 /* int strcmp(const char *s1, const char *s2); */ 1412 .global VG_(x86_solaris_REDIR_FOR_strcmp) 1413 .type VG_(x86_solaris_REDIR_FOR_strcmp), @function 1414 VG_(x86_solaris_REDIR_FOR_strcmp): 1415 pushl %ebp /* establish a stack frame */ 1416 movl %esp, %ebp 1417 movl 8(%ebp), %edx /* get s1 */ 1418 movl 12(%esp), %ecx /* get s2 */ 1419 jmp 2f /* go compare the first characters */ 1420 1: 1421 incl %edx /* skip to the next s1 character */ 1422 incl %ecx /* skip to the next s2 character */ 1423 2: 1424 movzbl (%edx), %eax /* load a character from s1 */ 1425 testb %al, %al /* is it null? */ 1426 jz 3f /* yes, exit */ 1427 cmpb (%ecx), %al /* are the characters equal? */ 1428 je 1b /* yes, proceed with next characters */ 1429 3: 1430 movzbl (%ecx), %edx /* load a character from s2 */ 1431 subl %edx, %eax /* calculate the return value */ 1432 popl %ebp /* destroy the stack frame */ 1433 ret /* return to the caller */ 1434 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp) 1435 1436 /* size_t strlen(const char *s); */ 1437 .global VG_(x86_solaris_REDIR_FOR_strlen) 1438 .type VG_(x86_solaris_REDIR_FOR_strlen), @function 1439 VG_(x86_solaris_REDIR_FOR_strlen): 1440 pushl %ebp /* establish a stack frame */ 1441 movl %esp, %ebp 1442 movl 8(%ebp), %edx /* get s */ 1443 movl %edx, %eax /* copy s */ 1444 jmp 2f /* go handle the first character */ 1445 1: 1446 incl %eax /* skip to the next s character */ 1447 2: 1448 cmpb $0, (%eax) /* is the s character null? */ 1449 jne 1b /* no, go process the next character */ 1450 subl %edx, %eax /* calculate the return value */ 1451 popl %ebp /* destroy the stack frame */ 1452 ret /* return to the caller */ 1453 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen) 1454 1455 .global VG_(trampoline_stuff_end) 1456 VG_(trampoline_stuff_end): 1457 1458 /*---------------- amd64-solaris ----------------*/ 1459 #else 1460 #if defined(VGP_amd64_solaris) 1461 1462 .global VG_(trampoline_stuff_start) 1463 VG_(trampoline_stuff_start): 1464 1465 /* char *strcpy(char *restrict s1, const char *restrict s2); */ 1466 .global VG_(amd64_solaris_REDIR_FOR_strcpy) 1467 .type VG_(amd64_solaris_REDIR_FOR_strcpy), @function 1468 VG_(amd64_solaris_REDIR_FOR_strcpy): 1469 pushq %rbp /* establish a stack frame */ 1470 movq %rsp, %rbp 1471 movq %rdi, %rdx /* copy s1 */ 1472 1: 1473 movzbl (%rsi), %eax /* load one input character */ 1474 movb %al, (%rdx) /* copy to output/s2 */ 1475 incq %rsi /* skip to the next output character */ 1476 incq %rdx /* skip to the next input character */ 1477 testb %al, %al /* is the copied character null? */ 1478 jnz 1b /* no, copy the next character */ 1479 leave /* destroy the stack frame */ 1480 movq %rdi, %rax /* set s1 as the return value */ 1481 ret /* return to the caller */ 1482 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy) 1483 1484 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */ 1485 .global VG_(amd64_solaris_REDIR_FOR_strncpy) 1486 .type VG_(amd64_solaris_REDIR_FOR_strncpy), @function 1487 VG_(amd64_solaris_REDIR_FOR_strncpy): 1488 pushq %rbp /* establish a stack frame */ 1489 movq %rsp, %rbp 1490 movq %rdi, %rcx /* copy s1 */ 1491 1: 1492 testq %rdx, %rdx /* is the remaining size zero? */ 1493 jz 3f /* yes, all done */ 1494 movzbl (%rsi), %eax /* load one input character */ 1495 movb %al, (%rcx) /* copy to output/s2 */ 1496 decq %rdx /* decrement the remaining size */ 1497 incq %rsi /* skip to the next output character */ 1498 incq %rcx /* skip to the next input character */ 1499 testb %al, %al /* is the copied character null? */ 1500 jnz 1b /* no, copy the next character */ 1501 2: 1502 testq %rdx, %rdx /* is the remaining size zero? */ 1503 jz 3f /* yes, all done */ 1504 movb $0, (%rdx) /* copy null to output/s2 */ 1505 decq %rdx /* decrement the remaining size */ 1506 incq %rsi /* skip to next output character */ 1507 jmp 2b /* proceed with the next character */ 1508 3: 1509 leave /* destroy the stack frame */ 1510 movq %rdi, %rax /* set s1 as the return value */ 1511 ret /* return to the caller */ 1512 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy) 1513 1514 /* int strcmp(const char *s1, const char *s2); */ 1515 .global VG_(amd64_solaris_REDIR_FOR_strcmp) 1516 .type VG_(amd64_solaris_REDIR_FOR_strcmp), @function 1517 VG_(amd64_solaris_REDIR_FOR_strcmp): 1518 pushq %rbp /* establish a stack frame */ 1519 movq %rsp, %rbp 1520 jmp 2f /* go compare the first characters */ 1521 1: 1522 incq %rdi /* skip to the next s1 character */ 1523 incq %rsi /* skip to the next s2 character */ 1524 2: 1525 movzbl (%rdi), %eax /* load a character from s1 */ 1526 testb %al, %al /* is it null? */ 1527 jz 3f /* yes, exit */ 1528 cmpb (%rsi), %al /* are the characters equal? */ 1529 je 1b /* yes, proceed with next characters */ 1530 3: 1531 movzbl (%rsi), %edx /* load a character from s2 */ 1532 subl %edx, %eax /* calculate the return value */ 1533 leave /* destroy the stack frame */ 1534 ret /* return to the caller */ 1535 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp) 1536 1537 /* char *strcat(char *restrict s1, const char *restrict s2); */ 1538 .global VG_(amd64_solaris_REDIR_FOR_strcat) 1539 .type VG_(amd64_solaris_REDIR_FOR_strcat), @function 1540 VG_(amd64_solaris_REDIR_FOR_strcat): 1541 pushq %rbp /* establish a stack frame */ 1542 movq %rsp, %rbp 1543 movq %rdi, %rdx /* copy s1 */ 1544 jmp 2f /* go handle the first character */ 1545 1: 1546 incq %rdx /* skip to the next s1 character */ 1547 2: 1548 cmpb $0, (%rdx) /* is the s1 character null? */ 1549 jne 1b /* no, go check the next character */ 1550 3: 1551 movzbl (%rsi), %eax /* load a character from s2 */ 1552 movb %al, (%rdx) /* copy the s2 character to s1 */ 1553 incq %rdx /* skip to the next s1 character */ 1554 incq %rsi /* skip to the next s2 character */ 1555 testb %al, %al /* was the character null? */ 1556 jnz 3b /* no, go copy the next character */ 1557 movq %rdi, %rax /* set s1 as the return value */ 1558 leave /* destroy the stack frame */ 1559 ret /* return to the caller */ 1560 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat) 1561 1562 /* size_t strlen(const char *s); */ 1563 .global VG_(amd64_solaris_REDIR_FOR_strlen) 1564 .type VG_(amd64_solaris_REDIR_FOR_strlen), @function 1565 VG_(amd64_solaris_REDIR_FOR_strlen): 1566 pushq %rbp /* establish a stack frame */ 1567 movq %rsp, %rbp 1568 movq %rdi, %rax /* copy s */ 1569 jmp 2f /* go handle the first character */ 1570 1: 1571 incq %rax /* skip to the next s character */ 1572 2: 1573 cmpb $0, (%rax) /* is the s character null? */ 1574 jne 1b /* no, go process the next character */ 1575 subq %rdi, %rax /* calculate the return value */ 1576 leave /* destroy the stack frame */ 1577 ret /* return to the caller */ 1578 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen) 1579 1580 .global VG_(trampoline_stuff_end) 1581 VG_(trampoline_stuff_end): 1582 1583 /*---------------- unknown ----------------*/ 1584 #else 1585 # error Unknown platform 1586 1587 #endif 1588 #endif 1589 #endif 1590 #endif 1591 #endif 1592 #endif 1593 #endif 1594 #endif 1595 #endif 1596 #endif 1597 #endif 1598 #endif 1599 #endif 1600 #endif 1601 1602 /* Let the linker know we don't need an executable stack */ 1603 MARK_STACK_NO_EXEC 1604 1605 /*--------------------------------------------------------------------*/ 1606 /*--- end ---*/ 1607 /*--------------------------------------------------------------------*/ 1608