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