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