Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <private/bionic_asm.h>
     30 
     31     .syntax unified
     32     .fpu    neon
     33     .thumb
     34     .thumb_func
     35 
     36 // Get the length of the source string first, then do a memcpy of the data
     37 // instead of a strcpy.
     38 ENTRY(__strcpy_chk)
     39     pld     [r0, #0]
     40     push    {r0, lr}
     41     .cfi_def_cfa_offset 8
     42     .cfi_rel_offset r0, 0
     43     .cfi_rel_offset lr, 4
     44 
     45     mov     lr, r2
     46     mov     r0, r1
     47 
     48     ands    r3, r0, #7
     49     bne     .L_align_src
     50 
     51     .p2align 2
     52 .L_mainloop:
     53     ldmia   r0!, {r2, r3}
     54 
     55     pld     [r0, #64]
     56 
     57     sub     ip, r2, #0x01010101
     58     bic     ip, ip, r2
     59     ands    ip, ip, #0x80808080
     60     bne     .L_zero_in_first_register
     61 
     62     sub     ip, r3, #0x01010101
     63     bic     ip, ip, r3
     64     ands    ip, ip, #0x80808080
     65     bne     .L_zero_in_second_register
     66     b       .L_mainloop
     67 
     68 .L_zero_in_first_register:
     69     sub     r3, r0, r1
     70     // Check for zero in byte 0.
     71     lsls    r2, ip, #17
     72     beq     .L_check_byte1_reg1
     73 
     74     sub     r3, r3, #8
     75     b       .L_check_size
     76 
     77 .L_check_byte1_reg1:
     78     bcc     .L_check_byte2_reg1
     79 
     80     sub     r3, r3, #7
     81     b       .L_check_size
     82 
     83 .L_check_byte2_reg1:
     84     // Check for zero in byte 2.
     85     tst     ip, #0x800000
     86     it      ne
     87     subne   r3, r3, #6
     88     bne     .L_check_size
     89     sub     r3, r3, #5
     90     b       .L_check_size
     91 
     92 .L_zero_in_second_register:
     93     sub     r3, r0, r1
     94     // Check for zero in byte 0.
     95     lsls    r2, ip, #17
     96     beq     .L_check_byte1_reg2
     97 
     98     sub     r3, r3, #4
     99     b       .L_check_size
    100 
    101 .L_check_byte1_reg2:
    102     bcc     .L_check_byte2_reg2
    103 
    104     sub     r3, r3, #3
    105     b       .L_check_size
    106 
    107 .L_check_byte2_reg2:
    108     // Check for zero in byte 2.
    109     tst     ip, #0x800000
    110     it      ne
    111     subne   r3, r3, #2
    112     bne     .L_check_size
    113     sub     r3, r3, #1
    114     b       .L_check_size
    115 
    116 .L_align_src:
    117     // Align to a double word (64 bits).
    118     rsb     r3, r3, #8
    119     lsls    ip, r3, #31
    120     beq     .L_align_to_32
    121 
    122     ldrb    r2, [r0], #1
    123     cbz     r2, .L_done
    124 
    125 .L_align_to_32:
    126     bcc     .L_align_to_64
    127 
    128     ldrb    r2, [r0], #1
    129     cbz     r2, .L_done
    130     ldrb    r2, [r0], #1
    131     cbz     r2, .L_done
    132 
    133 .L_align_to_64:
    134     tst     r3, #4
    135     beq     .L_mainloop
    136     ldr     r2, [r0], #4
    137 
    138     sub     ip, r2, #0x01010101
    139     bic     ip, ip, r2
    140     ands    ip, ip, #0x80808080
    141     bne     .L_zero_in_second_register
    142     b       .L_mainloop
    143 
    144 .L_done:
    145     sub     r3, r0, r1
    146     sub     r3, r3, #1
    147 
    148 .L_check_size:
    149     pld     [r1, #0]
    150     pld     [r1, #64]
    151     ldr     r0, [sp]
    152 
    153     // Add 1 for copy length to get the string terminator.
    154     add     r2, r3, #1
    155 
    156     cmp     r2, lr
    157     itt     hi
    158     movhi   r0, r2
    159     bhi     __strcpy_chk_fail
    160 
    161     // Fall through into the memcpy_base function.
    162 END(__strcpy_chk)
    163 
    164 #define MEMCPY_BASE         __strcpy_chk_memcpy_base
    165 #define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
    166 #include "memcpy_base.S"
    167