From 721e76d1af1d248d0e6fefb2a090cd4b1c4a08f2 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:06:37 +0900 Subject: Add LZ4_FREESTANDING --- lib/lz4.c | 4 +++- lib/lz4.h | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/lz4.c b/lib/lz4.c index 5fae0029..ad12281f 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -209,7 +209,9 @@ void LZ4_free(void* p); # define FREEMEM(p) free(p) #endif -#include /* memset, memcpy */ +#if ! LZ4_FREESTANDING +# include /* memset, memcpy */ +#endif #if !defined(LZ4_memset) # define LZ4_memset(p,v,s) memset((p),(v),(s)) #endif diff --git a/lib/lz4.h b/lib/lz4.h index fee8890e..01ab4459 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -97,6 +97,29 @@ extern "C" { # define LZ4LIB_API LZ4LIB_VISIBILITY #endif +/*! + * LZ4_FREESTANDING : + * Enable "freestanding mode" that is suitable for typical freestanding environment. + * In freestanding mode, some LZ4/HC functions which use heap are disabled. + */ +#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1) +# define LZ4_HEAPMODE 0 +# define LZ4HC_HEAPMODE 0 +# define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1 +# if !defined(LZ4_memcpy) +# error "LZ4_FREESTANDING requires macro 'LZ4_memcpy'." +# endif +# if !defined(LZ4_memset) +# error "LZ4_FREESTANDING requires macro 'LZ4_memset'." +# endif +# if !defined(LZ4_memmove) +# error "LZ4_FREESTANDING requires macro 'LZ4_memmove'." +# endif +#elif ! defined(LZ4_FREESTANDING) +# define LZ4_FREESTANDING 0 +#endif + + /*------ Version ------*/ #define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ #define LZ4_VERSION_MINOR 9 /* for new (non-breaking) interface capabilities */ -- cgit v1.2.3 From 50915609a9a0c1feb616c4de534f4a388d48f79a Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:07:41 +0900 Subject: Fix: Disable LZ4HC correspond functions when LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION is enabled --- lib/lz4hc.c | 2 ++ lib/lz4hc.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 4771ef8f..b21ad6bb 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -1225,6 +1225,7 @@ int LZ4_resetStreamStateHC(void* state, char* inputBuffer) return 0; } +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) void* LZ4_createHC (const char* inputBuffer) { LZ4_streamHC_t* const hc4 = LZ4_createStreamHC(); @@ -1239,6 +1240,7 @@ int LZ4_freeHC (void* LZ4HC_Data) FREEMEM(LZ4HC_Data); return 0; } +#endif int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel) { diff --git a/lib/lz4hc.h b/lib/lz4hc.h index d2e51934..e937acfe 100644 --- a/lib/lz4hc.h +++ b/lib/lz4hc.h @@ -270,9 +270,11 @@ LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_comp * LZ4_slideInputBufferHC() will truncate the history of the stream, rather * than preserve a window-sized chunk of history. */ +#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer); -LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data); LZ4_DEPRECATED("use LZ4_freeStreamHC() instead") LZ4LIB_API int LZ4_freeHC (void* LZ4HC_Data); +#endif +LZ4_DEPRECATED("use LZ4_saveDictHC() instead") LZ4LIB_API char* LZ4_slideInputBufferHC (void* LZ4HC_Data); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_compress_HC_continue() instead") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel); LZ4_DEPRECATED("use LZ4_createStreamHC() instead") LZ4LIB_API int LZ4_sizeofStreamStateHC(void); -- cgit v1.2.3 From f88f02f78c6c609c912ce0ee1773ee07d6e2e7ac Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:08:59 +0900 Subject: Add LZ4_FREESTANDING test on Linux x86-64 platform Also added tests/Makefile entry "test-freestanding". --- tests/.gitignore | 1 + tests/Makefile | 15 +++- tests/freestanding.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 3 deletions(-) create mode 100644 tests/freestanding.c diff --git a/tests/.gitignore b/tests/.gitignore index 5337fdbd..c7d8f19b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -14,6 +14,7 @@ checkFrame decompress-partial decompress-partial-usingDict abiTest +freestanding # test artefacts tmp* diff --git a/tests/Makefile b/tests/Makefile index 4b6ea489..33309b45 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -56,7 +56,7 @@ NB_LOOPS ?= -i1 .PHONY: default default: all -all: fullbench fuzzer frametest roundTripTest datagen checkFrame decompress-partial +all: fullbench fuzzer frametest roundTripTest datagen checkFrame decompress-partial freestanding all32: CFLAGS+=-m32 all32: all @@ -115,6 +115,9 @@ decompress-partial: lz4.o decompress-partial.c decompress-partial-usingDict: lz4.o decompress-partial-usingDict.c $(CC) $(FLAGS) $^ -o $@$(EXT) +freestanding: freestanding.c + $(CC) -ffreestanding -nostdlib $^ -o $@$(EXT) + .PHONY: clean clean: @$(MAKE) -C $(LZ4DIR) $@ > $(VOID) @@ -127,7 +130,7 @@ clean: fasttest$(EXT) roundTripTest$(EXT) \ datagen$(EXT) checkTag$(EXT) \ frameTest$(EXT) decompress-partial$(EXT) \ - abiTest$(EXT) \ + abiTest$(EXT) freestanding$(EXT) \ lz4_all.c @$(RM) -rf $(TESTDIR) @echo Cleaning completed @@ -179,7 +182,7 @@ list: check: test-lz4-essentials .PHONY: test -test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-amalgamation listTest test-decompress-partial +test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-amalgamation listTest test-decompress-partial test-freestanding .PHONY: test32 test32: CFLAGS+=-m32 @@ -606,4 +609,10 @@ test-decompress-partial : decompress-partial decompress-partial-usingDict @echo "\n ---- test decompress-partial-usingDict ----" ./decompress-partial-usingDict$(EXT) +test-freestanding: freestanding + @echo "\n ---- test freestanding ----" + ./freestanding$(EXT) + strace ./freestanding$(EXT) + ltrace ./freestanding$(EXT) + endif diff --git a/tests/freestanding.c b/tests/freestanding.c new file mode 100644 index 00000000..27813582 --- /dev/null +++ b/tests/freestanding.c @@ -0,0 +1,231 @@ +// Basic test for LZ4_FREESTANDING + +// $ gcc -ffreestanding -nostdlib freestanding.c && ./a.out || echo $? + +// $ strace ./a.out +// execve("./a.out", ["./a.out"], 0x7fffaf5fa580 /* 22 vars */) = 0 +// brk(NULL) = 0x56536f4fe000 +// arch_prctl(0x3001 /* ARCH_??? */, 0x7fffc9e74950) = -1 EINVAL (Invalid argument) +// mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd5c9c2b000 +// access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) +// arch_prctl(ARCH_SET_FS, 0x7fd5c9c2bc40) = 0 +// set_tid_address(0x7fd5c9c2bf10) = 381 +// set_robust_list(0x7fd5c9c2bf20, 24) = 0 +// rseq(0x7fd5c9c2c5e0, 0x20, 0, 0x53053053) = 0 +// mprotect(0x56536ea63000, 4096, PROT_READ) = 0 +// exit(0) = ? +// +++ exited with 0 +++ + +// $ ltrace ./a.out +// +++ exited (status 0) +++ + +#if !defined(__x86_64__) || !defined(__linux__) +# error This test only supports Linux __x86_64__ +#endif + +#include +#include + +static void MY_exit(int exitCode); +static void MY_abort(void); +void *memmove(void *dst, const void *src, size_t n); +void *memcpy(void * restrict dst, const void * restrict src, size_t n); +void *memset(void *s, int c, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); + +// LZ4/HC basic freestanding setup +#define LZ4_FREESTANDING 1 +#define LZ4_memmove(dst, src, size) memmove((dst),(src),(size)) +#define LZ4_memcpy(dst, src, size) memcpy((dst),(src),(size)) +#define LZ4_memset(p,v,s) memset((p),(v),(s)) + +#include "../lib/lz4.c" +#include "../lib/lz4hc.c" + + +// Test for LZ4 +static void test_lz4(const uint8_t* srcData, int srcSize) { + // Compress + static uint8_t compressBuffer[1024 * 1024]; + const int compressedSize = LZ4_compress_default( + srcData, + compressBuffer, + srcSize, + sizeof(compressBuffer) + ); + if (compressedSize <= 0) { + MY_exit(__LINE__); + } + + // Decompress + static uint8_t decompressBuffer[1024 * 1024]; + const int decompressedSize = LZ4_decompress_safe( + compressBuffer, + decompressBuffer, + compressedSize, + sizeof(decompressBuffer) + ); + if (decompressedSize <= 0) { + MY_exit(__LINE__); + } + + // Verify + if (decompressedSize != srcSize) { + MY_exit(__LINE__); + } + if (memcmp(srcData, decompressBuffer, srcSize) != 0) { + MY_exit(__LINE__); + } +} + + +// Test for LZ4HC +static void test_lz4hc(const uint8_t* srcData, int srcSize) { + // Compress + static uint8_t compressBuffer[1024 * 1024]; + const int compressedSize = LZ4_compress_HC( + srcData, + compressBuffer, + srcSize, + sizeof(compressBuffer), + LZ4HC_CLEVEL_DEFAULT + ); + if (compressedSize <= 0) { + MY_exit(__LINE__); + } + + // Decompress + static uint8_t decompressBuffer[1024 * 1024]; + const int decompressedSize = LZ4_decompress_safe( + compressBuffer, + decompressBuffer, + compressedSize, + sizeof(decompressBuffer) + ); + if (decompressedSize <= 0) { + MY_exit(__LINE__); + } + + // Verify + if (decompressedSize != srcSize) { + MY_exit(__LINE__); + } + if (memcmp(srcData, decompressBuffer, srcSize) != 0) { + MY_exit(__LINE__); + } +} + + +static void test(void) { + // First 256 bytes of lz4/README.md + static const uint8_t README_md[] = { + 0x4c, 0x5a, 0x34, 0x20, 0x2d, 0x20, 0x45, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65, 0x6c, 0x79, 0x20, + 0x66, 0x61, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x0a, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, + 0x3d, 0x0a, 0x0a, 0x4c, 0x5a, 0x34, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x6f, 0x73, 0x73, 0x6c, 0x65, + 0x73, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2c, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, + 0x73, 0x70, 0x65, 0x65, 0x64, 0x20, 0x3e, 0x20, 0x35, 0x30, 0x30, 0x20, 0x4d, 0x42, 0x2f, 0x73, + 0x20, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x2c, 0x0a, 0x73, 0x63, 0x61, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x63, + 0x6f, 0x72, 0x65, 0x73, 0x20, 0x43, 0x50, 0x55, 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65, + 0x6c, 0x79, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2c, + 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x70, 0x65, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x47, 0x42, 0x2f, 0x73, 0x20, 0x70, 0x65, 0x72, + }; + + static const uint8_t* srcData = README_md; + static const int srcSize = (int) sizeof(README_md); + test_lz4 (srcData, srcSize); + test_lz4hc(srcData, srcSize); +} + + +// low level syscall +#define SYS_exit (60) + +static __inline long os_syscall1(long n, long a1) { + register long rax __asm__ ("rax") = n; + register long rdi __asm__ ("rdi") = a1; + __asm__ __volatile__ ("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory"); + return rax; +} + +static void MY_exit(int exitCode) { + (void) os_syscall1(SYS_exit, exitCode); + __builtin_unreachable(); // suppress "warning: 'noreturn' function does return" +} + +static void MY_abort(void) { + MY_exit(-1); +} + +// https://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---assert-fail-1.html +void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) { + MY_abort(); +} + + +// GCC requires memcpy, memmove, memset and memcmp. +// https://gcc.gnu.org/onlinedocs/gcc/Standards.html +// > GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. +void *memmove(void *dst, const void *src, size_t n) { + uint8_t* d = dst; + const uint8_t* s = src; + + if (d > s) { + d += n; + s += n; + while (n--) { + *--d = *--s; + } + } else { + while (n--) { + *d++ = *s++; + } + } + return dst; +} + +void *memcpy(void * restrict dst, const void * restrict src, size_t n) { + return memmove(dst, src, n); +} + +void *memset(void *s, int c, size_t n) { + uint8_t* p = s; + while (n--) { + *p++ = (uint8_t) c; + } + return s; +} + +int memcmp(const void *s1, const void *s2, size_t n) { + const uint8_t* p1 = (const uint8_t*) s1; + const uint8_t* p2 = (const uint8_t*) s2; + while (n--) { + const uint8_t c1 = *p1++; + const uint8_t c2 = *p2++; + if (c1 < c2) { + return -1; + } else if (c1 > c2) { + return 1; + } + } + return 0; +} + + +// +void _start(void) { + test(); + MY_exit(0); +} + +int main(int argc, char** argv) { + test(); + MY_exit(0); + return 0; +} -- cgit v1.2.3 From 70e76e50b1f011685d95622049e63cf2bd47e5f8 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:26:01 +0900 Subject: Fix for ctocpptest --- tests/freestanding.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/freestanding.c b/tests/freestanding.c index 27813582..00cd6957 100644 --- a/tests/freestanding.c +++ b/tests/freestanding.c @@ -29,7 +29,7 @@ static void MY_exit(int exitCode); static void MY_abort(void); void *memmove(void *dst, const void *src, size_t n); -void *memcpy(void * restrict dst, const void * restrict src, size_t n); +void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n); void *memset(void *s, int c, size_t n); int memcmp(const void *s1, const void *s2, size_t n); @@ -48,8 +48,8 @@ static void test_lz4(const uint8_t* srcData, int srcSize) { // Compress static uint8_t compressBuffer[1024 * 1024]; const int compressedSize = LZ4_compress_default( - srcData, - compressBuffer, + (const char*) srcData, + (char*) compressBuffer, srcSize, sizeof(compressBuffer) ); @@ -60,8 +60,8 @@ static void test_lz4(const uint8_t* srcData, int srcSize) { // Decompress static uint8_t decompressBuffer[1024 * 1024]; const int decompressedSize = LZ4_decompress_safe( - compressBuffer, - decompressBuffer, + (const char*) compressBuffer, + (char*) decompressBuffer, compressedSize, sizeof(decompressBuffer) ); @@ -84,8 +84,8 @@ static void test_lz4hc(const uint8_t* srcData, int srcSize) { // Compress static uint8_t compressBuffer[1024 * 1024]; const int compressedSize = LZ4_compress_HC( - srcData, - compressBuffer, + (const char*) srcData, + (char*) compressBuffer, srcSize, sizeof(compressBuffer), LZ4HC_CLEVEL_DEFAULT @@ -97,8 +97,8 @@ static void test_lz4hc(const uint8_t* srcData, int srcSize) { // Decompress static uint8_t decompressBuffer[1024 * 1024]; const int decompressedSize = LZ4_decompress_safe( - compressBuffer, - decompressBuffer, + (const char*) compressBuffer, + (char*) decompressBuffer, compressedSize, sizeof(decompressBuffer) ); @@ -173,8 +173,8 @@ void __assert_fail(const char * assertion, const char * file, unsigned int line, // https://gcc.gnu.org/onlinedocs/gcc/Standards.html // > GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. void *memmove(void *dst, const void *src, size_t n) { - uint8_t* d = dst; - const uint8_t* s = src; + uint8_t* d = (uint8_t*) dst; + const uint8_t* s = (const uint8_t*) src; if (d > s) { d += n; @@ -190,12 +190,12 @@ void *memmove(void *dst, const void *src, size_t n) { return dst; } -void *memcpy(void * restrict dst, const void * restrict src, size_t n) { +void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n) { return memmove(dst, src, n); } void *memset(void *s, int c, size_t n) { - uint8_t* p = s; + uint8_t* p = (uint8_t*) s; while (n--) { *p++ = (uint8_t) c; } @@ -219,6 +219,9 @@ int memcmp(const void *s1, const void *s2, size_t n) { // +#if defined(__cplusplus) +extern "C" +#endif void _start(void) { test(); MY_exit(0); -- cgit v1.2.3 From cdf515c90ff32f681be3ee97e5889f8cdd9ed143 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:39:50 +0900 Subject: Fix: Add extern "C" to all standard C replacement functions --- tests/freestanding.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/freestanding.c b/tests/freestanding.c index 00cd6957..6bf2e6d1 100644 --- a/tests/freestanding.c +++ b/tests/freestanding.c @@ -26,12 +26,19 @@ #include #include +#if defined(__cplusplus) +# define EXTERN_C extern "C" +#else +# define EXTERN_C +#endif + + static void MY_exit(int exitCode); static void MY_abort(void); -void *memmove(void *dst, const void *src, size_t n); -void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n); -void *memset(void *s, int c, size_t n); -int memcmp(const void *s1, const void *s2, size_t n); +EXTERN_C void *memmove(void *dst, const void *src, size_t n); +EXTERN_C void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n); +EXTERN_C void *memset(void *s, int c, size_t n); +EXTERN_C int memcmp(const void *s1, const void *s2, size_t n); // LZ4/HC basic freestanding setup #define LZ4_FREESTANDING 1 @@ -42,7 +49,6 @@ int memcmp(const void *s1, const void *s2, size_t n); #include "../lib/lz4.c" #include "../lib/lz4hc.c" - // Test for LZ4 static void test_lz4(const uint8_t* srcData, int srcSize) { // Compress @@ -172,7 +178,7 @@ void __assert_fail(const char * assertion, const char * file, unsigned int line, // GCC requires memcpy, memmove, memset and memcmp. // https://gcc.gnu.org/onlinedocs/gcc/Standards.html // > GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. -void *memmove(void *dst, const void *src, size_t n) { +EXTERN_C void *memmove(void *dst, const void *src, size_t n) { uint8_t* d = (uint8_t*) dst; const uint8_t* s = (const uint8_t*) src; @@ -190,11 +196,11 @@ void *memmove(void *dst, const void *src, size_t n) { return dst; } -void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n) { +EXTERN_C void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n) { return memmove(dst, src, n); } -void *memset(void *s, int c, size_t n) { +EXTERN_C void *memset(void *s, int c, size_t n) { uint8_t* p = (uint8_t*) s; while (n--) { *p++ = (uint8_t) c; @@ -202,7 +208,7 @@ void *memset(void *s, int c, size_t n) { return s; } -int memcmp(const void *s1, const void *s2, size_t n) { +EXTERN_C int memcmp(const void *s1, const void *s2, size_t n) { const uint8_t* p1 = (const uint8_t*) s1; const uint8_t* p2 = (const uint8_t*) s2; while (n--) { @@ -219,10 +225,7 @@ int memcmp(const void *s1, const void *s2, size_t n) { // -#if defined(__cplusplus) -extern "C" -#endif -void _start(void) { +EXTERN_C void _start(void) { test(); MY_exit(0); } -- cgit v1.2.3 From 431a793b243360bd962e8f6f02884606693b34d9 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 19:43:54 +0900 Subject: Fix: implement empty _start and main for non-Linux or x86-64 platforms --- tests/freestanding.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/freestanding.c b/tests/freestanding.c index 6bf2e6d1..ceff4c5a 100644 --- a/tests/freestanding.c +++ b/tests/freestanding.c @@ -19,10 +19,6 @@ // $ ltrace ./a.out // +++ exited (status 0) +++ -#if !defined(__x86_64__) || !defined(__linux__) -# error This test only supports Linux __x86_64__ -#endif - #include #include @@ -33,6 +29,11 @@ #endif +#if !defined(__x86_64__) || !defined(__linux__) +EXTERN_C void _start(void) { } +int main(int argc, char** argv) { return 0; } +#else + static void MY_exit(int exitCode); static void MY_abort(void); EXTERN_C void *memmove(void *dst, const void *src, size_t n); @@ -235,3 +236,4 @@ int main(int argc, char** argv) { MY_exit(0); return 0; } +#endif -- cgit v1.2.3 From 79b40d61b87531e76c70871e60166811a9e57563 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Sun, 7 Aug 2022 20:07:01 +0900 Subject: Fix: Ignore exitcode of strace and ltrace --- tests/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 33309b45..dc630417 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -612,7 +612,7 @@ test-decompress-partial : decompress-partial decompress-partial-usingDict test-freestanding: freestanding @echo "\n ---- test freestanding ----" ./freestanding$(EXT) - strace ./freestanding$(EXT) - ltrace ./freestanding$(EXT) + -strace ./freestanding$(EXT) + -ltrace ./freestanding$(EXT) endif -- cgit v1.2.3 From aa2699707b575d55dbc22e96e81cad6357cd8526 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Mon, 8 Aug 2022 18:04:13 +0900 Subject: Remove test-freestanding from tests/Makefile "all" and "test" Since test-freestanding is able to be compiled and executed in specific environment, we should not run it in our standard test. --- tests/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index dc630417..93a5581c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -56,7 +56,7 @@ NB_LOOPS ?= -i1 .PHONY: default default: all -all: fullbench fuzzer frametest roundTripTest datagen checkFrame decompress-partial freestanding +all: fullbench fuzzer frametest roundTripTest datagen checkFrame decompress-partial all32: CFLAGS+=-m32 all32: all @@ -182,7 +182,7 @@ list: check: test-lz4-essentials .PHONY: test -test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-amalgamation listTest test-decompress-partial test-freestanding +test: test-lz4 test-lz4c test-frametest test-fullbench test-fuzzer test-amalgamation listTest test-decompress-partial .PHONY: test32 test32: CFLAGS+=-m32 -- cgit v1.2.3 From 4b74762203201997a5d01c075809fd6f83b906b7 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Mon, 8 Aug 2022 18:04:48 +0900 Subject: Add test-freestanding to Makefile --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 9e12ae77..e70c3dbd 100644 --- a/Makefile +++ b/Makefile @@ -190,6 +190,10 @@ platformTest: clean versionsTest: clean $(MAKE) -C $(TESTDIR) $@ +.PHONY: test-freestanding +test-freestanding: + $(MAKE) -C $(TESTDIR) clean $@ + .PHONY: cxxtest cxx32test cxxtest cxx32test: CC := "$(CXX) -Wno-deprecated" cxxtest cxx32test: CFLAGS = -O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -- cgit v1.2.3 From d0460e4aaab84d50f2db0cb303ea0f6fe84745ce Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Mon, 8 Aug 2022 18:11:05 +0900 Subject: Add freestanding test to specific target in ci.yml The 'freestanding' flag indicates a capability of compiling and executing freestanding code. Currently it requires Linux, x86_64 and (relatively newer) gcc/g++. --- .github/workflows/ci.yml | 66 ++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3101d4f8..f27b99a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,42 +25,44 @@ jobs: include: [ # You can access the following values via ${{ matrix.??? }} # - # pkgs : apt-get package names. It can include multiple package names which are delimited by space. - # cc : C compiler executable. - # cxx : C++ compiler executable for `make ctocpptest`. - # x32 : Set 'true' if compiler supports x32. Otherwise, set 'false'. - # Set 'fail' if it supports x32 but fails for now. 'fail' cases must be removed. - # x86 : Set 'true' if compiler supports x86 (-m32). Otherwise, set 'false'. - # Set 'fail' if it supports x86 but fails for now. 'fail' cases must be removed. - # cxxtest : Set 'true' if it can be compiled as C++ code. Otherwise, set 'false'. - # os : GitHub Actions YAML workflow label. See https://github.com/actions/virtual-environments#available-environments + # pkgs : apt-get package names. It can include multiple package names which are delimited by space. + # cc : C compiler executable. + # cxx : C++ compiler executable for `make ctocpptest`. + # x32 : Set 'true' if compiler supports x32. Otherwise, set 'false'. + # Set 'fail' if it supports x32 but fails for now. 'fail' cases must be removed. + # x86 : Set 'true' if compiler supports x86 (-m32). Otherwise, set 'false'. + # Set 'fail' if it supports x86 but fails for now. 'fail' cases must be removed. + # cxxtest : Set 'true' if it can be compiled as C++ code. Otherwise, set 'false'. + # freestanding : Set 'true' if it can be compiled and execute freestanding code. Otherwise, set 'false'. + # Usually, it requires Linux, x86_64 and gcc/g++. + # os : GitHub Actions YAML workflow label. See https://github.com/actions/virtual-environments#available-environments # cc - { pkgs: '', cc: cc, cxx: c++, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-latest, }, + { pkgs: '', cc: cc, cxx: c++, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-latest, }, # gcc - { pkgs: '', cc: gcc, cxx: g++, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-latest, }, - { pkgs: 'gcc-11 g++-11 lib32gcc-11-dev libx32gcc-11-dev', cc: gcc-11, cxx: g++-11, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'gcc-10 lib32gcc-10-dev libx32gcc-10-dev', cc: gcc-10, cxx: g++-10, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'gcc-9 lib32gcc-9-dev libx32gcc-9-dev', cc: gcc-9, cxx: g++-9, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'gcc-8 g++-8 lib32gcc-8-dev libx32gcc-8-dev', cc: gcc-8, cxx: g++-8, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'gcc-7 g++-7 lib32gcc-7-dev libx32gcc-7-dev', cc: gcc-7, cxx: g++-7, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'gcc-6 g++-6 lib32gcc-6-dev libx32gcc-6-dev', cc: gcc-6, cxx: g++-6, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-18.04, }, - { pkgs: 'gcc-5 g++-5 lib32gcc-5-dev libx32gcc-5-dev', cc: gcc-5, cxx: g++-5, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-18.04, }, - { pkgs: 'gcc-4.8 g++-4.8 lib32gcc-4.8-dev libx32gcc-4.8-dev', cc: gcc-4.8, cxx: g++-4.8, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-18.04, }, + { pkgs: '', cc: gcc, cxx: g++, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-latest, }, + { pkgs: 'gcc-11 g++-11 lib32gcc-11-dev libx32gcc-11-dev', cc: gcc-11, cxx: g++-11, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-20.04, }, + { pkgs: 'gcc-10 lib32gcc-10-dev libx32gcc-10-dev', cc: gcc-10, cxx: g++-10, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-20.04, }, + { pkgs: 'gcc-9 lib32gcc-9-dev libx32gcc-9-dev', cc: gcc-9, cxx: g++-9, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-20.04, }, + { pkgs: 'gcc-8 g++-8 lib32gcc-8-dev libx32gcc-8-dev', cc: gcc-8, cxx: g++-8, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-20.04, }, + { pkgs: 'gcc-7 g++-7 lib32gcc-7-dev libx32gcc-7-dev', cc: gcc-7, cxx: g++-7, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-20.04, }, + { pkgs: 'gcc-6 g++-6 lib32gcc-6-dev libx32gcc-6-dev', cc: gcc-6, cxx: g++-6, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-18.04, }, + { pkgs: 'gcc-5 g++-5 lib32gcc-5-dev libx32gcc-5-dev', cc: gcc-5, cxx: g++-5, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-18.04, }, + { pkgs: 'gcc-4.8 g++-4.8 lib32gcc-4.8-dev libx32gcc-4.8-dev', cc: gcc-4.8, cxx: g++-4.8, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'true', os: ubuntu-18.04, }, # clang - { pkgs: 'lib32gcc-11-dev libx32gcc-11-dev', cc: clang, cxx: clang++, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-latest, }, - { pkgs: 'clang-12 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-12, cxx: clang++-12, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-11 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-11, cxx: clang++-11, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-10 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-10, cxx: clang++-10, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-9 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-9, cxx: clang++-9, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-8 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-8, cxx: clang++-8, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-7 lib32gcc-7-dev libx32gcc-7-dev', cc: clang-7, cxx: clang++-7, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-6.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-6.0, cxx: clang++-6.0, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-20.04, }, - { pkgs: 'clang-5.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-5.0, cxx: clang++-5.0, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-18.04, }, - { pkgs: 'clang-4.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-4.0, cxx: clang++-4.0, x32: 'true', x86: 'true', cxxtest: 'true', os: ubuntu-18.04, }, - { pkgs: 'clang-3.9', cc: clang-3.9, cxx: clang++-3.9, x32: 'fail', x86: 'fail', cxxtest: 'false', os: ubuntu-18.04, }, + { pkgs: 'lib32gcc-11-dev libx32gcc-11-dev', cc: clang, cxx: clang++, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-latest, }, + { pkgs: 'clang-12 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-12, cxx: clang++-12, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-11 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-11, cxx: clang++-11, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-10 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-10, cxx: clang++-10, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-9 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-9, cxx: clang++-9, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-8 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-8, cxx: clang++-8, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-7 lib32gcc-7-dev libx32gcc-7-dev', cc: clang-7, cxx: clang++-7, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-6.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-6.0, cxx: clang++-6.0, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-20.04, }, + { pkgs: 'clang-5.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-5.0, cxx: clang++-5.0, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-18.04, }, + { pkgs: 'clang-4.0 lib32gcc-11-dev libx32gcc-11-dev', cc: clang-4.0, cxx: clang++-4.0, x32: 'true', x86: 'true', cxxtest: 'true', freestanding: 'false', os: ubuntu-18.04, }, + { pkgs: 'clang-3.9', cc: clang-3.9, cxx: clang++-3.9, x32: 'fail', x86: 'fail', cxxtest: 'false', freestanding: 'false', os: ubuntu-18.04, }, ] runs-on: ${{ matrix.os }} @@ -111,6 +113,10 @@ jobs: if: ${{ matrix.cxxtest == 'true' }} run: make V=1 clean cxxtest + - name: make test-freestanding + if: ${{ matrix.freestanding == 'true' }} + run: make V=1 clean test-freestanding + - name: make -C programs default if: always() run: make V=1 -C programs clean default -- cgit v1.2.3 From d0928a7f2071b9f06a32780d79c0c5a0b204c360 Mon Sep 17 00:00:00 2001 From: Takayuki Matsuoka Date: Thu, 11 Aug 2022 01:09:53 +0900 Subject: Add short document of LZ4_FREESTANDING to lz4.h --- lib/lz4.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/lz4.h b/lib/lz4.h index 01ab4459..9d93eb1f 100644 --- a/lib/lz4.h +++ b/lib/lz4.h @@ -97,10 +97,17 @@ extern "C" { # define LZ4LIB_API LZ4LIB_VISIBILITY #endif -/*! - * LZ4_FREESTANDING : - * Enable "freestanding mode" that is suitable for typical freestanding environment. - * In freestanding mode, some LZ4/HC functions which use heap are disabled. +/*! LZ4_FREESTANDING : + * When this macro is set to 1, it enables "freestanding mode" that is + * suitable for typical freestanding environment which doesn't support + * standard C library. + * + * - LZ4_FREESTANDING is a compile-time switch. + * - It requires the following macros to be defined: + * LZ4_memcpy, LZ4_memmove, LZ4_memset. + * - It only enables LZ4/HC functions which don't use heap. + * All LZ4F_* functions are not supported. + * - See tests/freestanding.c to check its basic setup. */ #if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1) # define LZ4_HEAPMODE 0 -- cgit v1.2.3