Path: blob/master/thirdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
21827 views
/*1* Stack-less Just-In-Time compiler2*3* Copyright Zoltan Herczeg ([email protected]). All rights reserved.4*5* Redistribution and use in source and binary forms, with or without modification, are6* permitted provided that the following conditions are met:7*8* 1. Redistributions of source code must retain the above copyright notice, this list of9* conditions and the following disclaimer.10*11* 2. Redistributions in binary form must reproduce the above copyright notice, this list12* of conditions and the following disclaimer in the documentation and/or other materials13* provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT18* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED20* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR21* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN22* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN23* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.24*/2526#define SLJIT_GET_LABEL_INDEX(label) \27((label)->u.index < SLJIT_LABEL_ALIGNED ? (label)->u.index : ((struct sljit_extended_label*)(label))->index)2829SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label)30{31return SLJIT_GET_LABEL_INDEX(label);32}3334SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump)35{36return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);37}3839SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump)40{41return (jump->flags & JUMP_ADDR) != 0;42}4344SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump)45{46return (jump->flags & JUMP_MOV_ADDR) != 0;47}4849#define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1)5051struct sljit_serialized_compiler {52sljit_u32 signature;53sljit_u16 version;54sljit_u16 cpu_type;5556sljit_uw buf_segment_count;57sljit_uw label_count;58sljit_uw aligned_label_count;59sljit_uw jump_count;60sljit_uw const_count;6162sljit_s32 options;63sljit_s32 scratches;64sljit_s32 saveds;65sljit_s32 fscratches;66sljit_s32 fsaveds;67sljit_s32 local_size;68sljit_uw size;6970#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)71sljit_s32 status_flags_state;72#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */7374#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)75sljit_s32 args_size;76#endif /* SLJIT_CONFIG_X86_32 */7778#if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \79|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)80sljit_uw args_size;81#endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */8283#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)84sljit_uw cpool_diff;85sljit_uw cpool_fill;86sljit_uw patches;87#endif /* SLJIT_CONFIG_ARM_V6 */8889#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)90sljit_s32 delay_slot;91#endif /* SLJIT_CONFIG_MIPS */9293};9495struct sljit_serialized_debug_info {96sljit_sw last_flags;97sljit_s32 last_return;98sljit_s32 logical_local_size;99};100101struct sljit_serialized_label {102sljit_uw size;103};104105struct sljit_serialized_aligned_label {106sljit_uw size;107sljit_uw data;108};109110struct sljit_serialized_jump {111sljit_uw addr;112sljit_uw flags;113sljit_uw value;114};115116struct sljit_serialized_const {117sljit_uw addr;118};119120#define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1))121#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)122#define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54123#else /* !SLJIT_LITTLE_ENDIAN */124#define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53125#endif /* SLJIT_LITTLE_ENDIAN */126#define SLJIT_SERIALIZE_VERSION 1127128SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,129sljit_s32 options, sljit_uw *size)130{131sljit_uw serialized_size = sizeof(struct sljit_serialized_compiler);132struct sljit_memory_fragment *buf;133struct sljit_label *label;134struct sljit_jump *jump;135struct sljit_const *const_;136struct sljit_serialized_compiler *serialized_compiler;137struct sljit_serialized_label *serialized_label;138struct sljit_serialized_aligned_label *serialized_aligned_label;139struct sljit_serialized_jump *serialized_jump;140struct sljit_serialized_const *serialized_const;141#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \142|| (defined SLJIT_DEBUG && SLJIT_DEBUG)143struct sljit_serialized_debug_info *serialized_debug_info;144#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */145sljit_uw counter, used_size;146sljit_u8 *result;147sljit_u8 *ptr;148SLJIT_UNUSED_ARG(options);149150if (size != NULL)151*size = 0;152153PTR_FAIL_IF(compiler->error);154155#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \156|| (defined SLJIT_DEBUG && SLJIT_DEBUG)157if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG))158serialized_size += sizeof(struct sljit_serialized_debug_info);159#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */160161#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)162serialized_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));163#endif /* SLJIT_CONFIG_ARM_V6 */164165/* Compute the size of the data. */166buf = compiler->buf;167while (buf != NULL) {168serialized_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size);169buf = buf->next;170}171172label = compiler->labels;173while (label != NULL) {174used_size = sizeof(struct sljit_serialized_label);175176if (label->u.index >= SLJIT_LABEL_ALIGNED)177used_size += sizeof(struct sljit_serialized_aligned_label);178179serialized_size += used_size;180label = label->next;181}182183jump = compiler->jumps;184while (jump != NULL) {185serialized_size += sizeof(struct sljit_serialized_jump);186jump = jump->next;187}188189const_ = compiler->consts;190while (const_ != NULL) {191serialized_size += sizeof(struct sljit_serialized_const);192const_ = const_->next;193}194195result = (sljit_u8*)SLJIT_MALLOC(serialized_size, compiler->allocator_data);196PTR_FAIL_IF_NULL(result);197198if (size != NULL)199*size = serialized_size;200201ptr = result;202serialized_compiler = (struct sljit_serialized_compiler*)ptr;203ptr += sizeof(struct sljit_serialized_compiler);204205serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE;206serialized_compiler->version = SLJIT_SERIALIZE_VERSION;207serialized_compiler->cpu_type = 0;208serialized_compiler->label_count = compiler->label_count;209serialized_compiler->options = compiler->options;210serialized_compiler->scratches = compiler->scratches;211serialized_compiler->saveds = compiler->saveds;212serialized_compiler->fscratches = compiler->fscratches;213serialized_compiler->fsaveds = compiler->fsaveds;214serialized_compiler->local_size = compiler->local_size;215serialized_compiler->size = compiler->size;216217#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)218serialized_compiler->status_flags_state = compiler->status_flags_state;219#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */220221#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \222|| ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \223|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)224serialized_compiler->args_size = compiler->args_size;225#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */226227#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)228serialized_compiler->cpool_diff = compiler->cpool_diff;229serialized_compiler->cpool_fill = compiler->cpool_fill;230serialized_compiler->patches = compiler->patches;231232SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw));233SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill);234ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));235#endif /* SLJIT_CONFIG_ARM_V6 */236237#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)238serialized_compiler->delay_slot = compiler->delay_slot;239#endif /* SLJIT_CONFIG_MIPS */240241buf = compiler->buf;242counter = 0;243while (buf != NULL) {244used_size = buf->used_size;245*(sljit_uw*)ptr = used_size;246ptr += sizeof(sljit_uw);247SLJIT_MEMCPY(ptr, buf->memory, used_size);248ptr += SLJIT_SERIALIZE_ALIGN(used_size);249buf = buf->next;250counter++;251}252serialized_compiler->buf_segment_count = counter;253254label = compiler->labels;255counter = 0;256while (label != NULL) {257serialized_label = (struct sljit_serialized_label*)ptr;258serialized_label->size = (label->u.index < SLJIT_LABEL_ALIGNED) ? label->size : label->u.index;259ptr += sizeof(struct sljit_serialized_label);260261if (label->u.index >= SLJIT_LABEL_ALIGNED) {262serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;263serialized_aligned_label->size = label->size;264serialized_aligned_label->data = ((struct sljit_extended_label*)label)->data;265ptr += sizeof(struct sljit_serialized_aligned_label);266counter++;267}268269label = label->next;270}271serialized_compiler->aligned_label_count = counter;272273jump = compiler->jumps;274counter = 0;275while (jump != NULL) {276serialized_jump = (struct sljit_serialized_jump*)ptr;277serialized_jump->addr = jump->addr;278serialized_jump->flags = jump->flags;279280if (jump->flags & JUMP_ADDR)281serialized_jump->value = jump->u.target;282else if (jump->u.label != NULL)283serialized_jump->value = SLJIT_GET_LABEL_INDEX(jump->u.label);284else285serialized_jump->value = SLJIT_MAX_ADDRESS;286287ptr += sizeof(struct sljit_serialized_jump);288jump = jump->next;289counter++;290}291serialized_compiler->jump_count = counter;292293const_ = compiler->consts;294counter = 0;295while (const_ != NULL) {296serialized_const = (struct sljit_serialized_const*)ptr;297serialized_const->addr = const_->addr;298ptr += sizeof(struct sljit_serialized_const);299const_ = const_->next;300counter++;301}302serialized_compiler->const_count = counter;303304#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \305|| (defined SLJIT_DEBUG && SLJIT_DEBUG)306if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) {307serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;308serialized_debug_info->last_flags = compiler->last_flags;309serialized_debug_info->last_return = compiler->last_return;310serialized_debug_info->logical_local_size = compiler->logical_local_size;311serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG;312#if (defined SLJIT_DEBUG && SLJIT_DEBUG)313ptr += sizeof(struct sljit_serialized_debug_info);314#endif /* SLJIT_DEBUG */315}316#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */317318SLJIT_ASSERT((sljit_uw)(ptr - result) == serialized_size);319return (sljit_uw*)result;320}321322SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,323sljit_s32 options, void *allocator_data)324{325struct sljit_compiler *compiler;326struct sljit_serialized_compiler *serialized_compiler;327struct sljit_serialized_label *serialized_label;328struct sljit_serialized_aligned_label *serialized_aligned_label;329struct sljit_serialized_jump *serialized_jump;330struct sljit_serialized_const *serialized_const;331#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \332|| (defined SLJIT_DEBUG && SLJIT_DEBUG)333struct sljit_serialized_debug_info *serialized_debug_info;334#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */335struct sljit_memory_fragment *buf;336struct sljit_memory_fragment *last_buf;337struct sljit_label *label;338struct sljit_label *last_label;339struct sljit_label **label_list = NULL;340struct sljit_label **label_list_ptr = NULL;341struct sljit_jump *jump;342struct sljit_jump *last_jump;343struct sljit_const *const_;344struct sljit_const *last_const;345sljit_u8 *ptr = (sljit_u8*)buffer;346sljit_u8 *end = ptr + size;347sljit_uw i, type, used_size, aligned_size;348sljit_uw label_count, aligned_label_count;349SLJIT_UNUSED_ARG(options);350351if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)352return NULL;353354serialized_compiler = (struct sljit_serialized_compiler*)ptr;355356if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION)357return NULL;358359compiler = sljit_create_compiler(allocator_data);360PTR_FAIL_IF(compiler == NULL);361362compiler->label_count = serialized_compiler->label_count;363compiler->options = serialized_compiler->options;364compiler->scratches = serialized_compiler->scratches;365compiler->saveds = serialized_compiler->saveds;366compiler->fscratches = serialized_compiler->fscratches;367compiler->fsaveds = serialized_compiler->fsaveds;368compiler->local_size = serialized_compiler->local_size;369compiler->size = serialized_compiler->size;370371#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)372compiler->status_flags_state = serialized_compiler->status_flags_state;373#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */374375#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \376|| ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \377|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)378compiler->args_size = serialized_compiler->args_size;379#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */380381#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)382used_size = serialized_compiler->cpool_fill;383aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1));384compiler->cpool_diff = serialized_compiler->cpool_diff;385compiler->cpool_fill = used_size;386compiler->patches = serialized_compiler->patches;387388if ((sljit_uw)(end - ptr) < aligned_size)389goto error;390391SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw));392SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size);393ptr += aligned_size;394#endif /* SLJIT_CONFIG_ARM_V6 */395396#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)397compiler->delay_slot = serialized_compiler->delay_slot;398#endif /* SLJIT_CONFIG_MIPS */399400#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \401|| (defined SLJIT_DEBUG && SLJIT_DEBUG)402if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG))403goto error;404#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */405406ptr += sizeof(struct sljit_serialized_compiler);407i = serialized_compiler->buf_segment_count;408last_buf = NULL;409while (i > 0) {410if ((sljit_uw)(end - ptr) < sizeof(sljit_uw))411goto error;412413used_size = *(sljit_uw*)ptr;414aligned_size = SLJIT_SERIALIZE_ALIGN(used_size);415ptr += sizeof(sljit_uw);416417if ((sljit_uw)(end - ptr) < aligned_size)418goto error;419420if (last_buf == NULL) {421SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL);422buf = compiler->buf;423} else {424buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);425if (!buf)426goto error;427buf->next = NULL;428}429430buf->used_size = used_size;431SLJIT_MEMCPY(buf->memory, ptr, used_size);432433if (last_buf != NULL)434last_buf->next = buf;435last_buf = buf;436437ptr += aligned_size;438i--;439}440441last_label = NULL;442label_count = serialized_compiler->label_count;443aligned_label_count = serialized_compiler->aligned_label_count;444i = (label_count * sizeof(struct sljit_serialized_label)) + (aligned_label_count * sizeof(struct sljit_serialized_aligned_label));445446if ((sljit_uw)(end - ptr) < i)447goto error;448449label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);450if (label_list == NULL)451goto error;452453label_list_ptr = label_list;454for (i = 0; i < label_count; i++) {455serialized_label = (struct sljit_serialized_label*)ptr;456type = serialized_label->size;457458if (type < SLJIT_LABEL_ALIGNED) {459label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));460} else {461label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));462}463464if (label == NULL)465goto error;466467label->next = NULL;468469if (last_label != NULL)470last_label->next = label;471else472compiler->labels = label;473last_label = label;474475*label_list_ptr++ = label;476477ptr += sizeof(struct sljit_serialized_label);478479if (type < SLJIT_LABEL_ALIGNED) {480label->u.index = i;481label->size = type;482} else {483if (aligned_label_count == 0)484goto error;485486aligned_label_count--;487488serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;489label->u.index = type;490label->size = serialized_aligned_label->size;491492((struct sljit_extended_label*)label)->index = i;493((struct sljit_extended_label*)label)->data = serialized_aligned_label->data;494ptr += sizeof(struct sljit_serialized_aligned_label);495}496}497compiler->last_label = last_label;498499if (aligned_label_count != 0)500goto error;501502last_jump = NULL;503i = serialized_compiler->jump_count;504if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))505goto error;506507while (i > 0) {508jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));509if (jump == NULL)510goto error;511512serialized_jump = (struct sljit_serialized_jump*)ptr;513jump->next = NULL;514jump->addr = serialized_jump->addr;515jump->flags = serialized_jump->flags;516517if (!(serialized_jump->flags & JUMP_ADDR)) {518if (serialized_jump->value != SLJIT_MAX_ADDRESS) {519if (serialized_jump->value >= label_count)520goto error;521jump->u.label = label_list[serialized_jump->value];522} else523jump->u.label = NULL;524} else525jump->u.target = serialized_jump->value;526527if (last_jump != NULL)528last_jump->next = jump;529else530compiler->jumps = jump;531last_jump = jump;532533ptr += sizeof(struct sljit_serialized_jump);534i--;535}536compiler->last_jump = last_jump;537538SLJIT_FREE(label_list, allocator_data);539label_list = NULL;540541last_const = NULL;542i = serialized_compiler->const_count;543if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const))544goto error;545546while (i > 0) {547const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));548if (const_ == NULL)549goto error;550551serialized_const = (struct sljit_serialized_const*)ptr;552const_->next = NULL;553const_->addr = serialized_const->addr;554555if (last_const != NULL)556last_const->next = const_;557else558compiler->consts = const_;559last_const = const_;560561ptr += sizeof(struct sljit_serialized_const);562i--;563}564compiler->last_const = last_const;565566#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \567|| (defined SLJIT_DEBUG && SLJIT_DEBUG)568if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info))569goto error;570571serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;572compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags;573compiler->last_return = serialized_debug_info->last_return;574compiler->logical_local_size = serialized_debug_info->logical_local_size;575#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */576577return compiler;578579error:580sljit_free_compiler(compiler);581if (label_list != NULL)582SLJIT_FREE(label_list, allocator_data);583return NULL;584}585586587