mirror of
https://github.com/GrapheneOS/hardened_malloc.git
synced 2025-04-20 06:20:20 +02:00
Compare commits
2 commits
a3ca492fb8
...
a1ee47bc16
Author | SHA1 | Date | |
---|---|---|---|
|
a1ee47bc16 | ||
|
c0b4033769 |
11 changed files with 83 additions and 397 deletions
24
CREDITS
24
CREDITS
|
@ -23,30 +23,6 @@ h_malloc.c open-addressed hash table (regions_grow, regions_insert, regions_find
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
memcpy.c, memmove.c, memset.c and their wide variants:
|
|
||||||
Copyright © 2005-2020 Rich Felker, et al.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
Contributor list: https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
|
|
||||||
|
|
||||||
libdivide:
|
libdivide:
|
||||||
|
|
||||||
Copyright (C) 2010 - 2019 ridiculous_fish, <libdivide@ridiculousfish.com>
|
Copyright (C) 2010 - 2019 ridiculous_fish, <libdivide@ridiculousfish.com>
|
||||||
|
|
17
Makefile
17
Makefile
|
@ -39,7 +39,7 @@ CFLAGS := $(CFLAGS) -std=c17 $(SHARED_FLAGS) -Wmissing-prototypes -Wstrict-proto
|
||||||
CXXFLAGS := $(CXXFLAGS) -std=c++17 -fsized-deallocation $(SHARED_FLAGS)
|
CXXFLAGS := $(CXXFLAGS) -std=c++17 -fsized-deallocation $(SHARED_FLAGS)
|
||||||
LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z,text
|
LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z,text
|
||||||
|
|
||||||
SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c memcpy.c memmove.c memset.c wmemcpy.c wmemmove.c wmemset.c
|
SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c
|
||||||
OBJECTS := $(SOURCES:.c=.o)
|
OBJECTS := $(SOURCES:.c=.o)
|
||||||
|
|
||||||
ifeq ($(CONFIG_CXX_ALLOCATOR),true)
|
ifeq ($(CONFIG_CXX_ALLOCATOR),true)
|
||||||
|
@ -123,7 +123,7 @@ $(OUT):
|
||||||
|
|
||||||
$(OUT)/chacha.o: chacha.c chacha.h util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/chacha.o: chacha.c chacha.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/h_malloc.o: h_malloc.c include/h_malloc.h mutex.h memory.h musl.h pages.h random.h util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/h_malloc.o: h_malloc.c include/h_malloc.h mutex.h memory.h pages.h random.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/memory.o: memory.c memory.h util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/memory.o: memory.c memory.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
|
@ -136,19 +136,6 @@ $(OUT)/random.o: random.c random.h chacha.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
$(OUT)/memcpy.o: memcpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/memmove.o: memmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/memset.o: memset.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/wmemcpy.o: wmemcpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/wmemmove.o: wmemmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/wmemset.o: wmemset.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
|
|
||||||
check: tidy
|
check: tidy
|
||||||
|
|
||||||
tidy:
|
tidy:
|
||||||
|
|
74
h_malloc.c
74
h_malloc.c
|
@ -15,11 +15,11 @@
|
||||||
#include "h_malloc.h"
|
#include "h_malloc.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "memtag.h"
|
#include "memtag.h"
|
||||||
#include "musl.h"
|
|
||||||
#include "mutex.h"
|
#include "mutex.h"
|
||||||
#include "pages.h"
|
#include "pages.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#ifdef USE_PKEY
|
#ifdef USE_PKEY
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -1876,46 +1876,70 @@ EXPORT size_t h_malloc_object_size_fast(const void *p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||||
EXPORT void *memcpy(void *restrict dst, const void *restrict src, size_t len) {
|
FILE *(*original_memcpy)(void *restrict, const void *restrict, size_t);
|
||||||
|
inline void *h_memcpy_real(void *restrict dst, const void *restrict src, size_t len) {
|
||||||
|
if(!original_memcpy) original_memcpy = dlsym(RTLD_NEXT, "memcpy");
|
||||||
|
return (*original_memcpy)(dst, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void *h_memcpy_wrapped(void *restrict dst, const void *restrict src, size_t len) {
|
||||||
if(dst == src || len == 0) {
|
if(dst == src || len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
if (unlikely(dst < src + len && dst + len > src)) {
|
if (dst < src + len && dst + len > src) {
|
||||||
fatal_error("memcpy overlap");
|
fatal_error("memcpy overlap");
|
||||||
}
|
}
|
||||||
if (unlikely(len > malloc_object_size(src))) {
|
if (len > malloc_object_size(src)) {
|
||||||
fatal_error("memcpy read overflow");
|
fatal_error("memcpy read overflow");
|
||||||
}
|
}
|
||||||
if (unlikely(len > malloc_object_size(dst))) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("memcpy buffer overflow");
|
fatal_error("memcpy buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_memcpy(dst, src, len);
|
return h_memcpy_real(dst, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void *memmove(void *dst, const void *src, size_t len) {
|
FILE *(*original_memmove)(void *, const void *, size_t);
|
||||||
|
inline void *h_memmove_real(void *dst, const void *src, size_t len) {
|
||||||
|
if(!original_memmove) original_memmove = dlsym(RTLD_NEXT, "memmove");
|
||||||
|
return (*original_memmove)(dst, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void *h_memmove_wrapped(void *dst, const void *src, size_t len) {
|
||||||
if(dst == src || len == 0) {
|
if(dst == src || len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
if (unlikely(len > malloc_object_size(src))) {
|
if (len > malloc_object_size(src)) {
|
||||||
fatal_error("memmove read overflow");
|
fatal_error("memmove read overflow");
|
||||||
}
|
}
|
||||||
if (unlikely(len > malloc_object_size(dst))) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("memmove buffer overflow");
|
fatal_error("memmove buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_memmove(dst, src, len);
|
return h_memmove_real(dst, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void *memset(void *dst, int value, size_t len) {
|
FILE *(*original_memset)(void *, int, size_t);
|
||||||
|
inline void *h_memset_real(void *dst, int value, size_t len) {
|
||||||
|
if(!original_memset) original_memset = dlsym(RTLD_NEXT, "memset");
|
||||||
|
return (*original_memset)(dst, value, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void *h_memset_wrapped(void *dst, int value, size_t len) {
|
||||||
if(len == 0) {
|
if(len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
if (unlikely(len > malloc_object_size(dst))) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("memset buffer overflow");
|
fatal_error("memset buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_memset(dst, value, len);
|
return h_memset_real(dst, value, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT wchar_t *wmemcpy(wchar_t *restrict dst, const wchar_t *restrict src, size_t len) {
|
wchar_t *(*original_wmemcpy)(wchar_t *restrict, const wchar_t *restrict, size_t);
|
||||||
|
inline wchar_t *h_wmemcpy_real(wchar_t *restrict dst, const wchar_t *restrict src, size_t len) {
|
||||||
|
if(!original_wmemcpy) original_wmemcpy = dlsym(RTLD_NEXT, "wmemcpy");
|
||||||
|
return (*original_wmemcpy)(dst, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT wchar_t *h_wmemcpy_wrapped(wchar_t *restrict dst, const wchar_t *restrict src, size_t len) {
|
||||||
if(dst == src || len == 0) {
|
if(dst == src || len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
@ -1928,10 +1952,16 @@ EXPORT wchar_t *wmemcpy(wchar_t *restrict dst, const wchar_t *restrict src, size
|
||||||
if (len > malloc_object_size(dst)) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("wmemcpy buffer overflow");
|
fatal_error("wmemcpy buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_wmemcpy(dst, src, len);
|
return h_wmemcpy_real(dst, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len) {
|
wchar_t *(*original_wmemmove)(wchar_t *, const wchar_t *, size_t);
|
||||||
|
inline wchar_t *h_wmemmove_real(wchar_t *dst, const wchar_t *src, size_t len) {
|
||||||
|
if(!original_wmemmove) original_wmemmove = dlsym(RTLD_NEXT, "wmemmove");
|
||||||
|
return (*original_wmemmove)(dst, src, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT wchar_t *h_wmemmove_wrapped(wchar_t *dst, const wchar_t *src, size_t len) {
|
||||||
if(dst == src || len == 0) {
|
if(dst == src || len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
@ -1941,17 +1971,23 @@ EXPORT wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len) {
|
||||||
if (len > malloc_object_size(dst)) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("wmemmove buffer overflow");
|
fatal_error("wmemmove buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_wmemmove(dst, src, len);
|
return h_wmemmove_real(dst, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT wchar_t *wmemset(wchar_t *dst, wchar_t value, size_t len) {
|
wchar_t *(*original_wmemset)(wchar_t *, wchar_t, size_t);
|
||||||
|
inline wchar_t *h_wmemset_real(wchar_t *dst, wchar_t value, size_t len) {
|
||||||
|
if(!original_wmemset) original_wmemset = dlsym(RTLD_NEXT, "wmemset");
|
||||||
|
return (*original_wmemset)(dst, value, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT wchar_t *h_wmemset_wrapped(wchar_t *dst, wchar_t value, size_t len) {
|
||||||
if(len == 0) {
|
if(len == 0) {
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
if (len > malloc_object_size(dst)) {
|
if (len > malloc_object_size(dst)) {
|
||||||
fatal_error("wmemset buffer overflow");
|
fatal_error("wmemset buffer overflow");
|
||||||
}
|
}
|
||||||
return musl_wmemset(dst, value, len);
|
return h_wmemset_real(dst, value, len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,14 @@ extern "C" {
|
||||||
#define h_realloc realloc
|
#define h_realloc realloc
|
||||||
#define h_aligned_alloc aligned_alloc
|
#define h_aligned_alloc aligned_alloc
|
||||||
#define h_free free
|
#define h_free free
|
||||||
|
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||||
|
#define h_memcpy_wrapped memcpy
|
||||||
|
#define h_memmove_wrapped memmove
|
||||||
|
#define h_memset_wrapped memset
|
||||||
|
#define h_wmemcpy_wrapped wmemcpy
|
||||||
|
#define h_wmemmove_wrapped wmemmove
|
||||||
|
#define h_wmemset_wrapped wmemset
|
||||||
|
#endif
|
||||||
|
|
||||||
#define h_posix_memalign posix_memalign
|
#define h_posix_memalign posix_memalign
|
||||||
|
|
||||||
|
@ -56,19 +64,25 @@ void *h_aligned_alloc(size_t alignment, size_t size);
|
||||||
void h_free(void *ptr);
|
void h_free(void *ptr);
|
||||||
|
|
||||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||||
void *memcpy(void *dst, const void *src, size_t len);
|
void *h_memcpy_real(void *dst, const void *src, size_t len);
|
||||||
void *memmove(void *dst, const void *src, size_t len);
|
void *h_memcpy_wrapped(void *dst, const void *src, size_t len);
|
||||||
void *memset(void *dst, int value, size_t len);
|
void *h_memmove_real(void *dst, const void *src, size_t len);
|
||||||
wchar_t *wmemcpy(wchar_t *dst, const wchar_t *src, size_t len);
|
void *h_memmove_wrapped(void *dst, const void *src, size_t len);
|
||||||
wchar_t *wmemmove(wchar_t *dst, const wchar_t *src, size_t len);
|
void *h_memset_real(void *dst, int value, size_t len);
|
||||||
wchar_t *wmemset(wchar_t *dst, wchar_t value, size_t len);
|
void *h_memset_wrapped(void *dst, int value, size_t len);
|
||||||
#define h_memcpy_internal musl_memcpy
|
wchar_t *h_wmemcpy_real(wchar_t *dst, const wchar_t *src, size_t len);
|
||||||
#define h_memmove_internal musl_memmove
|
wchar_t *h_wmemcpy_wrapped(wchar_t *dst, const wchar_t *src, size_t len);
|
||||||
#define h_memset_internal musl_memset
|
wchar_t *h_wmemmove_real(wchar_t *dst, const wchar_t *src, size_t len);
|
||||||
|
wchar_t *h_wmemmove_wrapped(wchar_t *dst, const wchar_t *src, size_t len);
|
||||||
|
wchar_t *h_wmemset_real(wchar_t *dst, wchar_t value, size_t len);
|
||||||
|
wchar_t *h_wmemset_wrapped(wchar_t *dst, wchar_t value, size_t len);
|
||||||
|
#define h_memcpy_internal h_memcpy_real
|
||||||
|
#define h_memove_internal h_memmove_real
|
||||||
|
#define h_memset_internal h_memset_real
|
||||||
#else
|
#else
|
||||||
#define h_memcpy_internal memcpy
|
#define h_memcpy_internal __builtin_memcpy
|
||||||
#define h_memmove_internal memmove
|
#define h_memove_internal __builtin_memmove
|
||||||
#define h_memset_internal memset
|
#define h_memset_internal __builtin_memset
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// POSIX
|
// POSIX
|
||||||
|
|
132
memcpy.c
132
memcpy.c
|
@ -1,132 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from musl libc version 1.2.5 licensed under the MIT license
|
|
||||||
*
|
|
||||||
* Christian Göttsche: Added const qualifiers to retain const correctness.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <endian.h>
|
|
||||||
|
|
||||||
void *musl_memcpy(void *restrict dest, const void *restrict src, size_t n)
|
|
||||||
{
|
|
||||||
unsigned char *d = dest;
|
|
||||||
const unsigned char *s = src;
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
||||||
#define LS >>
|
|
||||||
#define RS <<
|
|
||||||
#else
|
|
||||||
#define LS <<
|
|
||||||
#define RS >>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
|
||||||
uint32_t w, x;
|
|
||||||
|
|
||||||
for (; (uintptr_t)s % 4 && n; n--) *d++ = *s++;
|
|
||||||
|
|
||||||
if ((uintptr_t)d % 4 == 0) {
|
|
||||||
for (; n>=16; s+=16, d+=16, n-=16) {
|
|
||||||
*(u32 *)(d+0) = *(const u32 *)(s+0);
|
|
||||||
*(u32 *)(d+4) = *(const u32 *)(s+4);
|
|
||||||
*(u32 *)(d+8) = *(const u32 *)(s+8);
|
|
||||||
*(u32 *)(d+12) = *(const u32 *)(s+12);
|
|
||||||
}
|
|
||||||
if (n&8) {
|
|
||||||
*(u32 *)(d+0) = *(const u32 *)(s+0);
|
|
||||||
*(u32 *)(d+4) = *(const u32 *)(s+4);
|
|
||||||
d += 8; s += 8;
|
|
||||||
}
|
|
||||||
if (n&4) {
|
|
||||||
*(u32 *)(d+0) = *(const u32 *)(s+0);
|
|
||||||
d += 4; s += 4;
|
|
||||||
}
|
|
||||||
if (n&2) {
|
|
||||||
*d++ = *s++; *d++ = *s++;
|
|
||||||
}
|
|
||||||
if (n&1) {
|
|
||||||
*d = *s;
|
|
||||||
}
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n >= 32) switch ((uintptr_t)d % 4) {
|
|
||||||
case 1:
|
|
||||||
w = *(const u32 *)s;
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
n -= 3;
|
|
||||||
for (; n>=17; s+=16, d+=16, n-=16) {
|
|
||||||
x = *(const u32 *)(s+1);
|
|
||||||
*(u32 *)(d+0) = (w LS 24) | (x RS 8);
|
|
||||||
w = *(const u32 *)(s+5);
|
|
||||||
*(u32 *)(d+4) = (x LS 24) | (w RS 8);
|
|
||||||
x = *(const u32 *)(s+9);
|
|
||||||
*(u32 *)(d+8) = (w LS 24) | (x RS 8);
|
|
||||||
w = *(const u32 *)(s+13);
|
|
||||||
*(u32 *)(d+12) = (x LS 24) | (w RS 8);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
w = *(const u32 *)s;
|
|
||||||
*d++ = *s++;
|
|
||||||
*d++ = *s++;
|
|
||||||
n -= 2;
|
|
||||||
for (; n>=18; s+=16, d+=16, n-=16) {
|
|
||||||
x = *(const u32 *)(s+2);
|
|
||||||
*(u32 *)(d+0) = (w LS 16) | (x RS 16);
|
|
||||||
w = *(const u32 *)(s+6);
|
|
||||||
*(u32 *)(d+4) = (x LS 16) | (w RS 16);
|
|
||||||
x = *(const u32 *)(s+10);
|
|
||||||
*(u32 *)(d+8) = (w LS 16) | (x RS 16);
|
|
||||||
w = *(const u32 *)(s+14);
|
|
||||||
*(u32 *)(d+12) = (x LS 16) | (w RS 16);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
w = *(const u32 *)s;
|
|
||||||
*d++ = *s++;
|
|
||||||
n -= 1;
|
|
||||||
for (; n>=19; s+=16, d+=16, n-=16) {
|
|
||||||
x = *(const u32 *)(s+3);
|
|
||||||
*(u32 *)(d+0) = (w LS 8) | (x RS 24);
|
|
||||||
w = *(const u32 *)(s+7);
|
|
||||||
*(u32 *)(d+4) = (x LS 8) | (w RS 24);
|
|
||||||
x = *(const u32 *)(s+11);
|
|
||||||
*(u32 *)(d+8) = (w LS 8) | (x RS 24);
|
|
||||||
w = *(const u32 *)(s+15);
|
|
||||||
*(u32 *)(d+12) = (x LS 8) | (w RS 24);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (n&16) {
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
}
|
|
||||||
if (n&8) {
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
}
|
|
||||||
if (n&4) {
|
|
||||||
*d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++;
|
|
||||||
}
|
|
||||||
if (n&2) {
|
|
||||||
*d++ = *s++; *d++ = *s++;
|
|
||||||
}
|
|
||||||
if (n&1) {
|
|
||||||
*d = *s;
|
|
||||||
}
|
|
||||||
return dest;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (; n; n--) *d++ = *s++;
|
|
||||||
return dest;
|
|
||||||
}
|
|
50
memmove.c
50
memmove.c
|
@ -1,50 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copied from musl libc version 1.2.5 licensed under the MIT license
|
|
||||||
*
|
|
||||||
* Christian Göttsche: Added const qualifiers to retain const correctness.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
typedef __attribute__((__may_alias__)) size_t WT;
|
|
||||||
#define WS (sizeof(WT))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *musl_memmove(void *dest, const void *src, size_t n)
|
|
||||||
{
|
|
||||||
char *d = dest;
|
|
||||||
const char *s = src;
|
|
||||||
|
|
||||||
if (d==s) return d;
|
|
||||||
if ((uintptr_t)s-(uintptr_t)d-n <= -2*n) return memcpy(d, s, n);
|
|
||||||
|
|
||||||
if (d<s) {
|
|
||||||
#ifdef __GNUC__
|
|
||||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
|
|
||||||
while ((uintptr_t)d % WS) {
|
|
||||||
if (!n--) return dest;
|
|
||||||
*d++ = *s++;
|
|
||||||
}
|
|
||||||
for (; n>=WS; n-=WS, d+=WS, s+=WS) *(WT *)d = *(const WT *)s;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (; n; n--) *d++ = *s++;
|
|
||||||
} else {
|
|
||||||
#ifdef __GNUC__
|
|
||||||
if ((uintptr_t)s % WS == (uintptr_t)d % WS) {
|
|
||||||
while ((uintptr_t)(d+n) % WS) {
|
|
||||||
if (!n--) return dest;
|
|
||||||
d[n] = s[n];
|
|
||||||
}
|
|
||||||
while (n>=WS) n-=WS, *(WT *)(d+n) = *(const WT *)(s+n);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
while (n) n--, d[n] = s[n];
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
|
94
memset.c
94
memset.c
|
@ -1,94 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
void *musl_memset(void *dest, int c, size_t n)
|
|
||||||
{
|
|
||||||
unsigned char *s = dest;
|
|
||||||
size_t k;
|
|
||||||
|
|
||||||
/* Fill head and tail with minimal branching. Each
|
|
||||||
* conditional ensures that all the subsequently used
|
|
||||||
* offsets are well-defined and in the dest region. */
|
|
||||||
|
|
||||||
if (!n) return dest;
|
|
||||||
s[0] = c;
|
|
||||||
s[n-1] = c;
|
|
||||||
if (n <= 2) return dest;
|
|
||||||
s[1] = c;
|
|
||||||
s[2] = c;
|
|
||||||
s[n-2] = c;
|
|
||||||
s[n-3] = c;
|
|
||||||
if (n <= 6) return dest;
|
|
||||||
s[3] = c;
|
|
||||||
s[n-4] = c;
|
|
||||||
if (n <= 8) return dest;
|
|
||||||
|
|
||||||
/* Advance pointer to align it at a 4-byte boundary,
|
|
||||||
* and truncate n to a multiple of 4. The previous code
|
|
||||||
* already took care of any head/tail that get cut off
|
|
||||||
* by the alignment. */
|
|
||||||
|
|
||||||
k = -(uintptr_t)s & 3;
|
|
||||||
s += k;
|
|
||||||
n -= k;
|
|
||||||
n &= -4;
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
typedef uint32_t __attribute__((__may_alias__)) u32;
|
|
||||||
typedef uint64_t __attribute__((__may_alias__)) u64;
|
|
||||||
|
|
||||||
u32 c32 = ((u32)-1)/255 * (unsigned char)c;
|
|
||||||
|
|
||||||
/* In preparation to copy 32 bytes at a time, aligned on
|
|
||||||
* an 8-byte bounary, fill head/tail up to 28 bytes each.
|
|
||||||
* As in the initial byte-based head/tail fill, each
|
|
||||||
* conditional below ensures that the subsequent offsets
|
|
||||||
* are valid (e.g. !(n<=24) implies n>=28). */
|
|
||||||
|
|
||||||
*(u32 *)(s+0) = c32;
|
|
||||||
*(u32 *)(s+n-4) = c32;
|
|
||||||
if (n <= 8) return dest;
|
|
||||||
*(u32 *)(s+4) = c32;
|
|
||||||
*(u32 *)(s+8) = c32;
|
|
||||||
*(u32 *)(s+n-12) = c32;
|
|
||||||
*(u32 *)(s+n-8) = c32;
|
|
||||||
if (n <= 24) return dest;
|
|
||||||
*(u32 *)(s+12) = c32;
|
|
||||||
*(u32 *)(s+16) = c32;
|
|
||||||
*(u32 *)(s+20) = c32;
|
|
||||||
*(u32 *)(s+24) = c32;
|
|
||||||
*(u32 *)(s+n-28) = c32;
|
|
||||||
*(u32 *)(s+n-24) = c32;
|
|
||||||
*(u32 *)(s+n-20) = c32;
|
|
||||||
*(u32 *)(s+n-16) = c32;
|
|
||||||
|
|
||||||
/* Align to a multiple of 8 so we can fill 64 bits at a time,
|
|
||||||
* and avoid writing the same bytes twice as much as is
|
|
||||||
* practical without introducing additional branching. */
|
|
||||||
|
|
||||||
k = 24 + ((uintptr_t)s & 4);
|
|
||||||
s += k;
|
|
||||||
n -= k;
|
|
||||||
|
|
||||||
/* If this loop is reached, 28 tail bytes have already been
|
|
||||||
* filled, so any remainder when n drops below 32 can be
|
|
||||||
* safely ignored. */
|
|
||||||
|
|
||||||
u64 c64 = c32 | ((u64)c32 << 32);
|
|
||||||
for (; n >= 32; n-=32, s+=32) {
|
|
||||||
*(u64 *)(s+0) = c64;
|
|
||||||
*(u64 *)(s+8) = c64;
|
|
||||||
*(u64 *)(s+16) = c64;
|
|
||||||
*(u64 *)(s+24) = c64;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Pure C fallback with no aliasing violations. */
|
|
||||||
for (; n; n--, s++) *s = c;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
|
10
musl.h
10
musl.h
|
@ -1,10 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void *musl_memcpy(void *dst, const void *src, size_t len);
|
|
||||||
void *musl_memmove(void *dst, const void *src, size_t len);
|
|
||||||
void *musl_memset(void *dst, int value, size_t len);
|
|
||||||
wchar_t *musl_wmemcpy(wchar_t *dst, const wchar_t *src, size_t len);
|
|
||||||
wchar_t *musl_wmemmove(wchar_t *dst, const wchar_t *src, size_t len);
|
|
||||||
wchar_t *musl_wmemset(wchar_t *dst, wchar_t value, size_t len);
|
|
12
wmemcpy.c
12
wmemcpy.c
|
@ -1,12 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
wchar_t *musl_wmemcpy(wchar_t *restrict d, const wchar_t *restrict s, size_t n)
|
|
||||||
{
|
|
||||||
wchar_t *a = d;
|
|
||||||
while (n--) *d++ = *s++;
|
|
||||||
return a;
|
|
||||||
}
|
|
17
wmemmove.c
17
wmemmove.c
|
@ -1,17 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
wchar_t *musl_wmemmove(wchar_t *d, const wchar_t *s, size_t n)
|
|
||||||
{
|
|
||||||
wchar_t *d0 = d;
|
|
||||||
if (d == s) return d;
|
|
||||||
if ((uintptr_t)d-(uintptr_t)s < n * sizeof *d)
|
|
||||||
while (n--) d[n] = s[n];
|
|
||||||
else
|
|
||||||
while (n--) *d++ = *s++;
|
|
||||||
return d0;
|
|
||||||
}
|
|
12
wmemset.c
12
wmemset.c
|
@ -1,12 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
wchar_t *musl_wmemset(wchar_t *d, wchar_t c, size_t n)
|
|
||||||
{
|
|
||||||
wchar_t *ret = d;
|
|
||||||
while (n--) *d++ = c;
|
|
||||||
return ret;
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue