1 /*
2  * Copyright (c) 2016-2020, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 #include "hs_common.h"
31 #include "hs_runtime.h"
32 #include "ue2common.h"
33 #include "util/cpuid_inline.h"
34 #include "util/join.h"
35 
36 #if defined(DISABLE_AVX512_DISPATCH)
37 #define avx512_ disabled_
38 #define check_avx512() (0)
39 #endif
40 
41 #if defined(DISABLE_AVX512VBMI_DISPATCH)
42 #define avx512vbmi_ disabled_
43 #define check_avx512vbmi() (0)
44 #endif
45 
46 #define CREATE_DISPATCH(RTYPE, NAME, ...)                                      \
47     /* create defns */                                                         \
48     RTYPE JOIN(avx512vbmi_, NAME)(__VA_ARGS__);                                \
49     RTYPE JOIN(avx512_, NAME)(__VA_ARGS__);                                    \
50     RTYPE JOIN(avx2_, NAME)(__VA_ARGS__);                                      \
51     RTYPE JOIN(corei7_, NAME)(__VA_ARGS__);                                    \
52     RTYPE JOIN(core2_, NAME)(__VA_ARGS__);                                     \
53                                                                                \
54     /* error func */                                                           \
55     static inline RTYPE JOIN(error_, NAME)(__VA_ARGS__) {                      \
56         return (RTYPE)HS_ARCH_ERROR;                                           \
57     }                                                                          \
58                                                                                \
59     /* resolver */                                                             \
60     static RTYPE (*JOIN(resolve_, NAME)(void))(__VA_ARGS__) {                  \
61         if (check_avx512vbmi()) {                                              \
62             return JOIN(avx512vbmi_, NAME);                                    \
63         }                                                                      \
64         if (check_avx512()) {                                                  \
65             return JOIN(avx512_, NAME);                                        \
66         }                                                                      \
67         if (check_avx2()) {                                                    \
68             return JOIN(avx2_, NAME);                                          \
69         }                                                                      \
70         if (check_sse42() && check_popcnt()) {                                 \
71             return JOIN(corei7_, NAME);                                        \
72         }                                                                      \
73         if (check_ssse3()) {                                                   \
74             return JOIN(core2_, NAME);                                         \
75         }                                                                      \
76         /* anything else is fail */                                            \
77         return JOIN(error_, NAME);                                             \
78     }                                                                          \
79                                                                                \
80     /* function */                                                             \
81     HS_PUBLIC_API                                                              \
82     RTYPE NAME(__VA_ARGS__) __attribute__((ifunc("resolve_" #NAME)))
83 
84 CREATE_DISPATCH(hs_error_t, hs_scan, const hs_database_t *db, const char *data,
85                 unsigned length, unsigned flags, hs_scratch_t *scratch,
86                 match_event_handler onEvent, void *userCtx);
87 
88 CREATE_DISPATCH(hs_error_t, hs_stream_size, const hs_database_t *database,
89                 size_t *stream_size);
90 
91 CREATE_DISPATCH(hs_error_t, hs_database_size, const hs_database_t *db,
92                 size_t *size);
93 CREATE_DISPATCH(hs_error_t, dbIsValid, const hs_database_t *db);
94 CREATE_DISPATCH(hs_error_t, hs_free_database, hs_database_t *db);
95 
96 CREATE_DISPATCH(hs_error_t, hs_open_stream, const hs_database_t *db,
97                 unsigned int flags, hs_stream_t **stream);
98 
99 CREATE_DISPATCH(hs_error_t, hs_scan_stream, hs_stream_t *id, const char *data,
100                 unsigned int length, unsigned int flags, hs_scratch_t *scratch,
101                 match_event_handler onEvent, void *ctxt);
102 
103 CREATE_DISPATCH(hs_error_t, hs_close_stream, hs_stream_t *id,
104                 hs_scratch_t *scratch, match_event_handler onEvent, void *ctxt);
105 
106 CREATE_DISPATCH(hs_error_t, hs_scan_vector, const hs_database_t *db,
107                 const char *const *data, const unsigned int *length,
108                 unsigned int count, unsigned int flags, hs_scratch_t *scratch,
109                 match_event_handler onevent, void *context);
110 
111 CREATE_DISPATCH(hs_error_t, hs_database_info, const hs_database_t *db, char **info);
112 
113 CREATE_DISPATCH(hs_error_t, hs_copy_stream, hs_stream_t **to_id,
114                 const hs_stream_t *from_id);
115 
116 CREATE_DISPATCH(hs_error_t, hs_reset_stream, hs_stream_t *id,
117                 unsigned int flags, hs_scratch_t *scratch,
118                 match_event_handler onEvent, void *context);
119 
120 CREATE_DISPATCH(hs_error_t, hs_reset_and_copy_stream, hs_stream_t *to_id,
121                 const hs_stream_t *from_id, hs_scratch_t *scratch,
122                 match_event_handler onEvent, void *context);
123 
124 CREATE_DISPATCH(hs_error_t, hs_serialize_database, const hs_database_t *db,
125                 char **bytes, size_t *length);
126 
127 CREATE_DISPATCH(hs_error_t, hs_deserialize_database, const char *bytes,
128                 const size_t length, hs_database_t **db);
129 
130 CREATE_DISPATCH(hs_error_t, hs_deserialize_database_at, const char *bytes,
131                 const size_t length, hs_database_t *db);
132 
133 CREATE_DISPATCH(hs_error_t, hs_serialized_database_info, const char *bytes,
134                 size_t length, char **info);
135 
136 CREATE_DISPATCH(hs_error_t, hs_serialized_database_size, const char *bytes,
137                 const size_t length, size_t *deserialized_size);
138 
139 CREATE_DISPATCH(hs_error_t, hs_compress_stream, const hs_stream_t *stream,
140                 char *buf, size_t buf_space, size_t *used_space);
141 
142 CREATE_DISPATCH(hs_error_t, hs_expand_stream, const hs_database_t *db,
143                 hs_stream_t **stream, const char *buf,size_t buf_size);
144 
145 CREATE_DISPATCH(hs_error_t, hs_reset_and_expand_stream, hs_stream_t *to_stream,
146                 const char *buf, size_t buf_size, hs_scratch_t *scratch,
147                 match_event_handler onEvent, void *context);
148 
149 /** INTERNALS **/
150 
151 CREATE_DISPATCH(u32, Crc32c_ComputeBuf, u32 inCrc32, const void *buf, size_t bufLen);
152