1 #include "asan_impl.h"
2 #include "libc.h"
3 #include <endian.h>
4 #include <stdint.h>
5 #include <string.h>
6
memcpy(void * restrict dest,const void * restrict src,size_t n)7 NO_ASAN void* memcpy(void* restrict dest, const void* restrict src, size_t n) {
8 unsigned char* d = dest;
9 const unsigned char* s = src;
10
11 #ifdef __GNUC__
12
13 #if __BYTE_ORDER == __LITTLE_ENDIAN
14 #define LS >>
15 #define RS <<
16 #else
17 #define LS <<
18 #define RS >>
19 #endif
20
21 typedef uint32_t __attribute__((__may_alias__)) u32;
22 uint32_t w, x;
23
24 for (; (uintptr_t)s % 4 && n; n--)
25 *d++ = *s++;
26
27 if ((uintptr_t)d % 4 == 0) {
28 for (; n >= 16; s += 16, d += 16, n -= 16) {
29 *(u32*)(d + 0) = *(u32*)(s + 0);
30 *(u32*)(d + 4) = *(u32*)(s + 4);
31 *(u32*)(d + 8) = *(u32*)(s + 8);
32 *(u32*)(d + 12) = *(u32*)(s + 12);
33 }
34 if (n & 8) {
35 *(u32*)(d + 0) = *(u32*)(s + 0);
36 *(u32*)(d + 4) = *(u32*)(s + 4);
37 d += 8;
38 s += 8;
39 }
40 if (n & 4) {
41 *(u32*)(d + 0) = *(u32*)(s + 0);
42 d += 4;
43 s += 4;
44 }
45 if (n & 2) {
46 *d++ = *s++;
47 *d++ = *s++;
48 }
49 if (n & 1) {
50 *d = *s;
51 }
52 return dest;
53 }
54
55 if (n >= 32)
56 switch ((uintptr_t)d % 4) {
57 case 1:
58 w = *(u32*)s;
59 *d++ = *s++;
60 *d++ = *s++;
61 *d++ = *s++;
62 n -= 3;
63 for (; n >= 17; s += 16, d += 16, n -= 16) {
64 x = *(u32*)(s + 1);
65 *(u32*)(d + 0) = (w LS 24) | (x RS 8);
66 w = *(u32*)(s + 5);
67 *(u32*)(d + 4) = (x LS 24) | (w RS 8);
68 x = *(u32*)(s + 9);
69 *(u32*)(d + 8) = (w LS 24) | (x RS 8);
70 w = *(u32*)(s + 13);
71 *(u32*)(d + 12) = (x LS 24) | (w RS 8);
72 }
73 break;
74 case 2:
75 w = *(u32*)s;
76 *d++ = *s++;
77 *d++ = *s++;
78 n -= 2;
79 for (; n >= 18; s += 16, d += 16, n -= 16) {
80 x = *(u32*)(s + 2);
81 *(u32*)(d + 0) = (w LS 16) | (x RS 16);
82 w = *(u32*)(s + 6);
83 *(u32*)(d + 4) = (x LS 16) | (w RS 16);
84 x = *(u32*)(s + 10);
85 *(u32*)(d + 8) = (w LS 16) | (x RS 16);
86 w = *(u32*)(s + 14);
87 *(u32*)(d + 12) = (x LS 16) | (w RS 16);
88 }
89 break;
90 case 3:
91 w = *(u32*)s;
92 *d++ = *s++;
93 n -= 1;
94 for (; n >= 19; s += 16, d += 16, n -= 16) {
95 x = *(u32*)(s + 3);
96 *(u32*)(d + 0) = (w LS 8) | (x RS 24);
97 w = *(u32*)(s + 7);
98 *(u32*)(d + 4) = (x LS 8) | (w RS 24);
99 x = *(u32*)(s + 11);
100 *(u32*)(d + 8) = (w LS 8) | (x RS 24);
101 w = *(u32*)(s + 15);
102 *(u32*)(d + 12) = (x LS 8) | (w RS 24);
103 }
104 break;
105 }
106 if (n & 16) {
107 *d++ = *s++;
108 *d++ = *s++;
109 *d++ = *s++;
110 *d++ = *s++;
111 *d++ = *s++;
112 *d++ = *s++;
113 *d++ = *s++;
114 *d++ = *s++;
115 *d++ = *s++;
116 *d++ = *s++;
117 *d++ = *s++;
118 *d++ = *s++;
119 *d++ = *s++;
120 *d++ = *s++;
121 *d++ = *s++;
122 *d++ = *s++;
123 }
124 if (n & 8) {
125 *d++ = *s++;
126 *d++ = *s++;
127 *d++ = *s++;
128 *d++ = *s++;
129 *d++ = *s++;
130 *d++ = *s++;
131 *d++ = *s++;
132 *d++ = *s++;
133 }
134 if (n & 4) {
135 *d++ = *s++;
136 *d++ = *s++;
137 *d++ = *s++;
138 *d++ = *s++;
139 }
140 if (n & 2) {
141 *d++ = *s++;
142 *d++ = *s++;
143 }
144 if (n & 1) {
145 *d = *s;
146 }
147 return dest;
148 #endif
149
150 for (; n; n--)
151 *d++ = *s++;
152 return dest;
153 }
154
155 __typeof(memcpy) __unsanitized_memcpy __attribute__((alias("memcpy")));
156 __asan_weak_alias(memcpy)
157