From 4fda5bba36d34675bc863a9562613b2bb4c47f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Herczeg?= Date: Tue, 30 Sep 2014 07:06:48 +0000 Subject: [PATCH] PCRE2 successfully compiles with --enable-jit now. --- Makefile.am | 2 -- src/pcre2.h.generic | 3 +- src/pcre2.h.in | 3 +- src/pcre2_intmodedep.h | 8 +++++ src/pcre2_jit_compile.c | 72 ++++++++++++++++++++++++++++++++++++++++- src/pcre2_jit_match.c | 7 ++-- src/pcre2_jit_misc.c | 32 +++++++++++------- src/pcre2_jit_test.c | 48 +++++++++++++++++++++++++++ src/pcre2test.c | 22 ++++++------- 9 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 src/pcre2_jit_test.c diff --git a/Makefile.am b/Makefile.am index b471a87..2210cff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -271,8 +271,6 @@ COMMON_SOURCES = \ src/pcre2_internal.h \ src/pcre2_intmodedep.h \ src/pcre2_jit_compile.c \ - src/pcre2_jit_match.c \ - src/pcre2_jit_misc.c \ src/pcre2_maketables.c \ src/pcre2_match.c \ src/pcre2_match_data.c \ diff --git a/src/pcre2.h.generic b/src/pcre2.h.generic index ad84726..3d7c9fd 100644 --- a/src/pcre2.h.generic +++ b/src/pcre2.h.generic @@ -457,7 +457,8 @@ PCRE2_EXP_DECL int pcre2_substring_list_get(pcre2_match_data *, \ /* Functions for JIT processing */ #define PCRE2_JIT_FUNCTIONS \ -PCRE2_EXP_DECL void pcre2_jit_compile(pcre2_code *, uint32_t); \ +PCRE2_EXP_DECL int pcre2_jit_compile(pcre2_code *, uint32_t, \ + pcre2_match_context *); \ PCRE2_EXP_DECL int pcre2_jit_match(const pcre2_code *, \ PCRE2_SPTR, int, PCRE2_OFFSET, uint32_t, \ pcre2_match_data *, pcre2_match_context *, \ diff --git a/src/pcre2.h.in b/src/pcre2.h.in index 39b1f7d..0ae1afd 100644 --- a/src/pcre2.h.in +++ b/src/pcre2.h.in @@ -457,7 +457,8 @@ PCRE2_EXP_DECL int pcre2_substring_list_get(pcre2_match_data *, \ /* Functions for JIT processing */ #define PCRE2_JIT_FUNCTIONS \ -PCRE2_EXP_DECL int pcre2_jit_compile(pcre2_code *, uint32_t); \ +PCRE2_EXP_DECL int pcre2_jit_compile(pcre2_code *, uint32_t, \ + pcre2_match_context *); \ PCRE2_EXP_DECL int pcre2_jit_match(const pcre2_code *, \ PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, uint32_t, \ pcre2_match_data *, pcre2_match_context *, \ diff --git a/src/pcre2_intmodedep.h b/src/pcre2_intmodedep.h index d4c4a72..f0ee6f7 100644 --- a/src/pcre2_intmodedep.h +++ b/src/pcre2_intmodedep.h @@ -682,6 +682,14 @@ typedef struct compile_block { BOOL dupnames; /* Duplicate names exist */ } compile_block; +/* Structure for keeping the properties of the in-memory stack used +by the JIT matcher. */ + +typedef struct pcre2_real_jit_stack { + pcre2_memctl memctl; + void* stack; +} pcre2_real_jit_stack; + /* Structure for keeping a chain of heap blocks used for saving ovectors during pattern recursion when the ovector is larger than can be saved on the system stack. */ diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c index 4aebfbf..5eec313 100644 --- a/src/pcre2_jit_compile.c +++ b/src/pcre2_jit_compile.c @@ -45,6 +45,68 @@ POSSIBILITY OF SUCH DAMAGE. #include "pcre2_internal.h" +#ifdef SUPPORT_JIT + +/* All-in-one: Since we use the JIT compiler only from here, +we just include it. This way we don't need to touch the build +system files. */ + +#define SLJIT_CONFIG_AUTO 1 +#define SLJIT_CONFIG_STATIC 1 +#define SLJIT_VERBOSE 0 +#define SLJIT_DEBUG 0 + +#define SLJIT_MALLOC(size, allocator_data) pcre2_jit_malloc(size, allocator_data) +#define SLJIT_FREE(ptr, allocator_data) pcre2_jit_free(ptr, allocator_data) + +static void * pcre2_jit_malloc(size_t size, void *allocator_data) +{ +pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data); +return allocator->malloc(size, allocator->memory_data); +} + +static void pcre2_jit_free(void *ptr, void *allocator_data) +{ +pcre2_memctl *allocator = ((pcre2_memctl*)allocator_data); +return allocator->free(ptr, allocator->memory_data); +} + +#include "sljit/sljitLir.c" + +#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED +#error Unsupported architecture +#endif + +/* Defines for debugging purposes. */ + +/* 1 - Use unoptimized capturing brackets. + 2 - Enable capture_last_ptr (includes option 1). */ +/* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */ + +/* 1 - Always have a control head. */ +/* #define DEBUG_FORCE_CONTROL_HEAD 1 */ + +/* Allocate memory for the regex stack on the real machine stack. +Fast, but limited size. */ +#define MACHINE_STACK_SIZE 32768 + +/* Growth rate for stack allocated by the OS. Should be the multiply +of page size. */ +#define STACK_GROWTH_RATE 8192 + +/* Enable to check that the allocation could destroy temporaries. */ +#if defined SLJIT_DEBUG && SLJIT_DEBUG +#define DESTROY_REGISTERS 1 +#endif + + + + + + + + +#endif /************************************************* * JIT compile a Regular Expression * @@ -63,7 +125,7 @@ Returns: nothing /* FIXME: this is currently a placeholder function */ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION -pcre2_jit_compile(pcre2_code *code, uint32_t options) +pcre2_jit_compile(pcre2_code *code, uint32_t options, pcre2_match_context *mcontext) { #ifndef SUPPORT_JIT @@ -81,4 +143,12 @@ return PCRE2_ERROR_JIT_BADOPTION; #endif /* SUPPORT_JIT */ } +/* JIT compiler uses an all-in-one approach. This improves security, + since the code generator functions are not exported. */ + +#define INCLUDED_FROM_PCRE2_JIT_COMPILE + +#include "pcre2_jit_match.c" +#include "pcre2_jit_misc.c" + /* End of pcre2_jit_compile.c */ diff --git a/src/pcre2_jit_match.c b/src/pcre2_jit_match.c index 847feb2..d183cb8 100644 --- a/src/pcre2_jit_match.c +++ b/src/pcre2_jit_match.c @@ -38,13 +38,10 @@ POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------------------- */ - -#ifdef HAVE_CONFIG_H -#include "config.h" +#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE +#error This file must be included from pcre2_jit_compile.c. #endif -#include "pcre2_internal.h" - /************************************************* * Do a JIT pattern match * diff --git a/src/pcre2_jit_misc.c b/src/pcre2_jit_misc.c index 95ed670..f681007 100644 --- a/src/pcre2_jit_misc.c +++ b/src/pcre2_jit_misc.c @@ -39,12 +39,10 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" +#ifndef INCLUDED_FROM_PCRE2_JIT_COMPILE +#error This file must be included from pcre2_jit_compile.c. #endif -#include "pcre2_internal.h" - /* FIXME: these are dummy functions */ @@ -64,7 +62,7 @@ pcre2_jit_free_unused_memory(pcre2_general_context *gcontext) #else /* SUPPORT_JIT */ /* Dummy code */ -gcontext=gcontext; +sljit_free_unused_memory_exec(); #endif /* SUPPORT_JIT */ } @@ -88,11 +86,18 @@ return NULL; #else /* SUPPORT_JIT */ -/* Dummy code */ -gcontext=gcontext; -startsize=startsize; -maxsize=maxsize; -return NULL; +pcre2_jit_stack *jit_stack; + +if (startsize < 1 || maxsize < 1) + return NULL; +if (startsize > maxsize) + startsize = maxsize; +startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); +maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); + +jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext); +jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl); +return jit_stack; #endif } @@ -137,7 +142,12 @@ pcre2_jit_stack_free(pcre2_jit_stack *jit_stack) #else /* SUPPORT_JIT */ /* Dummy code */ -jit_stack=jit_stack; + +if (jit_stack != NULL) + { + sljit_free_stack((struct sljit_stack *)(jit_stack->stack), &jit_stack->memctl); + jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data); + } #endif /* SUPPORT_JIT */ } diff --git a/src/pcre2_jit_test.c b/src/pcre2_jit_test.c new file mode 100644 index 0000000..d26218a --- /dev/null +++ b/src/pcre2_jit_test.c @@ -0,0 +1,48 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Original API code Copyright (c) 1997-2012 University of Cambridge + New API code Copyright (c) 2014 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +int main() +{ +return 0; +} diff --git a/src/pcre2test.c b/src/pcre2test.c index 1aa40b4..e4a74f3 100644 --- a/src/pcre2test.c +++ b/src/pcre2test.c @@ -767,10 +767,10 @@ are supported. */ else \ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size)) -#define PCRE2_JIT_COMPILE(a,b) \ - if (test_mode == PCRE8_MODE) pcre2_jit_compile_8(G(a,8),b); \ - else if (test_mode == PCRE16_MODE) pcre2_jit_compile_16(G(a,16),b); \ - else pcre2_jit_compile_32(G(a,32),b) +#define PCRE2_JIT_COMPILE(a,b,c) \ + if (test_mode == PCRE8_MODE) pcre2_jit_compile_8(G(a,8),b,G(c,8)); \ + else if (test_mode == PCRE16_MODE) pcre2_jit_compile_16(G(a,16),b,G(c,16)); \ + else pcre2_jit_compile_32(G(a,32),b,G(c,32)) #define PCRE2_MAKETABLES(a) \ if (test_mode == PCRE8_MODE) a = pcre2_maketables_8(NULL); \ @@ -1054,11 +1054,11 @@ the three different cases. */ else \ r = G(pcre2_get_error_message_,BITTWO)(a,G(b,BITTWO),G(G(b,BITTWO),_size)) -#define PCRE2_JIT_COMPILE(a,b) \ +#define PCRE2_JIT_COMPILE(a,b,c) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ - G(pcre2_jit_compile_,BITONE)(G(a,BITONE),b); \ + G(pcre2_jit_compile_,BITONE)(G(a,BITONE),b,G(c,BITONE)); \ else \ - G(pcre2_jit_compile_,BITTWO)(G(a,BITTWO),b) + G(pcre2_jit_compile_,BITTWO)(G(a,BITTWO),b,G(c,BITTWO)) #define PCRE2_MAKETABLES(a) \ if (test_mode == G(G(PCRE,BITONE),_MODE)) \ @@ -1252,7 +1252,7 @@ the three different cases. */ a = pcre2_dfa_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8),i,j) #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_8(a,G(b,8),G(G(b,8),_size)) -#define PCRE2_JIT_COMPILE(a,b) pcre2_jit_compile_8(G(a,8),b) +#define PCRE2_JIT_COMPILE(a,b,c) pcre2_jit_compile_8(G(a,8),b,G(c,8)) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_8(G(b,8),(PCRE2_SPTR8)c,d,e,f,G(g,8),G(h,8)) #define PCRE2_MAKETABLES(a) a = pcre2_maketables_8(NULL) @@ -1311,7 +1311,7 @@ the three different cases. */ a = pcre2_dfa_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16),i,j) #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_16(a,G(b,16),G(G(b,16),_size)) -#define PCRE2_JIT_COMPILE(a,b) pcre2_jit_compile_16(G(a,16),b) +#define PCRE2_JIT_COMPILE(a,b,c) pcre2_jit_compile_16(G(a,16),b,G(c,16)) #define PCRE2_MAKETABLES(a) a = pcre2_maketables_16(NULL) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_16(G(b,16),(PCRE2_SPTR16)c,d,e,f,G(g,16),G(h,16)) @@ -1370,7 +1370,7 @@ the three different cases. */ a = pcre2_dfa_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),G(h,32),i,j) #define PCRE2_GET_ERROR_MESSAGE(r,a,b) \ r = pcre2_get_error_message_32(a,G(b,32),G(G(b,32),_size)) -#define PCRE2_JIT_COMPILE(a,b) pcre2_jit_compile_32(G(a,32),b) +#define PCRE2_JIT_COMPILE(a,b,c) pcre2_jit_compile_32(G(a,32),b,G(c,32)) #define PCRE2_MATCH(a,b,c,d,e,f,g,h) \ a = pcre2_match_32(G(b,32),(PCRE2_SPTR32)c,d,e,f,G(g,32),g(h,32)) #define PCRE2_MAKETABLES(a) a = pcre2_maketables_32(NULL) @@ -3641,7 +3641,7 @@ if (TEST(compiled_code, ==, NULL)) /* Call the JIT compiler if requested. */ if (pat_patctl.jit != 0) - { PCRE2_JIT_COMPILE(compiled_code, pat_patctl.jit); } + { PCRE2_JIT_COMPILE(compiled_code, pat_patctl.jit, dat_context); } /* Output code size and other information if requested. */