am 70a9f0a3: Merge "Fix over read in strcpy/stpcpy/strcat."
* commit '70a9f0a3bc310c863b5c90c9860aae842f82e47f': Fix over read in strcpy/stpcpy/strcat.
This commit is contained in:
commit
6eb06b0399
@ -169,13 +169,20 @@ ENTRY(strcat)
|
|||||||
.L_strcpy_align_to_64:
|
.L_strcpy_align_to_64:
|
||||||
tst r3, #4
|
tst r3, #4
|
||||||
beq .L_strcpy_check_src_align
|
beq .L_strcpy_check_src_align
|
||||||
ldr r2, [r1], #4
|
// Read one byte at a time since we don't know the src alignment
|
||||||
|
// and we don't want to read into a different page.
|
||||||
sub ip, r2, #0x01010101
|
ldrb r2, [r1], #1
|
||||||
bic ip, ip, r2
|
strb r2, [r0], #1
|
||||||
ands ip, ip, #0x80808080
|
cbz r2, .L_strcpy_complete
|
||||||
bne .L_strcpy_zero_in_first_register
|
ldrb r2, [r1], #1
|
||||||
str r2, [r0], #4
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .L_strcpy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .L_strcpy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .L_strcpy_complete
|
||||||
|
|
||||||
.L_strcpy_check_src_align:
|
.L_strcpy_check_src_align:
|
||||||
// At this point dst is aligned to a double word, check if src
|
// At this point dst is aligned to a double word, check if src
|
||||||
|
@ -149,13 +149,20 @@ ENTRY(strcpy)
|
|||||||
.Lstringcopy_align_to_64:
|
.Lstringcopy_align_to_64:
|
||||||
tst r3, #4
|
tst r3, #4
|
||||||
beq .Lstringcopy_check_src_align
|
beq .Lstringcopy_check_src_align
|
||||||
ldr r2, [r1], #4
|
// Read one byte at a time since we don't have any idea about the alignment
|
||||||
|
// of the source and we don't want to read into a different page.
|
||||||
sub ip, r2, #0x01010101
|
ldrb r2, [r1], #1
|
||||||
bic ip, ip, r2
|
strb r2, [r0], #1
|
||||||
ands ip, ip, #0x80808080
|
cbz r2, .Lstringcopy_complete
|
||||||
bne .Lstringcopy_zero_in_first_register
|
ldrb r2, [r1], #1
|
||||||
str r2, [r0], #4
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
|
|
||||||
.Lstringcopy_check_src_align:
|
.Lstringcopy_check_src_align:
|
||||||
// At this point dst is aligned to a double word, check if src
|
// At this point dst is aligned to a double word, check if src
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
.macro m_scan_byte
|
.macro m_scan_byte
|
||||||
ldrb r3, [r0]
|
ldrb r3, [r0]
|
||||||
cbz r3, strcat_r0_scan_done
|
cbz r3, .Lstrcat_r0_scan_done
|
||||||
add r0, #1
|
add r0, #1
|
||||||
.endm // m_scan_byte
|
.endm // m_scan_byte
|
||||||
|
|
||||||
@ -84,10 +84,10 @@ ENTRY(strcat)
|
|||||||
// Quick check to see if src is empty.
|
// Quick check to see if src is empty.
|
||||||
ldrb r2, [r1]
|
ldrb r2, [r1]
|
||||||
pld [r1, #0]
|
pld [r1, #0]
|
||||||
cbnz r2, strcat_continue
|
cbnz r2, .Lstrcat_continue
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
strcat_continue:
|
.Lstrcat_continue:
|
||||||
// To speed up really small dst strings, unroll checking the first 4 bytes.
|
// To speed up really small dst strings, unroll checking the first 4 bytes.
|
||||||
m_push
|
m_push
|
||||||
m_scan_byte
|
m_scan_byte
|
||||||
@ -96,10 +96,10 @@ strcat_continue:
|
|||||||
m_scan_byte
|
m_scan_byte
|
||||||
|
|
||||||
ands r3, r0, #7
|
ands r3, r0, #7
|
||||||
bne strcat_align_src
|
bne .Lstrcat_align_src
|
||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
strcat_mainloop:
|
.Lstrcat_mainloop:
|
||||||
ldmia r0!, {r2, r3}
|
ldmia r0!, {r2, r3}
|
||||||
|
|
||||||
pld [r0, #64]
|
pld [r0, #64]
|
||||||
@ -107,28 +107,28 @@ strcat_mainloop:
|
|||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcat_zero_in_first_register
|
bne .Lstrcat_zero_in_first_register
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcat_zero_in_second_register
|
bne .Lstrcat_zero_in_second_register
|
||||||
b strcat_mainloop
|
b .Lstrcat_mainloop
|
||||||
|
|
||||||
strcat_zero_in_first_register:
|
.Lstrcat_zero_in_first_register:
|
||||||
sub r0, r0, #4
|
sub r0, r0, #4
|
||||||
|
|
||||||
strcat_zero_in_second_register:
|
.Lstrcat_zero_in_second_register:
|
||||||
// Check for zero in byte 0.
|
// Check for zero in byte 0.
|
||||||
tst ip, #0x80
|
tst ip, #0x80
|
||||||
it ne
|
it ne
|
||||||
subne r0, r0, #4
|
subne r0, r0, #4
|
||||||
bne strcat_r0_scan_done
|
bne .Lstrcat_r0_scan_done
|
||||||
// Check for zero in byte 1.
|
// Check for zero in byte 1.
|
||||||
tst ip, #0x8000
|
tst ip, #0x8000
|
||||||
it ne
|
it ne
|
||||||
subne r0, r0, #3
|
subne r0, r0, #3
|
||||||
bne strcat_r0_scan_done
|
bne .Lstrcat_r0_scan_done
|
||||||
// Check for zero in byte 2.
|
// Check for zero in byte 2.
|
||||||
tst ip, #0x800000
|
tst ip, #0x800000
|
||||||
it ne
|
it ne
|
||||||
@ -137,33 +137,33 @@ strcat_zero_in_second_register:
|
|||||||
// Zero is in byte 3.
|
// Zero is in byte 3.
|
||||||
subeq r0, r0, #1
|
subeq r0, r0, #1
|
||||||
|
|
||||||
strcat_r0_scan_done:
|
.Lstrcat_r0_scan_done:
|
||||||
// Unroll the first 8 bytes that will be copied.
|
// Unroll the first 8 bytes that will be copied.
|
||||||
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r5, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r2, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r3, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
|
m_copy_byte reg=r4, cmd=cbz, label=.Lstrcpy_finish
|
||||||
m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
|
m_copy_byte reg=r5, cmd=cbnz, label=.Lstrcpy_continue
|
||||||
|
|
||||||
strcpy_finish:
|
.Lstrcpy_finish:
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_continue:
|
.Lstrcpy_continue:
|
||||||
pld [r1, #0]
|
pld [r1, #0]
|
||||||
ands r3, r0, #7
|
ands r3, r0, #7
|
||||||
bne strcpy_align_dst
|
bne .Lstrcpy_align_dst
|
||||||
|
|
||||||
strcpy_check_src_align:
|
.Lstrcpy_check_src_align:
|
||||||
// At this point dst is aligned to a double word, check if src
|
// At this point dst is aligned to a double word, check if src
|
||||||
// is also aligned to a double word.
|
// is also aligned to a double word.
|
||||||
ands r3, r1, #7
|
ands r3, r1, #7
|
||||||
bne strcpy_unaligned_copy
|
bne .Lstrcpy_unaligned_copy
|
||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
strcpy_mainloop:
|
.Lstrcpy_mainloop:
|
||||||
ldmia r1!, {r2, r3}
|
ldmia r1!, {r2, r3}
|
||||||
|
|
||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
@ -171,17 +171,17 @@ strcpy_mainloop:
|
|||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_mainloop
|
b .Lstrcpy_mainloop
|
||||||
|
|
||||||
strcpy_zero_in_first_register:
|
.Lstrcpy_zero_in_first_register:
|
||||||
lsls lr, ip, #17
|
lsls lr, ip, #17
|
||||||
itt ne
|
itt ne
|
||||||
strbne r2, [r0]
|
strbne r2, [r0]
|
||||||
@ -198,7 +198,7 @@ strcpy_zero_in_first_register:
|
|||||||
strb r3, [r0]
|
strb r3, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_zero_in_second_register:
|
.Lstrcpy_zero_in_second_register:
|
||||||
lsls lr, ip, #17
|
lsls lr, ip, #17
|
||||||
ittt ne
|
ittt ne
|
||||||
stmiane r0!, {r2}
|
stmiane r0!, {r2}
|
||||||
@ -218,18 +218,18 @@ strcpy_zero_in_second_register:
|
|||||||
strb r4, [r0]
|
strb r4, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_align_dst:
|
.Lstrcpy_align_dst:
|
||||||
// Align to a double word (64 bits).
|
// Align to a double word (64 bits).
|
||||||
rsb r3, r3, #8
|
rsb r3, r3, #8
|
||||||
lsls ip, r3, #31
|
lsls ip, r3, #31
|
||||||
beq strcpy_align_to_32
|
beq .Lstrcpy_align_to_32
|
||||||
|
|
||||||
ldrb r2, [r1], #1
|
ldrb r2, [r1], #1
|
||||||
strb r2, [r0], #1
|
strb r2, [r0], #1
|
||||||
cbz r2, strcpy_complete
|
cbz r2, .Lstrcpy_complete
|
||||||
|
|
||||||
strcpy_align_to_32:
|
.Lstrcpy_align_to_32:
|
||||||
bcc strcpy_align_to_64
|
bcc .Lstrcpy_align_to_64
|
||||||
|
|
||||||
ldrb r4, [r1], #1
|
ldrb r4, [r1], #1
|
||||||
strb r4, [r0], #1
|
strb r4, [r0], #1
|
||||||
@ -242,76 +242,83 @@ strcpy_align_to_32:
|
|||||||
it eq
|
it eq
|
||||||
m_ret inst=popeq
|
m_ret inst=popeq
|
||||||
|
|
||||||
strcpy_align_to_64:
|
.Lstrcpy_align_to_64:
|
||||||
tst r3, #4
|
tst r3, #4
|
||||||
beq strcpy_check_src_align
|
beq .Lstrcpy_check_src_align
|
||||||
ldr r2, [r1], #4
|
// Read one byte at a time since we don't know the src alignment
|
||||||
|
// and we don't want to read into a different page.
|
||||||
|
ldrb r4, [r1], #1
|
||||||
|
strb r4, [r0], #1
|
||||||
|
cbz r4, .Lstrcpy_complete
|
||||||
|
ldrb r5, [r1], #1
|
||||||
|
strb r5, [r0], #1
|
||||||
|
cbz r5, .Lstrcpy_complete
|
||||||
|
ldrb r4, [r1], #1
|
||||||
|
strb r4, [r0], #1
|
||||||
|
cbz r4, .Lstrcpy_complete
|
||||||
|
ldrb r5, [r1], #1
|
||||||
|
strb r5, [r0], #1
|
||||||
|
cbz r5, .Lstrcpy_complete
|
||||||
|
b .Lstrcpy_check_src_align
|
||||||
|
|
||||||
sub ip, r2, #0x01010101
|
.Lstrcpy_complete:
|
||||||
bic ip, ip, r2
|
|
||||||
ands ip, ip, #0x80808080
|
|
||||||
bne strcpy_zero_in_first_register
|
|
||||||
stmia r0!, {r2}
|
|
||||||
b strcpy_check_src_align
|
|
||||||
|
|
||||||
strcpy_complete:
|
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unaligned_copy:
|
.Lstrcpy_unaligned_copy:
|
||||||
// Dst is aligned to a double word, while src is at an unknown alignment.
|
// Dst is aligned to a double word, while src is at an unknown alignment.
|
||||||
// There are 7 different versions of the unaligned copy code
|
// There are 7 different versions of the unaligned copy code
|
||||||
// to prevent overreading the src. The mainloop of every single version
|
// to prevent overreading the src. The mainloop of every single version
|
||||||
// will store 64 bits per loop. The difference is how much of src can
|
// will store 64 bits per loop. The difference is how much of src can
|
||||||
// be read without potentially crossing a page boundary.
|
// be read without potentially crossing a page boundary.
|
||||||
tbb [pc, r3]
|
tbb [pc, r3]
|
||||||
strcpy_unaligned_branchtable:
|
.Lstrcpy_unaligned_branchtable:
|
||||||
.byte 0
|
.byte 0
|
||||||
.byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign7 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign6 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign5 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign4 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign3 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign2 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
.byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
|
.byte ((.Lstrcpy_unalign1 - .Lstrcpy_unaligned_branchtable)/2)
|
||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 7 bytes before possibly crossing a page.
|
// Can read 7 bytes before possibly crossing a page.
|
||||||
strcpy_unalign7:
|
.Lstrcpy_unalign7:
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
|
|
||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
ldrb r3, [r1]
|
ldrb r3, [r1]
|
||||||
cbz r3, strcpy_unalign7_copy5bytes
|
cbz r3, .Lstrcpy_unalign7_copy5bytes
|
||||||
ldrb r4, [r1, #1]
|
ldrb r4, [r1, #1]
|
||||||
cbz r4, strcpy_unalign7_copy6bytes
|
cbz r4, .Lstrcpy_unalign7_copy6bytes
|
||||||
ldrb r5, [r1, #2]
|
ldrb r5, [r1, #2]
|
||||||
cbz r5, strcpy_unalign7_copy7bytes
|
cbz r5, .Lstrcpy_unalign7_copy7bytes
|
||||||
|
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
|
|
||||||
lsrs ip, r3, #24
|
lsrs ip, r3, #24
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
beq strcpy_unalign_return
|
beq .Lstrcpy_unalign_return
|
||||||
b strcpy_unalign7
|
b .Lstrcpy_unalign7
|
||||||
|
|
||||||
strcpy_unalign7_copy5bytes:
|
.Lstrcpy_unalign7_copy5bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strb r3, [r0]
|
strb r3, [r0]
|
||||||
strcpy_unalign_return:
|
.Lstrcpy_unalign_return:
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign7_copy6bytes:
|
.Lstrcpy_unalign7_copy6bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strb r3, [r0], #1
|
strb r3, [r0], #1
|
||||||
strb r4, [r0], #1
|
strb r4, [r0], #1
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign7_copy7bytes:
|
.Lstrcpy_unalign7_copy7bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strb r3, [r0], #1
|
strb r3, [r0], #1
|
||||||
strb r4, [r0], #1
|
strb r4, [r0], #1
|
||||||
@ -320,30 +327,30 @@ strcpy_unalign7_copy7bytes:
|
|||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 6 bytes before possibly crossing a page.
|
// Can read 6 bytes before possibly crossing a page.
|
||||||
strcpy_unalign6:
|
.Lstrcpy_unalign6:
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
|
|
||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
ldrb r4, [r1]
|
ldrb r4, [r1]
|
||||||
cbz r4, strcpy_unalign_copy5bytes
|
cbz r4, .Lstrcpy_unalign_copy5bytes
|
||||||
ldrb r5, [r1, #1]
|
ldrb r5, [r1, #1]
|
||||||
cbz r5, strcpy_unalign_copy6bytes
|
cbz r5, .Lstrcpy_unalign_copy6bytes
|
||||||
|
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
|
|
||||||
tst r3, #0xff0000
|
tst r3, #0xff0000
|
||||||
beq strcpy_unalign6_copy7bytes
|
beq .Lstrcpy_unalign6_copy7bytes
|
||||||
lsrs ip, r3, #24
|
lsrs ip, r3, #24
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
beq strcpy_unalign_return
|
beq .Lstrcpy_unalign_return
|
||||||
b strcpy_unalign6
|
b .Lstrcpy_unalign6
|
||||||
|
|
||||||
strcpy_unalign6_copy7bytes:
|
.Lstrcpy_unalign6_copy7bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strh r3, [r0], #2
|
strh r3, [r0], #2
|
||||||
lsr r3, #16
|
lsr r3, #16
|
||||||
@ -352,16 +359,16 @@ strcpy_unalign6_copy7bytes:
|
|||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 5 bytes before possibly crossing a page.
|
// Can read 5 bytes before possibly crossing a page.
|
||||||
strcpy_unalign5:
|
.Lstrcpy_unalign5:
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
|
|
||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
ldrb r4, [r1]
|
ldrb r4, [r1]
|
||||||
cbz r4, strcpy_unalign_copy5bytes
|
cbz r4, .Lstrcpy_unalign_copy5bytes
|
||||||
|
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
|
|
||||||
@ -370,17 +377,17 @@ strcpy_unalign5:
|
|||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_unalign5
|
b .Lstrcpy_unalign5
|
||||||
|
|
||||||
strcpy_unalign_copy5bytes:
|
.Lstrcpy_unalign_copy5bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strb r4, [r0]
|
strb r4, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign_copy6bytes:
|
.Lstrcpy_unalign_copy6bytes:
|
||||||
stmia r0!, {r2}
|
stmia r0!, {r2}
|
||||||
strb r4, [r0], #1
|
strb r4, [r0], #1
|
||||||
strb r5, [r0]
|
strb r5, [r0]
|
||||||
@ -388,13 +395,13 @@ strcpy_unalign_copy6bytes:
|
|||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 4 bytes before possibly crossing a page.
|
// Can read 4 bytes before possibly crossing a page.
|
||||||
strcpy_unalign4:
|
.Lstrcpy_unalign4:
|
||||||
ldmia r1!, {r2}
|
ldmia r1!, {r2}
|
||||||
|
|
||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
ldmia r1!, {r3}
|
ldmia r1!, {r3}
|
||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
@ -402,20 +409,20 @@ strcpy_unalign4:
|
|||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_unalign4
|
b .Lstrcpy_unalign4
|
||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 3 bytes before possibly crossing a page.
|
// Can read 3 bytes before possibly crossing a page.
|
||||||
strcpy_unalign3:
|
.Lstrcpy_unalign3:
|
||||||
ldrb r2, [r1]
|
ldrb r2, [r1]
|
||||||
cbz r2, strcpy_unalign3_copy1byte
|
cbz r2, .Lstrcpy_unalign3_copy1byte
|
||||||
ldrb r3, [r1, #1]
|
ldrb r3, [r1, #1]
|
||||||
cbz r3, strcpy_unalign3_copy2bytes
|
cbz r3, .Lstrcpy_unalign3_copy2bytes
|
||||||
ldrb r4, [r1, #2]
|
ldrb r4, [r1, #2]
|
||||||
cbz r4, strcpy_unalign3_copy3bytes
|
cbz r4, .Lstrcpy_unalign3_copy3bytes
|
||||||
|
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
@ -423,26 +430,26 @@ strcpy_unalign3:
|
|||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
|
|
||||||
lsrs lr, r2, #24
|
lsrs lr, r2, #24
|
||||||
beq strcpy_unalign_copy4bytes
|
beq .Lstrcpy_unalign_copy4bytes
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_unalign3
|
b .Lstrcpy_unalign3
|
||||||
|
|
||||||
strcpy_unalign3_copy1byte:
|
.Lstrcpy_unalign3_copy1byte:
|
||||||
strb r2, [r0]
|
strb r2, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign3_copy2bytes:
|
.Lstrcpy_unalign3_copy2bytes:
|
||||||
strb r2, [r0], #1
|
strb r2, [r0], #1
|
||||||
strb r3, [r0]
|
strb r3, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign3_copy3bytes:
|
.Lstrcpy_unalign3_copy3bytes:
|
||||||
strb r2, [r0], #1
|
strb r2, [r0], #1
|
||||||
strb r3, [r0], #1
|
strb r3, [r0], #1
|
||||||
strb r4, [r0]
|
strb r4, [r0]
|
||||||
@ -450,34 +457,34 @@ strcpy_unalign3_copy3bytes:
|
|||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 2 bytes before possibly crossing a page.
|
// Can read 2 bytes before possibly crossing a page.
|
||||||
strcpy_unalign2:
|
.Lstrcpy_unalign2:
|
||||||
ldrb r2, [r1]
|
ldrb r2, [r1]
|
||||||
cbz r2, strcpy_unalign_copy1byte
|
cbz r2, .Lstrcpy_unalign_copy1byte
|
||||||
ldrb r3, [r1, #1]
|
ldrb r3, [r1, #1]
|
||||||
cbz r3, strcpy_unalign_copy2bytes
|
cbz r3, .Lstrcpy_unalign_copy2bytes
|
||||||
|
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
pld [r1, #64]
|
pld [r1, #64]
|
||||||
|
|
||||||
tst r2, #0xff0000
|
tst r2, #0xff0000
|
||||||
beq strcpy_unalign_copy3bytes
|
beq .Lstrcpy_unalign_copy3bytes
|
||||||
lsrs ip, r2, #24
|
lsrs ip, r2, #24
|
||||||
beq strcpy_unalign_copy4bytes
|
beq .Lstrcpy_unalign_copy4bytes
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_unalign2
|
b .Lstrcpy_unalign2
|
||||||
|
|
||||||
.p2align 2
|
.p2align 2
|
||||||
// Can read 1 byte before possibly crossing a page.
|
// Can read 1 byte before possibly crossing a page.
|
||||||
strcpy_unalign1:
|
.Lstrcpy_unalign1:
|
||||||
ldrb r2, [r1]
|
ldrb r2, [r1]
|
||||||
cbz r2, strcpy_unalign_copy1byte
|
cbz r2, .Lstrcpy_unalign_copy1byte
|
||||||
|
|
||||||
ldr r2, [r1], #4
|
ldr r2, [r1], #4
|
||||||
ldr r3, [r1], #4
|
ldr r3, [r1], #4
|
||||||
@ -487,62 +494,62 @@ strcpy_unalign1:
|
|||||||
sub ip, r2, #0x01010101
|
sub ip, r2, #0x01010101
|
||||||
bic ip, ip, r2
|
bic ip, ip, r2
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_first_register
|
bne .Lstrcpy_zero_in_first_register
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcpy_zero_in_second_register
|
bne .Lstrcpy_zero_in_second_register
|
||||||
|
|
||||||
stmia r0!, {r2, r3}
|
stmia r0!, {r2, r3}
|
||||||
b strcpy_unalign1
|
b .Lstrcpy_unalign1
|
||||||
|
|
||||||
strcpy_unalign_copy1byte:
|
.Lstrcpy_unalign_copy1byte:
|
||||||
strb r2, [r0]
|
strb r2, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign_copy2bytes:
|
.Lstrcpy_unalign_copy2bytes:
|
||||||
strb r2, [r0], #1
|
strb r2, [r0], #1
|
||||||
strb r3, [r0]
|
strb r3, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign_copy3bytes:
|
.Lstrcpy_unalign_copy3bytes:
|
||||||
strh r2, [r0], #2
|
strh r2, [r0], #2
|
||||||
lsr r2, #16
|
lsr r2, #16
|
||||||
strb r2, [r0]
|
strb r2, [r0]
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcpy_unalign_copy4bytes:
|
.Lstrcpy_unalign_copy4bytes:
|
||||||
stmia r0, {r2}
|
stmia r0, {r2}
|
||||||
m_ret inst=pop
|
m_ret inst=pop
|
||||||
|
|
||||||
strcat_align_src:
|
.Lstrcat_align_src:
|
||||||
// Align to a double word (64 bits).
|
// Align to a double word (64 bits).
|
||||||
rsb r3, r3, #8
|
rsb r3, r3, #8
|
||||||
lsls ip, r3, #31
|
lsls ip, r3, #31
|
||||||
beq strcat_align_to_32
|
beq .Lstrcat_align_to_32
|
||||||
ldrb r2, [r0], #1
|
ldrb r2, [r0], #1
|
||||||
cbz r2, strcat_r0_update
|
cbz r2, .Lstrcat_r0_update
|
||||||
|
|
||||||
strcat_align_to_32:
|
.Lstrcat_align_to_32:
|
||||||
bcc strcat_align_to_64
|
bcc .Lstrcat_align_to_64
|
||||||
ldrb r2, [r0], #1
|
ldrb r2, [r0], #1
|
||||||
cbz r2, strcat_r0_update
|
cbz r2, .Lstrcat_r0_update
|
||||||
ldrb r2, [r0], #1
|
ldrb r2, [r0], #1
|
||||||
cbz r2, strcat_r0_update
|
cbz r2, .Lstrcat_r0_update
|
||||||
|
|
||||||
strcat_align_to_64:
|
.Lstrcat_align_to_64:
|
||||||
tst r3, #4
|
tst r3, #4
|
||||||
beq strcat_mainloop
|
beq .Lstrcat_mainloop
|
||||||
ldr r3, [r0], #4
|
ldr r3, [r0], #4
|
||||||
|
|
||||||
sub ip, r3, #0x01010101
|
sub ip, r3, #0x01010101
|
||||||
bic ip, ip, r3
|
bic ip, ip, r3
|
||||||
ands ip, ip, #0x80808080
|
ands ip, ip, #0x80808080
|
||||||
bne strcat_zero_in_second_register
|
bne .Lstrcat_zero_in_second_register
|
||||||
b strcat_mainloop
|
b .Lstrcat_mainloop
|
||||||
|
|
||||||
strcat_r0_update:
|
.Lstrcat_r0_update:
|
||||||
sub r0, r0, #1
|
sub r0, r0, #1
|
||||||
b strcat_r0_scan_done
|
b .Lstrcat_r0_scan_done
|
||||||
END(strcat)
|
END(strcat)
|
||||||
|
@ -244,13 +244,20 @@ ENTRY(strcpy)
|
|||||||
.Lstringcopy_align_to_64:
|
.Lstringcopy_align_to_64:
|
||||||
tst r3, #4
|
tst r3, #4
|
||||||
beq .Lstringcopy_check_src_align
|
beq .Lstringcopy_check_src_align
|
||||||
ldr r2, [r1], #4
|
// Read one byte at a time since we don't have any idea about the alignment
|
||||||
|
// of the source and we don't want to read into a different page.
|
||||||
sub ip, r2, #0x01010101
|
ldrb r2, [r1], #1
|
||||||
bic ip, ip, r2
|
strb r2, [r0], #1
|
||||||
ands ip, ip, #0x80808080
|
cbz r2, .Lstringcopy_complete
|
||||||
bne .Lstringcopy_zero_in_first_register
|
ldrb r2, [r1], #1
|
||||||
stmia r0!, {r2}
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
|
ldrb r2, [r1], #1
|
||||||
|
strb r2, [r0], #1
|
||||||
|
cbz r2, .Lstringcopy_complete
|
||||||
b .Lstringcopy_check_src_align
|
b .Lstringcopy_check_src_align
|
||||||
|
|
||||||
.Lstringcopy_complete:
|
.Lstringcopy_complete:
|
||||||
|
@ -381,15 +381,19 @@ void RunSrcDstBufferOverreadTest(void (*test_func)(uint8_t*, uint8_t*, size_t))
|
|||||||
// Make the second page unreadable and unwritable.
|
// Make the second page unreadable and unwritable.
|
||||||
ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
|
ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
|
||||||
|
|
||||||
uint8_t* dst = new uint8_t[pagesize];
|
uint8_t* dst_buffer = new uint8_t[2*pagesize];
|
||||||
for (size_t i = 0; i < pagesize; i++) {
|
// Change the dst alignment as we change the source.
|
||||||
uint8_t* src = &memory[pagesize-i];
|
for (size_t i = 0; i < 16; i++) {
|
||||||
|
uint8_t* dst = &dst_buffer[i];
|
||||||
|
for (size_t j = 0; j < pagesize; j++) {
|
||||||
|
uint8_t* src = &memory[pagesize-j];
|
||||||
|
|
||||||
test_func(src, dst, i);
|
test_func(src, dst, j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
|
ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
|
||||||
free(memory);
|
free(memory);
|
||||||
delete[] dst;
|
delete[] dst_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunCmpBufferOverreadTest(
|
void RunCmpBufferOverreadTest(
|
||||||
|
@ -1174,7 +1174,7 @@ static size_t LargeSetIncrement(size_t len) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STRCAT_DST_LEN 128
|
#define STRCAT_DST_LEN 64
|
||||||
|
|
||||||
static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
||||||
if (len >= 1) {
|
if (len >= 1) {
|
||||||
@ -1189,7 +1189,7 @@ static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
|||||||
int value2 = 32 + (value + 2) % 96;
|
int value2 = 32 + (value + 2) % 96;
|
||||||
memset(cmp_buf, value2, sizeof(cmp_buf));
|
memset(cmp_buf, value2, sizeof(cmp_buf));
|
||||||
|
|
||||||
for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
|
for (size_t i = 1; i <= STRCAT_DST_LEN;) {
|
||||||
memset(dst, value2, i-1);
|
memset(dst, value2, i-1);
|
||||||
memset(dst+i-1, 0, len-i);
|
memset(dst+i-1, 0, len-i);
|
||||||
src[len-i] = '\0';
|
src[len-i] = '\0';
|
||||||
@ -1197,6 +1197,13 @@ static void DoStrcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
|||||||
reinterpret_cast<char*>(src))));
|
reinterpret_cast<char*>(src))));
|
||||||
ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
|
ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
|
||||||
ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
|
ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
|
||||||
|
// This is an expensive loop, so don't loop through every value,
|
||||||
|
// get to a certain size and then start doubling.
|
||||||
|
if (i < 16) {
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
i <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
@ -1229,7 +1236,7 @@ static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
|||||||
int value2 = 32 + (value + 2) % 96;
|
int value2 = 32 + (value + 2) % 96;
|
||||||
memset(cmp_buf, value2, sizeof(cmp_buf));
|
memset(cmp_buf, value2, sizeof(cmp_buf));
|
||||||
|
|
||||||
for (size_t i = 1; i <= STRCAT_DST_LEN; i++) {
|
for (size_t i = 1; i <= STRCAT_DST_LEN;) {
|
||||||
memset(dst, value2, i-1);
|
memset(dst, value2, i-1);
|
||||||
memset(dst+i-1, 0, len-i);
|
memset(dst+i-1, 0, len-i);
|
||||||
src[len-i] = '\0';
|
src[len-i] = '\0';
|
||||||
@ -1237,6 +1244,13 @@ static void DoStrlcatTest(uint8_t* src, uint8_t* dst, size_t len) {
|
|||||||
reinterpret_cast<char*>(src), len));
|
reinterpret_cast<char*>(src), len));
|
||||||
ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
|
ASSERT_TRUE(memcmp(dst, cmp_buf, i-1) == 0);
|
||||||
ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
|
ASSERT_TRUE(memcmp(src, dst+i-1, len-i+1) == 0);
|
||||||
|
// This is an expensive loop, so don't loop through every value,
|
||||||
|
// get to a certain size and then start doubling.
|
||||||
|
if (i < 16) {
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
i <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dst[0] = '\0';
|
dst[0] = '\0';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user