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