1*27162e4eSAndroid Build Coastguard Worker // Basic test for LZ4_FREESTANDING
2*27162e4eSAndroid Build Coastguard Worker
3*27162e4eSAndroid Build Coastguard Worker // $ gcc -ffreestanding -nostdlib freestanding.c && ./a.out || echo $?
4*27162e4eSAndroid Build Coastguard Worker
5*27162e4eSAndroid Build Coastguard Worker // $ strace ./a.out
6*27162e4eSAndroid Build Coastguard Worker // execve("./a.out", ["./a.out"], 0x7fffaf5fa580 /* 22 vars */) = 0
7*27162e4eSAndroid Build Coastguard Worker // brk(NULL) = 0x56536f4fe000
8*27162e4eSAndroid Build Coastguard Worker // arch_prctl(0x3001 /* ARCH_??? */, 0x7fffc9e74950) = -1 EINVAL (Invalid argument)
9*27162e4eSAndroid Build Coastguard Worker // mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd5c9c2b000
10*27162e4eSAndroid Build Coastguard Worker // access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
11*27162e4eSAndroid Build Coastguard Worker // arch_prctl(ARCH_SET_FS, 0x7fd5c9c2bc40) = 0
12*27162e4eSAndroid Build Coastguard Worker // set_tid_address(0x7fd5c9c2bf10) = 381
13*27162e4eSAndroid Build Coastguard Worker // set_robust_list(0x7fd5c9c2bf20, 24) = 0
14*27162e4eSAndroid Build Coastguard Worker // rseq(0x7fd5c9c2c5e0, 0x20, 0, 0x53053053) = 0
15*27162e4eSAndroid Build Coastguard Worker // mprotect(0x56536ea63000, 4096, PROT_READ) = 0
16*27162e4eSAndroid Build Coastguard Worker // exit(0) = ?
17*27162e4eSAndroid Build Coastguard Worker // +++ exited with 0 +++
18*27162e4eSAndroid Build Coastguard Worker
19*27162e4eSAndroid Build Coastguard Worker // $ ltrace ./a.out
20*27162e4eSAndroid Build Coastguard Worker // +++ exited (status 0) +++
21*27162e4eSAndroid Build Coastguard Worker
22*27162e4eSAndroid Build Coastguard Worker #include <stddef.h>
23*27162e4eSAndroid Build Coastguard Worker #include <stdint.h>
24*27162e4eSAndroid Build Coastguard Worker
25*27162e4eSAndroid Build Coastguard Worker #if defined(__cplusplus)
26*27162e4eSAndroid Build Coastguard Worker # define EXTERN_C extern "C"
27*27162e4eSAndroid Build Coastguard Worker #else
28*27162e4eSAndroid Build Coastguard Worker # define EXTERN_C
29*27162e4eSAndroid Build Coastguard Worker #endif
30*27162e4eSAndroid Build Coastguard Worker
31*27162e4eSAndroid Build Coastguard Worker
32*27162e4eSAndroid Build Coastguard Worker #if !defined(__x86_64__) || !defined(__linux__)
main(int argc,char ** argv)33*27162e4eSAndroid Build Coastguard Worker int main(int argc, char** argv) { return 0; }
34*27162e4eSAndroid Build Coastguard Worker #else
35*27162e4eSAndroid Build Coastguard Worker
36*27162e4eSAndroid Build Coastguard Worker static void MY_exit(int exitCode);
37*27162e4eSAndroid Build Coastguard Worker static void MY_abort(void);
38*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memmove(void *dst, const void *src, size_t n);
39*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n);
40*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memset(void *s, int c, size_t n);
41*27162e4eSAndroid Build Coastguard Worker EXTERN_C int memcmp(const void *s1, const void *s2, size_t n);
42*27162e4eSAndroid Build Coastguard Worker
43*27162e4eSAndroid Build Coastguard Worker // LZ4/HC basic freestanding setup
44*27162e4eSAndroid Build Coastguard Worker #define LZ4_FREESTANDING 1
45*27162e4eSAndroid Build Coastguard Worker #define LZ4_memmove(dst, src, size) memmove((dst),(src),(size))
46*27162e4eSAndroid Build Coastguard Worker #define LZ4_memcpy(dst, src, size) memcpy((dst),(src),(size))
47*27162e4eSAndroid Build Coastguard Worker #define LZ4_memset(p,v,s) memset((p),(v),(s))
48*27162e4eSAndroid Build Coastguard Worker
49*27162e4eSAndroid Build Coastguard Worker #include "../lib/lz4.c"
50*27162e4eSAndroid Build Coastguard Worker #include "../lib/lz4hc.c"
51*27162e4eSAndroid Build Coastguard Worker
52*27162e4eSAndroid Build Coastguard Worker // Test for LZ4
test_lz4(const uint8_t * srcData,int srcSize)53*27162e4eSAndroid Build Coastguard Worker static void test_lz4(const uint8_t* srcData, int srcSize) {
54*27162e4eSAndroid Build Coastguard Worker // Compress
55*27162e4eSAndroid Build Coastguard Worker static uint8_t compressBuffer[1024 * 1024];
56*27162e4eSAndroid Build Coastguard Worker const int compressedSize = LZ4_compress_default(
57*27162e4eSAndroid Build Coastguard Worker (const char*) srcData,
58*27162e4eSAndroid Build Coastguard Worker (char*) compressBuffer,
59*27162e4eSAndroid Build Coastguard Worker srcSize,
60*27162e4eSAndroid Build Coastguard Worker sizeof(compressBuffer)
61*27162e4eSAndroid Build Coastguard Worker );
62*27162e4eSAndroid Build Coastguard Worker if (compressedSize <= 0) {
63*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
64*27162e4eSAndroid Build Coastguard Worker }
65*27162e4eSAndroid Build Coastguard Worker
66*27162e4eSAndroid Build Coastguard Worker // Decompress
67*27162e4eSAndroid Build Coastguard Worker static uint8_t decompressBuffer[1024 * 1024];
68*27162e4eSAndroid Build Coastguard Worker const int decompressedSize = LZ4_decompress_safe(
69*27162e4eSAndroid Build Coastguard Worker (const char*) compressBuffer,
70*27162e4eSAndroid Build Coastguard Worker (char*) decompressBuffer,
71*27162e4eSAndroid Build Coastguard Worker compressedSize,
72*27162e4eSAndroid Build Coastguard Worker sizeof(decompressBuffer)
73*27162e4eSAndroid Build Coastguard Worker );
74*27162e4eSAndroid Build Coastguard Worker if (decompressedSize <= 0) {
75*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
76*27162e4eSAndroid Build Coastguard Worker }
77*27162e4eSAndroid Build Coastguard Worker
78*27162e4eSAndroid Build Coastguard Worker // Verify
79*27162e4eSAndroid Build Coastguard Worker if (decompressedSize != srcSize) {
80*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
81*27162e4eSAndroid Build Coastguard Worker }
82*27162e4eSAndroid Build Coastguard Worker if (memcmp(srcData, decompressBuffer, srcSize) != 0) {
83*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
84*27162e4eSAndroid Build Coastguard Worker }
85*27162e4eSAndroid Build Coastguard Worker }
86*27162e4eSAndroid Build Coastguard Worker
87*27162e4eSAndroid Build Coastguard Worker
88*27162e4eSAndroid Build Coastguard Worker // Test for LZ4HC
test_lz4hc(const uint8_t * srcData,int srcSize)89*27162e4eSAndroid Build Coastguard Worker static void test_lz4hc(const uint8_t* srcData, int srcSize) {
90*27162e4eSAndroid Build Coastguard Worker // Compress
91*27162e4eSAndroid Build Coastguard Worker static uint8_t compressBuffer[1024 * 1024];
92*27162e4eSAndroid Build Coastguard Worker const int compressedSize = LZ4_compress_HC(
93*27162e4eSAndroid Build Coastguard Worker (const char*) srcData,
94*27162e4eSAndroid Build Coastguard Worker (char*) compressBuffer,
95*27162e4eSAndroid Build Coastguard Worker srcSize,
96*27162e4eSAndroid Build Coastguard Worker sizeof(compressBuffer),
97*27162e4eSAndroid Build Coastguard Worker LZ4HC_CLEVEL_DEFAULT
98*27162e4eSAndroid Build Coastguard Worker );
99*27162e4eSAndroid Build Coastguard Worker if (compressedSize <= 0) {
100*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
101*27162e4eSAndroid Build Coastguard Worker }
102*27162e4eSAndroid Build Coastguard Worker
103*27162e4eSAndroid Build Coastguard Worker // Decompress
104*27162e4eSAndroid Build Coastguard Worker static uint8_t decompressBuffer[1024 * 1024];
105*27162e4eSAndroid Build Coastguard Worker const int decompressedSize = LZ4_decompress_safe(
106*27162e4eSAndroid Build Coastguard Worker (const char*) compressBuffer,
107*27162e4eSAndroid Build Coastguard Worker (char*) decompressBuffer,
108*27162e4eSAndroid Build Coastguard Worker compressedSize,
109*27162e4eSAndroid Build Coastguard Worker sizeof(decompressBuffer)
110*27162e4eSAndroid Build Coastguard Worker );
111*27162e4eSAndroid Build Coastguard Worker if (decompressedSize <= 0) {
112*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
113*27162e4eSAndroid Build Coastguard Worker }
114*27162e4eSAndroid Build Coastguard Worker
115*27162e4eSAndroid Build Coastguard Worker // Verify
116*27162e4eSAndroid Build Coastguard Worker if (decompressedSize != srcSize) {
117*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
118*27162e4eSAndroid Build Coastguard Worker }
119*27162e4eSAndroid Build Coastguard Worker if (memcmp(srcData, decompressBuffer, srcSize) != 0) {
120*27162e4eSAndroid Build Coastguard Worker MY_exit(__LINE__);
121*27162e4eSAndroid Build Coastguard Worker }
122*27162e4eSAndroid Build Coastguard Worker }
123*27162e4eSAndroid Build Coastguard Worker
124*27162e4eSAndroid Build Coastguard Worker
test(void)125*27162e4eSAndroid Build Coastguard Worker static void test(void) {
126*27162e4eSAndroid Build Coastguard Worker // First 256 bytes of lz4/README.md
127*27162e4eSAndroid Build Coastguard Worker static const uint8_t README_md[] = {
128*27162e4eSAndroid Build Coastguard Worker 0x4c, 0x5a, 0x34, 0x20, 0x2d, 0x20, 0x45, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65, 0x6c, 0x79, 0x20,
129*27162e4eSAndroid Build Coastguard Worker 0x66, 0x61, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
130*27162e4eSAndroid Build Coastguard Worker 0x0a, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
131*27162e4eSAndroid Build Coastguard Worker 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
132*27162e4eSAndroid Build Coastguard Worker 0x3d, 0x0a, 0x0a, 0x4c, 0x5a, 0x34, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x6f, 0x73, 0x73, 0x6c, 0x65,
133*27162e4eSAndroid Build Coastguard Worker 0x73, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61,
134*27162e4eSAndroid Build Coastguard Worker 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2c, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64,
135*27162e4eSAndroid Build Coastguard Worker 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
136*27162e4eSAndroid Build Coastguard Worker 0x73, 0x70, 0x65, 0x65, 0x64, 0x20, 0x3e, 0x20, 0x35, 0x30, 0x30, 0x20, 0x4d, 0x42, 0x2f, 0x73,
137*27162e4eSAndroid Build Coastguard Worker 0x20, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x2c, 0x0a, 0x73, 0x63, 0x61, 0x6c, 0x61,
138*27162e4eSAndroid Build Coastguard Worker 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x63,
139*27162e4eSAndroid Build Coastguard Worker 0x6f, 0x72, 0x65, 0x73, 0x20, 0x43, 0x50, 0x55, 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x66, 0x65, 0x61,
140*27162e4eSAndroid Build Coastguard Worker 0x74, 0x75, 0x72, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x74, 0x72, 0x65, 0x6d, 0x65,
141*27162e4eSAndroid Build Coastguard Worker 0x6c, 0x79, 0x20, 0x66, 0x61, 0x73, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2c,
142*27162e4eSAndroid Build Coastguard Worker 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x70, 0x65, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6d,
143*27162e4eSAndroid Build Coastguard Worker 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x47, 0x42, 0x2f, 0x73, 0x20, 0x70, 0x65, 0x72,
144*27162e4eSAndroid Build Coastguard Worker };
145*27162e4eSAndroid Build Coastguard Worker
146*27162e4eSAndroid Build Coastguard Worker static const uint8_t* srcData = README_md;
147*27162e4eSAndroid Build Coastguard Worker static const int srcSize = (int) sizeof(README_md);
148*27162e4eSAndroid Build Coastguard Worker test_lz4 (srcData, srcSize);
149*27162e4eSAndroid Build Coastguard Worker test_lz4hc(srcData, srcSize);
150*27162e4eSAndroid Build Coastguard Worker }
151*27162e4eSAndroid Build Coastguard Worker
152*27162e4eSAndroid Build Coastguard Worker
153*27162e4eSAndroid Build Coastguard Worker // low level syscall
154*27162e4eSAndroid Build Coastguard Worker #define SYS_exit (60)
155*27162e4eSAndroid Build Coastguard Worker
os_syscall1(long n,long a1)156*27162e4eSAndroid Build Coastguard Worker static __inline long os_syscall1(long n, long a1) {
157*27162e4eSAndroid Build Coastguard Worker register long rax __asm__ ("rax") = n;
158*27162e4eSAndroid Build Coastguard Worker register long rdi __asm__ ("rdi") = a1;
159*27162e4eSAndroid Build Coastguard Worker __asm__ __volatile__ ("syscall" : "+r"(rax) : "r"(rdi) : "rcx", "r11", "memory");
160*27162e4eSAndroid Build Coastguard Worker return rax;
161*27162e4eSAndroid Build Coastguard Worker }
162*27162e4eSAndroid Build Coastguard Worker
MY_exit(int exitCode)163*27162e4eSAndroid Build Coastguard Worker static void MY_exit(int exitCode) {
164*27162e4eSAndroid Build Coastguard Worker (void) os_syscall1(SYS_exit, exitCode);
165*27162e4eSAndroid Build Coastguard Worker __builtin_unreachable(); // suppress "warning: 'noreturn' function does return"
166*27162e4eSAndroid Build Coastguard Worker }
167*27162e4eSAndroid Build Coastguard Worker
MY_abort(void)168*27162e4eSAndroid Build Coastguard Worker static void MY_abort(void) {
169*27162e4eSAndroid Build Coastguard Worker MY_exit(-1);
170*27162e4eSAndroid Build Coastguard Worker }
171*27162e4eSAndroid Build Coastguard Worker
172*27162e4eSAndroid Build Coastguard Worker // https://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---assert-fail-1.html
__assert_fail(const char * assertion,const char * file,unsigned int line,const char * function)173*27162e4eSAndroid Build Coastguard Worker void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) {
174*27162e4eSAndroid Build Coastguard Worker MY_abort();
175*27162e4eSAndroid Build Coastguard Worker }
176*27162e4eSAndroid Build Coastguard Worker
177*27162e4eSAndroid Build Coastguard Worker
178*27162e4eSAndroid Build Coastguard Worker // GCC requires memcpy, memmove, memset and memcmp.
179*27162e4eSAndroid Build Coastguard Worker // https://gcc.gnu.org/onlinedocs/gcc/Standards.html
180*27162e4eSAndroid Build Coastguard Worker // > GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp.
memmove(void * dst,const void * src,size_t n)181*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memmove(void *dst, const void *src, size_t n) {
182*27162e4eSAndroid Build Coastguard Worker uint8_t* d = (uint8_t*) dst;
183*27162e4eSAndroid Build Coastguard Worker const uint8_t* s = (const uint8_t*) src;
184*27162e4eSAndroid Build Coastguard Worker
185*27162e4eSAndroid Build Coastguard Worker if (d > s) {
186*27162e4eSAndroid Build Coastguard Worker d += n;
187*27162e4eSAndroid Build Coastguard Worker s += n;
188*27162e4eSAndroid Build Coastguard Worker while (n--) {
189*27162e4eSAndroid Build Coastguard Worker *--d = *--s;
190*27162e4eSAndroid Build Coastguard Worker }
191*27162e4eSAndroid Build Coastguard Worker } else {
192*27162e4eSAndroid Build Coastguard Worker while (n--) {
193*27162e4eSAndroid Build Coastguard Worker *d++ = *s++;
194*27162e4eSAndroid Build Coastguard Worker }
195*27162e4eSAndroid Build Coastguard Worker }
196*27162e4eSAndroid Build Coastguard Worker return dst;
197*27162e4eSAndroid Build Coastguard Worker }
198*27162e4eSAndroid Build Coastguard Worker
memcpy(void * __restrict__ dst,const void * __restrict__ src,size_t n)199*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memcpy(void * __restrict__ dst, const void * __restrict__ src, size_t n) {
200*27162e4eSAndroid Build Coastguard Worker return memmove(dst, src, n);
201*27162e4eSAndroid Build Coastguard Worker }
202*27162e4eSAndroid Build Coastguard Worker
memset(void * s,int c,size_t n)203*27162e4eSAndroid Build Coastguard Worker EXTERN_C void *memset(void *s, int c, size_t n) {
204*27162e4eSAndroid Build Coastguard Worker uint8_t* p = (uint8_t*) s;
205*27162e4eSAndroid Build Coastguard Worker while (n--) {
206*27162e4eSAndroid Build Coastguard Worker *p++ = (uint8_t) c;
207*27162e4eSAndroid Build Coastguard Worker }
208*27162e4eSAndroid Build Coastguard Worker return s;
209*27162e4eSAndroid Build Coastguard Worker }
210*27162e4eSAndroid Build Coastguard Worker
memcmp(const void * s1,const void * s2,size_t n)211*27162e4eSAndroid Build Coastguard Worker EXTERN_C int memcmp(const void *s1, const void *s2, size_t n) {
212*27162e4eSAndroid Build Coastguard Worker const uint8_t* p1 = (const uint8_t*) s1;
213*27162e4eSAndroid Build Coastguard Worker const uint8_t* p2 = (const uint8_t*) s2;
214*27162e4eSAndroid Build Coastguard Worker while (n--) {
215*27162e4eSAndroid Build Coastguard Worker const uint8_t c1 = *p1++;
216*27162e4eSAndroid Build Coastguard Worker const uint8_t c2 = *p2++;
217*27162e4eSAndroid Build Coastguard Worker if (c1 < c2) {
218*27162e4eSAndroid Build Coastguard Worker return -1;
219*27162e4eSAndroid Build Coastguard Worker } else if (c1 > c2) {
220*27162e4eSAndroid Build Coastguard Worker return 1;
221*27162e4eSAndroid Build Coastguard Worker }
222*27162e4eSAndroid Build Coastguard Worker }
223*27162e4eSAndroid Build Coastguard Worker return 0;
224*27162e4eSAndroid Build Coastguard Worker }
225*27162e4eSAndroid Build Coastguard Worker
226*27162e4eSAndroid Build Coastguard Worker
227*27162e4eSAndroid Build Coastguard Worker //
_start(void)228*27162e4eSAndroid Build Coastguard Worker EXTERN_C void _start(void) {
229*27162e4eSAndroid Build Coastguard Worker test();
230*27162e4eSAndroid Build Coastguard Worker MY_exit(0);
231*27162e4eSAndroid Build Coastguard Worker }
232*27162e4eSAndroid Build Coastguard Worker
main(int argc,char ** argv)233*27162e4eSAndroid Build Coastguard Worker int main(int argc, char** argv) {
234*27162e4eSAndroid Build Coastguard Worker test();
235*27162e4eSAndroid Build Coastguard Worker MY_exit(0);
236*27162e4eSAndroid Build Coastguard Worker return 0;
237*27162e4eSAndroid Build Coastguard Worker }
238*27162e4eSAndroid Build Coastguard Worker #endif
239