FreeBSD Helgrind: turn off check for locks held on exit for FreeBSD 14.2
[valgrind.git] / coregrind / m_trampoline.S
blobe897963be21a46ae2c8b674cd9d67ed4bb4b82c4
2 /*--------------------------------------------------------------------*/
3 /*--- Trampoline code page stuff.                   m_trampoline.S ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
10   Copyright (C) 2000-2017 Julian Seward 
11      jseward@acm.org
12   Copyright (C) 2006-2017 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.
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.
25   You should have received a copy of the GNU General Public License
26   along with this program; if not, see <http://www.gnu.org/licenses/>.
28   The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics_asm.h"
32 #include "pub_core_vkiscnums_asm.h"
34 /* ------------------ SIMULATED CPU HELPERS ------------------ */
35 /* 
36    Replacements for some functions to do with vsyscalls and signals.
37    This code runs on the simulated CPU.
39         
40 /*---------------------- x86-linux ----------------------*/
41 #if defined(VGP_x86_linux)
43 #       define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
44 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
45 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
46 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
47 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
49         /* a leading page of unexecutable code */
50         UD2_PAGE
52 .global VG_(trampoline_stuff_start)
53 VG_(trampoline_stuff_start):
55 .global VG_(x86_linux_SUBST_FOR_sigreturn)
56 VG_(x86_linux_SUBST_FOR_sigreturn):
57         /* This is a very specific sequence which GDB uses to
58            recognize signal handler frames.  Also gcc: see
59            x86_fallback_frame_state() in
60            gcc-4.1.0/gcc/config/i386/linux-unwind.h */
61         popl    %eax
62         movl    $ __NR_sigreturn, %eax
63         int     $0x80
64         ud2
66 .global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
67 VG_(x86_linux_SUBST_FOR_rt_sigreturn):
68         /* Likewise for rt signal frames */
69         movl    $ __NR_rt_sigreturn, %eax
70         int     $0x80
71         ud2
73 /* There's no particular reason that this needs to be handwritten
74    assembly, but since that's what this file contains, here's a
75    simple index implementation (written in C and compiled by gcc.)
77    unsigned char* REDIR_FOR_index ( const char* s, int c ) 
78    { 
79       unsigned char  ch = (unsigned char)((unsigned int)c); 
80       unsigned char* p  = (unsigned char*)s; 
81       while (1) { 
82          if (*p == ch) return p;
83          if (*p == 0)  return 0; 
84          p++; 
85       } 
86    }
88 .global VG_(x86_linux_REDIR_FOR_index)
89 .type   VG_(x86_linux_REDIR_FOR_index), @function
90 VG_(x86_linux_REDIR_FOR_index):
91         pushl   %ebp
92         movl    %esp, %ebp
93         movl    8(%ebp), %eax
94         movzbl  12(%ebp), %ecx
95         movzbl  (%eax), %edx
96         cmpb    %dl, %cl
97         jne     .L9
98         jmp     .L2
99 .L11:
100         addl    $1, %eax
101         movzbl  (%eax), %edx
102         cmpb    %dl, %cl
103         je      .L2
104 .L9:
105         testb   %dl, %dl
106         jne     .L11
107         xorl    %eax, %eax
108 .L2:
109         popl    %ebp
110         ret
111 .size VG_(x86_linux_REDIR_FOR_index), .-VG_(x86_linux_REDIR_FOR_index)
113 /* There's no particular reason that this needs to be handwritten
114    assembly, but since that's what this file contains, here's a
115    simple strlen implementation (written in C and compiled by gcc.)
117 .global VG_(x86_linux_REDIR_FOR_strlen)
118 .type   VG_(x86_linux_REDIR_FOR_strlen), @function
119 VG_(x86_linux_REDIR_FOR_strlen):
120         pushl   %ebp
121         movl    %esp, %ebp
122         movl    8(%ebp), %edx
123         movl    %edx, %eax
124         jmp     2f
125 1:      incl    %eax
126 2:      cmpb    $0, (%eax)
127         jne     1b
128         subl    %edx, %eax
129         popl    %ebp
130         ret
131 .size VG_(x86_linux_REDIR_FOR_strlen), .-VG_(x86_linux_REDIR_FOR_strlen)
134 .global VG_(trampoline_stuff_end)
135 VG_(trampoline_stuff_end):
137         /* and a trailing page of unexecutable code */
138         UD2_PAGE
140 #       undef UD2_16
141 #       undef UD2_64
142 #       undef UD2_256
143 #       undef UD2_1024
144 #       undef UD2_PAGE
145         
146 /*---------------------- amd64-linux ----------------------*/
147 #else
148 #if defined(VGP_amd64_linux)
150 #       define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
151 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
152 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
153 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
154 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
156         /* a leading page of unexecutable code */
157         UD2_PAGE
159 .global VG_(trampoline_stuff_start)
160 VG_(trampoline_stuff_start):
162 .global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
163 VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
164         /* This is a very specific sequence which GDB uses to
165            recognize signal handler frames. */
166         movq    $__NR_rt_sigreturn, %rax
167         syscall
168         ud2
170 .global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
171 .type   VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
172 VG_(amd64_linux_REDIR_FOR_vgettimeofday):
173 .LfnB2:
174         movq    $__NR_gettimeofday, %rax
175         syscall
176         ret
177 .LfnE2:
178 .size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
179         
180 .global VG_(amd64_linux_REDIR_FOR_vtime)
181 .type   VG_(amd64_linux_REDIR_FOR_vtime), @function
182 VG_(amd64_linux_REDIR_FOR_vtime):
183 .LfnB3: 
184         movq    $__NR_time, %rax
185         syscall
186         ret
187 .LfnE3:
188 .size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
190 .global VG_(amd64_linux_REDIR_FOR_vgetcpu)
191 .type   VG_(amd64_linux_REDIR_FOR_vgetcpu), @function
192 VG_(amd64_linux_REDIR_FOR_vgetcpu):
193 .LfnB4:
194         movq    $__NR_getcpu, %rax
195         syscall
196         ret
197 .LfnE4:
198 .size VG_(amd64_linux_REDIR_FOR_vgetcpu), .-.LfnB4
200 /* There's no particular reason that this needs to be handwritten
201    assembly, but since that's what this file contains, here's a
202    simple strlen implementation (written in C and compiled by gcc.)
204 .global VG_(amd64_linux_REDIR_FOR_strlen)
205 .type   VG_(amd64_linux_REDIR_FOR_strlen), @function
206 VG_(amd64_linux_REDIR_FOR_strlen):
207 .LfnB5:
208         xorl    %eax, %eax
209         cmpb    $0, (%rdi)
210         movq    %rdi, %rdx
211         je      .L41
212 .L40:   addq    $1, %rdx
213         cmpb    $0, (%rdx)
214         jne     .L40
215         movq    %rdx, %rax
216         subq    %rdi, %rax
217 .L41:   ret
218 .LfnE5:
219 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
221 /* There's no particular reason that this needs to be handwritten
222    assembly, but since that's what this file contains, here's a
223    simple strcmp.)
225 .global VG_(amd64_linux_REDIR_FOR_strcmp)
226 .type   VG_(amd64_linux_REDIR_FOR_strcmp), @function
227 VG_(amd64_linux_REDIR_FOR_strcmp):
228         xorl    %ecx, %ecx
230         movzbl  (%rdi, %rcx), %eax
231         movzbl  (%rsi, %rcx), %edx
232         testb   %al, %al
233         jne     2f
234         movl    %edx, %eax
235         negl    %eax
236         ret
238         incq    %rcx
239         subl    %edx, %eax
240         je      1b
241         ret
242 .size VG_(amd64_linux_REDIR_FOR_strcmp), .-VG_(amd64_linux_REDIR_FOR_strcmp)
244 .global VG_(amd64_linux_REDIR_FOR_index)
245 .type   VG_(amd64_linux_REDIR_FOR_index), @function
246 VG_(amd64_linux_REDIR_FOR_index):
247         movzbl  (%rdi), %eax
248         movl    %esi, %edx
249         cmpb    %sil, %al
250         jne     .L4
251         jmp     .L5
252 .L10:
253         addq    $1, %rdi
254         movzbl  (%rdi), %eax
255         cmpb    %dl, %al
256         je      .L5
257 .L4:
258         testb   %al, %al
259         jne     .L10
260         xorl    %eax, %eax
261         ret
262 .L5:
263         movq    %rdi, %rax
264         ret
265 .size VG_(amd64_linux_REDIR_FOR_index), .-VG_(amd64_linux_REDIR_FOR_index)
269 /* A CIE for the above four functions, followed by their FDEs */
270         .section .eh_frame,"a",@progbits
271 .Lframe1:
272         .long   .LEcie1-.LScie1
273 .LScie1:
274         .long   0x0
275         .byte   0x1
276         .string "zR"
277         .uleb128 0x1
278         .sleb128 -8
279         .byte   0x10
280         .uleb128 0x1
281         .byte   0x3
282         .byte   0xc
283         .uleb128 0x7
284         .uleb128 0x8
285         .byte   0x90
286         .uleb128 0x1
287         .align 8
288 .LEcie1:
289 .LSfde2:
290         .long   .LEfde2-.LASfde2
291 .LASfde2:
292         .long   .LASfde2-.Lframe1
293         .long   .LfnB2
294         .long   .LfnE2-.LfnB2
295         .uleb128 0x0
296         .align 8
297 .LEfde2:
298 .LSfde3:
299         .long   .LEfde3-.LASfde3
300 .LASfde3:
301         .long   .LASfde3-.Lframe1
302         .long   .LfnB3
303         .long   .LfnE3-.LfnB3
304         .uleb128 0x0
305         .align 8
306 .LEfde3:
307 .LSfde4:
308         .long   .LEfde4-.LASfde4
309 .LASfde4:
310         .long   .LASfde4-.Lframe1
311         .long   .LfnB4
312         .long   .LfnE4-.LfnB4
313         .uleb128 0x0
314         .align 8
315 .LEfde4:
316 .LSfde5:
317         .long   .LEfde5-.LASfde5
318 .LASfde5:
319         .long   .LASfde5-.Lframe1
320         .long   .LfnB5
321         .long   .LfnE5-.LfnB5
322         .uleb128 0x0
323         .align 8
324 .LEfde5:
325         .previous
327 .global VG_(trampoline_stuff_end)
328 VG_(trampoline_stuff_end):
330         /* and a trailing page of unexecutable code */
331         UD2_PAGE
333 #       undef UD2_16
334 #       undef UD2_64
335 #       undef UD2_256
336 #       undef UD2_1024
337 #       undef UD2_PAGE
339 /*---------------- ppc32-linux ----------------*/
340 #else
341 #if defined(VGP_ppc32_linux)
343 #       define UD2_16     trap ; trap ; trap; trap
344 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
345 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
346 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
347 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
349         /* a leading page of unexecutable code */
350         UD2_PAGE
352 .global VG_(trampoline_stuff_start)
353 VG_(trampoline_stuff_start):
355 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
356 VG_(ppc32_linux_SUBST_FOR_sigreturn):
357         li 0,__NR_sigreturn
358         sc
359         .long 0 /*illegal insn*/
361 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
362 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
363         li 0,__NR_rt_sigreturn
364         sc
365         .long 0 /*illegal insn*/
366         
367 /* There's no particular reason that this needs to be handwritten
368    assembly, but since that's what this file contains, here's a
369    simple strlen implementation (written in C and compiled by gcc.)
371 .global VG_(ppc32_linux_REDIR_FOR_strlen)
372 .type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
373 VG_(ppc32_linux_REDIR_FOR_strlen):
374         lbz 4,0(3)
375         li 9,0
376         cmpwi 0,4,0
377         beq- 0,.L18
378 .L19:
379         lbzu 5,1(3)
380         addi 9,9,1
381         cmpwi 0,5,0
382         bne+ 0,.L19
383 .L18:
384         mr 3,9
385         blr
386 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
388 /* Ditto strcmp */
389 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
390 .type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
391 VG_(ppc32_linux_REDIR_FOR_strcmp):
392 .L20:
393         lbz 0,0(3)
394         cmpwi 7,0,0
395         bne- 7,.L21
396         lbz 0,0(4)
397         li 11,0
398         cmpwi 7,0,0
399         beq- 7,.L22
400 .L21:
401         lbz 0,0(3)
402         li 11,-1
403         cmpwi 7,0,0
404         beq- 7,.L22
405         lbz 0,0(4)
406         li 11,1
407         cmpwi 7,0,0
408         beq- 7,.L22
409         lbz 9,0(3)
410         lbz 0,0(4)
411         li 11,-1
412         cmplw 7,9,0
413         blt- 7,.L22
414         lbz 9,0(3)
415         lbz 0,0(4)
416         li 11,1
417         addi 3,3,1
418         addi 4,4,1
419         cmplw 7,9,0
420         ble+ 7,.L20
421 .L22:
422         mr 3,11
423         blr
424 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
426 /* Ditto index/strchr */
427 .global VG_(ppc32_linux_REDIR_FOR_strchr)
428 .type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
429 VG_(ppc32_linux_REDIR_FOR_strchr):
430         lbz 0,0(3)
431         rlwinm 4,4,0,0xff
432         cmpw 7,4,0
433         beqlr 7
434         cmpwi 7,0,0
435         bne 7,.L308
436         b .L304
437 .L309:  
438         beq 6,.L304
439 .L308:  
440         lbzu 0,1(3)
441         cmpw 7,4,0
442         cmpwi 6,0,0
443         bne 7,.L309
444         blr
445 .L304:  
446         li 3,0
447         blr
448 .size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
449         
450 .global VG_(trampoline_stuff_end)
451 VG_(trampoline_stuff_end):
453         /* and a trailing page of unexecutable code */
454         UD2_PAGE
456 #       undef UD2_16
457 #       undef UD2_64
458 #       undef UD2_256
459 #       undef UD2_1024
460 #       undef UD2_PAGE
462 /*---------------- ppc64-linux ----------------*/
463 #else
464 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
466 #       define UD2_16     trap ; trap ; trap; trap
467 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
468 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
469 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
470 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
472         /* a leading page of unexecutable code */
473         UD2_PAGE
475 .global VG_(trampoline_stuff_start)
476 VG_(trampoline_stuff_start):
478 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
479 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
480         li 0,__NR_rt_sigreturn
481         sc
482         .long 0 /*illegal insn*/
484         /* See comment in pub_core_trampoline.h for what this is for */
485 .global VG_(ppctoc_magic_redirect_return_stub)
486 VG_(ppctoc_magic_redirect_return_stub):
487         trap
489         /* this function is written using the "dotless" ABI convention */
490         .align 2
491         .globl VG_(ppc64_linux_REDIR_FOR_strlen)
492 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
493         /* Little Endian uses ELF version 2 */
494         .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
495 VG_(ppc64_linux_REDIR_FOR_strlen):
496 #else
497         /* Big Endian uses ELF version 1 */
498         .section        ".opd","aw"
499         .align 3
500 VG_(ppc64_linux_REDIR_FOR_strlen):
501         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
502         .previous
503         .size   VG_(ppc64_linux_REDIR_FOR_strlen), \
504                         .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
505         .type   VG_(ppc64_linux_REDIR_FOR_strlen), @function
507 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
508 #endif
509 #if _CALL_ELF == 2
510 0:      addis        2,12,.TOC.-0b@ha
511         addi         2,2,.TOC.-0b@l
512         .localentry  VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
513 #endif
514         mr 9,3
515         lbz 0,0(3)
516         li 3,0
517         cmpwi 7,0,0
518         beqlr 7
519         li 3,0
520 .L01:
521         addi 0,3,1
522         extsw 3,0
523         lbzx 0,9,3
524         cmpwi 7,0,0
525         bne 7,.L01
526         blr
528 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
529         .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
530 #else
531         .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
532 #endif
533         .long 0
534         .byte 0,0,0,0,0,0,0,0
535 .L0end:
537         /* this function is written using the "dotless" ABI convention */
538         .align 2
539         .globl VG_(ppc64_linux_REDIR_FOR_strchr)
540 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
541         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
542 VG_(ppc64_linux_REDIR_FOR_strchr):
543 #else
544         .section        ".opd","aw"
545         .align 3
546 VG_(ppc64_linux_REDIR_FOR_strchr):
547         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
548         .previous
549         .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
550                         .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
551         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
553 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
554 #endif
555 #if  _CALL_ELF == 2
556 0:      addis         2,12,.TOC.-0b@ha
557         addi         2,2,.TOC.-0b@l
558         .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
559 #endif
560         lbz 0,0(3)
561         rldicl 4,4,0,56
562         cmpw 7,4,0
563         beqlr 7
564         cmpdi 7,0,0
565         bne 7,.L18
566         b .L14
567 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
568         .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
569 #else
570         .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
571 #endif
572 .L19:   
573         beq 6,.L14
574 .L18:   
575         lbzu 0,1(3)
576         cmpw 7,4,0
577         cmpdi 6,0,0
578         bne 7,.L19
579         blr
580 .L14:   
581         li 3,0
582         blr
583         .long 0
584         .byte 0,0,0,0,0,0,0,0
585 .L1end:
587         
588 .global VG_(trampoline_stuff_end)
589 VG_(trampoline_stuff_end):
591         /* and a trailing page of unexecutable code */
592         UD2_PAGE
594 #       undef UD2_16
595 #       undef UD2_64
596 #       undef UD2_256
597 #       undef UD2_1024
598 #       undef UD2_PAGE
600 /*---------------- arm-linux ----------------*/
601 #else
602 #if defined(VGP_arm_linux)
604 #       define UD2_4      .word 0xFFFFFFFF
605 #       define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
606 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
607 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
608 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
609 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
611         /* a leading page of unexecutable code */
612         UD2_PAGE
614 .global VG_(trampoline_stuff_start)
615 VG_(trampoline_stuff_start):
617 .global VG_(arm_linux_SUBST_FOR_sigreturn)
618 .type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
619 VG_(arm_linux_SUBST_FOR_sigreturn):
620         mov r7, # __NR_sigreturn
621         svc #0
622         .long 0xFFFFFFFF /*illegal insn*/
623 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
625 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
626 .type   VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
627 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
628         mov r7, # __NR_rt_sigreturn
629         svc #0
630         .long 0xFFFFFFFF /*illegal insn*/
631 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
632         
633 .global VG_(arm_linux_REDIR_FOR_strlen)
634 VG_(arm_linux_REDIR_FOR_strlen):
635         mov     r2, r0
636         ldrb    r0, [r0, #0]    @ zero_extendqisi2
637         @ lr needed for prologue
638         cmp     r0, #0
639         bxeq    lr
640         mov     r0, #0
641 .L5:
642         add     r0, r0, #1
643         ldrb    r3, [r0, r2]    @ zero_extendqisi2
644         cmp     r3, #0
645         bne     .L5
646         bx      lr
647         UD2_4
649 .global VG_(arm_linux_REDIR_FOR_index)
650 VG_(arm_linux_REDIR_FOR_index):
651         ldrb    r3, [r0, #0]    @ zero_extendqisi2
652         and     r1, r1, #255
653         cmp     r3, r1
654         @ lr needed for prologue
655         bne     .L9
656         bx      lr
657 .L12:
658         ldrb    r3, [r0, #1]!   @ zero_extendqisi2
659         cmp     r3, r1
660         beq     .L11
661 .L9:
662         cmp     r3, #0
663         bne     .L12
664         mov     r0, #0
665         bx      lr
666 .L11:
667         bx      lr
668         UD2_4
670 .global VG_(arm_linux_REDIR_FOR_memcpy)
671 VG_(arm_linux_REDIR_FOR_memcpy):
672         stmfd   sp!, {r4, r5, lr}
673         subs    lr, r2, #0
674         mov     r5, r0
675         beq     .L2
676         cmp     r0, r1
677         bls     .L4
678         add     r3, r0, lr
679         add     r1, lr, r1
680         cmp     lr, #3
681         sub     r4, r3, #1
682         sub     r0, r1, #1
683         ble     .L28
684         sub     ip, r3, #5
685         sub     r1, r1, #5
686 .L8:
687         ldrb    r3, [r1, #4]    @ zero_extendqisi2
688         sub     lr, lr, #4
689         strb    r3, [ip, #4]
690         ldrb    r2, [r1, #3]    @ zero_extendqisi2
691         cmp     lr, #3
692         strb    r2, [ip, #3]
693         ldrb    r3, [r1, #2]    @ zero_extendqisi2
694         mov     r4, ip
695         strb    r3, [ip, #2]
696         ldrb    r2, [r1, #1]    @ zero_extendqisi2
697         mov     r0, r1
698         strb    r2, [ip, #1]
699         sub     r1, r1, #4
700         sub     ip, ip, #4
701         bgt     .L8
702         cmp     lr, #0
703         beq     .L2
704 .L28:
705         sub     r2, lr, #1
706 .L21:
707         sub     r2, r2, #1
708         ldrb    r3, [r0], #-1   @ zero_extendqisi2
709         cmn     r2, #1
710         strb    r3, [r4], #-1
711         bne     .L21
712 .L2:
713         mov     r0, r5
714         ldmfd   sp!, {r4, r5, pc}
715 .L4:
716         bcs     .L2
717         cmp     lr, #3
718         mov     ip, r0
719         ble     .L29
720 .L19:
721         ldrb    r3, [r1, #0]    @ zero_extendqisi2
722         sub     lr, lr, #4
723         strb    r3, [ip, #0]
724         ldrb    r2, [r1, #1]    @ zero_extendqisi2
725         cmp     lr, #3
726         strb    r2, [ip, #1]
727         ldrb    r3, [r1, #2]    @ zero_extendqisi2
728         strb    r3, [ip, #2]
729         ldrb    r2, [r1, #3]    @ zero_extendqisi2
730         add     r1, r1, #4
731         strb    r2, [ip, #3]
732         add     ip, ip, #4
733         bgt     .L19
734         cmp     lr, #0
735         beq     .L2
736 .L29:
737         sub     r2, lr, #1
738 .L20:
739         sub     r2, r2, #1
740         ldrb    r3, [r1], #1    @ zero_extendqisi2
741         cmn     r2, #1
742         strb    r3, [ip], #1
743         bne     .L20
744         mov     r0, r5
745         ldmfd   sp!, {r4, r5, pc}
746         UD2_4
748 .global VG_(arm_linux_REDIR_FOR_strcmp)
749 VG_(arm_linux_REDIR_FOR_strcmp):
750 .L64:
751         ldrb    r3, [r0], #1    @ zero_extendqisi2
752         ldrb    r2, [r1], #1    @ zero_extendqisi2
753         cmp     r3, #0
754         beq     .L67
755         cmp     r3, r2
756         beq     .L64
757         rsb     r0, r2, r3
758         bx      lr
759 .L67:
760         rsb     r0, r2, #0
761         bx      lr
762         UD2_4
764 .global VG_(trampoline_stuff_end)
765 VG_(trampoline_stuff_end):
767         /* and a trailing page of unexecutable code */
768         UD2_PAGE
770 #       undef UD2_4
771 #       undef UD2_16
772 #       undef UD2_64
773 #       undef UD2_256
774 #       undef UD2_1024
775 #       undef UD2_PAGE
776         
777 /*---------------- arm64-linux ----------------*/
778 #else
779 #if defined(VGP_arm64_linux)
781 #       define UD2_4      .word 0xFFFFFFFF
782 #       define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
783 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
784 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
785 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
786 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
788         /* a leading page of unexecutable code */
789         UD2_PAGE
791 .global VG_(trampoline_stuff_start)
792 VG_(trampoline_stuff_start):
794 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
795 .type   VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
796 VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
797         mov x8, # __NR_rt_sigreturn
798         svc #0
799         .long 0xFFFFFFFF /*illegal insn*/
800 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
801         .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
803 .global VG_(arm64_linux_REDIR_FOR_strlen)
804 .type   VG_(arm64_linux_REDIR_FOR_strlen),#function
805 VG_(arm64_linux_REDIR_FOR_strlen):
806         mov     x2, x0
807         ldrb    w0, [x0]
808         cbz     w0, .L5
809         mov     x0, 0
810 .L4:
811         add     x0, x0, 1
812         ldrb    w1, [x2,x0]
813         cbnz    w1, .L4
814         ret
815 .L5:
816         mov     x0, 0
817         ret
818 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
820 .global VG_(arm64_linux_REDIR_FOR_index)
821 .type   VG_(arm64_linux_REDIR_FOR_index),#function
822 VG_(arm64_linux_REDIR_FOR_index):
823         ldrb    w2, [x0]
824         uxtb    w1, w1
825         cmp     w2, w1
826         beq     .L11
827 .L13:
828         cbz     w2, .L16
829         ldrb    w2, [x0,1]!
830         cmp     w2, w1
831         bne     .L13
832 .L11:
833         ret
834 .L16:
835         mov     x0, 0
836         ret
837 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
839 .global VG_(arm64_linux_REDIR_FOR_strcmp)
840 .type   VG_(arm64_linux_REDIR_FOR_strcmp),#function
841 VG_(arm64_linux_REDIR_FOR_strcmp):
842         ldrb    w2, [x0]
843         ldrb    w3, [x1]
844         cmp     w2, w3
845         bcc     .L22
846 .L21:
847         bhi     .L25
848         cbz     w2, .L26
849         ldrb    w2, [x0,1]!
850         ldrb    w3, [x1,1]!
851         cmp     w2, w3
852         bcs     .L21
853 .L22:
854         mov     x0, -1
855         ret
856 .L25:
857         mov     x0, 1
858         ret
859 .L26:
860         mov     x0, 0
861         ret
862 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
864 .global VG_(trampoline_stuff_end)
865 VG_(trampoline_stuff_end):
867         /* and a trailing page of unexecutable code */
868         UD2_PAGE
870 #       undef UD2_4
871 #       undef UD2_16
872 #       undef UD2_64
873 #       undef UD2_256
874 #       undef UD2_1024
875 #       undef UD2_PAGE
876         
877 /*---------------- x86-freebsd ----------------*/
878 #else
879 #if defined(VGP_x86_freebsd)
881 .global VG_(trampoline_stuff_start)
882 VG_(trampoline_stuff_start):
884 .global VG_(x86_freebsd_SUBST_FOR_sigreturn)
885 VG_(x86_freebsd_SUBST_FOR_sigreturn):
886         /*
887          * PJF this magic number is fairly flakey
888          * If ever it is wrong sys_fake_sigreturn will fail
889          * the sigreturn will be to some bogus EIP address and
890          * the client will likely terminate with a SIGILL
891          * In this case adding some printfs to sigframe_create
892          * and sys_fake_sigreturn should help debugging to
893          * find the right offset
894          */
895         lea     0x1c(%esp), %eax        /* args to sigreturn(ucontext_t *) */
896         pushl   %eax
897         pushl   %eax                    /* fake return addr */
898 /*      movl    0x44(%eax), %gs ; restore %gs, not done by sigreturn */
899         movl    $__NR_fake_sigreturn, %eax
900         int     $0x80
901         ud2
903 .global VG_(trampoline_stuff_end)
904 VG_(trampoline_stuff_end):
906 #else
907 #if defined(VGP_amd64_freebsd)
909 #       define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
910 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
911 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
912 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
913 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
915         /* a leading page of unexecutable code */
916         UD2_PAGE
918 .global VG_(trampoline_stuff_start)
919 VG_(trampoline_stuff_start):
921 .global VG_(amd64_freebsd_SUBST_FOR_sigreturn)
922 VG_(amd64_freebsd_SUBST_FOR_sigreturn):
923         /* This is a very specific sequence which GDB uses to
924            recognize signal handler frames. */
926         movq    $__NR_fake_sigreturn, %rax
928         /* running the preprocessor on
929          * src/amd64.amd64/lib/libc/sigreturn.S
930          * gives
931          * .text; .p2align 4,0x90; .globl __sys_sigreturn;
932          * .type __sys_sigreturn,@function; __sys_sigreturn:;
933          * .cfi_startproc; .weak sigreturn; .equ sigreturn,__sys_sigreturn;
934          *  .weak _sigreturn; .equ _sigreturn,__sys_sigreturn;
935          *  mov $417,%eax;
936          * movq %rcx, %r10;
937          * syscall; jb .cerror; ret; .size __sys_sigreturn, . - __sys_sigreturn;
938          *  .cfi_endproc
939          */
941         /*
942          * sigframe in sigframe-amd64-freebsd.c
943          * differs from sigframe in /usr/include/x86/sigframe.h
944          * by having the address to this trampoline first
945          * so I assume that the +8 is to get back to the
946          * FreeBSD sigframe
947          */
948         movq    %rsp, %rdi
949         addq    $8,%rdi
950         syscall
951         ud2
953 .global VG_(trampoline_stuff_end)
954 VG_(trampoline_stuff_end):
956         /* and a trailing page of unexecutable code */
957         UD2_PAGE
959 #       undef UD2_16
960 #       undef UD2_64
961 #       undef UD2_256
962 #       undef UD2_1024
963 #       undef UD2_PAGE
965 /*---------------- arm64-freebsd ----------------*/
966 #else
967 #if defined(VGP_arm64_freebsd)
969 #       define UD2_4      .word 0xFFFFFFFF
970 #       define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
971 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
972 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
973 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
974 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024
976         /* a leading page of unexecutable code */
977         UD2_PAGE
979 .global VG_(trampoline_stuff_start)
980 VG_(trampoline_stuff_start):
982 .global VG_(arm64_freebsd_SUBST_FOR_sigreturn)
983 .type   VG_(arm64_freebsd_SUBST_FOR_sigreturn),#function
984 VG_(arm64_freebsd_SUBST_FOR_sigreturn):
985         mov x8, # __NR_fake_sigreturn
986         mov x0, sp
987         svc #0
988         .long 0xFFFFFFFF /*illegal insn*/
989 .size VG_(arm64_freebsd_SUBST_FOR_sigreturn), \
990         .-VG_(arm64_freebsd_SUBST_FOR_sigreturn)
992 .global VG_(trampoline_stuff_end)
993 VG_(trampoline_stuff_end):
995         /* and a trailing page of unexecutable code */
996         UD2_PAGE
998 #       undef UD2_4
999 #       undef UD2_16
1000 #       undef UD2_64
1001 #       undef UD2_256
1002 #       undef UD2_1024
1003 #       undef UD2_PAGE
1007 /*---------------- x86-darwin ----------------*/
1008 #else
1009 #if defined(VGP_x86_darwin)
1011         /* a leading page of unexecutable code */
1012 .fill 2048, 2, 0x0b0f /* `ud2` */
1014 .globl VG_(trampoline_stuff_start)
1015 VG_(trampoline_stuff_start):
1017 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
1018 VG_(x86_darwin_SUBST_FOR_sigreturn):
1019         /* XXX does this need to have any special form? (cf x86-linux
1020         version) */
1021         movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
1022         int     $0x80
1023         ud2
1025 .globl VG_(x86_darwin_REDIR_FOR_strlen)
1026 VG_(x86_darwin_REDIR_FOR_strlen):
1027         movl    4(%esp), %edx
1028         movl    %edx, %eax
1029         jmp     1f
1031         incl    %eax
1033         cmpb    $0, (%eax)
1034         jne     0b
1035         subl    %edx, %eax
1036         ret
1038 .globl VG_(x86_darwin_REDIR_FOR_strcat)
1039 VG_(x86_darwin_REDIR_FOR_strcat):
1040         pushl   %esi
1041         movl    8(%esp), %esi
1042         movl    12(%esp), %ecx
1043         movl    %esi, %edx
1044         jmp     1f
1046         incl    %edx
1048         cmpb    $0, (%edx)
1049         jne     0b
1051         movzbl  (%ecx), %eax
1052         incl    %ecx
1053         movb    %al, (%edx)
1054         incl    %edx
1055         testb   %al, %al
1056         jne     2b
1057         movl    %esi, %eax
1058         popl    %esi
1059         ret
1062 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
1063 VG_(x86_darwin_REDIR_FOR_strcmp):
1064         movl    4(%esp), %edx
1065         movl    8(%esp), %ecx
1066         jmp     1f
1068         incl    %edx
1069         incl    %ecx
1071         movzbl  (%edx), %eax
1072         testb   %al, %al
1073         je      2f
1074         cmpb    (%ecx), %al
1075         je      0b
1077         movzbl  (%ecx),%edx
1078         movzbl  %al,%eax
1079         subl    %edx, %eax
1080         ret
1083 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
1084 VG_(x86_darwin_REDIR_FOR_strcpy):
1085         pushl   %ebp
1086         movl    %esp, %ebp
1087         pushl   %esi
1088         movl    8(%ebp), %esi
1089         movl    12(%ebp), %ecx
1090         movl    %esi, %edx
1091         jmp     1f
1093         incl    %ecx
1094         incl    %edx
1096         movzbl  (%ecx), %eax
1097         testb   %al, %al
1098         movb    %al, (%edx)
1099         jne     0b
1100         movl    %esi, %eax
1101         popl    %esi
1102         leave
1103         ret
1105 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
1106 VG_(x86_darwin_REDIR_FOR_strlcat):
1107         pushl   %ebp
1108         movl    %esp, %ebp
1109         pushl   %edi
1110         pushl   %esi
1111         subl    $16, %esp
1112         movl    8(%ebp), %esi
1113         movl    16(%ebp), %ecx
1114         movl    %esi, %edx
1115         leal    (%ecx,%esi), %eax
1116         jmp     1f
1118         incl    %edx
1120         cmpl    %edx, %eax
1121         je      2f
1122         cmpb    $0, (%edx)
1123         jne     0b
1125         movl    %edx, %edi
1126         subl    %esi, %edi
1127         movl    %ecx, %esi
1128         subl    %edi, %esi
1129         je      3f
1130         movl    12(%ebp), %eax
1131         jmp     6f
1133         movl    12(%ebp), %eax
1134         movl    %eax, (%esp)
1135         call    VG_(x86_darwin_REDIR_FOR_strlen)
1136         jmp     7f
1138         cmpl    $1, %esi
1139         je      5f
1140         movb    %cl, (%edx)
1141         decl    %esi
1142         incl    %edx
1144         incl    %eax
1146         movzbl  (%eax), %ecx
1147         testb   %cl, %cl
1148         jne     4b
1149         movb    $0, (%edx)
1150         subl    12(%ebp), %eax
1152         addl    $16, %esp
1153         leal    (%edi,%eax), %eax
1154         popl    %esi
1155         popl    %edi
1156         leave
1157         ret
1158         
1159         
1160 .globl VG_(trampoline_stuff_end)
1161 VG_(trampoline_stuff_end):
1163         /* a trailing page of unexecutable code */
1164 .fill 2048, 2, 0x0b0f /* `ud2` */
1167 /*---------------- amd64-darwin ----------------*/
1168 #else
1169 #if defined(VGP_amd64_darwin)
1171         /* a leading page of unexecutable code */
1172 .fill 2048, 2, 0x0b0f /* `ud2` */
1174 .globl VG_(trampoline_stuff_start)
1175 VG_(trampoline_stuff_start):
1177 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1178 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1179         /* XXX does this need to have any special form? (cf x86-linux
1180         version) */
1181         movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1182         syscall
1183         ud2
1185 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1186 VG_(amd64_darwin_REDIR_FOR_strlen):
1187         movq    %rdi, %rax
1188         jmp     1f
1190         incq    %rax
1192         cmpb    $0, (%rax)
1193         jne     0b
1194         subq    %rdi, %rax
1195         ret
1197 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1198 VG_(amd64_darwin_REDIR_FOR_strcat):
1199         movq    %rdi, %rdx
1200         jmp     1f
1202         incq    %rdx
1204         cmpb    $0, (%rdx)
1205         jne     0b
1207         movzbl  (%rsi), %eax
1208         incq    %rsi
1209         movb    %al, (%rdx)
1210         incq    %rdx
1211         testb   %al, %al
1212         jne     2b
1213         movq    %rdi, %rax
1214         ret
1217 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1218 VG_(amd64_darwin_REDIR_FOR_strcmp):
1219         jmp     1f
1221         incq    %rdi
1222         incq    %rsi
1224         movzbl  (%rdi), %eax
1225         testb   %al, %al
1226         je      2f
1227         cmpb    (%rsi), %al
1228         je      0b
1230         movzbl  (%rsi), %edx
1231         movzbl  %al, %eax
1232         subl    %edx, %eax
1233         ret
1235 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1236 VG_(amd64_darwin_REDIR_FOR_strcpy):
1237         pushq   %rbp
1238         movq    %rdi, %rdx
1239         movq    %rsp, %rbp
1240         jmp     1f
1242         incq    %rsi
1243         incq    %rdx
1245         movzbl  (%rsi), %eax
1246         testb   %al, %al
1247         movb    %al, (%rdx)
1248         jne     0b
1249         leave
1250         movq    %rdi, %rax
1251         ret
1252         
1253 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1254 VG_(amd64_darwin_REDIR_FOR_strlcat):
1255         pushq   %rbp
1256         leaq    (%rdx,%rdi), %rax
1257         movq    %rdi, %rcx
1258         movq    %rsp, %rbp
1259         pushq   %rbx
1260         subq    $8, %rsp
1261         jmp     1f
1263         incq    %rcx
1265         cmpq    %rcx, %rax
1266         je      2f
1267         cmpb    $0, (%rcx)
1268         jne     0b
1270         movq    %rcx, %rbx
1271         subq    %rdi, %rbx
1272         movq    %rdx, %rdi
1273         subq    %rbx, %rdi
1274         je      3f
1275         movq    %rsi, %rax
1276         jmp     6f
1278         movq    %rsi, %rdi
1279         call    VG_(amd64_darwin_REDIR_FOR_strlen)
1280         jmp     7f
1282         cmpq    $1, %rdi
1283         je      5f
1284         movb    %dl, (%rcx)
1285         decq    %rdi
1286         incq    %rcx
1288         incq    %rax
1290         movzbl  (%rax), %edx
1291         testb   %dl, %dl
1292         jne     4b
1293         movb    $0, (%rcx)
1294         subq    %rsi, %rax
1296         leaq    (%rbx,%rax), %rax
1297         addq    $8, %rsp
1298         popq    %rbx
1299         leave
1300         ret
1302 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1303 VG_(amd64_darwin_REDIR_FOR_arc4random):
1304         /* not very random, hope dyld won't mind */
1305         movq    $0x76616c6772696e64, %rax
1306         ret
1308 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1309 VG_(amd64_darwin_REDIR_FOR_strchr):
1310         pushq   %rbp
1311         movq    %rsp, %rbp
1312         movb    (%rdi), %cl
1313         cmpb    %sil, %cl
1314         jne     1f
1315         movq    %rdi, %rax
1316         popq    %rbp
1317         ret
1319         testb   %cl, %cl
1320         movl    $0, %eax
1321         je      2f
1322         movb    1(%rdi), %cl
1323         incq    %rdi
1324         cmpb    %sil, %cl
1325         movq    %rdi, %rax
1326         jne     1b
1328         popq    %rbp
1329         ret
1330         
1331 .globl VG_(trampoline_stuff_end)
1332 VG_(trampoline_stuff_end):
1334         /* a trailing page of unexecutable code */
1335 .fill 2048, 2, 0x0b0f /* `ud2` */
1338 /*---------------- s390x-linux ----------------*/
1339 #else
1340 #if defined(VGP_s390x_linux)
1342         /* a leading page of unexecutable code */
1343         .fill 2048, 2, 0x0000
1345 .global VG_(trampoline_stuff_start)
1346 VG_(trampoline_stuff_start):
1348 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1349 VG_(s390x_linux_SUBST_FOR_sigreturn):
1350         svc __NR_sigreturn
1351         .short 0
1353 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1354 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1355         /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1356            for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1357            set ra to this trampoline, but the cfa is still in the stack,
1358            the unwinder thinks, that this is a non-rt frame  and causes a
1359            crash in the gcc unwinder - which is used by the thread library
1360            and others. Therefore we add a lr 1,1 nop, to let the gcc
1361            unwinder bail out gracefully. This might also affect unwinding
1362            across the signal frame - tough luck. fixs390 */
1363         lr 1,1
1364         svc __NR_rt_sigreturn
1365         .short 0
1367 .global VG_(s390x_linux_REDIR_FOR_index)
1368 .type   VG_(s390x_linux_REDIR_FOR_index),@function
1369 VG_(s390x_linux_REDIR_FOR_index):
1371 #   %r2 = address of string
1372 #   %r3 = character to find
1374         lghi    %r0,255
1375         ngr     %r0,%r3        # r0 = (unsigned char)r3
1376         lghi    %r4,0
1377 .L1:
1378         llgc    %r1,0(%r2)     # r1 = byte from string
1379         cr      %r1,%r0        # compare
1380         ber     %r14           # return if found
1381         cr      %r1,%r4        # end of string ?
1382         je      .L2
1383         aghi    %r2,1          # increment r2
1384         j       .L1
1385 .L2:    lghi    %r2,0          # return value 0
1386         br      %r14
1387 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1389 .globl VG_(trampoline_stuff_end)
1390 VG_(trampoline_stuff_end):
1391         .fill 2048, 2, 0x0000
1393 /*---------------------- mips32-linux ----------------------*/
1394 #else
1395 #if defined(VGP_mips32_linux)
1397 #       define UD2_16     trap ; trap ; trap; trap
1398 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1399 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1400 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1401 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
1404 .global VG_(trampoline_stuff_start)
1405 VG_(trampoline_stuff_start):
1407 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1408 VG_(mips32_linux_SUBST_FOR_sigreturn):
1409         li $v0,__NR_sigreturn
1410         syscall
1411         nop
1412         .long 0 /*illegal insn*/
1414 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1415 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1416         li $v0,__NR_rt_sigreturn
1417         syscall
1418         nop
1419         .long 0 /*illegal insn*/
1420         
1421 /* There's no particular reason that this needs to be handwritten
1422    assembly, but since that's what this file contains, here's a
1423    simple index() and strlen() implementations.
1426 .set push
1427 .set noreorder
1429 .global VG_(mips32_linux_REDIR_FOR_index)
1430 .type   VG_(mips32_linux_REDIR_FOR_index), @function
1431 VG_(mips32_linux_REDIR_FOR_index):
1432       move $v0, $a0
1433    index_loop:
1434       lbu $t0, 0($v0)
1435       beq $t0, $a1, index_end
1436       nop
1437       bne $t0, $zero, index_loop
1438       addiu $v0, $v0, 1
1439       move $v0, $zero
1440    index_end:
1441       jr $ra
1442       nop
1443 .size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1445 .global VG_(mips32_linux_REDIR_FOR_strlen)
1446 .type   VG_(mips32_linux_REDIR_FOR_strlen), @function
1447 VG_(mips32_linux_REDIR_FOR_strlen):
1448       move $v0, $a0
1449    strlen_loop:
1450       lbu $t0, 0($a0)
1451       bne $t0, $zero, strlen_loop
1452       addiu $a0, $a0, 1
1453       subu $v0, $a0, $v0
1454       jr $ra
1455       addiu $v0, $v0, -1
1456 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1458 .set pop
1460 .global VG_(trampoline_stuff_end)
1461 VG_(trampoline_stuff_end):
1464 #       undef UD2_16
1465 #       undef UD2_64
1466 #       undef UD2_256
1467 #       undef UD2_1024
1468 #       undef UD2_PAGE
1470 /*---------------------- nanomips-linux --------------------*/
1471 #else
1472 #if defined(VGP_nanomips_linux)
1474 .global VG_(trampoline_stuff_start)
1475 VG_(trampoline_stuff_start):
1477 .set push
1478 .set noreorder
1480 .global VG_(nanomips_linux_SUBST_FOR_rt_sigreturn)
1481 VG_(nanomips_linux_SUBST_FOR_rt_sigreturn):
1482    li $t4, __NR_rt_sigreturn
1483    syscall[32]
1484    .long 0
1486 .global VG_(nanomips_linux_REDIR_FOR_index)
1487 .type   VG_(nanomips_linux_REDIR_FOR_index), @function
1488 VG_(nanomips_linux_REDIR_FOR_index):
1489    index_loop:
1490       lbu $t0, 0($a0)
1491       beqc $t0, $a1, index_end
1492       addiu $a0, $a0, 1
1493       bnec $t0, $zero, index_loop
1494       move $a0, $zero
1495    index_end:
1496       jrc $ra
1497 .size VG_(nanomips_linux_REDIR_FOR_index), .-VG_(nanomips_linux_REDIR_FOR_index)
1499 .global VG_(nanomips_linux_REDIR_FOR_strlen)
1500 .type   VG_(nanomips_linux_REDIR_FOR_strlen), @function
1501 VG_(nanomips_linux_REDIR_FOR_strlen):
1502       move $t1, $a0
1503    strlen_loop:
1504       lbu $t0, 0($a0)
1505       addiu $a0, $a0, 1
1506       bnec $t0, $zero, strlen_loop
1507       subu $a0, $a0, $t1
1508       addiu $a0, $a0, -1
1509       jrc $ra
1511 .size VG_(nanomips_linux_REDIR_FOR_strlen), .-VG_(nanomips_linux_REDIR_FOR_strlen)
1513 .set pop
1515 .global VG_(trampoline_stuff_end)
1516 VG_(trampoline_stuff_end):
1519 /*---------------------- mips64-linux ----------------------*/
1520 #else
1521 #if defined(VGP_mips64_linux)
1523 #       define UD2_16     trap ; trap ; trap; trap
1524 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1525 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1526 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1527 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
1529 .global VG_(trampoline_stuff_start)
1530 VG_(trampoline_stuff_start):
1532 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1533 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1534         li $2,__NR_rt_sigreturn
1535         syscall
1536         nop
1537         .long 0 /*illegal insn*/
1539 /* There's no particular reason that this needs to be handwritten
1540    assembly, but since that's what this file contains, here's a
1541    simple index() and strlen() implementations.
1544 .set push
1545 .set noreorder
1547 .global VG_(mips64_linux_REDIR_FOR_index)
1548 .type   VG_(mips64_linux_REDIR_FOR_index), @function
1549 VG_(mips64_linux_REDIR_FOR_index):
1550       move $v0, $a0
1551    index_loop:
1552       lbu $t0, 0($v0)
1553       beq $t0, $a1, index_end
1554       nop
1555       bne $t0, $zero, index_loop
1556       daddiu $v0, $v0, 1
1557       move $v0, $zero
1558    index_end:
1559       jr $ra
1560       nop
1561 .size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1563 .global VG_(mips64_linux_REDIR_FOR_strlen)
1564 .type   VG_(mips64_linux_REDIR_FOR_strlen), @function
1565 VG_(mips64_linux_REDIR_FOR_strlen):
1566       move $v0, $a0
1567    strlen_loop:
1568       lbu $t0, 0($a0)
1569       bne $t0, $zero, strlen_loop
1570       daddiu $a0, $a0, 1
1571       dsubu $v0, $a0, $v0
1572       jr $ra
1573       daddiu $v0, $v0, -1
1574 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1576 .set pop
1578 .global VG_(trampoline_stuff_end)
1579 VG_(trampoline_stuff_end):
1582 #       undef UD2_16
1583 #       undef UD2_64
1584 #       undef UD2_256
1585 #       undef UD2_1024
1586 #       undef UD2_PAGE
1588 /*---------------- x86-solaris ----------------*/
1589 #else
1590 #if defined(VGP_x86_solaris)
1592 .global VG_(trampoline_stuff_start)
1593 VG_(trampoline_stuff_start):
1595 /* int strcmp(const char *s1, const char *s2); */
1596 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1597 .type   VG_(x86_solaris_REDIR_FOR_strcmp), @function
1598 VG_(x86_solaris_REDIR_FOR_strcmp):
1599         pushl   %ebp                    /* establish a stack frame */
1600         movl    %esp, %ebp
1601         movl    8(%ebp), %edx           /* get s1 */
1602         movl    12(%esp), %ecx          /* get s2 */
1603         jmp     2f                      /* go compare the first characters */
1605         incl    %edx                    /* skip to the next s1 character */
1606         incl    %ecx                    /* skip to the next s2 character */
1608         movzbl  (%edx), %eax            /* load a character from s1 */
1609         testb   %al, %al                /* is it null? */
1610         jz      3f                      /* yes, exit */
1611         cmpb    (%ecx), %al             /* are the characters equal? */
1612         je      1b                      /* yes, proceed with next characters */
1614         movzbl  (%ecx), %edx            /* load a character from s2 */
1615         subl    %edx, %eax              /* calculate the return value */
1616         popl    %ebp                    /* destroy the stack frame */
1617         ret                             /* return to the caller */
1618 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1620 /* size_t strlen(const char *s); */
1621 .global VG_(x86_solaris_REDIR_FOR_strlen)
1622 .type   VG_(x86_solaris_REDIR_FOR_strlen), @function
1623 VG_(x86_solaris_REDIR_FOR_strlen):
1624         pushl   %ebp                    /* establish a stack frame */
1625         movl    %esp, %ebp
1626         movl    8(%ebp), %edx           /* get s */
1627         movl    %edx, %eax              /* copy s */
1628         jmp     2f                      /* go handle the first character */
1630         incl    %eax                    /* skip to the next s character */
1632         cmpb    $0, (%eax)              /* is the s character null? */
1633         jne     1b                      /* no, go process the next character */
1634         subl    %edx, %eax              /* calculate the return value */
1635         popl    %ebp                    /* destroy the stack frame */
1636         ret                             /* return to the caller */
1637 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1639 .global VG_(trampoline_stuff_end)
1640 VG_(trampoline_stuff_end):
1642 /*---------------- amd64-solaris ----------------*/
1643 #else
1644 #if defined(VGP_amd64_solaris)
1646 .global VG_(trampoline_stuff_start)
1647 VG_(trampoline_stuff_start):
1649 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1650 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1651 .type   VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1652 VG_(amd64_solaris_REDIR_FOR_strcpy):
1653         pushq   %rbp                    /* establish a stack frame */
1654         movq    %rsp, %rbp
1655         movq    %rdi, %rdx              /* copy s1 */
1657         movzbl  (%rsi), %eax            /* load one input character */
1658         movb    %al, (%rdx)             /* copy to output/s1 */
1659         incq    %rsi                    /* skip to the next output character */
1660         incq    %rdx                    /* skip to the next input character */
1661         testb   %al, %al                /* is the copied character null? */
1662         jnz     1b                      /* no, copy the next character */
1663         leave                           /* destroy the stack frame */
1664         movq    %rdi, %rax              /* set s1 as the return value */
1665         ret                             /* return to the caller */
1666 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1668 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1669 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1670 .type   VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1671 VG_(amd64_solaris_REDIR_FOR_strncpy):
1672         pushq   %rbp                    /* establish a stack frame */
1673         movq    %rsp, %rbp
1674         movq    %rdi, %rcx              /* copy s1 */
1676         testq   %rdx, %rdx              /* is the remaining size zero? */
1677         jz      3f                      /* yes, all done */
1678         movzbl  (%rsi), %eax            /* load one input character */
1679         movb    %al, (%rcx)             /* copy to output/s1 */
1680         decq    %rdx                    /* decrement the remaining size */
1681         incq    %rsi                    /* skip to the next output character */
1682         incq    %rcx                    /* skip to the next input character */
1683         testb   %al, %al                /* is the copied character null? */
1684         jnz     1b                      /* no, copy the next character */
1686         testq   %rdx, %rdx              /* is the remaining size zero? */
1687         jz      3f                      /* yes, all done */
1688         movb    $0, (%rdx)              /* copy null to output/s2 */
1689         decq    %rdx                    /* decrement the remaining size */
1690         incq    %rsi                    /* skip to next output character */
1691         jmp     2b                      /* proceed with the next character */
1693         leave                           /* destroy the stack frame */
1694         movq    %rdi, %rax              /* set s1 as the return value */
1695         ret                             /* return to the caller */
1696 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1698 /* int strcmp(const char *s1, const char *s2); */
1699 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1700 .type   VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1701 VG_(amd64_solaris_REDIR_FOR_strcmp):
1702         pushq   %rbp                    /* establish a stack frame */
1703         movq    %rsp, %rbp
1704         jmp     2f                      /* go compare the first characters */
1706         incq    %rdi                    /* skip to the next s1 character */
1707         incq    %rsi                    /* skip to the next s2 character */
1709         movzbl  (%rdi), %eax            /* load a character from s1 */
1710         testb   %al, %al                /* is it null? */
1711         jz      3f                      /* yes, exit */
1712         cmpb    (%rsi), %al             /* are the characters equal? */
1713         je      1b                      /* yes, proceed with next characters */
1715         movzbl  (%rsi), %edx            /* load a character from s2 */
1716         subl    %edx, %eax              /* calculate the return value */
1717         leave                           /* destroy the stack frame */
1718         ret                             /* return to the caller */
1719 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1721 /* char *strcat(char *restrict s1, const char *restrict s2); */
1722 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1723 .type   VG_(amd64_solaris_REDIR_FOR_strcat), @function
1724 VG_(amd64_solaris_REDIR_FOR_strcat):
1725         pushq   %rbp                    /* establish a stack frame */
1726         movq    %rsp, %rbp
1727         movq    %rdi, %rdx              /* copy s1 */
1728         jmp     2f                      /* go handle the first character */
1730         incq    %rdx                    /* skip to the next s1 character */
1732         cmpb    $0, (%rdx)              /* is the s1 character null? */
1733         jne     1b                      /* no, go check the next character */
1735         movzbl  (%rsi), %eax            /* load a character from s2 */
1736         movb    %al, (%rdx)             /* copy the s2 character to s1 */
1737         incq    %rdx                    /* skip to the next s1 character */
1738         incq    %rsi                    /* skip to the next s2 character */
1739         testb   %al, %al                /* was the character null? */
1740         jnz     3b                      /* no, go copy the next character */
1741         movq    %rdi, %rax              /* set s1 as the return value */
1742         leave                           /* destroy the stack frame */
1743         ret                             /* return to the caller */
1744 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1746 /* size_t strlen(const char *s); */
1747 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1748 .type   VG_(amd64_solaris_REDIR_FOR_strlen), @function
1749 VG_(amd64_solaris_REDIR_FOR_strlen):
1750         pushq   %rbp                    /* establish a stack frame */
1751         movq    %rsp, %rbp
1752         movq    %rdi, %rax              /* copy s */
1753         jmp     2f                      /* go handle the first character */
1755         incq    %rax                    /* skip to the next s character */
1757         cmpb    $0, (%rax)              /* is the s character null? */
1758         jne     1b                      /* no, go process the next character */
1759         subq    %rdi, %rax              /* calculate the return value */
1760         leave                           /* destroy the stack frame */
1761         ret                             /* return to the caller */
1762 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1764 .global VG_(trampoline_stuff_end)
1765 VG_(trampoline_stuff_end):
1767 /*---------------- unknown ----------------*/
1768 #else
1769 #  error Unknown platform
1771 #endif
1772 #endif
1773 #endif
1774 #endif
1775 #endif
1776 #endif
1777 #endif
1778 #endif
1779 #endif
1780 #endif
1781 #endif
1782 #endif
1783 #endif
1784 #endif
1785 #endif
1786 #endif
1787 #endif
1789 /* Let the linker know we don't need an executable stack */
1790 MARK_STACK_NO_EXEC
1792 /*--------------------------------------------------------------------*/
1793 /*--- end                                                          ---*/
1794 /*--------------------------------------------------------------------*/