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 33 .thumb 34 .thumb_func 35 36// Get the length of src string, then get the source of the dst string. 37// Check that the two lengths together don't exceed the threshold, then 38// do a memcpy of the data. 39ENTRY(__strcat_chk) 40 pld [r0, #0] 41 push {r0, lr} 42 .cfi_def_cfa_offset 8 43 .cfi_rel_offset r0, 0 44 .cfi_rel_offset lr, 4 45 push {r4, r5} 46 .cfi_adjust_cfa_offset 8 47 .cfi_rel_offset r4, 0 48 .cfi_rel_offset r5, 4 49 50 mov lr, r2 51 52 // Save the dst register to r5 53 mov r5, r0 54 55 // Zero out r4 56 eor r4, r4, r4 57 58 // r1 contains the address of the string to count. 59.L_strlen_start: 60 mov r0, r1 61 ands r3, r1, #7 62 beq .L_mainloop 63 64 // Align to a double word (64 bits). 65 rsb r3, r3, #8 66 lsls ip, r3, #31 67 beq .L_align_to_32 68 69 ldrb r2, [r1], #1 70 cbz r2, .L_update_count_and_finish 71 72.L_align_to_32: 73 bcc .L_align_to_64 74 ands ip, r3, #2 75 beq .L_align_to_64 76 77 ldrb r2, [r1], #1 78 cbz r2, .L_update_count_and_finish 79 ldrb r2, [r1], #1 80 cbz r2, .L_update_count_and_finish 81 82.L_align_to_64: 83 tst r3, #4 84 beq .L_mainloop 85 ldr r3, [r1], #4 86 87 sub ip, r3, #0x01010101 88 bic ip, ip, r3 89 ands ip, ip, #0x80808080 90 bne .L_zero_in_second_register 91 92 .p2align 2 93.L_mainloop: 94 ldrd r2, r3, [r1], #8 95 96 pld [r1, #64] 97 98 sub ip, r2, #0x01010101 99 bic ip, ip, r2 100 ands ip, ip, #0x80808080 101 bne .L_zero_in_first_register 102 103 sub ip, r3, #0x01010101 104 bic ip, ip, r3 105 ands ip, ip, #0x80808080 106 bne .L_zero_in_second_register 107 b .L_mainloop 108 109.L_update_count_and_finish: 110 sub r3, r1, r0 111 sub r3, r3, #1 112 b .L_finish 113 114.L_zero_in_first_register: 115 sub r3, r1, r0 116 lsls r2, ip, #17 117 bne .L_sub8_and_finish 118 bcs .L_sub7_and_finish 119 lsls ip, ip, #1 120 bne .L_sub6_and_finish 121 122 sub r3, r3, #5 123 b .L_finish 124 125.L_sub8_and_finish: 126 sub r3, r3, #8 127 b .L_finish 128 129.L_sub7_and_finish: 130 sub r3, r3, #7 131 b .L_finish 132 133.L_sub6_and_finish: 134 sub r3, r3, #6 135 b .L_finish 136 137.L_zero_in_second_register: 138 sub r3, r1, r0 139 lsls r2, ip, #17 140 bne .L_sub4_and_finish 141 bcs .L_sub3_and_finish 142 lsls ip, ip, #1 143 bne .L_sub2_and_finish 144 145 sub r3, r3, #1 146 b .L_finish 147 148.L_sub4_and_finish: 149 sub r3, r3, #4 150 b .L_finish 151 152.L_sub3_and_finish: 153 sub r3, r3, #3 154 b .L_finish 155 156.L_sub2_and_finish: 157 sub r3, r3, #2 158 159.L_finish: 160 cmp r4, #0 161 bne .L_strlen_done 162 163 // Time to get the dst string length. 164 mov r1, r5 165 166 // Save the original source address to r5. 167 mov r5, r0 168 169 // Save the current length (adding 1 for the terminator). 170 add r4, r3, #1 171 b .L_strlen_start 172 173 // r0 holds the pointer to the dst string. 174 // r3 holds the dst string length. 175 // r4 holds the src string length + 1. 176.L_strlen_done: 177 add r2, r3, r4 178 cmp r2, lr 179 itt hi 180 movhi r0, lr 181 bhi __strcat_chk_fail 182 183 // Set up the registers for the memcpy code. 184 mov r1, r5 185 pld [r1, #64] 186 mov r2, r4 187 add r0, r0, r3 188 pop {r4, r5} 189 .cfi_adjust_cfa_offset -8 190 .cfi_restore r4 191 .cfi_restore r5 192 193#include "memcpy_base.S" 194 195 // Undo the above cfi directives 196 .cfi_adjust_cfa_offset 8 197 .cfi_rel_offset r4, 0 198 .cfi_rel_offset r5, 4 199END(__strcat_chk) 200