Rename jit/ to vm/.

This commit is contained in:
David Anderson
2015-03-07 10:50:35 -08:00
parent ea684d5933
commit d459ebee41
71 changed files with 2 additions and 2 deletions
+93
View File
@@ -0,0 +1,93 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
Includes = [
os.path.join(SM.mms_root, 'core', 'sourcehook'),
os.path.join(builder.sourcePath, 'sourcepawn', 'vm'),
os.path.join(builder.sourcePath, 'public'),
os.path.join(builder.sourcePath, 'public', 'sourcepawn'),
os.path.join(builder.sourcePath, 'public', 'amtl'),
os.path.join(builder.sourcePath, 'public', 'jit'),
os.path.join(builder.sourcePath, 'public', 'jit', 'x86'),
# The include path for SP v2 stuff.
os.path.join(builder.sourcePath, 'sourcepawn', 'include'),
]
def setup(binary):
compiler = binary.compiler
compiler.includes += Includes
if compiler.vendor == 'gcc' or compiler.vendor == 'clang':
compiler.cxxflags += [
'-fno-rtti',
'-Wno-invalid-offsetof',
]
elif binary.compiler.vendor == 'msvc':
compiler.cxxflags += ['/GR-']
if binary.compiler.cc.behavior == 'msvc':
compiler.cxxflags.remove('/TP')
return binary
# Build the static library.
library = setup(builder.compiler.StaticLibrary('sourcepawn'))
library.sources += [
'api.cpp',
'code-allocator.cpp',
'code-stubs.cpp',
'compiled-function.cpp',
'environment.cpp',
'file-utils.cpp',
'opcodes.cpp',
'plugin-context.cpp',
'plugin-runtime.cpp',
'scripted-invoker.cpp',
'stack-frames.cpp',
'smx-v1-image.cpp',
'watchdog_timer.cpp',
'x86/code-stubs-x86.cpp',
'x86/jit_x86.cpp',
'x86/x86-utils.cpp',
'zlib/adler32.c',
'zlib/compress.c',
'zlib/crc32.c',
'zlib/deflate.c',
'zlib/gzio.c',
'zlib/infback.c',
'zlib/inffast.c',
'zlib/inflate.c',
'zlib/inftrees.c',
'zlib/trees.c',
'zlib/uncompr.c',
'zlib/zutil.c',
'md5/md5.cpp',
'../../public/jit/x86/assembler-x86.cpp',
]
libsourcepawn = builder.Add(library).binary
# Build the dynamically-linked library.
dll = setup(SM.Library(builder, 'sourcepawn.jit.x86'))
dll.compiler.linkflags[0:0] = [libsourcepawn]
dll.sources += [
'dll_exports.cpp'
]
if builder.target_platform == 'linux':
dll.compiler.postlink += ['-lpthread', '-lrt']
SM.binaries += [builder.Add(dll)]
# Build the debug shell.
shell = setup(SM.Program(builder, 'spshell'))
shell.compiler.defines += ['SPSHELL']
shell.compiler.linkflags[0:0] = [libsourcepawn]
shell.sources += [
'dll_exports.cpp'
]
if shell.compiler.cc.behavior == 'msvc':
shell.compiler.linkflags.remove('/SUBSYSTEM:WINDOWS')
shell.compiler.linkflags.append('/SUBSYSTEM:CONSOLE')
if builder.target_platform == 'linux':
shell.compiler.postlink += ['-lpthread', '-lrt']
builder.Add(shell)
+119
View File
@@ -0,0 +1,119 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
MMSOURCE17 = ../../../mmsource-1.7
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = sourcepawn.jit.x86
OBJECTS = dll_exports.cpp \
environment.cpp \
x86/jit_x86.cpp \
sp_vm_basecontext.cpp \
sp_vm_engine.cpp \
scripted-invoker.cpp \
engine2.cpp \
plugin-runtime.cpp \
opcodes.cpp \
compiled-function.cpp \
md5/md5.cpp \
zlib/adler32.c \
zlib/compress.c \
zlib/crc32.c \
zlib/deflate.c \
zlib/gzio.c \
zlib/infback.c \
zlib/inffast.c \
zlib/inflate.c \
zlib/inftrees.c \
zlib/trees.c \
zlib/uncompr.c \
zlib/zutil.c \
OBJECTS += ../../knight/shared/KeCodeAllocator.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
LINK = -m32 -ldl -lm
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
-I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
-m32 -Wno-uninitialized -Werror
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
OS := $(shell uname -s)
ifeq "$(OS)" "Darwin"
LINK += -dynamiclib
BINARY = $(PROJECT).dylib
else
LINK += -static-libgcc -shared
BINARY = $(PROJECT).so
endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:../../knight/shared/%.cpp=$(BIN_DIR)/knight/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
default: all
$(BIN_DIR)/%.o: %.c
$(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
$(BIN_DIR)/knight/%.o: ../../knight/shared/%.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/x86
mkdir -p $(BIN_DIR)/zlib
mkdir -p $(BIN_DIR)/knight
$(MAKE) -f Makefile jit
jit: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f Makefile all DEBUG=true
clean:
rm -rf $(BIN_DIR)/x86/*.o
rm -rf $(BIN_DIR)/zlib/*.o
rm -rf $(BIN_DIR)/knight/*.o
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/$(BINARY)
+120
View File
@@ -0,0 +1,120 @@
# (C)2004-2008 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
SMSDK = ../..
MMSOURCE17 = ../../../mmsource-1.7
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = spshell
OBJECTS = dll_exports.cpp \
environment.cpp \
x86/jit_x86.cpp \
sp_vm_basecontext.cpp \
sp_vm_engine.cpp \
scripted-invoker.cpp \
engine2.cpp \
plugin-runtime.cpp \
compiled-function.cpp \
opcodes.cpp \
watchdog_timer.cpp \
interpreter.cpp \
md5/md5.cpp \
zlib/adler32.c \
zlib/compress.c \
zlib/crc32.c \
zlib/deflate.c \
zlib/gzio.c \
zlib/infback.c \
zlib/inffast.c \
zlib/inflate.c \
zlib/inftrees.c \
zlib/trees.c \
zlib/uncompr.c \
zlib/zutil.c \
OBJECTS += ../../knight/shared/KeCodeAllocator.cpp
OBJECTS += ../../public/jit/x86/assembler-x86.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CXX_GCC4_FLAGS = -fvisibility-inlines-hidden
CXX = c++
CC = cc
LINK = -m32 -lm -lpthread -lrt
INCLUDE = -I. -I.. -I$(SMSDK)/public -I$(SMSDK)/public/jit -I$(SMSDK)/public/jit/x86 \
-I$(SMSDK)/public/sourcepawn -I$(MMSOURCE17)/core/sourcehook -I$(SMSDK)/knight/shared -Ix86 \
-I$(SMSDK)/public/amtl -I$(SMSDK)/sourcepawn/include
CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -DHAVE_STDINT_H \
-m32 -Wno-uninitialized -Werror -DSPSHELL -ggdb3 -Wno-unused
CXXFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti -Wno-delete-non-virtual-dtor -std=c++11
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug.shell
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release.shell
CFLAGS += $(C_OPT_FLAGS)
endif
GCC_VERSION := $(shell $(CXX) -dumpversion >&1 | cut -b1)
ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(C_GCC4_FLAGS)
CXXFLAGS += $(CXX_GCC4_FLAGS)
endif
OBJ_LINUX := $(OBJECTS:../../knight/shared/%.cpp=$(BIN_DIR)/knight/%.o)
OBJ_LINUX := $(OBJ_LINUX:../../public/jit/x86/%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.cpp=$(BIN_DIR)/%.o)
OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o)
default: all
$(BIN_DIR)/%.o: %.c
$(CC) $(INCLUDE) $(CFLAGS) -o $@ -c $<
$(BIN_DIR)/%.o: %.cpp
$(CXX) $(INCLUDE) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
$(BIN_DIR)/knight/%.o: ../../knight/shared/%.cpp
$(CXX) $(INCLUDE) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
$(BIN_DIR)/assembler-x86.o: ../../public/jit/x86/assembler-x86.cpp
$(CXX) $(INCLUDE) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
all:
mkdir -p $(BIN_DIR)/x86
mkdir -p $(BIN_DIR)/md5
mkdir -p $(BIN_DIR)/zlib
mkdir -p $(BIN_DIR)/knight
$(MAKE) -f Makefile.shell jit
jit: $(OBJ_LINUX)
$(CXX) $(INCLUDE) $(OBJ_LINUX) $(LINK) -o $(BIN_DIR)/$(PROJECT)
debug:
$(MAKE) -f Makefile.shell all DEBUG=true
clean:
rm -f $(BIN_DIR)/x86/*.o
# rm -rf $(BIN_DIR)/zlib/*.o
# rm -rf $(BIN_DIR)/knight/*.o
rm -f $(BIN_DIR)/*.o
rm -f $(BIN_DIR)/$(PROJECT)
+405
View File
@@ -0,0 +1,405 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "x86/jit_x86.h"
#include "environment.h"
#include "api.h"
#include "zlib/zlib.h"
#if defined __GNUC__
#include <unistd.h>
#endif
#if defined WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined __GNUC__
#include <sys/mman.h>
#endif
#if defined __linux__
#include <malloc.h>
#endif
#include <sourcemod_version.h>
#include "code-stubs.h"
#include "smx-v1-image.h"
using namespace sp;
using namespace SourcePawn;
// ////// //
// API v1
// ////// //
SourcePawnEngine::SourcePawnEngine()
{
}
const char *
SourcePawnEngine::GetErrorString(int error)
{
return Environment::get()->GetErrorString(error);
}
void *
SourcePawnEngine::ExecAlloc(size_t size)
{
#if defined WIN32
return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined __GNUC__
# if defined __APPLE__
void *base = valloc(size);
# else
void *base = memalign(sysconf(_SC_PAGESIZE), size);
# endif
if (mprotect(base, size, PROT_READ|PROT_WRITE|PROT_EXEC) != 0) {
free(base);
return NULL;
}
return base;
#endif
}
void *
SourcePawnEngine::AllocatePageMemory(size_t size)
{
return Environment::get()->AllocateCode(size);
}
void
SourcePawnEngine::SetReadExecute(void *ptr)
{
/* already re */
}
void
SourcePawnEngine::SetReadWrite(void *ptr)
{
/* already rw */
}
void
SourcePawnEngine::FreePageMemory(void *ptr)
{
Environment::get()->FreeCode(ptr);
}
void
SourcePawnEngine::ExecFree(void *address)
{
#if defined WIN32
VirtualFree(address, 0, MEM_RELEASE);
#elif defined __GNUC__
free(address);
#endif
}
void
SourcePawnEngine::SetReadWriteExecute(void *ptr)
{
//:TODO: g_ExeMemory.SetRWE(ptr);
SetReadExecute(ptr);
}
void *
SourcePawnEngine::BaseAlloc(size_t size)
{
return malloc(size);
}
void
SourcePawnEngine::BaseFree(void *memory)
{
free(memory);
}
sp_plugin_t *
SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
{
if (err != NULL)
*err = SP_ERROR_ABORTED;
return NULL;
}
sp_plugin_t *
SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
{
if (err != NULL)
*err = SP_ERROR_ABORTED;
return NULL;
}
int
SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
{
return SP_ERROR_ABORTED;
}
IDebugListener *
SourcePawnEngine::SetDebugListener(IDebugListener *pListener)
{
IDebugListener *old = Environment::get()->debugger();
Environment::get()->SetDebugger(pListener);
return old;
}
unsigned int
SourcePawnEngine::GetEngineAPIVersion()
{
return 4;
}
unsigned int
SourcePawnEngine::GetContextCallCount()
{
return 0;
}
// ////// //
// API v2
// ////// //
SourcePawnEngine2::SourcePawnEngine2()
{
}
size_t
sp::UTIL_FormatVA(char *buffer, size_t maxlength, const char *fmt, va_list ap)
{
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
if (len >= maxlength) {
buffer[maxlength - 1] = '\0';
return maxlength - 1;
}
return len;
}
size_t
sp::UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
size_t len = UTIL_FormatVA(buffer, maxlength, fmt, ap);
va_end(ap);
return len;
}
IPluginRuntime *
SourcePawnEngine2::LoadPlugin(ICompilation *co, const char *file, int *err)
{
if (co) {
if (err)
*err = SP_ERROR_PARAM;
return nullptr;
}
IPluginRuntime *rt = LoadBinaryFromFile(file, nullptr, 0);
if (!rt) {
if (err) {
if (FILE *fp = fopen(file, "rb")) {
fclose(fp);
*err = SP_ERROR_FILE_FORMAT;
} else {
*err = SP_ERROR_NOT_FOUND;
}
}
return nullptr;
}
return rt;
}
IPluginRuntime *
SourcePawnEngine2::LoadBinaryFromFile(const char *file, char *error, size_t maxlength)
{
FILE *fp = fopen(file, "rb");
if (!fp) {
UTIL_Format(error, maxlength, "file not found");
return nullptr;
}
ke::AutoPtr<SmxV1Image> image(new SmxV1Image(fp));
fclose(fp);
if (!image->validate()) {
const char *errorMessage = image->errorMessage();
if (!errorMessage)
errorMessage = "file parse error";
UTIL_Format(error, maxlength, "%s", errorMessage);
return nullptr;
}
PluginRuntime *pRuntime = new PluginRuntime(image.take());
if (!pRuntime->Initialize()) {
delete pRuntime;
UTIL_Format(error, maxlength, "out of memory");
return nullptr;
}
size_t len = strlen(file);
for (size_t i = len - 1; i < len; i--) {
if (file[i] == '/'
# if defined WIN32
|| file[i] == '\\'
# endif
)
{
pRuntime->SetNames(file, &file[i + 1]);
break;
}
}
if (!pRuntime->Name())
pRuntime->SetNames(file, file);
return pRuntime;
}
SPVM_NATIVE_FUNC
SourcePawnEngine2::CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData)
{
return Environment::get()->stubs()->CreateFakeNativeStub(callback, pData);
}
void
SourcePawnEngine2::DestroyFakeNative(SPVM_NATIVE_FUNC func)
{
return Environment::get()->FreeCode((void *)func);
}
const char *
SourcePawnEngine2::GetEngineName()
{
return "SourcePawn 1.7, jit-x86";
}
const char *
SourcePawnEngine2::GetVersionString()
{
return SOURCEMOD_VERSION;
}
IDebugListener *
SourcePawnEngine2::SetDebugListener(IDebugListener *listener)
{
IDebugListener *old = Environment::get()->debugger();
Environment::get()->SetDebugger(listener);
return old;
}
unsigned int
SourcePawnEngine2::GetAPIVersion()
{
return SOURCEPAWN_ENGINE2_API_VERSION;
}
ICompilation *
SourcePawnEngine2::StartCompilation()
{
return nullptr;
}
const char *
SourcePawnEngine2::GetErrorString(int err)
{
return Environment::get()->GetErrorString(err);
}
bool
SourcePawnEngine2::Initialize()
{
return true;
}
void
SourcePawnEngine2::Shutdown()
{
}
IPluginRuntime *
SourcePawnEngine2::CreateEmptyRuntime(const char *name, uint32_t memory)
{
int err;
ke::AutoPtr<EmptyImage> image(new EmptyImage(memory));
PluginRuntime *rt = new PluginRuntime(image.take());
if (!rt->Initialize()) {
delete rt;
return NULL;
}
if (!name)
name = "<anonymous>";
rt->SetNames(name, name);
return rt;
}
bool
SourcePawnEngine2::InstallWatchdogTimer(size_t timeout_ms)
{
return Environment::get()->InstallWatchdogTimer(timeout_ms);
}
bool
SourcePawnEngine2::SetJitEnabled(bool enabled)
{
Environment::get()->SetJitEnabled(enabled);
return Environment::get()->IsJitEnabled() == enabled;
}
bool
SourcePawnEngine2::IsJitEnabled()
{
return Environment::get()->IsJitEnabled();
}
void
SourcePawnEngine2::SetProfiler(IProfiler *profiler)
{
// Deprecated.
}
void
SourcePawnEngine2::EnableProfiling()
{
Environment::get()->EnableProfiling();
}
void
SourcePawnEngine2::DisableProfiling()
{
Environment::get()->DisableProfiling();
}
void
SourcePawnEngine2::SetProfilingTool(IProfilingTool *tool)
{
Environment::get()->SetProfiler(tool);
}
ISourcePawnEnvironment *
SourcePawnEngine2::Environment()
{
return Environment::get();
}
+79
View File
@@ -0,0 +1,79 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_api_h_
#define _include_sourcepawn_vm_api_h_
#include <sp_vm_api.h>
#include <am-utility.h> // Replace with am-cxx later.
namespace sp {
using namespace SourcePawn;
class SourcePawnEngine : public ISourcePawnEngine
{
public:
SourcePawnEngine();
sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err) KE_OVERRIDE;
sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err) KE_OVERRIDE;
int FreeFromMemory(sp_plugin_t *plugin) KE_OVERRIDE;
void *BaseAlloc(size_t size) KE_OVERRIDE;
void BaseFree(void *memory) KE_OVERRIDE;
void *ExecAlloc(size_t size) KE_OVERRIDE;
void ExecFree(void *address) KE_OVERRIDE;
IDebugListener *SetDebugListener(IDebugListener *pListener) KE_OVERRIDE;
unsigned int GetContextCallCount() KE_OVERRIDE;
unsigned int GetEngineAPIVersion() KE_OVERRIDE;
void *AllocatePageMemory(size_t size) KE_OVERRIDE;
void SetReadWrite(void *ptr) KE_OVERRIDE;
void SetReadExecute(void *ptr) KE_OVERRIDE;
void FreePageMemory(void *ptr) KE_OVERRIDE;
void SetReadWriteExecute(void *ptr);
const char *GetErrorString(int err);
};
class SourcePawnEngine2 : public ISourcePawnEngine2
{
public:
SourcePawnEngine2();
unsigned int GetAPIVersion() KE_OVERRIDE;
const char *GetEngineName() KE_OVERRIDE;
const char *GetVersionString() KE_OVERRIDE;
IPluginRuntime *LoadPlugin(ICompilation *co, const char *file, int *err) KE_OVERRIDE;
SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData) KE_OVERRIDE;
void DestroyFakeNative(SPVM_NATIVE_FUNC func) KE_OVERRIDE;
IDebugListener *SetDebugListener(IDebugListener *listener) KE_OVERRIDE;
ICompilation *StartCompilation() KE_OVERRIDE;
const char *GetErrorString(int err) KE_OVERRIDE;
bool Initialize() KE_OVERRIDE;
void Shutdown() KE_OVERRIDE;
IPluginRuntime *CreateEmptyRuntime(const char *name, uint32_t memory) KE_OVERRIDE;
bool InstallWatchdogTimer(size_t timeout_ms) KE_OVERRIDE;
bool SetJitEnabled(bool enabled) KE_OVERRIDE;
bool IsJitEnabled() KE_OVERRIDE;
void SetProfiler(IProfiler *profiler) KE_OVERRIDE;
void EnableProfiling() KE_OVERRIDE;
void DisableProfiling() KE_OVERRIDE;
void SetProfilingTool(IProfilingTool *tool) KE_OVERRIDE;
IPluginRuntime *LoadBinaryFromFile(const char *file, char *error, size_t maxlength) KE_OVERRIDE;
ISourcePawnEnvironment *Environment() KE_OVERRIDE;
};
extern size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
extern size_t UTIL_FormatVA(char *buffer, size_t maxlength, const char *fmt, va_list ap);
} // namespace sp
#endif // _include_sourcepawn_vm_api_h_
+419
View File
@@ -0,0 +1,419 @@
#include <assert.h>
#include <string.h>
#include <am-utility.h>
#if defined(WIN32)
#include <windows.h>
#else
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#endif
#include "code-allocator.h"
#define ALIGNMENT 16
using namespace Knight;
struct KeFreedCode;
/**
* Defines a region of memory that is made of pages.
*/
struct KeCodeRegion
{
KeCodeRegion *next;
unsigned char *block_start;
unsigned char *block_pos;
KeFreedCode *free_list;
size_t total_size;
size_t end_free;
size_t total_free;
};
/**
* Defines freed code. We keep the size here because
* when we touch the linked list we don't want to dirty pages.
*/
struct KeFreedCode
{
KeCodeRegion *region;
unsigned char *block_start;
size_t size;
KeFreedCode *next;
};
struct KeSecret
{
KeCodeRegion *region;
size_t size;
};
class Knight::KeCodeCache
{
public:
/**
* First region that is live for use.
*/
KeCodeRegion *first_live;
/**
* First region that is full but has free entries.
*/
KeCodeRegion *first_partial;
/**
* First region that is full.
*/
KeCodeRegion *first_full;
/**
* Page granularity and size.
*/
unsigned int page_size;
unsigned int page_granularity;
/**
* This isn't actually for code, this is the node cache.
*/
KeCodeRegion *node_cache;
KeFreedCode *free_node_list;
};
KeCodeCache *Knight::KE_CreateCodeCache()
{
KeCodeCache *cache;
cache = new KeCodeCache;
memset(cache, 0, sizeof(KeCodeCache));
#if defined(WIN32)
SYSTEM_INFO info;
GetSystemInfo(&info);
cache->page_size = info.dwPageSize;
cache->page_granularity = info.dwAllocationGranularity;
#else
cache->page_size = cache->page_granularity = sysconf(_SC_PAGESIZE);
#endif
return cache;
}
inline size_t MinAllocSize()
{
size_t size;
size = sizeof(KeSecret);
size += ALIGNMENT;
size -= size % ALIGNMENT;
return size;
}
inline size_t ke_GetAllocSize(size_t size)
{
size += sizeof(KeSecret);
size += ALIGNMENT;
size -= size % ALIGNMENT;
return size;
}
void *ke_AllocInRegion(KeCodeCache *cache,
KeCodeRegion **prev,
KeCodeRegion *region,
unsigned char *ptr,
size_t alloc_size,
bool is_live)
{
KeSecret *secret;
/* Squirrel some info in the alloc. */
secret = (KeSecret *)ptr;
secret->region = region;
secret->size = alloc_size;
ptr += sizeof(KeSecret);
region->total_free -= alloc_size;
/* Check if we can't use the fast-path anymore. */
if ((is_live && region->end_free < MinAllocSize())
|| (!is_live && region->total_free < MinAllocSize()))
{
KeCodeRegion **start;
*prev = region->next;
/* Select the appropriate arena. */
if (is_live)
{
if (region->total_free < MinAllocSize())
{
start = &cache->first_full;
}
else
{
start = &cache->first_partial;
}
}
else
{
start = &cache->first_full;
}
region->next = *start;
*start = region;
}
return ptr;
}
void *ke_AllocFromLive(KeCodeCache *cache, size_t size)
{
void *ptr;
size_t alloc_size;
KeCodeRegion *region, **prev;
region = cache->first_live;
prev = &cache->first_live;
alloc_size = ke_GetAllocSize(size);
while (region != NULL)
{
if (region->end_free >= alloc_size)
{
/* Yay! We can do a simple alloc here. */
ptr = ke_AllocInRegion(cache, prev, region, region->block_pos, alloc_size, true);
/* Update our counters. */
region->block_pos += alloc_size;
region->end_free -= alloc_size;
return ptr;
}
prev = &region->next;
region = region->next;
}
return NULL;
}
void *ke_AllocFromPartial(KeCodeCache *cache, size_t size)
{
void *ptr;
size_t alloc_size;
KeCodeRegion *region, **prev;
region = cache->first_partial;
prev = &cache->first_partial;
alloc_size = ke_GetAllocSize(size);
while (region != NULL)
{
if (region->total_free >= alloc_size)
{
KeFreedCode *node, **last;
assert(region->free_list != NULL);
last = &region->free_list;
node = region->free_list;
while (node != NULL)
{
if (node->size >= alloc_size)
{
/* Use this node */
ptr = ke_AllocInRegion(cache, prev, region, node->block_start, alloc_size, false);
region->total_free -= node->size;
*last = node->next;
/* Make sure bookkeepping is correct. */
assert((region->free_list == NULL && region->total_free == 0)
|| (region->free_list != NULL && region->total_free != 0));
/* Link us back into the free node list. */
node->next = cache->free_node_list;
cache->free_node_list = node->next;
return ptr;
}
last = &node->next;
node = node->next;
}
}
prev = &region->next;
region = region->next;
}
return NULL;
}
KeCodeRegion *ke_AddRegionForSize(KeCodeCache *cache, size_t size)
{
KeCodeRegion *region;
region = new KeCodeRegion;
size = ke_GetAllocSize(size);
size += cache->page_granularity * 2;
size -= size % cache->page_granularity;
#if defined(WIN32)
region->block_start = (unsigned char *)VirtualAlloc(NULL, size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
#else
region->block_start = (unsigned char *)mmap(NULL, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, -1, 0);
region->block_start = (region->block_start == MAP_FAILED) ? NULL : region->block_start;
#endif
if (region->block_start == NULL)
{
delete region;
return NULL;
}
region->block_pos = region->block_start;
region->end_free = region->total_free = region->total_size = size;
region->next = cache->first_live;
cache->first_live = region;
region->free_list = NULL;
return region;
}
void *Knight::KE_AllocCode(KeCodeCache *cache, size_t size)
{
void *ptr;
/* Check live easy-adds */
if (cache->first_live != NULL)
{
if ((ptr = ke_AllocFromLive(cache, size)) != NULL)
{
return ptr;
}
}
/* Try looking in the free lists */
if (cache->first_partial != NULL)
{
if ((ptr = ke_AllocFromPartial(cache, size)) != NULL)
{
return ptr;
}
}
/* Create a new region */
if (ke_AddRegionForSize(cache, size) == NULL)
{
return NULL;
}
return ke_AllocFromLive(cache, size);
}
KeFreedCode *ke_GetFreeNode(KeCodeCache *cache)
{
KeFreedCode *ret;
if (cache->free_node_list != NULL)
{
ret = cache->free_node_list;
cache->free_node_list = ret->next;
return ret;
}
/* See if the current free node region has space. */
if (cache->node_cache != NULL
&& cache->node_cache->end_free >= sizeof(KeFreedCode))
{
ret = (KeFreedCode *)cache->node_cache->block_pos;
cache->node_cache->block_pos += sizeof(KeFreedCode);
cache->node_cache->total_free -= sizeof(KeFreedCode);
cache->node_cache->end_free -= sizeof(KeFreedCode);
return ret;
}
/* Otherwise, we need to alloc a new region. */
KeCodeRegion *region = new KeCodeRegion;
region->block_start = new unsigned char[cache->page_size / sizeof(KeFreedCode)];
region->block_pos = region->block_start + sizeof(KeFreedCode);
region->total_size = cache->page_size / sizeof(KeFreedCode);
region->total_free = region->end_free = (region->total_size - sizeof(KeFreedCode));
region->free_list = NULL;
region->next = cache->node_cache;
cache->node_cache = region;
return (KeFreedCode *)region->block_start;
}
void Knight::KE_FreeCode(KeCodeCache *cache, void *code)
{
KeSecret *secret;
KeFreedCode *node;
unsigned char *ptr;
KeCodeRegion *region;
ptr = (unsigned char *)code;
secret = (KeSecret *)(ptr - sizeof(KeSecret));
region = secret->region;
node = ke_GetFreeNode(cache);
node->block_start = (unsigned char *)code;
node->next = region->free_list;
region->free_list = node;
node->region = region;
node->size = secret->size;
}
KeCodeRegion *ke_DestroyRegion(KeCodeRegion *region)
{
KeCodeRegion *next;
next = region->next;
#if defined(WIN32)
VirtualFree(region->block_start, 0, MEM_RELEASE);
#else
munmap(region->block_start, region->total_size);
#endif
delete region;
return next;
}
void ke_DestroyRegionChain(KeCodeRegion *first)
{
while (first != NULL)
{
first = ke_DestroyRegion(first);
}
}
void Knight::KE_DestroyCodeCache(KeCodeCache *cache)
{
/* Destroy every region and call it a day. */
ke_DestroyRegionChain(cache->first_full);
ke_DestroyRegionChain(cache->first_live);
ke_DestroyRegionChain(cache->first_partial);
/* We use normal malloc for node cache regions */
KeCodeRegion *region, *next;
region = cache->node_cache;
while (region != NULL)
{
next = region->next;
delete [] region->block_start;
delete region;
region = next;
}
delete cache;
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef _INCLUDE_KNIGHT_KE_CODE_ALLOCATOR_H_
#define _INCLUDE_KNIGHT_KE_CODE_ALLOCATOR_H_
#include <stddef.h>
#include <stdint.h>
namespace Knight
{
class KeCodeCache;
/**
* @brief Creates a new code cache/allocator.
*
* @return New code cache allocator.
*/
extern KeCodeCache *KE_CreateCodeCache();
/**
* @brief Destroys a code cache allocator.
*
* @param cache Code cache object.
*/
extern void KE_DestroyCodeCache(KeCodeCache *cache);
/**
* @brief Allocates code memory that is readable, writable,
* and executable.
*
* The address returned wlil be aligned, minimally, on a 16-byte
* boundary.
*
* @param cache Code cache object.
* @param size Amount of memory needed.
* @return Address pointing to the memory.
*/
extern void *KE_AllocCode(KeCodeCache *cache, size_t size);
/**
* @brief Frees code memory.
*
* @param cache Code cache object.
* @param code Address of code memory.
*/
extern void KE_FreeCode(KeCodeCache *cache, void *code);
}
#endif //_INCLUDE_KNIGHT_KE_CODE_ALLOCATOR_H_
+40
View File
@@ -0,0 +1,40 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "code-stubs.h"
#include "environment.h"
using namespace sp;
CodeStubs::CodeStubs(Environment *env)
: env_(env),
invoke_stub_(nullptr),
return_stub_(nullptr)
{
}
bool
CodeStubs::Initialize()
{
if (!InitializeFeatureDetection())
return false;
if (!CompileInvokeStub())
return false;
return true;
}
void
CodeStubs::Shutdown()
{
if (invoke_stub_)
env_->FreeCode(invoke_stub_);
}
+56
View File
@@ -0,0 +1,56 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_code_stubs_h_
#define _include_sourcepawn_vm_code_stubs_h_
#include <stdint.h>
#include <sp_vm_api.h>
namespace sp {
class PluginContext;
class Environment;
typedef int (*InvokeStubFn)(PluginContext *cx, void *code, cell_t *rval);
class CodeStubs
{
public:
CodeStubs(Environment *env);
public:
bool Initialize();
void Shutdown();
SPVM_NATIVE_FUNC CreateFakeNativeStub(SPVM_FAKENATIVE_FUNC callback, void *userData);
InvokeStubFn InvokeStub() const {
return (InvokeStubFn)invoke_stub_;
}
void *ReturnStub() const {
return return_stub_;
}
private:
bool InitializeFeatureDetection();
bool CompileInvokeStub();
private:
Environment *env_;
void *invoke_stub_;
void *return_stub_; // Owned by invoke_stub_.
};
}
#endif // _include_sourcepawn_vm_code_stubs_h_
+71
View File
@@ -0,0 +1,71 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "compiled-function.h"
#include "x86/jit_x86.h"
#include "environment.h"
using namespace sp;
CompiledFunction::CompiledFunction(void *entry_addr, size_t code_length,
cell_t pcode_offs,
FixedArray<LoopEdge> *edges,
FixedArray<CipMapEntry> *cipmap)
: entry_(entry_addr),
code_length_(code_length),
code_offset_(pcode_offs),
edges_(edges),
cip_map_(cipmap)
{
}
CompiledFunction::~CompiledFunction()
{
Environment::get()->FreeCode(entry_);
}
static int cip_map_entry_cmp(const void *a1, const void *aEntry)
{
uint32_t pcoffs = (uint32_t)a1;
const CipMapEntry *entry = reinterpret_cast<const CipMapEntry *>(aEntry);
if (pcoffs < entry->pcoffs)
return -1;
if (pcoffs == entry->pcoffs)
return 0;
return pcoffs > entry->pcoffs;
}
ucell_t
CompiledFunction::FindCipByPc(void *pc)
{
if (uintptr_t(pc) < uintptr_t(entry_))
return kInvalidCip;
uint32_t pcoffs = intptr_t(pc) - intptr_t(entry_);
if (pcoffs > code_length_)
return kInvalidCip;
void *ptr = bsearch(
(void *)pcoffs,
cip_map_->buffer(),
cip_map_->length(),
sizeof(CipMapEntry),
cip_map_entry_cmp);
assert(ptr);
if (!ptr) {
// Shouldn't happen, but fail gracefully.
return kInvalidCip;
}
return code_offset_ + reinterpret_cast<CipMapEntry *>(ptr)->cipoffs;
}
+79
View File
@@ -0,0 +1,79 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
#define _INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
#include <sp_vm_types.h>
#include <am-fixedarray.h>
#include <am-refcounting.h>
namespace sp {
using namespace ke;
struct LoopEdge
{
// Offset to the patchable jump instruction, such that (base + offset - 4)
// yields a patchable location.
uint32_t offset;
// The displacement to either the timeout routine or the original
// displacement, depending on the timeout state.
int32_t disp32;
};
struct CipMapEntry {
// Offset from the first cip of the function.
uint32_t cipoffs;
// Offset from the first pc of the function.
uint32_t pcoffs;
};
static const ucell_t kInvalidCip = 0xffffffff;
class CompiledFunction
{
public:
CompiledFunction(void *entry_addr,
size_t code_length,
cell_t pcode_offs,
FixedArray<LoopEdge> *edges,
FixedArray<CipMapEntry> *cip_map);
~CompiledFunction();
public:
void *GetEntryAddress() const {
return entry_;
}
cell_t GetCodeOffset() const {
return code_offset_;
}
uint32_t NumLoopEdges() const {
return edges_->length();
}
LoopEdge &GetLoopEdge(size_t i) {
return edges_->at(i);
}
ucell_t FindCipByPc(void *pc);
private:
void *entry_;
size_t code_length_;
cell_t code_offset_;
AutoPtr<FixedArray<LoopEdge>> edges_;
AutoPtr<FixedArray<CipMapEntry>> cip_map_;
};
}
#endif //_INCLUDE_SOURCEPAWN_JIT2_FUNCTION_H_
+282
View File
@@ -0,0 +1,282 @@
/**
* vim: set ts=4 sts=4 sw=4 tw=99 noet:
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <sp_vm_api.h>
#include <stdlib.h>
#include <stdarg.h>
#include <am-utility.h> // Replace with am-cxx later.
#include "dll_exports.h"
#include "environment.h"
#include "stack-frames.h"
using namespace ke;
using namespace sp;
using namespace SourcePawn;
class SourcePawnFactory : public ISourcePawnFactory
{
public:
int ApiVersion() KE_OVERRIDE {
return SOURCEPAWN_API_VERSION;
}
ISourcePawnEnvironment *NewEnvironment() KE_OVERRIDE {
return Environment::New();
}
ISourcePawnEnvironment *CurrentEnvironment() KE_OVERRIDE {
return Environment::get();
}
} sFactory;
#ifdef SPSHELL
Environment *sEnv;
static void
DumpStack(IFrameIterator &iter)
{
int index = 0;
for (; !iter.Done(); iter.Next(), index++) {
const char *name = iter.FunctionName();
if (!name) {
fprintf(stdout, " [%d] <unknown>\n", index);
continue;
}
if (iter.IsScriptedFrame()) {
const char *file = iter.FilePath();
if (!file)
file = "<unknown>";
fprintf(stdout, " [%d] %s::%s, line %d\n", index, file, name, iter.LineNumber());
} else {
fprintf(stdout, " [%d] %s()\n", index, name);
}
}
}
class ShellDebugListener : public IDebugListener
{
public:
void ReportError(const IErrorReport &report, IFrameIterator &iter) KE_OVERRIDE {
fprintf(stdout, "Exception thrown: %s\n", report.Message());
DumpStack(iter);
}
void OnDebugSpew(const char *msg, ...) {
#if !defined(NDEBUG) && defined(DEBUG)
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
#endif
}
};
static cell_t Print(IPluginContext *cx, const cell_t *params)
{
char *p;
cx->LocalToString(params[1], &p);
return printf("%s", p);
}
static cell_t PrintNum(IPluginContext *cx, const cell_t *params)
{
return printf("%d\n", params[1]);
}
static cell_t PrintNums(IPluginContext *cx, const cell_t *params)
{
for (size_t i = 1; i <= size_t(params[0]); i++) {
int err;
cell_t *addr;
if ((err = cx->LocalToPhysAddr(params[i], &addr)) != SP_ERROR_NONE)
return cx->ThrowNativeErrorEx(err, "Could not read argument");
fprintf(stdout, "%d", *addr);
if (i != size_t(params[0]))
fprintf(stdout, ", ");
}
fprintf(stdout, "\n");
return 1;
}
static cell_t DoNothing(IPluginContext *cx, const cell_t *params)
{
return 1;
}
static void BindNative(IPluginRuntime *rt, const char *name, SPVM_NATIVE_FUNC fn)
{
int err;
uint32_t index;
if ((err = rt->FindNativeByName(name, &index)) != SP_ERROR_NONE)
return;
rt->UpdateNativeBinding(index, fn, 0, nullptr);
}
static cell_t PrintFloat(IPluginContext *cx, const cell_t *params)
{
return printf("%f\n", sp_ctof(params[1]));
}
static cell_t DoExecute(IPluginContext *cx, const cell_t *params)
{
int32_t ok = 0;
for (size_t i = 0; i < size_t(params[2]); i++) {
if (IPluginFunction *fn = cx->GetFunctionById(params[1])) {
if (fn->Execute(nullptr) != SP_ERROR_NONE)
continue;
ok++;
}
}
return ok;
}
static cell_t DoInvoke(IPluginContext *cx, const cell_t *params)
{
for (size_t i = 0; i < size_t(params[2]); i++) {
if (IPluginFunction *fn = cx->GetFunctionById(params[1])) {
if (!fn->Invoke())
return 0;
}
}
return 1;
}
static cell_t DumpStackTrace(IPluginContext *cx, const cell_t *params)
{
FrameIterator iter;
DumpStack(iter);
return 0;
}
static int Execute(const char *file)
{
char error[255];
AutoPtr<IPluginRuntime> rt(sEnv->APIv2()->LoadBinaryFromFile(file, error, sizeof(error)));
if (!rt) {
fprintf(stderr, "Could not load plugin: %s\n", error);
return 1;
}
BindNative(rt, "print", Print);
BindNative(rt, "printnum", PrintNum);
BindNative(rt, "printnums", PrintNums);
BindNative(rt, "printfloat", PrintFloat);
BindNative(rt, "donothing", DoNothing);
BindNative(rt, "execute", DoExecute);
BindNative(rt, "invoke", DoInvoke);
BindNative(rt, "dump_stack_trace", DumpStackTrace);
IPluginFunction *fun = rt->GetFunctionByName("main");
if (!fun)
return 0;
IPluginContext *cx = rt->GetDefaultContext();
int result;
{
ExceptionHandler eh(cx);
if (!fun->Invoke(&result)) {
fprintf(stderr, "Error executing main: %s\n", eh.Message());
return 1;
}
}
return result;
}
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Usage: <file>\n");
return 1;
}
if ((sEnv = Environment::New()) == nullptr) {
fprintf(stderr, "Could not initialize ISourcePawnEngine2\n");
return 1;
}
if (getenv("DISABLE_JIT"))
sEnv->SetJitEnabled(false);
ShellDebugListener debug;
sEnv->SetDebugger(&debug);
sEnv->InstallWatchdogTimer(5000);
int errcode = Execute(argv[1]);
sEnv->SetDebugger(NULL);
sEnv->Shutdown();
delete sEnv;
return errcode;
}
#else
#define MIN_API_VERSION 0x0207
EXPORTFUNC ISourcePawnFactory *
GetSourcePawnFactory(int apiVersion)
{
if (apiVersion < MIN_API_VERSION || apiVersion > SOURCEPAWN_API_VERSION)
return nullptr;
return &sFactory;
}
#endif
#if defined __linux__ || defined __APPLE__
extern "C" void __cxa_pure_virtual(void)
{
}
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
}
#endif
+47
View File
@@ -0,0 +1,47 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
#define _INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
#include <sp_vm_base.h>
#if defined WIN32
#define EXPORTFUNC extern "C" __declspec(dllexport)
#elif defined __GNUC__
#if __GNUC__ >= 3
#define EXPORTFUNC extern "C" __attribute__((visibility("default")))
#else
#define EXPORTFUNC extern "C"
#endif //__GNUC__ >= 3
#endif //defined __GNUC__
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_DLL_H_
+402
View File
@@ -0,0 +1,402 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "environment.h"
#include "x86/jit_x86.h"
#include "watchdog_timer.h"
#include "api.h"
#include "code-stubs.h"
#include "watchdog_timer.h"
#include <stdarg.h>
using namespace sp;
using namespace SourcePawn;
static Environment *sEnvironment = nullptr;
Environment::Environment()
: debugger_(nullptr),
exception_code_(SP_ERROR_NONE),
profiler_(nullptr),
jit_enabled_(true),
profiling_enabled_(false),
code_pool_(nullptr),
top_(nullptr)
{
}
Environment::~Environment()
{
}
Environment *
Environment::New()
{
assert(!sEnvironment);
if (sEnvironment)
return nullptr;
sEnvironment = new Environment();
if (!sEnvironment->Initialize()) {
delete sEnvironment;
sEnvironment = nullptr;
return nullptr;
}
return sEnvironment;
}
Environment *
Environment::get()
{
return sEnvironment;
}
bool
Environment::Initialize()
{
api_v1_ = new SourcePawnEngine();
api_v2_ = new SourcePawnEngine2();
code_stubs_ = new CodeStubs(this);
watchdog_timer_ = new WatchdogTimer(this);
if ((code_pool_ = Knight::KE_CreateCodeCache()) == nullptr)
return false;
// Safe to initialize code now that we have the code cache.
if (!code_stubs_->Initialize())
return false;
return true;
}
void
Environment::Shutdown()
{
watchdog_timer_->Shutdown();
code_stubs_->Shutdown();
Knight::KE_DestroyCodeCache(code_pool_);
assert(sEnvironment == this);
sEnvironment = nullptr;
}
void
Environment::EnableProfiling()
{
profiling_enabled_ = !!profiler_;
}
void
Environment::DisableProfiling()
{
profiling_enabled_ = false;
}
bool
Environment::InstallWatchdogTimer(int timeout_ms)
{
return watchdog_timer_->Initialize(timeout_ms);
}
ISourcePawnEngine *
Environment::APIv1()
{
return api_v1_;
}
ISourcePawnEngine2 *
Environment::APIv2()
{
return api_v2_;
}
static const char *sErrorMsgTable[] =
{
NULL,
"Unrecognizable file format",
"Decompressor was not found",
"Not enough space on the heap",
"Invalid parameter or parameter type",
"Invalid plugin address",
"Object or index not found",
"Invalid index or index not found",
"Not enough space on the stack",
"Debug section not found or debug not enabled",
"Invalid instruction",
"Invalid memory access",
"Stack went below stack boundary",
"Heap went below heap boundary",
"Divide by zero",
"Array index is out of bounds",
"Instruction contained invalid parameter",
"Stack memory leaked by native",
"Heap memory leaked by native",
"Dynamic array is too big",
"Tracker stack is out of bounds",
"Native is not bound",
"Maximum number of parameters reached",
"Native detected error",
"Plugin not runnable",
"Call was aborted",
"Plugin format is too old",
"Plugin format is too new",
"Out of memory",
"Integer overflow",
"Script execution timed out",
"Custom error",
"Fatal error"
};
const char *
Environment::GetErrorString(int error)
{
if (error < 1 || error > int(sizeof(sErrorMsgTable) / sizeof(sErrorMsgTable[0])))
return NULL;
return sErrorMsgTable[error];
}
void *
Environment::AllocateCode(size_t size)
{
return Knight::KE_AllocCode(code_pool_, size);
}
void
Environment::FreeCode(void *code)
{
Knight::KE_FreeCode(code_pool_, code);
}
void
Environment::RegisterRuntime(PluginRuntime *rt)
{
mutex_.AssertCurrentThreadOwns();
runtimes_.append(rt);
}
void
Environment::DeregisterRuntime(PluginRuntime *rt)
{
mutex_.AssertCurrentThreadOwns();
runtimes_.remove(rt);
}
static inline void
SwapLoopEdge(uint8_t *code, LoopEdge &e)
{
int32_t *loc = reinterpret_cast<int32_t *>(code + e.offset - 4);
int32_t new_disp32 = e.disp32;
e.disp32 = *loc;
*loc = new_disp32;
}
void
Environment::PatchAllJumpsForTimeout()
{
mutex_.AssertCurrentThreadOwns();
for (ke::InlineList<PluginRuntime>::iterator iter = runtimes_.begin(); iter != runtimes_.end(); iter++) {
PluginRuntime *rt = *iter;
for (size_t i = 0; i < rt->NumJitFunctions(); i++) {
CompiledFunction *fun = rt->GetJitFunction(i);
uint8_t *base = reinterpret_cast<uint8_t *>(fun->GetEntryAddress());
for (size_t j = 0; j < fun->NumLoopEdges(); j++)
SwapLoopEdge(base, fun->GetLoopEdge(j));
}
}
}
void
Environment::UnpatchAllJumpsFromTimeout()
{
mutex_.AssertCurrentThreadOwns();
for (ke::InlineList<PluginRuntime>::iterator iter = runtimes_.begin(); iter != runtimes_.end(); iter++) {
PluginRuntime *rt = *iter;
for (size_t i = 0; i < rt->NumJitFunctions(); i++) {
CompiledFunction *fun = rt->GetJitFunction(i);
uint8_t *base = reinterpret_cast<uint8_t *>(fun->GetEntryAddress());
for (size_t j = 0; j < fun->NumLoopEdges(); j++)
SwapLoopEdge(base, fun->GetLoopEdge(j));
}
}
}
int
Environment::Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result)
{
// Must be in an invoke frame.
assert(top_ && top_->cx() == runtime->GetBaseContext());
PluginContext *cx = runtime->GetBaseContext();
InvokeStubFn invoke = code_stubs_->InvokeStub();
return invoke(cx, fn->GetEntryAddress(), result);
}
void
Environment::ReportError(int code)
{
const char *message = GetErrorString(code);
if (!message) {
char buffer[255];
UTIL_Format(buffer, sizeof(buffer), "Unknown error code %d", code);
ReportError(code, buffer);
} else {
ReportError(code, message);
}
}
class ErrorReport : public SourcePawn::IErrorReport
{
public:
ErrorReport(int code, const char *message, PluginContext *cx)
: code_(code),
message_(message),
context_(cx)
{}
const char *Message() const KE_OVERRIDE {
return message_;
}
bool IsFatal() const KE_OVERRIDE {
switch (code_) {
case SP_ERROR_HEAPLOW:
case SP_ERROR_INVALID_ADDRESS:
case SP_ERROR_STACKLOW:
case SP_ERROR_INVALID_INSTRUCTION:
case SP_ERROR_MEMACCESS:
case SP_ERROR_STACKMIN:
case SP_ERROR_HEAPMIN:
case SP_ERROR_INSTRUCTION_PARAM:
case SP_ERROR_STACKLEAK:
case SP_ERROR_HEAPLEAK:
case SP_ERROR_TRACKER_BOUNDS:
case SP_ERROR_PARAMS_MAX:
case SP_ERROR_ABORTED:
case SP_ERROR_OUT_OF_MEMORY:
case SP_ERROR_FATAL:
return true;
default:
return false;
}
}
IPluginContext *Context() const KE_OVERRIDE {
return context_;
}
private:
int code_;
const char *message_;
PluginContext *context_;
};
void
Environment::ReportErrorVA(const char *fmt, va_list ap)
{
ReportErrorVA(SP_ERROR_USER, fmt, ap);
}
void
Environment::ReportErrorVA(int code, const char *fmt, va_list ap)
{
// :TODO: right-size the string rather than rely on this buffer.
char buffer[1024];
UTIL_FormatVA(buffer, sizeof(buffer), fmt, ap);
ReportError(code, buffer);
}
void
Environment::ReportErrorFmt(int code, const char *message, ...)
{
va_list ap;
va_start(ap, message);
ReportErrorVA(code, message, ap);
va_end(ap);
}
void
Environment::ReportError(int code, const char *message)
{
FrameIterator iter;
ErrorReport report(code, message, top_ ? top_->cx() : nullptr);
// If this fires, someone forgot to propagate an error.
assert(!hasPendingException());
// Save the exception state.
if (eh_top_) {
exception_code_ = code;
UTIL_Format(exception_message_, sizeof(exception_message_), "%s", message);
}
// For now, we always report exceptions even if they might be handled.
if (debugger_)
debugger_->ReportError(report, iter);
}
void
Environment::EnterExceptionHandlingScope(ExceptionHandler *handler)
{
handler->next_ = eh_top_;
eh_top_ = handler;
}
void
Environment::LeaveExceptionHandlingScope(ExceptionHandler *handler)
{
assert(handler == eh_top_);
eh_top_ = eh_top_->next_;
// To preserve compatibility with older API, we clear the exception state
// when there is no EH handler.
if (!eh_top_ || handler->catch_)
exception_code_ = SP_ERROR_NONE;
}
bool
Environment::HasPendingException(const ExceptionHandler *handler)
{
// Note here and elsewhere - this is not a sanity assert. In the future, the
// API may need to query the handler.
assert(handler == eh_top_);
return hasPendingException();
}
const char *
Environment::GetPendingExceptionMessage(const ExceptionHandler *handler)
{
// Note here and elsewhere - this is not a sanity assert. In the future, the
// API may need to query the handler.
assert(handler == eh_top_);
assert(HasPendingException(handler));
return exception_message_;
}
bool
Environment::hasPendingException() const
{
return exception_code_ != SP_ERROR_NONE;
}
void
Environment::clearPendingException()
{
exception_code_ = SP_ERROR_NONE;
}
int
Environment::getPendingExceptionCode() const
{
return exception_code_;
}
+200
View File
@@ -0,0 +1,200 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_environment_h_
#define _include_sourcepawn_vm_environment_h_
#include <sp_vm_api.h>
#include <am-utility.h> // Replace with am-cxx later.
#include <am-inlinelist.h>
#include <am-thread-utils.h>
#include "code-allocator.h"
#include "plugin-runtime.h"
#include "stack-frames.h"
namespace sp {
using namespace SourcePawn;
class PluginRuntime;
class CodeStubs;
class WatchdogTimer;
// An Environment encapsulates everything that's needed to load and run
// instances of plugins on a single thread. There can be at most one
// environment per thread.
//
// Currently, the VM is single threaded in that no more than one
// Environment can be created per process.
class Environment : public ISourcePawnEnvironment
{
public:
Environment();
~Environment();
static Environment *New();
void Shutdown() KE_OVERRIDE;
ISourcePawnEngine *APIv1() KE_OVERRIDE;
ISourcePawnEngine2 *APIv2() KE_OVERRIDE;
int ApiVersion() KE_OVERRIDE {
return SOURCEPAWN_API_VERSION;
}
// Access the current Environment.
static Environment *get();
bool InstallWatchdogTimer(int timeout_ms);
void EnterExceptionHandlingScope(ExceptionHandler *handler) KE_OVERRIDE;
void LeaveExceptionHandlingScope(ExceptionHandler *handler) KE_OVERRIDE;
bool HasPendingException(const ExceptionHandler *handler) KE_OVERRIDE;
const char *GetPendingExceptionMessage(const ExceptionHandler *handler) KE_OVERRIDE;
// Runtime functions.
const char *GetErrorString(int err);
void ReportError(int code);
void ReportError(int code, const char *message);
void ReportErrorFmt(int code, const char *message, ...);
void ReportErrorVA(const char *fmt, va_list ap);
void ReportErrorVA(int code, const char *fmt, va_list ap);
// Allocate and free executable memory.
void *AllocateCode(size_t size);
void FreeCode(void *code);
CodeStubs *stubs() {
return code_stubs_;
}
// Runtime management.
void RegisterRuntime(PluginRuntime *rt);
void DeregisterRuntime(PluginRuntime *rt);
void PatchAllJumpsForTimeout();
void UnpatchAllJumpsFromTimeout();
ke::Mutex *lock() {
return &mutex_;
}
int Invoke(PluginRuntime *runtime, CompiledFunction *fn, cell_t *result);
// Helpers.
void SetProfiler(IProfilingTool *profiler) {
profiler_ = profiler;
}
IProfilingTool *profiler() const {
return profiler_;
}
bool IsProfilingEnabled() const {
return profiling_enabled_;
}
void EnableProfiling();
void DisableProfiling();
void SetJitEnabled(bool enabled) {
}
bool IsJitEnabled() const {
return jit_enabled_;
}
void SetDebugger(IDebugListener *debugger) {
debugger_ = debugger;
}
IDebugListener *debugger() const {
return debugger_;
}
WatchdogTimer *watchdog() const {
return watchdog_timer_;
}
bool hasPendingException() const;
void clearPendingException();
int getPendingExceptionCode() const;
// These are indicators used for the watchdog timer.
uintptr_t FrameId() const {
return frame_id_;
}
bool RunningCode() const {
return !!top_;
}
void enterInvoke(InvokeFrame *frame) {
if (!top_)
frame_id_++;
top_ = frame;
}
void leaveInvoke() {
exit_frame_ = top_->prev_exit_frame();
top_ = top_->prev();
}
InvokeFrame *top() const {
return top_;
}
const ExitFrame &exit_frame() const {
return exit_frame_;
}
public:
static inline size_t offsetOfTopFrame() {
return offsetof(Environment, top_);
}
static inline size_t offsetOfExceptionCode() {
return offsetof(Environment, exception_code_);
}
private:
bool Initialize();
private:
ke::AutoPtr<ISourcePawnEngine> api_v1_;
ke::AutoPtr<ISourcePawnEngine2> api_v2_;
ke::AutoPtr<WatchdogTimer> watchdog_timer_;
ke::Mutex mutex_;
IDebugListener *debugger_;
ExceptionHandler *eh_top_;
int exception_code_;
char exception_message_[1024];
IProfilingTool *profiler_;
bool jit_enabled_;
bool profiling_enabled_;
Knight::KeCodeCache *code_pool_;
ke::InlineList<PluginRuntime> runtimes_;
uintptr_t frame_id_;
ke::AutoPtr<CodeStubs> code_stubs_;
InvokeFrame *top_;
ExitFrame exit_frame_;
};
class EnterProfileScope
{
public:
EnterProfileScope(const char *group, const char *name)
{
if (Environment::get()->IsProfilingEnabled())
Environment::get()->profiler()->EnterScope(group, name);
}
~EnterProfileScope()
{
if (Environment::get()->IsProfilingEnabled())
Environment::get()->profiler()->LeaveScope();
}
};
} // namespace sp
#endif // _include_sourcepawn_vm_environment_h_
+52
View File
@@ -0,0 +1,52 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2004-2015 AlliedModers LLC
//
// This file is part of SourcePawn. SourcePawn is licensed under the GNU
// General Public License, version 3.0 (GPL). If a copy of the GPL was not
// provided with this file, you can obtain it here:
// http://www.gnu.org/licenses/gpl.html
//
#include <stdint.h>
#include <smx/smx-headers.h>
#include "file-utils.h"
using namespace sp;
FileType
sp::DetectFileType(FILE *fp)
{
uint32_t magic = 0;
if (fread(&magic, sizeof(uint32_t), 1, fp) != 1)
return FileType::UNKNOWN;
if (magic == SmxConsts::FILE_MAGIC)
return FileType::SPFF;
return FileType::UNKNOWN;
}
FileReader::FileReader(FILE *fp)
: length_(0)
{
if (fseek(fp, 0, SEEK_END) != 0)
return;
long size = ftell(fp);
if (size < 0)
return;
if (fseek(fp, 0, SEEK_SET) != 0)
return;
ke::AutoArray<uint8_t> bytes(new uint8_t[size]);
if (!bytes || fread(bytes, sizeof(uint8_t), size, fp) != (size_t)size)
return;
buffer_ = bytes.take();
length_ = size;
}
FileReader::FileReader(ke::AutoArray<uint8_t> &buffer, size_t length)
: buffer_(buffer.take()),
length_(length)
{
}
+47
View File
@@ -0,0 +1,47 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2004-2015 AlliedModers LLC
//
// This file is part of SourcePawn. SourcePawn is licensed under the GNU
// General Public License, version 3.0 (GPL). If a copy of the GPL was not
// provided with this file, you can obtain it here:
// http://www.gnu.org/licenses/gpl.html
//
#ifndef _include_sourcepawn_file_parser_h_
#define _include_sourcepawn_file_parser_h_
#include <stdio.h>
#include <am-utility.h>
namespace sp {
enum class FileType {
UNKNOWN,
AMX,
AMXMODX,
SPFF
};
FileType DetectFileType(FILE *fp);
class FileReader
{
public:
FileReader(FILE *fp);
FileReader(ke::AutoArray<uint8_t> &buffer, size_t length);
const uint8_t *buffer() const {
return buffer_;
}
size_t length() const {
return length_;
}
protected:
ke::AutoArray<uint8_t> buffer_;
size_t length_;
};
} // namespace sp
#endif // _include_sourcepawn_file_parser_h_
+138
View File
@@ -0,0 +1,138 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_legacy_image_h_
#define _include_sourcepawn_vm_legacy_image_h_
#include <string.h>
namespace sp {
// A LegacyImage is an abstraction layer for reading the various types of
// binaries that expose Pawn or SourcePawn v1 pcode.
class LegacyImage
{
public:
virtual ~LegacyImage()
{}
enum class CodeVersion {
Unknown,
SP_1_0,
SP_1_1
};
struct Code {
const uint8_t *bytes;
size_t length;
CodeVersion version;
};
struct Data {
const uint8_t *bytes;
size_t length;
};
// (Almost) everything needed to implement the AMX and SPVM API.
virtual Code DescribeCode() const = 0;
virtual Data DescribeData() const = 0;
virtual size_t NumNatives() const = 0;
virtual const char *GetNative(size_t index) const = 0;
virtual bool FindNative(const char *name, size_t *indexp) const = 0;
virtual size_t NumPublics() const = 0;
virtual void GetPublic(size_t index, uint32_t *offsetp, const char **namep) const = 0;
virtual bool FindPublic(const char *name, size_t *indexp) const = 0;
virtual size_t NumPubvars() const = 0;
virtual void GetPubvar(size_t index, uint32_t *offsetp, const char **namep) const = 0;
virtual bool FindPubvar(const char *name, size_t *indexp) const = 0;
virtual size_t HeapSize() const = 0;
virtual size_t ImageSize() const = 0;
virtual const char *LookupFile(uint32_t code_offset) = 0;
virtual const char *LookupFunction(uint32_t code_offset) = 0;
virtual bool LookupLine(uint32_t code_offset, uint32_t *line) = 0;
};
class EmptyImage : public LegacyImage
{
public:
EmptyImage(size_t heapSize)
: heap_size_(heapSize)
{
heap_size_ += sizeof(uint32_t);
heap_size_ -= heap_size_ % sizeof(uint32_t);
memset(data_, 0, sizeof(data_));
memset(code_, 0, sizeof(code_));
}
public:
Code DescribeCode() const KE_OVERRIDE {
Code out;
out.bytes = code_;
out.length = sizeof(code_);
out.version = CodeVersion::SP_1_1;
return out;
}
Data DescribeData() const KE_OVERRIDE {
Data out;
out.bytes = data_;
out.length = sizeof(data_);
return out;
}
size_t NumNatives() const KE_OVERRIDE {
return 0;
}
const char *GetNative(size_t index) const KE_OVERRIDE {
return nullptr;
}
bool FindNative(const char *name, size_t *indexp) const KE_OVERRIDE {
return false;
}
size_t NumPublics() const KE_OVERRIDE {
return 0;
}
void GetPublic(size_t index, uint32_t *offsetp, const char **namep) const KE_OVERRIDE {
}
bool FindPublic(const char *name, size_t *indexp) const KE_OVERRIDE {
return false;
}
size_t NumPubvars() const KE_OVERRIDE {
return 0;
}
void GetPubvar(size_t index, uint32_t *offsetp, const char **namep) const KE_OVERRIDE {
}
bool FindPubvar(const char *name, size_t *indexp) const KE_OVERRIDE {
return false;
}
size_t HeapSize() const KE_OVERRIDE {
return heap_size_;
}
size_t ImageSize() const KE_OVERRIDE {
return 0;
}
const char *LookupFile(uint32_t code_offset) KE_OVERRIDE {
return nullptr;
}
const char *LookupFunction(uint32_t code_offset) {
return nullptr;
}
bool LookupLine(uint32_t code_offset, uint32_t *line) KE_OVERRIDE {
return false;
}
private:
size_t heap_size_;
uint8_t data_[4];
uint8_t code_[4];
};
}
#endif // _include_sourcepawn_vm_legacy_image_h_
+475
View File
@@ -0,0 +1,475 @@
// MD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
// Translation and modification (c) 1995 by Mordechai T. Abzug
// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
// The translator/ modifier does not claim (1) that MD5 will do what you think
// it does; (2) that this translation/ modification is accurate; or (3) that
// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
MDDRIVER.C - test driver for MD2, MD4 and MD5
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "md5.h"
#include <assert.h>
#include <string.h>
// MD5 simple initialization method
MD5::MD5(){
init();
}
// MD5 block update operation. Continues an MD5 message-digest
// operation, processing another message block, and updating the
// context.
void MD5::update (const uint1 *input, uint4 input_length) {
uint4 input_index, buffer_index;
uint4 buffer_space; // how much space is left in buffer
if (finalized){ // so we can't update!
/*cerr << "MD5::update: Can't update a finalized digest!" << endl;*/
return;
}
// Compute number of bytes mod 64
buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
// Update number of bits
if ( (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
count[1]++;
count[1] += ((uint4)input_length >> 29);
buffer_space = 64 - buffer_index; // how much space is left in buffer
// Transform as many times as possible.
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
// fill the rest of the buffer and transform
memcpy (buffer + buffer_index, input, buffer_space);
transform (buffer);
// now, transform each 64-byte piece of the input, bypassing the buffer
for (input_index = buffer_space; input_index + 63 < input_length;
input_index += 64)
transform (input+input_index);
buffer_index = 0; // so we can buffer remaining
}
else
input_index=0; // so we can buffer the whole input
// and here we do the buffering:
memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
}
// MD5 update for files.
// Like above, except that it works on files (and uses above as a primitive.)
void MD5::update(FILE *file){
unsigned char buffer[1024];
int len;
while ((len=fread(buffer, 1, 1024, file)))
update(buffer, len);
fclose (file);
}
// MD5 finalization. Ends an MD5 message-digest operation, writing the
// the message digest and zeroizing the context.
void MD5::finalize (){
unsigned char bits[8];
unsigned int index, padLen;
static uint1 PADDING[64]={
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (finalized){
/* cerr << "MD5::finalize: Already finalized this digest!" << endl;*/
return;
}
// Save number of bits
encode (bits, count, 8);
// Pad out to 56 mod 64.
index = (uint4) ((count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
update (PADDING, padLen);
// Append length (before padding)
update (bits, 8);
// Store state in digest
encode (digest, state, 16);
// Zeroize sensitive information
memset (buffer, 0, sizeof(*buffer));
finalized=1;
}
MD5::MD5(FILE *file){
init(); // must be called be all constructors
update(file);
finalize ();
}
unsigned char *MD5::raw_digest(){
if (!finalized){
/* cerr << "MD5::raw_digest: Can't get digest if you haven't "<<
"finalized the digest!" <<endl;*/
return ( (unsigned char*) "");
}
uint1 *s = new uint1[16];
memcpy(s, digest, 16);
return s;
}
unsigned char *MD5::raw_digest(unsigned char buffer[16])
{
if (!finalized)
{
return ( (unsigned char*) "");
}
memcpy(buffer, digest, 16);
return buffer;
}
char *MD5::hex_digest(){
int i;
char *s= new char[33];
assert(finalized);
for (i=0; i<16; i++)
sprintf(s+i*2, "%02x", digest[i]);
s[32]='\0';
return s;
}
char *MD5::hex_digest(char buffer[33]){
int i;
assert(finalized);
for (i=0; i<16; i++)
sprintf(buffer+i*2, "%02x", digest[i]);
buffer[32]='\0';
return buffer;
}
// PRIVATE METHODS:
void MD5::init(){
finalized=0; // we just started!
// Nothing counted, so count=0
count[0] = 0;
count[1] = 0;
// Load magic initialization constants.
state[0] = 0x67452301;
state[1] = 0xefcdab89;
state[2] = 0x98badcfe;
state[3] = 0x10325476;
}
// Constants for MD5Transform routine.
// Although we could use C++ style constants, defines are actually better,
// since they let us easily evade scope clashes.
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
// MD5 basic transformation. Transforms state based on block.
void MD5::transform (const uint1 block[64]){
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
decode (x, block, 64);
assert(!finalized); // not just a user error, since the method is private
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
// Zeroize sensitive information.
memset ( (uint1 *) x, 0, sizeof(x));
}
// Encodes input (UINT4) into output (unsigned char). Assumes len is
// a multiple of 4.
void MD5::encode (uint1 *output, const uint4 *input, uint4 len) {
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (uint1) (input[i] & 0xff);
output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
}
}
// Decodes input (unsigned char) into output (UINT4). Assumes len is
// a multiple of 4.
void MD5::decode (uint4 *output, const uint1 *input, uint4 len){
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
}
// Note: Replace "for loop" with standard memcpy if possible.
void MD5::memcpy (uint1 *output, const uint1 *input, uint4 len){
unsigned int i;
for (i = 0; i < len; i++)
output[i] = input[i];
}
// Note: Replace "for loop" with standard memset if possible.
void MD5::memset (uint1 *output, uint1 value, uint4 len){
unsigned int i;
for (i = 0; i < len; i++)
output[i] = value;
}
// ROTATE_LEFT rotates x left n bits.
inline unsigned int MD5::rotate_left (uint4 x, uint4 n){
return (x << n) | (x >> (32-n)) ;
}
// F, G, H and I are basic MD5 functions.
inline unsigned int MD5::F (uint4 x, uint4 y, uint4 z){
return (x & y) | (~x & z);
}
inline unsigned int MD5::G (uint4 x, uint4 y, uint4 z){
return (x & z) | (y & ~z);
}
inline unsigned int MD5::H (uint4 x, uint4 y, uint4 z){
return x ^ y ^ z;
}
inline unsigned int MD5::I (uint4 x, uint4 y, uint4 z){
return y ^ (x | ~z);
}
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
// Rotation is separate from addition to prevent recomputation.
inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += F(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += G(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += H(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac){
a += I(b, c, d) + x + ac;
a = rotate_left (a, s) +b;
}
+106
View File
@@ -0,0 +1,106 @@
// MD5.CC - source code for the C++/object oriented translation and
// modification of MD5.
// Translation and modification (c) 1995 by Mordechai T. Abzug
// This translation/ modification is provided "as is," without express or
// implied warranty of any kind.
// The translator/ modifier does not claim (1) that MD5 will do what you think
// it does; (2) that this translation/ modification is accurate; or (3) that
// this software is "merchantible." (Language for this disclaimer partially
// copied from the disclaimer below).
/* based on:
MD5.H - header file for MD5C.C
MDDRIVER.C - test driver for MD2, MD4 and MD5
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include <stdio.h>
//#include <fstream.h>
//#include <iostream.h>
class MD5 {
public:
// methods for controlled operation:
MD5 (); // simple initializer
void update (const unsigned char *input, unsigned int input_length);
void update (FILE *file);
void finalize ();
// constructors for special circumstances. All these constructors finalize
// the MD5 context.
MD5 (unsigned char *string); // digest string, finalize
MD5 (FILE *file); // digest file, close, finalize
// methods to acquire finalized result
unsigned char *raw_digest (); // digest as a 16-byte binary array
unsigned char *raw_digest(unsigned char buffer[16]);
char * hex_digest (); // digest as a 33-byte ascii-hex string
char * hex_digest (char buffer[33]); //same as above, passing buffer
private:
// first, some types:
typedef unsigned int uint4; // assumes integer is 4 words long
typedef unsigned short int uint2; // assumes short integer is 2 words long
typedef unsigned char uint1; // assumes char is 1 word long
// next, the private data:
uint4 state[4];
uint4 count[2]; // number of *bits*, mod 2^64
uint1 buffer[64]; // input buffer
uint1 digest[16];
uint1 finalized;
// last, the private methods, mostly static:
void init (); // called by all constructors
void transform (const uint1 *buffer); // does the real update work. Note
// that length is implied to be 64.
static void encode (uint1 *dest, const uint4 *src, uint4 length);
static void decode (uint4 *dest, const uint1 *src, uint4 length);
static void memcpy (uint1 *dest, const uint1 *src, uint4 length);
static void memset (uint1 *start, uint1 val, uint4 length);
static inline uint4 rotate_left (uint4 x, uint4 n);
static inline uint4 F (uint4 x, uint4 y, uint4 z);
static inline uint4 G (uint4 x, uint4 y, uint4 z);
static inline uint4 H (uint4 x, uint4 y, uint4 z);
static inline uint4 I (uint4 x, uint4 y, uint4 z);
static inline void FF (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void GG (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void HH (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
static inline void II (uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
uint4 s, uint4 ac);
};
+20
View File
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit-x86", "jit-x86.vcxproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+167
View File
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{307D9D61-51CA-4392-B111-4A3B4229100C}</ProjectGuid>
<RootNamespace>jitx86</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>sourcepawn.jit.x86</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>sourcepawn.jit.x86</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..;..\x86;..\..\..\public;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;$(MMSOURCE19)\core\sourcehook;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
</PostBuildEvent>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..;..\x86;..\..\..\public;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;$(MMSOURCE19)\core\sourcehook;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetFileName)</OutputFile>
<IgnoreSpecificDefaultLibraries>LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
<PostBuildEvent>
<Command>IF NOT "%SMOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%SMOUTDIR%\bin"</Command>
</PostBuildEvent>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\..\public</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\BaseRuntime.cpp" />
<ClCompile Include="..\dll_exports.cpp" />
<ClCompile Include="..\engine2.cpp" />
<ClCompile Include="..\jit_function.cpp" />
<ClCompile Include="..\md5\md5.cpp" />
<ClCompile Include="..\x86\jit_x86.cpp" />
<ClCompile Include="..\..\..\knight\shared\KeCodeAllocator.cpp" />
<ClCompile Include="..\x86\opcode_helpers.cpp" />
<ClCompile Include="..\sp_vm_basecontext.cpp" />
<ClCompile Include="..\sp_vm_engine.cpp" />
<ClCompile Include="..\sp_vm_function.cpp" />
<ClCompile Include="..\zlib\adler32.c" />
<ClCompile Include="..\zlib\compress.c" />
<ClCompile Include="..\zlib\crc32.c" />
<ClCompile Include="..\zlib\deflate.c" />
<ClCompile Include="..\zlib\gzio.c" />
<ClCompile Include="..\zlib\infback.c" />
<ClCompile Include="..\zlib\inffast.c" />
<ClCompile Include="..\zlib\inflate.c" />
<ClCompile Include="..\zlib\inftrees.c" />
<ClCompile Include="..\zlib\trees.c" />
<ClCompile Include="..\zlib\uncompr.c" />
<ClCompile Include="..\zlib\zutil.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\BaseRuntime.h" />
<ClInclude Include="..\dll_exports.h" />
<ClInclude Include="..\engine2.h" />
<ClInclude Include="..\jit_function.h" />
<ClInclude Include="..\jit_shared.h" />
<ClInclude Include="..\jit_version.h" />
<ClInclude Include="..\md5\md5.h" />
<ClInclude Include="..\x86\jit_x86.h" />
<ClInclude Include="..\x86\opcode_helpers.h" />
<ClInclude Include="..\sp_vm_basecontext.h" />
<ClInclude Include="..\sp_vm_engine.h" />
<ClInclude Include="..\sp_vm_function.h" />
<ClInclude Include="..\..\..\public\sourcepawn\sp_file_headers.h" />
<ClInclude Include="..\..\..\public\sourcepawn\sp_typeutil.h" />
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_api.h" />
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_base.h" />
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_types.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="SDK">
<UniqueIdentifier>{ed70871e-c6be-42d0-af01-c8b08e7645b3}</UniqueIdentifier>
</Filter>
<Filter Include="zlib">
<UniqueIdentifier>{be3a7952-1237-418c-82bb-d56f3b0f9204}</UniqueIdentifier>
</Filter>
<Filter Include="md5">
<UniqueIdentifier>{a4ac4f24-40e4-481c-9bd8-42a6f5b379f0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\BaseRuntime.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\dll_exports.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\engine2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\jit_function.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\x86\jit_x86.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\knight\shared\KeCodeAllocator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\x86\opcode_helpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sp_vm_basecontext.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sp_vm_engine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sp_vm_function.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\zlib\adler32.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\compress.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\crc32.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\deflate.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\gzio.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\infback.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\inffast.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\inflate.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\inftrees.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\trees.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\uncompr.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\zlib\zutil.c">
<Filter>zlib</Filter>
</ClCompile>
<ClCompile Include="..\md5\md5.cpp">
<Filter>md5</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\BaseRuntime.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\dll_exports.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\engine2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\jit_function.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\jit_shared.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\jit_version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\x86\jit_x86.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\x86\opcode_helpers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sp_vm_basecontext.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sp_vm_engine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sp_vm_function.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcepawn\sp_file_headers.h">
<Filter>SDK</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcepawn\sp_typeutil.h">
<Filter>SDK</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_api.h">
<Filter>SDK</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_base.h">
<Filter>SDK</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sourcepawn\sp_vm_types.h">
<Filter>SDK</Filter>
</ClInclude>
<ClInclude Include="..\md5\md5.h">
<Filter>md5</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\version.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+20
View File
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit-x86", "jit-x86.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+368
View File
@@ -0,0 +1,368 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="jit-x86"
ProjectGUID="{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
RootNamespace="jitx86"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\x86;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;&quot;$(MMSOURCE17)\core\sourcehook&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="0"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\x86;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;&quot;$(MMSOURCE17)\core\sourcehook&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="0"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\BaseRuntime.cpp"
>
</File>
<File
RelativePath="..\dll_exports.cpp"
>
</File>
<File
RelativePath="..\engine2.cpp"
>
</File>
<File
RelativePath="..\jit_function.cpp"
>
</File>
<File
RelativePath="..\x86\jit_x86.cpp"
>
</File>
<File
RelativePath="..\..\..\knight\shared\KeCodeAllocator.cpp"
>
</File>
<File
RelativePath="..\x86\opcode_helpers.cpp"
>
</File>
<File
RelativePath="..\sp_vm_basecontext.cpp"
>
</File>
<File
RelativePath="..\sp_vm_engine.cpp"
>
</File>
<File
RelativePath="..\sp_vm_function.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\BaseRuntime.h"
>
</File>
<File
RelativePath="..\dll_exports.h"
>
</File>
<File
RelativePath="..\engine2.h"
>
</File>
<File
RelativePath="..\jit_function.h"
>
</File>
<File
RelativePath="..\jit_shared.h"
>
</File>
<File
RelativePath="..\jit_version.h"
>
</File>
<File
RelativePath="..\x86\jit_x86.h"
>
</File>
<File
RelativePath="..\x86\opcode_helpers.h"
>
</File>
<File
RelativePath="..\sp_vm_basecontext.h"
>
</File>
<File
RelativePath="..\sp_vm_engine.h"
>
</File>
<File
RelativePath="..\sp_vm_function.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\version.rc"
>
</File>
</Filter>
<Filter
Name="SDK"
>
<File
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_typeutil.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_api.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_base.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_types.h"
>
</File>
</Filter>
<Filter
Name="zlib"
>
<File
RelativePath="..\zlib\adler32.c"
>
</File>
<File
RelativePath="..\zlib\compress.c"
>
</File>
<File
RelativePath="..\zlib\crc32.c"
>
</File>
<File
RelativePath="..\zlib\deflate.c"
>
</File>
<File
RelativePath="..\zlib\gzio.c"
>
</File>
<File
RelativePath="..\zlib\infback.c"
>
</File>
<File
RelativePath="..\zlib\inffast.c"
>
</File>
<File
RelativePath="..\zlib\inflate.c"
>
</File>
<File
RelativePath="..\zlib\inftrees.c"
>
</File>
<File
RelativePath="..\zlib\trees.c"
>
</File>
<File
RelativePath="..\zlib\uncompr.c"
>
</File>
<File
RelativePath="..\zlib\zutil.c"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+20
View File
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit-x86", "jit-x86.vcproj", "{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.ActiveCfg = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Debug|Win32.Build.0 = Debug|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.ActiveCfg = Release|Win32
{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+367
View File
@@ -0,0 +1,367 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="jit-x86"
ProjectGUID="{6EF06E6E-0ED5-4E2D-A8F3-01DD1EC25BA7}"
RootNamespace="jitx86"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\x86;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;&quot;$(MMSOURCE17)\core\sourcehook&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
EnableEnhancedInstructionSet="0"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
LinkIncremental="2"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMT"
GenerateDebugInformation="true"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..;..\x86;..\..\..\public\jit;..\..\..\public\jit\x86;..\..\..\public\sourcepawn;..\..\..\knight\shared;&quot;$(MMSOURCE17)\core\sourcehook&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JITX86_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
RuntimeLibrary="0"
EnableEnhancedInstructionSet="0"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\sourcepawn.jit.x86.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames="LIBC;LIBCD;LIBCMTD"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\BaseRuntime.cpp"
>
</File>
<File
RelativePath="..\dll_exports.cpp"
>
</File>
<File
RelativePath="..\engine2.cpp"
>
</File>
<File
RelativePath="..\jit_function.cpp"
>
</File>
<File
RelativePath="..\x86\jit_x86.cpp"
>
</File>
<File
RelativePath="..\..\..\knight\shared\KeCodeAllocator.cpp"
>
</File>
<File
RelativePath="..\x86\opcode_helpers.cpp"
>
</File>
<File
RelativePath="..\sp_vm_basecontext.cpp"
>
</File>
<File
RelativePath="..\sp_vm_engine.cpp"
>
</File>
<File
RelativePath="..\sp_vm_function.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\BaseRuntime.h"
>
</File>
<File
RelativePath="..\dll_exports.h"
>
</File>
<File
RelativePath="..\engine2.h"
>
</File>
<File
RelativePath="..\jit_function.h"
>
</File>
<File
RelativePath="..\jit_shared.h"
>
</File>
<File
RelativePath="..\jit_version.h"
>
</File>
<File
RelativePath="..\x86\jit_x86.h"
>
</File>
<File
RelativePath="..\x86\opcode_helpers.h"
>
</File>
<File
RelativePath="..\sp_vm_basecontext.h"
>
</File>
<File
RelativePath="..\sp_vm_engine.h"
>
</File>
<File
RelativePath="..\sp_vm_function.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath="..\version.rc"
>
</File>
</Filter>
<Filter
Name="SDK"
>
<File
RelativePath="..\..\..\public\sourcepawn\sp_file_headers.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_typeutil.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_api.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_base.h"
>
</File>
<File
RelativePath="..\..\..\public\sourcepawn\sp_vm_types.h"
>
</File>
</Filter>
<Filter
Name="zlib"
>
<File
RelativePath="..\zlib\adler32.c"
>
</File>
<File
RelativePath="..\zlib\compress.c"
>
</File>
<File
RelativePath="..\zlib\crc32.c"
>
</File>
<File
RelativePath="..\zlib\deflate.c"
>
</File>
<File
RelativePath="..\zlib\gzio.c"
>
</File>
<File
RelativePath="..\zlib\infback.c"
>
</File>
<File
RelativePath="..\zlib\inffast.c"
>
</File>
<File
RelativePath="..\zlib\inflate.c"
>
</File>
<File
RelativePath="..\zlib\inftrees.c"
>
</File>
<File
RelativePath="..\zlib\trees.c"
>
</File>
<File
RelativePath="..\zlib\uncompr.c"
>
</File>
<File
RelativePath="..\zlib\zutil.c"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+141
View File
@@ -0,0 +1,141 @@
/**
* vim: set ts=8 sw=2 tw=99 sts=2 et:
* =============================================================================
* SourceMod
* Copyright _(C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License), version 3.0), as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful), but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not), see <http://www.gnu.org/licenses/>.
*
* As a special exception), AlliedModders LLC gives you permission to link the
* code of this program _(as well as its derivative works) to "Half-Life 2)," the
* "Source Engine)," the "SourcePawn JIT)," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally), AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions), found in LICENSE.txt _(as of this writing), version JULY-31-2007)),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "opcodes.h"
using namespace sp;
using namespace SourcePawn;
const char *OpcodeNames[] = {
#define _(op, text) text,
OPCODE_LIST(_)
#undef _
NULL
};
#ifdef JIT_SPEW
void
SourcePawn::SpewOpcode(const sp_plugin_t *plugin, cell_t *start, cell_t *cip)
{
fprintf(stdout, " [%05d:%04d]", cip - (cell_t *)plugin->pcode, cip - start);
if (*cip >= OPCODES_TOTAL) {
fprintf(stdout, " unknown-opcode\n");
return;
}
OPCODE op = (OPCODE)*cip;
fprintf(stdout, " %s ", OpcodeNames[op]);
switch (op) {
case OP_PUSH_C:
case OP_PUSH_ADR:
case OP_SHL_C_PRI:
case OP_SHL_C_ALT:
case OP_SHR_C_PRI:
case OP_SHR_C_ALT:
case OP_ADD_C:
case OP_SMUL_C:
case OP_EQ_C_PRI:
case OP_EQ_C_ALT:
case OP_TRACKER_PUSH_C:
case OP_STACK:
case OP_PUSH_S:
case OP_HEAP:
case OP_GENARRAY:
case OP_GENARRAY_Z:
case OP_CONST_PRI:
case OP_CONST_ALT:
fprintf(stdout, "%d", cip[1]);
break;
case OP_JUMP:
case OP_JZER:
case OP_JNZ:
case OP_JEQ:
case OP_JNEQ:
case OP_JSLESS:
case OP_JSGRTR:
case OP_JSGEQ:
case OP_JSLEQ:
fprintf(stdout, "%05d:%04d",
cip[1] / 4,
((cell_t *)plugin->pcode + cip[1] / 4) - start);
break;
case OP_SYSREQ_C:
case OP_SYSREQ_N:
{
uint32_t index = cip[1];
if (index < plugin->num_natives)
fprintf(stdout, "%s", plugin->natives[index].name);
if (op == OP_SYSREQ_N)
fprintf(stdout, " ; (%d args, index %d)", cip[2], index);
else
fprintf(stdout, " ; (index %d)", index);
break;
}
case OP_PUSH2_C:
case OP_PUSH2:
case OP_PUSH2_S:
case OP_PUSH2_ADR:
fprintf(stdout, "%d, %d", cip[1], cip[2]);
break;
case OP_PUSH3_C:
case OP_PUSH3:
case OP_PUSH3_S:
case OP_PUSH3_ADR:
fprintf(stdout, "%d, %d, %d", cip[1], cip[2], cip[3]);
break;
case OP_PUSH4_C:
case OP_PUSH4:
case OP_PUSH4_S:
case OP_PUSH4_ADR:
fprintf(stdout, "%d, %d, %d, %d", cip[1], cip[2], cip[3], cip[4]);
break;
case OP_PUSH5_C:
case OP_PUSH5:
case OP_PUSH5_S:
case OP_PUSH5_ADR:
fprintf(stdout, "%d, %d, %d, %d, %d", cip[1], cip[2], cip[3], cip[4], cip[5]);
break;
default:
break;
}
fprintf(stdout, "\n");
}
#endif
+40
View File
@@ -0,0 +1,40 @@
/**
* vim: set ts=8 sw=2 tw=99 sts=2 et:
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License), version 3.0), as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful), but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not), see <http://www.gnu.org/licenses/>.
*
* As a special exception), AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2)," the
* "Source Engine)," the "SourcePawn JIT)," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally), AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions), found in LICENSE.txt (as of this writing), version JULY-31-2007)),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
#define _INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
#include <smx/smx-v1-opcodes.h>
namespace SourcePawn {
}
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_OPCODES_H_
+953
View File
@@ -0,0 +1,953 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include <limits.h>
#include <sp_vm_api.h>
#include "plugin-context.h"
#include "watchdog_timer.h"
#include "x86/jit_x86.h"
#include "environment.h"
#include "compiled-function.h"
using namespace sp;
using namespace SourcePawn;
#define CELLBOUNDMAX (INT_MAX/sizeof(cell_t))
#define STACKMARGIN ((cell_t)(16*sizeof(cell_t)))
static const size_t kMinHeapSize = 16384;
PluginContext::PluginContext(PluginRuntime *pRuntime)
: env_(Environment::get()),
m_pRuntime(pRuntime),
memory_(nullptr),
data_size_(m_pRuntime->data().length),
mem_size_(m_pRuntime->image()->HeapSize()),
m_pNullVec(nullptr),
m_pNullString(nullptr)
{
// Compute and align a minimum memory amount.
if (mem_size_ < data_size_)
mem_size_ = data_size_;
mem_size_ = ke::Align(mem_size_, sizeof(cell_t));
// Add a minimum heap size if needed.
if (mem_size_ < data_size_ + kMinHeapSize)
mem_size_ = data_size_ + kMinHeapSize;
assert(ke::IsAligned(mem_size_, sizeof(cell_t)));
hp_ = data_size_;
sp_ = mem_size_ - sizeof(cell_t);
frm_ = sp_;
tracker_.pBase = (ucell_t *)malloc(1024);
tracker_.pCur = tracker_.pBase;
tracker_.size = 1024 / sizeof(cell_t);
}
PluginContext::~PluginContext()
{
free(tracker_.pBase);
delete[] memory_;
}
bool
PluginContext::Initialize()
{
memory_ = new uint8_t[mem_size_];
if (!memory_)
return false;
memset(memory_ + data_size_, 0, mem_size_ - data_size_);
memcpy(memory_, m_pRuntime->data().bytes, data_size_);
/* Initialize the null references */
uint32_t index;
if (FindPubvarByName("NULL_VECTOR", &index) == SP_ERROR_NONE) {
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullVec = pubvar->offs;
} else {
m_pNullVec = NULL;
}
if (FindPubvarByName("NULL_STRING", &index) == SP_ERROR_NONE) {
sp_pubvar_t *pubvar;
GetPubvarByIndex(index, &pubvar);
m_pNullString = pubvar->offs;
} else {
m_pNullString = NULL;
}
return true;
}
IVirtualMachine *
PluginContext::GetVirtualMachine()
{
return NULL;
}
sp_context_t *
PluginContext::GetContext()
{
return reinterpret_cast<sp_context_t *>((IPluginContext * )this);
}
bool
PluginContext::IsDebugging()
{
return true;
}
int
PluginContext::SetDebugBreak(void *newpfn, void *oldpfn)
{
return SP_ERROR_ABORTED;
}
IPluginDebugInfo *
PluginContext::GetDebugInfo()
{
return NULL;
}
int
PluginContext::Execute(uint32_t code_addr, cell_t *result)
{
return SP_ERROR_ABORTED;
}
cell_t
PluginContext::ThrowNativeErrorEx(int error, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
env_->ReportErrorVA(error, msg, ap);
va_end(ap);
return 0;
}
cell_t
PluginContext::ThrowNativeError(const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
env_->ReportErrorVA(SP_ERROR_NATIVE, msg, ap);
va_end(ap);
return 0;
}
int
PluginContext::HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr)
{
cell_t *addr;
ucell_t realmem;
#if 0
if (cells > CELLBOUNDMAX)
{
return SP_ERROR_ARAM;
}
#else
assert(cells < CELLBOUNDMAX);
#endif
realmem = cells * sizeof(cell_t);
/**
* Check if the space between the heap and stack is sufficient.
*/
if ((cell_t)(sp_ - hp_ - realmem) < STACKMARGIN)
return SP_ERROR_HEAPLOW;
addr = (cell_t *)(memory_ + hp_);
/* store size of allocation in cells */
*addr = (cell_t)cells;
addr++;
hp_ += sizeof(cell_t);
*local_addr = hp_;
if (phys_addr)
*phys_addr = addr;
hp_ += realmem;
return SP_ERROR_NONE;
}
int
PluginContext::HeapPop(cell_t local_addr)
{
cell_t cellcount;
cell_t *addr;
/* check the bounds of this address */
local_addr -= sizeof(cell_t);
if (local_addr < (cell_t)data_size_ || local_addr >= sp_)
return SP_ERROR_INVALID_ADDRESS;
addr = (cell_t *)(memory_ + local_addr);
cellcount = (*addr) * sizeof(cell_t);
/* check if this memory count looks valid */
if ((signed)(hp_ - cellcount - sizeof(cell_t)) != local_addr)
return SP_ERROR_INVALID_ADDRESS;
hp_ = local_addr;
return SP_ERROR_NONE;
}
int
PluginContext::HeapRelease(cell_t local_addr)
{
if (local_addr < (cell_t)data_size_)
return SP_ERROR_INVALID_ADDRESS;
hp_ = local_addr - sizeof(cell_t);
return SP_ERROR_NONE;
}
int
PluginContext::FindNativeByName(const char *name, uint32_t *index)
{
return m_pRuntime->FindNativeByName(name, index);
}
int
PluginContext::GetNativeByIndex(uint32_t index, sp_native_t **native)
{
return m_pRuntime->GetNativeByIndex(index, native);
}
uint32_t
PluginContext::GetNativesNum()
{
return m_pRuntime->GetNativesNum();
}
int
PluginContext::FindPublicByName(const char *name, uint32_t *index)
{
return m_pRuntime->FindPublicByName(name, index);
}
int
PluginContext::GetPublicByIndex(uint32_t index, sp_public_t **pblic)
{
return m_pRuntime->GetPublicByIndex(index, pblic);
}
uint32_t
PluginContext::GetPublicsNum()
{
return m_pRuntime->GetPublicsNum();
}
int
PluginContext::GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar)
{
return m_pRuntime->GetPubvarByIndex(index, pubvar);
}
int
PluginContext::FindPubvarByName(const char *name, uint32_t *index)
{
return m_pRuntime->FindPubvarByName(name, index);
}
int
PluginContext::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
{
return m_pRuntime->GetPubvarAddrs(index, local_addr, phys_addr);
}
uint32_t
PluginContext::GetPubVarsNum()
{
return m_pRuntime->GetPubVarsNum();
}
int
PluginContext::BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::BindNative(const sp_nativeinfo_t *native)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC func)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::BindNativeToAny(SPVM_NATIVE_FUNC native)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr)
{
if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
{
return SP_ERROR_INVALID_ADDRESS;
}
if (phys_addr)
*phys_addr = (cell_t *)(memory_ + local_addr);
return SP_ERROR_NONE;
}
int
PluginContext::PushCell(cell_t value)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::PushCellsFromArray(cell_t array[], unsigned int numcells)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::LocalToString(cell_t local_addr, char **addr)
{
if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
{
return SP_ERROR_INVALID_ADDRESS;
}
*addr = (char *)(memory_ + local_addr);
return SP_ERROR_NONE;
}
int
PluginContext::PushString(cell_t *local_addr, char **phys_addr, const char *string)
{
return SP_ERROR_ABORTED;
}
int
PluginContext::StringToLocal(cell_t local_addr, size_t bytes, const char *source)
{
char *dest;
size_t len;
if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) || ((ucell_t)local_addr >= mem_size_))
{
return SP_ERROR_INVALID_ADDRESS;
}
if (bytes == 0)
return SP_ERROR_NONE;
len = strlen(source);
dest = (char *)(memory_ + local_addr);
if (len >= bytes)
len = bytes - 1;
memmove(dest, source, len);
dest[len] = '\0';
return SP_ERROR_NONE;
}
static inline int
__CheckValidChar(char *c)
{
int count;
int bytecount = 0;
for (count=1; (*c & 0xC0) == 0x80; count++)
c--;
switch (*c & 0xF0)
{
case 0xC0:
case 0xD0:
{
bytecount = 2;
break;
}
case 0xE0:
{
bytecount = 3;
break;
}
case 0xF0:
{
bytecount = 4;
break;
}
}
if (bytecount != count)
return count;
return 0;
}
int
PluginContext::StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes)
{
char *dest;
size_t len;
bool needtocheck = false;
if (((local_addr >= hp_) && (local_addr < sp_)) ||
(local_addr < 0) ||
((ucell_t)local_addr >= mem_size_))
{
return SP_ERROR_INVALID_ADDRESS;
}
if (maxbytes == 0)
return SP_ERROR_NONE;
len = strlen(source);
dest = (char *)(memory_ + local_addr);
if ((size_t)len >= maxbytes) {
len = maxbytes - 1;
needtocheck = true;
}
memmove(dest, source, len);
if ((dest[len-1] & 1<<7) && needtocheck)
len -= __CheckValidChar(dest+len-1);
dest[len] = '\0';
if (wrtnbytes)
*wrtnbytes = len;
return SP_ERROR_NONE;
}
IPluginFunction *
PluginContext::GetFunctionById(funcid_t func_id)
{
return m_pRuntime->GetFunctionById(func_id);
}
IPluginFunction *
PluginContext::GetFunctionByName(const char *public_name)
{
return m_pRuntime->GetFunctionByName(public_name);
}
int
PluginContext::LocalToStringNULL(cell_t local_addr, char **addr)
{
int err;
if ((err = LocalToString(local_addr, addr)) != SP_ERROR_NONE)
return err;
if ((cell_t *)*addr == m_pNullString)
*addr = NULL;
return SP_ERROR_NONE;
}
SourceMod::IdentityToken_t *
PluginContext::GetIdentity()
{
SourceMod::IdentityToken_t *tok;
if (GetKey(1, (void **)&tok))
return tok;
return NULL;
}
cell_t *
PluginContext::GetNullRef(SP_NULL_TYPE type)
{
if (type == SP_NULL_VECTOR)
return m_pNullVec;
return NULL;
}
bool
PluginContext::IsInExec()
{
for (InvokeFrame *ivk = env_->top(); ivk; ivk = ivk->prev()) {
if (ivk->cx() == this)
return true;
}
return false;
}
int
PluginContext::Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result)
{
ReportErrorNumber(SP_ERROR_ABORTED);
return SP_ERROR_ABORTED;
}
bool
PluginContext::Invoke(funcid_t fnid, const cell_t *params, unsigned int num_params, cell_t *result)
{
EnterProfileScope profileScope("SourcePawn", "EnterJIT");
if (!env_->watchdog()->HandleInterrupt()) {
ReportErrorNumber(SP_ERROR_TIMEOUT);
return false;
}
assert((fnid & 1) != 0);
unsigned public_id = fnid >> 1;
ScriptedInvoker *cfun = m_pRuntime->GetPublicFunction(public_id);
if (!cfun) {
ReportErrorNumber(SP_ERROR_NOT_FOUND);
return false;
}
if (m_pRuntime->IsPaused()) {
ReportErrorNumber(SP_ERROR_NOT_RUNNABLE);
return false;
}
if ((cell_t)(hp_ + 16*sizeof(cell_t)) > (cell_t)(sp_ - (sizeof(cell_t) * (num_params + 1)))) {
ReportErrorNumber(SP_ERROR_STACKLOW);
return false;
}
// Yuck. We have to do this for compatibility, otherwise something like
// ForwardSys or any sort of multi-callback-fire code would die. Later,
// we'll expose an Invoke() or something that doesn't do this.
env_->clearPendingException();
cell_t ignore_result;
if (result == NULL)
result = &ignore_result;
/* We got this far. It's time to start profiling. */
EnterProfileScope scriptScope("SourcePawn", cfun->FullName());
/* See if we have to compile the callee. */
CompiledFunction *fn = nullptr;
if (env_->IsJitEnabled()) {
/* We might not have to - check pcode offset. */
if ((fn = cfun->cachedCompiledFunction()) == nullptr) {
fn = m_pRuntime->GetJittedFunctionByOffset(cfun->Public()->code_offs);
if (!fn) {
int err = SP_ERROR_NONE;
if ((fn = CompileFunction(m_pRuntime, cfun->Public()->code_offs, &err)) == NULL) {
ReportErrorNumber(err);
return false;
}
}
cfun->setCachedCompiledFunction(fn);
}
} else {
ReportError("JIT is not enabled!");
return false;
}
/* Save our previous state. */
cell_t save_sp = sp_;
cell_t save_hp = hp_;
/* Push parameters */
sp_ -= sizeof(cell_t) * (num_params + 1);
cell_t *sp = (cell_t *)(memory_ + sp_);
sp[0] = num_params;
for (unsigned int i = 0; i < num_params; i++)
sp[i + 1] = params[i];
// Enter the execution engine.
int ir;
{
InvokeFrame ivkframe(this, fn->GetCodeOffset());
Environment *env = env_;
ir = env->Invoke(m_pRuntime, fn, result);
}
if (ir == SP_ERROR_NONE) {
// Verify that our state is still sane.
if (sp_ != save_sp) {
env_->ReportErrorFmt(
SP_ERROR_STACKLEAK,
"Stack leak detected: sp:%d should be %d!",
sp_,
save_sp);
return false;
}
if (hp_ != save_hp) {
env_->ReportErrorFmt(
SP_ERROR_HEAPLEAK,
"Heap leak detected: hp:%d should be %d!",
hp_,
save_hp);
return false;
}
}
sp_ = save_sp;
hp_ = save_hp;
return ir == SP_ERROR_NONE;
}
IPluginRuntime *
PluginContext::GetRuntime()
{
return m_pRuntime;
}
int
PluginContext::GetLastNativeError()
{
Environment *env = env_;
if (!env->hasPendingException())
return SP_ERROR_NONE;
return env->getPendingExceptionCode();
}
cell_t *
PluginContext::GetLocalParams()
{
return (cell_t *)(memory_ + frm_ + (2 * sizeof(cell_t)));
}
void
PluginContext::SetKey(int k, void *value)
{
if (k < 1 || k > 4)
return;
m_keys[k - 1] = value;
m_keys_set[k - 1] = true;
}
bool
PluginContext::GetKey(int k, void **value)
{
if (k < 1 || k > 4 || m_keys_set[k - 1] == false)
return false;
*value = m_keys[k - 1];
return true;
}
void
PluginContext::ClearLastNativeError()
{
if (env_->hasPendingException())
env_->clearPendingException();
}
int
PluginContext::popTrackerAndSetHeap()
{
assert(tracker_.pCur > tracker_.pBase);
tracker_.pCur--;
if (tracker_.pCur < tracker_.pBase)
return SP_ERROR_TRACKER_BOUNDS;
ucell_t amt = *tracker_.pCur;
if (amt > (hp_ - data_size_))
return SP_ERROR_HEAPMIN;
hp_ -= amt;
return SP_ERROR_NONE;
}
int
PluginContext::pushTracker(uint32_t amount)
{
if ((size_t)(tracker_.pCur - tracker_.pBase) >= tracker_.size)
return SP_ERROR_TRACKER_BOUNDS;
if (tracker_.pCur + 1 - (tracker_.pBase + tracker_.size) == 0) {
size_t disp = tracker_.size - 1;
tracker_.size *= 2;
tracker_.pBase = (ucell_t *)realloc(tracker_.pBase, tracker_.size * sizeof(cell_t));
if (!tracker_.pBase)
return SP_ERROR_TRACKER_BOUNDS;
tracker_.pCur = tracker_.pBase + disp;
}
*tracker_.pCur++ = amount;
return SP_ERROR_NONE;
}
cell_t
PluginContext::invokeNative(ucell_t native_idx, cell_t *params)
{
cell_t save_sp = sp_;
cell_t save_hp = hp_;
const sp_native_t *native = m_pRuntime->GetNative(native_idx);
if (native->status == SP_NATIVE_UNBOUND) {
ReportErrorNumber(SP_ERROR_INVALID_NATIVE);
return 0;
}
cell_t result = native->pfn(this, params);
if (save_sp != sp_) {
if (!env_->hasPendingException())
ReportErrorNumber(SP_ERROR_STACKLEAK);
return 0;
}
if (save_hp != hp_) {
if (!env_->hasPendingException())
ReportErrorNumber(SP_ERROR_HEAPLEAK);
return 0;
}
return result;
}
cell_t
PluginContext::invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params)
{
cell_t save_sp = sp_;
cell_t save_hp = hp_;
cell_t result = pfn(this, params);
if (save_sp != sp_) {
if (!env_->hasPendingException())
ReportErrorNumber(SP_ERROR_STACKLEAK);
return result;
}
if (save_hp != hp_) {
if (!env_->hasPendingException())
ReportErrorNumber(SP_ERROR_HEAPLEAK);
return result;
}
return result;
}
struct array_creation_t
{
const cell_t *dim_list; /* Dimension sizes */
cell_t dim_count; /* Number of dimensions */
cell_t *data_offs; /* Current offset AFTER the indirection vectors (data) */
cell_t *base; /* array base */
};
static cell_t
GenerateInnerArrayIndirectionVectors(array_creation_t *ar, int dim, cell_t cur_offs)
{
cell_t write_offs = cur_offs;
cell_t *data_offs = ar->data_offs;
cur_offs += ar->dim_list[dim];
// Dimension n-x where x > 2 will have sub-vectors.
// Otherwise, we just need to reference the data section.
if (ar->dim_count > 2 && dim < ar->dim_count - 2) {
// For each index at this dimension, write offstes to our sub-vectors.
// After we write one sub-vector, we generate its sub-vectors recursively.
// At the end, we're given the next offset we can use.
for (int i = 0; i < ar->dim_list[dim]; i++) {
ar->base[write_offs] = (cur_offs - write_offs) * sizeof(cell_t);
write_offs++;
cur_offs = GenerateInnerArrayIndirectionVectors(ar, dim + 1, cur_offs);
}
} else {
// In this section, there are no sub-vectors, we need to write offsets
// to the data. This is separate so the data stays in one big chunk.
// The data offset will increment by the size of the last dimension,
// because that is where the data is finally computed as.
for (int i = 0; i < ar->dim_list[dim]; i++) {
ar->base[write_offs] = (*data_offs - write_offs) * sizeof(cell_t);
write_offs++;
*data_offs = *data_offs + ar->dim_list[dim + 1];
}
}
return cur_offs;
}
static cell_t
calc_indirection(const array_creation_t *ar, cell_t dim)
{
cell_t size = ar->dim_list[dim];
if (dim < ar->dim_count - 2)
size += ar->dim_list[dim] * calc_indirection(ar, dim + 1);
return size;
}
static cell_t
GenerateArrayIndirectionVectors(cell_t *arraybase, cell_t dims[], cell_t _dimcount, bool autozero)
{
array_creation_t ar;
cell_t data_offs;
/* Reverse the dimensions */
cell_t dim_list[sDIMEN_MAX];
int cur_dim = 0;
for (int i = _dimcount - 1; i >= 0; i--)
dim_list[cur_dim++] = dims[i];
ar.base = arraybase;
ar.dim_list = dim_list;
ar.dim_count = _dimcount;
ar.data_offs = &data_offs;
data_offs = calc_indirection(&ar, 0);
GenerateInnerArrayIndirectionVectors(&ar, 0, 0);
return data_offs;
}
int
PluginContext::generateFullArray(uint32_t argc, cell_t *argv, int autozero)
{
// Calculate how many cells are needed.
if (argv[0] <= 0)
return SP_ERROR_ARRAY_TOO_BIG;
uint32_t cells = argv[0];
for (uint32_t dim = 1; dim < argc; dim++) {
cell_t dimsize = argv[dim];
if (dimsize <= 0)
return SP_ERROR_ARRAY_TOO_BIG;
if (!ke::IsUint32MultiplySafe(cells, dimsize))
return SP_ERROR_ARRAY_TOO_BIG;
cells *= uint32_t(dimsize);
if (!ke::IsUint32AddSafe(cells, dimsize))
return SP_ERROR_ARRAY_TOO_BIG;
cells += uint32_t(dimsize);
}
if (!ke::IsUint32MultiplySafe(cells, 4))
return SP_ERROR_ARRAY_TOO_BIG;
uint32_t bytes = cells * 4;
if (!ke::IsUint32AddSafe(hp_, bytes))
return SP_ERROR_ARRAY_TOO_BIG;
uint32_t new_hp = hp_ + bytes;
cell_t *dat_hp = reinterpret_cast<cell_t *>(memory_ + new_hp);
// argv, coincidentally, is STK.
if (dat_hp >= argv - STACK_MARGIN)
return SP_ERROR_HEAPLOW;
if (int err = pushTracker(bytes))
return err;
cell_t *base = reinterpret_cast<cell_t *>(memory_ + hp_);
cell_t offs = GenerateArrayIndirectionVectors(base, argv, argc, !!autozero);
assert(size_t(offs) == cells);
argv[argc - 1] = hp_;
hp_ = new_hp;
return SP_ERROR_NONE;
}
int
PluginContext::generateArray(cell_t dims, cell_t *stk, bool autozero)
{
if (dims == 1) {
uint32_t size = *stk;
if (size == 0 || !ke::IsUint32MultiplySafe(size, 4))
return SP_ERROR_ARRAY_TOO_BIG;
*stk = hp_;
uint32_t bytes = size * 4;
hp_ += bytes;
if (uintptr_t(memory_ + hp_) >= uintptr_t(stk))
return SP_ERROR_HEAPLOW;
if (int err = pushTracker(bytes))
return err;
if (autozero)
memset(memory_ + hp_, 0, bytes);
return SP_ERROR_NONE;
}
if (int err = generateFullArray(dims, stk, autozero))
return err;
return SP_ERROR_NONE;
}
ISourcePawnEngine2 *
PluginContext::APIv2()
{
return env_->APIv2();
}
void
PluginContext::ReportError(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
env_->ReportErrorVA(fmt, ap);
va_end(ap);
}
void
PluginContext::ReportErrorVA(const char *fmt, va_list ap)
{
env_->ReportErrorVA(fmt, ap);
}
void
PluginContext::ReportFatalError(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
env_->ReportErrorVA(SP_ERROR_FATAL, fmt, ap);
va_end(ap);
}
void
PluginContext::ReportFatalErrorVA(const char *fmt, va_list ap)
{
env_->ReportErrorVA(SP_ERROR_FATAL, fmt, ap);
}
void
PluginContext::ReportErrorNumber(int error)
{
env_->ReportError(error);
}
+193
View File
@@ -0,0 +1,193 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
#define _INCLUDE_SOURCEPAWN_BASECONTEXT_H_
#include "sp_vm_api.h"
#include "scripted-invoker.h"
#include "plugin-runtime.h"
namespace sp {
struct HeapTracker
{
HeapTracker()
: size(0),
pBase(nullptr),
pCur(nullptr)
{}
size_t size;
ucell_t *pBase;
ucell_t *pCur;
};
static const size_t SP_MAX_RETURN_STACK = 1024;
class Environment;
class PluginContext;
class PluginContext : public IPluginContext
{
public:
PluginContext(PluginRuntime *pRuntime);
~PluginContext();
bool Initialize();
public: //IPluginContext
IVirtualMachine *GetVirtualMachine();
sp_context_t *GetContext();
bool IsDebugging();
int SetDebugBreak(void *newpfn, void *oldpfn);
IPluginDebugInfo *GetDebugInfo();
int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr);
int HeapPop(cell_t local_addr);
int HeapRelease(cell_t local_addr);
int FindNativeByName(const char *name, uint32_t *index);
int GetNativeByIndex(uint32_t index, sp_native_t **native);
uint32_t GetNativesNum();
int FindPublicByName(const char *name, uint32_t *index);
int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
uint32_t GetPublicsNum();
int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
int FindPubvarByName(const char *name, uint32_t *index);
int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
uint32_t GetPubVarsNum();
int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr);
int LocalToString(cell_t local_addr, char **addr);
int StringToLocal(cell_t local_addr, size_t chars, const char *source);
int StringToLocalUTF8(cell_t local_addr, size_t maxbytes, const char *source, size_t *wrtnbytes);
int PushCell(cell_t value);
int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells);
int PushString(cell_t *local_addr, char **phys_addr, const char *string);
int PushCellsFromArray(cell_t array[], unsigned int numcells);
int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite);
int BindNative(const sp_nativeinfo_t *native);
int BindNativeToAny(SPVM_NATIVE_FUNC native);
int Execute(uint32_t code_addr, cell_t *result);
cell_t ThrowNativeErrorEx(int error, const char *msg, ...);
cell_t ThrowNativeError(const char *msg, ...);
IPluginFunction *GetFunctionByName(const char *public_name);
IPluginFunction *GetFunctionById(funcid_t func_id);
SourceMod::IdentityToken_t *GetIdentity();
cell_t *GetNullRef(SP_NULL_TYPE type);
int LocalToStringNULL(cell_t local_addr, char **addr);
int BindNativeToIndex(uint32_t index, SPVM_NATIVE_FUNC native);
int Execute2(IPluginFunction *function, const cell_t *params, unsigned int num_params, cell_t *result);
IPluginRuntime *GetRuntime();
int GetLastNativeError();
cell_t *GetLocalParams();
void SetKey(int k, void *value);
bool GetKey(int k, void **value);
void Refresh();
void ClearLastNativeError();
ISourcePawnEngine2 *APIv2() KE_OVERRIDE;
void ReportError(const char *fmt, ...) KE_OVERRIDE;
void ReportErrorVA(const char *fmt, va_list ap) KE_OVERRIDE;
void ReportFatalError(const char *fmt, ...) KE_OVERRIDE;
void ReportFatalErrorVA(const char *fmt, va_list ap) KE_OVERRIDE;
void ReportErrorNumber(int error) KE_OVERRIDE;
bool Invoke(funcid_t fnid, const cell_t *params, unsigned int num_params, cell_t *result);
size_t HeapSize() const {
return mem_size_;
}
uint8_t *memory() const {
return memory_;
}
size_t DataSize() const {
return data_size_;
}
PluginRuntime *runtime() const {
return m_pRuntime;
}
public:
bool IsInExec();
static inline size_t offsetOfTracker() {
return offsetof(PluginContext, tracker_);
}
static inline size_t offsetOfSp() {
return offsetof(PluginContext, sp_);
}
static inline size_t offsetOfRuntime() {
return offsetof(PluginContext, m_pRuntime);
}
static inline size_t offsetOfMemory() {
return offsetof(PluginContext, memory_);
}
int32_t *addressOfSp() {
return &sp_;
}
cell_t *addressOfFrm() {
return &frm_;
}
cell_t *addressOfHp() {
return &hp_;
}
cell_t frm() const {
return frm_;
}
cell_t hp() const {
return hp_;
}
int popTrackerAndSetHeap();
int pushTracker(uint32_t amount);
int generateArray(cell_t dims, cell_t *stk, bool autozero);
int generateFullArray(uint32_t argc, cell_t *argv, int autozero);
cell_t invokeNative(ucell_t native_idx, cell_t *params);
cell_t invokeBoundNative(SPVM_NATIVE_FUNC pfn, cell_t *params);
inline bool checkAddress(cell_t *stk, cell_t addr) {
if (uint32_t(addr) >= mem_size_)
return false;
if (addr < hp_)
return true;
if (reinterpret_cast<cell_t *>(memory_ + addr) < stk)
return false;
return true;
}
private:
Environment *env_;
PluginRuntime *m_pRuntime;
uint8_t *memory_;
uint32_t data_size_;
uint32_t mem_size_;
cell_t *m_pNullVec;
cell_t *m_pNullString;
void *m_keys[4];
bool m_keys_set[4];
// Tracker for local HEA growth.
HeapTracker tracker_;
// Stack, heap, and frame pointer.
cell_t sp_;
cell_t hp_;
cell_t frm_;
};
} // namespace sp
#endif //_INCLUDE_SOURCEPAWN_BASECONTEXT_H_
+494
View File
@@ -0,0 +1,494 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "plugin-runtime.h"
#include "x86/jit_x86.h"
#include "plugin-context.h"
#include "environment.h"
#include "md5/md5.h"
using namespace sp;
using namespace SourcePawn;
static inline bool
IsPointerCellAligned(void *p)
{
return uintptr_t(p) % 4 == 0;
}
PluginRuntime::PluginRuntime(LegacyImage *image)
: image_(image),
paused_(false),
computed_code_hash_(false),
computed_data_hash_(false)
{
code_ = image_->DescribeCode();
data_ = image_->DescribeData();
memset(code_hash_, 0, sizeof(code_hash_));
memset(data_hash_, 0, sizeof(data_hash_));
ke::AutoLock lock(Environment::get()->lock());
Environment::get()->RegisterRuntime(this);
}
PluginRuntime::~PluginRuntime()
{
// The watchdog thread takes the global JIT lock while it patches all
// runtimes. It is not enough to ensure that the unlinking of the runtime is
// protected; we cannot delete functions or code while the watchdog might be
// executing. Therefore, the entire destructor is guarded.
ke::AutoLock lock(Environment::get()->lock());
Environment::get()->DeregisterRuntime(this);
for (uint32_t i = 0; i < image_->NumPublics(); i++)
delete entrypoints_[i];
for (size_t i = 0; i < m_JitFunctions.length(); i++)
delete m_JitFunctions[i];
}
bool
PluginRuntime::Initialize()
{
if (!ke::IsAligned(code_.bytes, sizeof(cell_t))) {
// Align the code section.
aligned_code_ = new uint8_t[code_.length];
if (!aligned_code_)
return false;
memcpy(aligned_code_, code_.bytes, code_.length);
code_.bytes = aligned_code_;
}
natives_ = new sp_native_t[image_->NumNatives()];
if (!natives_)
return false;
memset(natives_, 0, sizeof(sp_native_t) * image_->NumNatives());
publics_ = new sp_public_t[image_->NumPublics()];
if (!publics_)
return false;
memset(publics_, 0, sizeof(sp_public_t) * image_->NumPublics());
pubvars_ = new sp_pubvar_t[image_->NumPubvars()];
if (!pubvars_)
return false;
memset(pubvars_, 0, sizeof(sp_pubvar_t) * image_->NumPubvars());
entrypoints_ = new ScriptedInvoker *[image_->NumPublics()];
if (!entrypoints_)
return false;
memset(entrypoints_, 0, sizeof(ScriptedInvoker *) * image_->NumPublics());
context_ = new PluginContext(this);
if (!context_->Initialize())
return false;
SetupFloatNativeRemapping();
if (!function_map_.init(32))
return false;
return true;
}
struct NativeMapping {
const char *name;
unsigned opcode;
};
static const NativeMapping sNativeMap[] = {
{ "FloatAbs", OP_FABS },
{ "FloatAdd", OP_FLOATADD },
{ "FloatSub", OP_FLOATSUB },
{ "FloatMul", OP_FLOATMUL },
{ "FloatDiv", OP_FLOATDIV },
{ "float", OP_FLOAT },
{ "FloatCompare", OP_FLOATCMP },
{ "RoundToCeil", OP_RND_TO_CEIL },
{ "RoundToZero", OP_RND_TO_ZERO },
{ "RoundToFloor", OP_RND_TO_FLOOR },
{ "RoundToNearest", OP_RND_TO_NEAREST },
{ "__FLOAT_GT__", OP_FLOAT_GT },
{ "__FLOAT_GE__", OP_FLOAT_GE },
{ "__FLOAT_LT__", OP_FLOAT_LT },
{ "__FLOAT_LE__", OP_FLOAT_LE },
{ "__FLOAT_EQ__", OP_FLOAT_EQ },
{ "__FLOAT_NE__", OP_FLOAT_NE },
{ "__FLOAT_NOT__", OP_FLOAT_NOT },
{ NULL, 0 },
};
void
PluginRuntime::SetupFloatNativeRemapping()
{
float_table_ = new floattbl_t[image_->NumNatives()];
for (size_t i = 0; i < image_->NumNatives(); i++) {
const char *name = image_->GetNative(i);
const NativeMapping *iter = sNativeMap;
while (iter->name) {
if (strcmp(name, iter->name) == 0) {
float_table_[i].found = true;
float_table_[i].index = iter->opcode;
break;
}
iter++;
}
}
}
unsigned
PluginRuntime::GetNativeReplacement(size_t index)
{
if (!float_table_[index].found)
return OP_NOP;
return float_table_[index].index;
}
void
PluginRuntime::SetNames(const char *fullname, const char *name)
{
name_ = name;
full_name_ = name;
}
static cell_t
InvalidNative(IPluginContext *pCtx, const cell_t *params)
{
return pCtx->ThrowNativeErrorEx(SP_ERROR_INVALID_NATIVE, "Invalid native");
}
void
PluginRuntime::AddJittedFunction(CompiledFunction *fn)
{
m_JitFunctions.append(fn);
ucell_t pcode_offset = fn->GetCodeOffset();
{
FunctionMap::Insert p = function_map_.findForAdd(pcode_offset);
assert(!p.found());
function_map_.add(p, pcode_offset, fn);
}
}
CompiledFunction *
PluginRuntime::GetJittedFunctionByOffset(cell_t pcode_offset)
{
FunctionMap::Result r = function_map_.find(pcode_offset);
if (!r.found())
return nullptr;
return r->value;
}
int
PluginRuntime::FindNativeByName(const char *name, uint32_t *index)
{
size_t idx;
if (!image_->FindNative(name, &idx))
return SP_ERROR_NOT_FOUND;
if (index)
*index = idx;
return SP_ERROR_NONE;
}
int
PluginRuntime::GetNativeByIndex(uint32_t index, sp_native_t **native)
{
return SP_ERROR_PARAM;
}
int
PluginRuntime::UpdateNativeBinding(uint32_t index, SPVM_NATIVE_FUNC pfn, uint32_t flags, void *data)
{
if (index >= image_->NumNatives())
return SP_ERROR_INDEX;
sp_native_t *native = &natives_[index];
native->pfn = pfn;
native->status = pfn
? SP_NATIVE_BOUND
: SP_NATIVE_UNBOUND;
native->flags = flags;
native->user = data;
return SP_ERROR_NONE;
}
const sp_native_t *
PluginRuntime::GetNative(uint32_t index)
{
if (index >= image_->NumNatives())
return nullptr;
if (!natives_[index].name)
natives_[index].name = image_->GetNative(index);
return &natives_[index];
}
uint32_t
PluginRuntime::GetNativesNum()
{
return image_->NumNatives();
}
int
PluginRuntime::FindPublicByName(const char *name, uint32_t *index)
{
size_t idx;
if (!image_->FindPublic(name, &idx))
return SP_ERROR_NOT_FOUND;
if (index)
*index = idx;
return SP_ERROR_NONE;
}
int
PluginRuntime::GetPublicByIndex(uint32_t index, sp_public_t **out)
{
if (index >= image_->NumPublics())
return SP_ERROR_INDEX;
sp_public_t &entry = publics_[index];
if (!entry.name) {
uint32_t offset;
image_->GetPublic(index, &offset, &entry.name);
entry.code_offs = offset;
entry.funcid = (index << 1) | 1;
}
if (out)
*out = &entry;
return SP_ERROR_NONE;
}
uint32_t
PluginRuntime::GetPublicsNum()
{
return image_->NumPublics();
}
int
PluginRuntime::GetPubvarByIndex(uint32_t index, sp_pubvar_t **out)
{
if (index >= image_->NumPubvars())
return SP_ERROR_INDEX;
sp_pubvar_t *pubvar = &pubvars_[index];
if (!pubvar->name) {
uint32_t offset;
image_->GetPubvar(index, &offset, &pubvar->name);
if (int err = context_->LocalToPhysAddr(offset, &pubvar->offs))
return err;
}
if (out)
*out = pubvar;
return SP_ERROR_NONE;
}
int
PluginRuntime::FindPubvarByName(const char *name, uint32_t *index)
{
size_t idx;
if (!image_->FindPubvar(name, &idx))
return SP_ERROR_NOT_FOUND;
if (index)
*index = idx;
return SP_ERROR_NONE;
}
int
PluginRuntime::GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr)
{
if (index >= image_->NumPubvars())
return SP_ERROR_INDEX;
uint32_t offset;
image_->GetPubvar(index, &offset, nullptr);
if (int err = context_->LocalToPhysAddr(offset, phys_addr))
return err;
*local_addr = offset;
return SP_ERROR_NONE;
}
uint32_t
PluginRuntime::GetPubVarsNum()
{
return image_->NumPubvars();
}
IPluginContext *
PluginRuntime::GetDefaultContext()
{
return context_;
}
IPluginDebugInfo *
PluginRuntime::GetDebugInfo()
{
return this;
}
IPluginFunction *
PluginRuntime::GetFunctionById(funcid_t func_id)
{
ScriptedInvoker *pFunc = NULL;
if (func_id & 1) {
func_id >>= 1;
if (func_id >= image_->NumPublics())
return NULL;
pFunc = entrypoints_[func_id];
if (!pFunc) {
entrypoints_[func_id] = new ScriptedInvoker(this, (func_id << 1) | 1, func_id);
pFunc = entrypoints_[func_id];
}
}
return pFunc;
}
ScriptedInvoker *
PluginRuntime::GetPublicFunction(size_t index)
{
assert(index < image_->NumPublics());
ScriptedInvoker *pFunc = entrypoints_[index];
if (!pFunc) {
sp_public_t *pub = NULL;
GetPublicByIndex(index, &pub);
if (pub)
entrypoints_[index] = new ScriptedInvoker(this, (index << 1) | 1, index);
pFunc = entrypoints_[index];
}
return pFunc;
}
IPluginFunction *
PluginRuntime::GetFunctionByName(const char *public_name)
{
uint32_t index;
if (FindPublicByName(public_name, &index) != SP_ERROR_NONE)
return NULL;
return GetPublicFunction(index);
}
bool
PluginRuntime::IsDebugging()
{
return true;
}
void
PluginRuntime::SetPauseState(bool paused)
{
paused_ = paused;
}
bool
PluginRuntime::IsPaused()
{
return paused_;
}
size_t
PluginRuntime::GetMemUsage()
{
return sizeof(*this) +
sizeof(PluginContext) +
image_->ImageSize() +
(aligned_code_ ? code_.length : 0) +
context_->HeapSize();
}
unsigned char *
PluginRuntime::GetCodeHash()
{
if (!computed_code_hash_) {
MD5 md5_pcode;
md5_pcode.update((const unsigned char *)code_.bytes, code_.length);
md5_pcode.finalize();
md5_pcode.raw_digest(code_hash_);
computed_code_hash_ = true;
}
return code_hash_;
}
unsigned char *
PluginRuntime::GetDataHash()
{
if (!computed_data_hash_) {
MD5 md5_data;
md5_data.update((const unsigned char *)data_.bytes, data_.length);
md5_data.finalize();
md5_data.raw_digest(data_hash_);
computed_data_hash_ = true;
}
return data_hash_;
}
PluginContext *
PluginRuntime::GetBaseContext()
{
return context_;
}
int
PluginRuntime::ApplyCompilationOptions(ICompilation *co)
{
return SP_ERROR_NONE;
}
int
PluginRuntime::LookupLine(ucell_t addr, uint32_t *line)
{
if (!image_->LookupLine(addr, line))
return SP_ERROR_NOT_FOUND;
return SP_ERROR_NONE;
}
int
PluginRuntime::LookupFunction(ucell_t addr, const char **out)
{
const char *name = image_->LookupFunction(addr);
if (!name)
return SP_ERROR_NOT_FOUND;
if (out)
*out = name;
return SP_ERROR_NONE;
}
int
PluginRuntime::LookupFile(ucell_t addr, const char **out)
{
const char *name = image_->LookupFile(addr);
if (!name)
return SP_ERROR_NOT_FOUND;
if (out)
*out = name;
return SP_ERROR_NONE;
}
+156
View File
@@ -0,0 +1,156 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
#define _INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
#include <sp_vm_api.h>
#include <am-vector.h>
#include <am-string.h>
#include <am-inlinelist.h>
#include <am-hashmap.h>
#include "compiled-function.h"
#include "scripted-invoker.h"
#include "legacy-image.h"
namespace sp {
class PluginContext;
struct floattbl_t
{
floattbl_t() {
found = false;
index = 0;
}
bool found;
unsigned int index;
};
/* Jit wants fast access to this so we expose things as public */
class PluginRuntime
: public SourcePawn::IPluginRuntime,
public SourcePawn::IPluginDebugInfo,
public ke::InlineListNode<PluginRuntime>
{
public:
PluginRuntime(LegacyImage *image);
~PluginRuntime();
bool Initialize();
public:
virtual bool IsDebugging();
virtual IPluginDebugInfo *GetDebugInfo();
virtual int FindNativeByName(const char *name, uint32_t *index);
virtual int GetNativeByIndex(uint32_t index, sp_native_t **native);
virtual uint32_t GetNativesNum();
virtual int FindPublicByName(const char *name, uint32_t *index);
virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr);
virtual uint32_t GetPublicsNum();
virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar);
virtual int FindPubvarByName(const char *name, uint32_t *index);
virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr);
virtual uint32_t GetPubVarsNum();
virtual IPluginFunction *GetFunctionByName(const char *public_name);
virtual IPluginFunction *GetFunctionById(funcid_t func_id);
virtual IPluginContext *GetDefaultContext();
virtual int ApplyCompilationOptions(ICompilation *co);
virtual void SetPauseState(bool paused);
virtual bool IsPaused();
virtual size_t GetMemUsage();
virtual unsigned char *GetCodeHash();
virtual unsigned char *GetDataHash();
CompiledFunction *GetJittedFunctionByOffset(cell_t pcode_offset);
void AddJittedFunction(CompiledFunction *fn);
void SetNames(const char *fullname, const char *name);
unsigned GetNativeReplacement(size_t index);
ScriptedInvoker *GetPublicFunction(size_t index);
int UpdateNativeBinding(uint32_t index, SPVM_NATIVE_FUNC pfn, uint32_t flags, void *data) KE_OVERRIDE;
const sp_native_t *GetNative(uint32_t index) KE_OVERRIDE;
int LookupLine(ucell_t addr, uint32_t *line) KE_OVERRIDE;
int LookupFunction(ucell_t addr, const char **name) KE_OVERRIDE;
int LookupFile(ucell_t addr, const char **filename) KE_OVERRIDE;
const char *GetFilename() KE_OVERRIDE {
return full_name_.chars();
}
PluginContext *GetBaseContext();
size_t NumJitFunctions() const {
return m_JitFunctions.length();
}
CompiledFunction *GetJitFunction(size_t i) const {
return m_JitFunctions[i];
}
const char *Name() const {
return name_.chars();
}
public:
typedef LegacyImage::Code Code;
typedef LegacyImage::Data Data;
const Code &code() const {
return code_;
}
const Data &data() const {
return data_;
}
LegacyImage *image() const {
return image_;
}
private:
void SetupFloatNativeRemapping();
private:
ke::AutoPtr<sp::LegacyImage> image_;
ke::AutoArray<uint8_t> aligned_code_;
ke::AutoArray<floattbl_t> float_table_;
ke::AString name_;
ke::AString full_name_;
Code code_;
Data data_;
ke::AutoArray<sp_native_t> natives_;
ke::AutoArray<sp_public_t> publics_;
ke::AutoArray<sp_pubvar_t> pubvars_;
ke::AutoArray<ScriptedInvoker *> entrypoints_;
ke::AutoPtr<PluginContext> context_;
struct FunctionMapPolicy {
static inline uint32_t hash(ucell_t value) {
return ke::HashInteger<4>(value);
}
static inline bool matches(ucell_t a, ucell_t b) {
return a == b;
}
};
typedef ke::HashMap<ucell_t, CompiledFunction *, FunctionMapPolicy> FunctionMap;
FunctionMap function_map_;
ke::Vector<CompiledFunction *> m_JitFunctions;
// Pause state.
bool paused_;
// Checksumming.
bool computed_code_hash_;
bool computed_data_hash_;
unsigned char code_hash_[16];
unsigned char data_hash_[16];
};
} // sp
#endif //_INCLUDE_SOURCEPAWN_JIT_RUNTIME_H_
+354
View File
@@ -0,0 +1,354 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <stdio.h>
#include <string.h>
#include "scripted-invoker.h"
#include "plugin-runtime.h"
#include "environment.h"
#include "plugin-context.h"
/********************
* FUNCTION CALLING *
********************/
using namespace sp;
using namespace SourcePawn;
ScriptedInvoker::ScriptedInvoker(PluginRuntime *runtime, funcid_t id, uint32_t pub_id)
: env_(Environment::get()),
context_(runtime->GetBaseContext()),
m_curparam(0),
m_errorstate(SP_ERROR_NONE),
m_FnId(id),
cc_function_(nullptr)
{
runtime->GetPublicByIndex(pub_id, &public_);
size_t rt_len = strlen(runtime->Name());
size_t len = rt_len + strlen("::") + strlen(public_->name);
full_name_ = new char[len + 1];
strcpy(full_name_, runtime->Name());
strcpy(&full_name_[rt_len], "::");
strcpy(&full_name_[rt_len + 2], public_->name);
}
ScriptedInvoker::~ScriptedInvoker()
{
}
bool
ScriptedInvoker::IsRunnable()
{
return !context_->runtime()->IsPaused();
}
int
ScriptedInvoker::CallFunction(const cell_t *params, unsigned int num_params, cell_t *result)
{
Environment::get()->ReportError(SP_ERROR_ABORTED);
return SP_ERROR_ABORTED;
}
int
ScriptedInvoker::CallFunction2(IPluginContext *pContext, const cell_t *params, unsigned int num_params, cell_t *result)
{
Environment::get()->ReportError(SP_ERROR_ABORTED);
return SP_ERROR_ABORTED;
}
IPluginContext *
ScriptedInvoker::GetParentContext()
{
return context_;
}
int ScriptedInvoker::PushCell(cell_t cell)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
m_info[m_curparam].marked = false;
m_params[m_curparam] = cell;
m_curparam++;
return SP_ERROR_NONE;
}
int
ScriptedInvoker::PushCellByRef(cell_t *cell, int flags)
{
return PushArray(cell, 1, flags);
}
int
ScriptedInvoker::PushFloat(float number)
{
cell_t val = *(cell_t *)&number;
return PushCell(val);
}
int
ScriptedInvoker::PushFloatByRef(float *number, int flags)
{
return PushCellByRef((cell_t *)number, flags);
}
int
ScriptedInvoker::PushArray(cell_t *inarray, unsigned int cells, int copyback)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
{
return SetError(SP_ERROR_PARAMS_MAX);
}
ParamInfo *info = &m_info[m_curparam];
info->flags = inarray ? copyback : 0;
info->marked = true;
info->size = cells;
info->str.is_sz = false;
info->orig_addr = inarray;
m_curparam++;
return SP_ERROR_NONE;
}
int
ScriptedInvoker::PushString(const char *string)
{
return _PushString(string, SM_PARAM_STRING_COPY, 0, strlen(string)+1);
}
int
ScriptedInvoker::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
{
return _PushString(buffer, sz_flags, cp_flags, length);
}
int
ScriptedInvoker::_PushString(const char *string, int sz_flags, int cp_flags, size_t len)
{
if (m_curparam >= SP_MAX_EXEC_PARAMS)
return SetError(SP_ERROR_PARAMS_MAX);
ParamInfo *info = &m_info[m_curparam];
info->marked = true;
info->orig_addr = (cell_t *)string;
info->flags = cp_flags;
info->size = len;
info->str.sz_flags = sz_flags;
info->str.is_sz = true;
m_curparam++;
return SP_ERROR_NONE;
}
void
ScriptedInvoker::Cancel()
{
if (!m_curparam)
return;
m_errorstate = SP_ERROR_NONE;
m_curparam = 0;
}
int
ScriptedInvoker::Execute(cell_t *result)
{
Environment *env = Environment::get();
env->clearPendingException();
// For backward compatibility, we have to clear the exception state.
// Otherwise code like this:
//
// static cell_t native(cx, params) {
// for (auto callback : callbacks) {
// callback->Execute();
// }
// }
//
// Could unintentionally leak a pending exception back to the caller,
// which wouldn't have happened before the Great Exception Refactoring.
ExceptionHandler eh(context_);
if (!Invoke(result)) {
assert(env->hasPendingException());
return env->getPendingExceptionCode();
}
return SP_ERROR_NONE;
}
bool
ScriptedInvoker::Invoke(cell_t *result)
{
if (!IsRunnable()) {
Cancel();
env_->ReportError(SP_ERROR_NOT_RUNNABLE);
return false;
}
if (int err = m_errorstate) {
Cancel();
env_->ReportError(err);
return false;
}
//This is for re-entrancy!
cell_t temp_params[SP_MAX_EXEC_PARAMS];
ParamInfo temp_info[SP_MAX_EXEC_PARAMS];
unsigned int numparams = m_curparam;
unsigned int i;
if (numparams)
{
//Save the info locally, then reset it for re-entrant calls.
memcpy(temp_info, m_info, numparams * sizeof(ParamInfo));
}
m_curparam = 0;
/* Browse the parameters and build arrays */
bool ok = true;
for (i=0; i<numparams; i++) {
/* Is this marked as an array? */
if (temp_info[i].marked) {
if (!temp_info[i].str.is_sz) {
/* Allocate a normal/generic array */
int err = context_->HeapAlloc(
temp_info[i].size,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
env_->ReportError(err);
ok = false;
break;
}
if (temp_info[i].orig_addr)
{
memcpy(temp_info[i].phys_addr, temp_info[i].orig_addr, sizeof(cell_t) * temp_info[i].size);
}
} else {
/* Calculate cells required for the string */
size_t cells = (temp_info[i].size + sizeof(cell_t) - 1) / sizeof(cell_t);
/* Allocate the buffer */
int err = context_->HeapAlloc(
cells,
&(temp_info[i].local_addr),
&(temp_info[i].phys_addr));
if (err != SP_ERROR_NONE) {
env_->ReportError(err);
ok = false;
break;
}
/* Copy original string if necessary */
if ((temp_info[i].str.sz_flags & SM_PARAM_STRING_COPY) && (temp_info[i].orig_addr != NULL))
{
/* Cut off UTF-8 properly */
if (temp_info[i].str.sz_flags & SM_PARAM_STRING_UTF8) {
context_->StringToLocalUTF8(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr,
NULL);
}
/* Copy a binary blob */
else if (temp_info[i].str.sz_flags & SM_PARAM_STRING_BINARY)
{
memmove(temp_info[i].phys_addr, temp_info[i].orig_addr, temp_info[i].size);
}
/* Copy ASCII characters */
else
{
context_->StringToLocal(
temp_info[i].local_addr,
temp_info[i].size,
(const char *)temp_info[i].orig_addr);
}
}
} /* End array/string calculation */
/* Update the pushed parameter with the byref local address */
temp_params[i] = temp_info[i].local_addr;
} else {
/* Just copy the value normally */
temp_params[i] = m_params[i];
}
}
/* Make the call if we can */
if (ok)
ok = context_->Invoke(m_FnId, temp_params, numparams, result);
/* i should be equal to the last valid parameter + 1 */
bool docopies = ok;
while (i--) {
if (!temp_info[i].marked)
continue;
if (docopies && (temp_info[i].flags & SM_PARAM_COPYBACK)) {
if (temp_info[i].orig_addr) {
if (temp_info[i].str.is_sz) {
memcpy(temp_info[i].orig_addr, temp_info[i].phys_addr, temp_info[i].size);
} else {
if (temp_info[i].size == 1) {
*temp_info[i].orig_addr = *(temp_info[i].phys_addr);
} else {
memcpy(temp_info[i].orig_addr,
temp_info[i].phys_addr,
temp_info[i].size * sizeof(cell_t));
}
}
}
}
if (int err = context_->HeapPop(temp_info[i].local_addr))
env_->ReportError(err);
}
return !env_->hasPendingException();
}
int
ScriptedInvoker::Execute2(IPluginContext *ctx, cell_t *result)
{
Environment::get()->ReportError(SP_ERROR_ABORTED);
return SP_ERROR_ABORTED;
}
IPluginRuntime *
ScriptedInvoker::GetParentRuntime()
{
return context_->runtime();
}
funcid_t
ScriptedInvoker::GetFunctionID()
{
return m_FnId;
}
int
ScriptedInvoker::SetError(int err)
{
m_errorstate = err;
return err;
}
+104
View File
@@ -0,0 +1,104 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#define _INCLUDE_SOURCEMOD_BASEFUNCTION_H_
#include <sp_vm_api.h>
#include <am-utility.h>
namespace sp {
using namespace SourcePawn;
class PluginRuntime;
class PluginContext;
class CompiledFunction;
struct ParamInfo
{
int flags; /* Copy-back flags */
bool marked; /* Whether this is marked as being used */
cell_t local_addr; /* Local address to free */
cell_t *phys_addr; /* Physical address of our copy */
cell_t *orig_addr; /* Original address to copy back to */
ucell_t size; /* Size of array in bytes */
struct {
bool is_sz; /* is a string */
int sz_flags; /* has sz flags */
} str;
};
class ScriptedInvoker : public IPluginFunction
{
public:
ScriptedInvoker(PluginRuntime *pRuntime, funcid_t fnid, uint32_t pub_id);
~ScriptedInvoker();
public:
int PushCell(cell_t cell);
int PushCellByRef(cell_t *cell, int flags);
int PushFloat(float number);
int PushFloatByRef(float *number, int flags);
int PushArray(cell_t *inarray, unsigned int cells, int copyback);
int PushString(const char *string);
int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
int Execute(cell_t *result);
void Cancel();
int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result);
IPluginContext *GetParentContext();
bool Invoke(cell_t *result);
bool IsRunnable();
funcid_t GetFunctionID();
int Execute2(IPluginContext *ctx, cell_t *result);
int CallFunction2(IPluginContext *ctx,
const cell_t *params,
unsigned int num_params,
cell_t *result);
IPluginRuntime *GetParentRuntime();
public:
const char *FullName() const {
return full_name_;
}
sp_public_t *Public() const {
return public_;
}
CompiledFunction *cachedCompiledFunction() const {
return cc_function_;
}
void setCachedCompiledFunction(CompiledFunction *fn) {
cc_function_ = fn;
}
private:
int _PushString(const char *string, int sz_flags, int cp_flags, size_t len);
int SetError(int err);
private:
Environment *env_;
PluginRuntime *m_pRuntime;
PluginContext *context_;
cell_t m_params[SP_MAX_EXEC_PARAMS];
ParamInfo m_info[SP_MAX_EXEC_PARAMS];
unsigned int m_curparam;
int m_errorstate;
funcid_t m_FnId;
ke::AutoArray<char> full_name_;
sp_public_t *public_;
CompiledFunction *cc_function_;
};
} // namespace sp
#endif //_INCLUDE_SOURCEMOD_BASEFUNCTION_H_
+617
View File
@@ -0,0 +1,617 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2004-2015 AlliedModers LLC
//
// This file is part of SourcePawn. SourcePawn is licensed under the GNU
// General Public License, version 3.0 (GPL). If a copy of the GPL was not
// provided with this file, you can obtain it here:
// http://www.gnu.org/licenses/gpl.html
//
#include "smx-v1-image.h"
#include "zlib/zlib.h"
using namespace ke;
using namespace sp;
SmxV1Image::SmxV1Image(FILE *fp)
: FileReader(fp),
hdr_(nullptr),
header_strings_(nullptr),
names_section_(nullptr),
names_(nullptr),
debug_names_section_(nullptr),
debug_names_(nullptr),
debug_syms_(nullptr),
debug_syms_unpacked_(nullptr)
{
}
// Validating SMX v1 scripts is fairly expensive. We reserve real validation
// for v2.
bool
SmxV1Image::validate()
{
if (length_ < sizeof(sp_file_hdr_t))
return error("bad header");
hdr_ = (sp_file_hdr_t *)buffer();
if (hdr_->magic != SmxConsts::FILE_MAGIC)
return error("bad header");
switch (hdr_->version) {
case SmxConsts::SP1_VERSION_1_0:
case SmxConsts::SP1_VERSION_1_1:
case SmxConsts::SP1_VERSION_1_7:
break;
default:
return error("unsupported version");
}
switch (hdr_->compression) {
case SmxConsts::FILE_COMPRESSION_GZ:
{
// The start of the compression cannot be larger than the file.
if (hdr_->dataoffs > length_)
return error("illegal compressed region");
// The compressed region must start after the header.
if (hdr_->dataoffs < sizeof(sp_file_hdr_t))
return error("illegal compressed region");
// The full size of the image must be at least as large as the start
// of the compressed region.
if (hdr_->imagesize < hdr_->dataoffs)
return error("illegal image size");
// Allocate the uncompressed image buffer.
uint32_t compressedSize = hdr_->disksize - hdr_->dataoffs;
AutoArray<uint8_t> uncompressed(new uint8_t[hdr_->imagesize]);
if (!uncompressed)
return error("out of memory");
// Decompress.
const uint8_t *src = buffer() + hdr_->dataoffs;
uint8_t *dest = (uint8_t *)uncompressed + hdr_->dataoffs;
uLongf destlen = hdr_->imagesize - hdr_->dataoffs;
int rv = uncompress(
(Bytef *)dest,
&destlen,
src,
compressedSize);
if (rv != Z_OK)
return error("could not decode compressed region");
// Copy the initial uncompressed region back in.
memcpy((uint8_t *)uncompressed, buffer(), hdr_->dataoffs);
// Replace the original buffer.
length_ = hdr_->imagesize;
buffer_ = uncompressed.take();
hdr_ = (sp_file_hdr_t *)buffer();
break;
}
case SmxConsts::FILE_COMPRESSION_NONE:
break;
default:
return error("unknown compression type");
}
// Validate the string table.
if (hdr_->stringtab >= length_)
return error("invalid string table");
header_strings_ = reinterpret_cast<const char *>(buffer() + hdr_->stringtab);
// Validate sections header.
if ((sizeof(sp_file_hdr_t) + hdr_->sections * sizeof(sp_file_section_t)) > length_)
return error("invalid section table");
size_t last_header_string = 0;
const sp_file_section_t *sections =
reinterpret_cast<const sp_file_section_t *>(buffer() + sizeof(sp_file_hdr_t));
for (size_t i = 0; i < hdr_->sections; i++) {
if (sections[i].nameoffs >= (hdr_->dataoffs - hdr_->stringtab))
return error("invalid section name");
if (sections[i].nameoffs > last_header_string)
last_header_string = sections[i].nameoffs;
sections_.append(Section());
sections_.back().dataoffs = sections[i].dataoffs;
sections_.back().size = sections[i].size;
sections_.back().name = header_strings_ + sections[i].nameoffs;
}
// Validate sanity of section header strings.
bool found_terminator = false;
for (const uint8_t *iter = buffer() + last_header_string;
iter < buffer() + hdr_->dataoffs;
iter++)
{
if (*iter == '\0') {
found_terminator = true;
break;
}
}
if (!found_terminator)
return error("malformed section names header");
names_section_ = findSection(".names");
if (!names_section_)
return error("could not find .names section");
if (!validateSection(names_section_))
return error("invalid names section");
names_ = reinterpret_cast<const char *>(buffer() + names_section_->dataoffs);
// The names section must be 0-length or be null-terminated.
if (names_section_->size != 0 &&
*(names_ + names_section_->size - 1) != '\0')
{
return error("malformed names section");
}
if (!validateCode())
return false;
if (!validateData())
return false;
if (!validatePublics())
return false;
if (!validatePubvars())
return false;
if (!validateNatives())
return false;
if (!validateDebugInfo())
return false;
return true;
}
const SmxV1Image::Section *
SmxV1Image::findSection(const char *name)
{
for (size_t i = 0; i < sections_.length(); i++) {
if (strcmp(sections_[i].name, name) == 0)
return &sections_[i];
}
return nullptr;
}
bool
SmxV1Image::validateSection(const Section *section)
{
if (section->dataoffs >= length_)
return false;
if (section->size > length_ - section->dataoffs)
return false;
return true;
}
bool
SmxV1Image::validateData()
{
// .data is required.
const Section *section = findSection(".data");
if (!section)
return error("could not find data");
if (!validateSection(section))
return error("invalid data section");
const sp_file_data_t *data =
reinterpret_cast<const sp_file_data_t *>(buffer() + section->dataoffs);
if (data->data > section->size)
return error("invalid data blob");
if (data->datasize > (section->size - data->data))
return error("invalid data blob");
const uint8_t *blob =
reinterpret_cast<const uint8_t *>(data) + data->data;
data_ = Blob<sp_file_data_t>(section, data, blob, data->datasize);
return true;
}
bool
SmxV1Image::validateCode()
{
// .code is required.
const Section *section = findSection(".code");
if (!section)
return error("could not find code");
if (!validateSection(section))
return error("invalid code section");
const sp_file_code_t *code =
reinterpret_cast<const sp_file_code_t *>(buffer() + section->dataoffs);
if (code->codeversion < SmxConsts::CODE_VERSION_SP1_MIN)
return error("code version is too old, no longer supported");
if (code->codeversion > SmxConsts::CODE_VERSION_SP1_MAX)
return error("code version is too new, not supported");
if (code->cellsize != 4)
return error("unsupported cellsize");
if (code->flags & ~CODEFLAG_DEBUG)
return error("unsupported code settings");
if (code->code > section->size)
return error("invalid code blob");
if (code->codesize > (section->size - code->code))
return error("invalid code blob");
const uint8_t *blob =
reinterpret_cast<const uint8_t *>(code) + code->code;
code_ = Blob<sp_file_code_t>(section, code, blob, code->codesize);
return true;
}
bool
SmxV1Image::validatePublics()
{
const Section *section = findSection(".publics");
if (!section)
return true;
if (!validateSection(section))
return error("invalid .publics section");
if ((section->size % sizeof(sp_file_publics_t)) != 0)
return error("invalid .publics section");
const sp_file_publics_t *publics =
reinterpret_cast<const sp_file_publics_t *>(buffer() + section->dataoffs);
size_t length = section->size / sizeof(sp_file_publics_t);
for (size_t i = 0; i < length; i++) {
if (!validateName(publics[i].name))
return error("invalid public name");
}
publics_ = List<sp_file_publics_t>(publics, length);
return true;
}
bool
SmxV1Image::validatePubvars()
{
const Section *section = findSection(".pubvars");
if (!section)
return true;
if (!validateSection(section))
return error("invalid .pubvars section");
if ((section->size % sizeof(sp_file_pubvars_t)) != 0)
return error("invalid .pubvars section");
const sp_file_pubvars_t *pubvars =
reinterpret_cast<const sp_file_pubvars_t *>(buffer() + section->dataoffs);
size_t length = section->size / sizeof(sp_file_pubvars_t);
for (size_t i = 0; i < length; i++) {
if (!validateName(pubvars[i].name))
return error("invalid pubvar name");
}
pubvars_ = List<sp_file_pubvars_t>(pubvars, length);
return true;
}
bool
SmxV1Image::validateNatives()
{
const Section *section = findSection(".natives");
if (!section)
return true;
if (!validateSection(section))
return error("invalid .natives section");
if ((section->size % sizeof(sp_file_natives_t)) != 0)
return error("invalid .natives section");
const sp_file_natives_t *natives =
reinterpret_cast<const sp_file_natives_t *>(buffer() + section->dataoffs);
size_t length = section->size / sizeof(sp_file_natives_t);
for (size_t i = 0; i < length; i++) {
if (!validateName(natives[i].name))
return error("invalid pubvar name");
}
natives_ = List<sp_file_natives_t>(natives, length);
return true;
}
bool
SmxV1Image::validateName(size_t offset)
{
return offset < names_section_->size;
}
bool
SmxV1Image::validateDebugInfo()
{
const Section *dbginfo = findSection(".dbg.info");
if (!dbginfo)
return true;
if (!validateSection(dbginfo))
return error("invalid .dbg.info section");
debug_info_ =
reinterpret_cast<const sp_fdbg_info_t *>(buffer() + dbginfo->dataoffs);
debug_names_section_ = findSection(".dbg.strings");
if (!debug_names_section_)
return error("no debug string table");
if (!validateSection(debug_names_section_))
return error("invalid .dbg.strings section");
debug_names_ = reinterpret_cast<const char *>(buffer() + debug_names_section_->dataoffs);
// Name tables must be null-terminated.
if (debug_names_section_->size != 0 &&
*(debug_names_ + debug_names_section_->size - 1) != '\0')
{
return error("invalid .dbg.strings section");
}
const Section *files = findSection(".dbg.files");
if (!files)
return error("no debug file table");
if (!validateSection(files))
return error("invalid debug file table");
if (files->size < sizeof(sp_fdbg_file_t) * debug_info_->num_files)
return error("invalid debug file table");
debug_files_ = List<sp_fdbg_file_t>(
reinterpret_cast<const sp_fdbg_file_t *>(buffer() + files->dataoffs),
debug_info_->num_files);
const Section *lines = findSection(".dbg.lines");
if (!lines)
return error("no debug lines table");
if (!validateSection(lines))
return error("invalid debug lines table");
if (lines->size < sizeof(sp_fdbg_line_t) * debug_info_->num_lines)
return error("invalid debug lines table");
debug_lines_ = List<sp_fdbg_line_t>(
reinterpret_cast<const sp_fdbg_line_t *>(buffer() + lines->dataoffs),
debug_info_->num_lines);
debug_symbols_section_ = findSection(".dbg.symbols");
if (!debug_symbols_section_)
return error("no debug symbol table");
if (!validateSection(debug_symbols_section_))
return error("invalid debug symbol table");
// See the note about unpacked debug sections in smx-headers.h.
if (hdr_->version == SmxConsts::SP1_VERSION_1_0 &&
!findSection(".dbg.natives"))
{
debug_syms_unpacked_ =
reinterpret_cast<const sp_u_fdbg_symbol_t *>(buffer() + debug_symbols_section_->dataoffs);
} else {
debug_syms_ =
reinterpret_cast<const sp_fdbg_symbol_t *>(buffer() + debug_symbols_section_->dataoffs);
}
return true;
}
auto
SmxV1Image::DescribeCode() const -> Code
{
Code code;
code.bytes = code_.blob();
code.length = code_.length();
switch (code_->codeversion) {
case SmxConsts::CODE_VERSION_JIT_1_0:
code.version = CodeVersion::SP_1_0;
break;
case SmxConsts::CODE_VERSION_JIT_1_1:
code.version = CodeVersion::SP_1_1;
break;
default:
assert(false);
code.version = CodeVersion::Unknown;
break;
}
return code;
}
auto
SmxV1Image::DescribeData() const -> Data
{
Data data;
data.bytes = data_.blob();
data.length = data_.length();
return data;
}
size_t
SmxV1Image::NumNatives() const
{
return natives_.length();
}
const char *
SmxV1Image::GetNative(size_t index) const
{
assert(index < natives_.length());
return names_ + natives_[index].name;
}
bool
SmxV1Image::FindNative(const char *name, size_t *indexp) const
{
for (size_t i = 0; i < natives_.length(); i++) {
const char *candidate = names_ + natives_[i].name;
if (strcmp(candidate, name) == 0) {
if (indexp)
*indexp = i;
return true;
}
}
return false;
}
size_t
SmxV1Image::NumPublics() const
{
return publics_.length();
}
void
SmxV1Image::GetPublic(size_t index, uint32_t *offsetp, const char **namep) const
{
assert(index < publics_.length());
if (offsetp)
*offsetp = publics_[index].address;
if (namep)
*namep = names_ + publics_[index].name;
}
bool
SmxV1Image::FindPublic(const char *name, size_t *indexp) const
{
int high = publics_.length() - 1;
int low = 0;
while (low <= high) {
int mid = (low + high) / 2;
const char *candidate = names_ + publics_[mid].name;
int diff = strcmp(candidate, name);
if (diff == 0) {
if (indexp) {
*indexp = mid;
return true;
}
}
if (diff < 0)
low = mid + 1;
else
high = mid - 1;
}
return false;
}
size_t
SmxV1Image::NumPubvars() const
{
return pubvars_.length();
}
void
SmxV1Image::GetPubvar(size_t index, uint32_t *offsetp, const char **namep) const
{
assert(index < pubvars_.length());
if (offsetp)
*offsetp = pubvars_[index].address;
if (namep)
*namep = names_ + pubvars_[index].name;
}
bool
SmxV1Image::FindPubvar(const char *name, size_t *indexp) const
{
int high = pubvars_.length() - 1;
int low = 0;
while (low <= high) {
int mid = (low + high) / 2;
const char *candidate = names_ + pubvars_[mid].name;
int diff = strcmp(candidate, name);
if (diff == 0) {
if (indexp) {
*indexp = mid;
return true;
}
}
if (diff < 0)
low = mid + 1;
else
high = mid - 1;
}
return false;
}
size_t
SmxV1Image::HeapSize() const
{
return data_->memsize;
}
size_t
SmxV1Image::ImageSize() const
{
return length_;
}
const char *
SmxV1Image::LookupFile(uint32_t addr)
{
int high = debug_files_.length();
int low = -1;
while (high - low > 1) {
int mid = (low + high) / 2;
if (debug_files_[mid].addr <= addr)
low = mid;
else
high = mid;
}
if (low == -1)
return nullptr;
if (debug_files_[low].name >= debug_names_section_->size)
return nullptr;
return debug_names_ + debug_files_[low].name;
}
template <typename SymbolType, typename DimType>
const char *
SmxV1Image::lookupFunction(const SymbolType *syms, uint32_t addr)
{
const uint8_t *cursor = reinterpret_cast<const uint8_t *>(syms);
const uint8_t *cursor_end = cursor + debug_symbols_section_->size;
for (uint32_t i = 0; i < debug_info_->num_syms; i++) {
if (cursor + sizeof(SymbolType) > cursor_end)
break;
const SymbolType *sym = reinterpret_cast<const SymbolType *>(cursor);
if (sym->ident == sp::IDENT_FUNCTION &&
sym->codestart <= addr &&
sym->codeend > addr)
{
if (sym->name >= debug_names_section_->size)
return nullptr;
return debug_names_ + sym->name;
}
if (sym->dimcount > 0)
cursor += sizeof(DimType) * sym->dimcount;
cursor += sizeof(SymbolType);
}
return nullptr;
}
const char *
SmxV1Image::LookupFunction(uint32_t code_offset)
{
if (debug_syms_) {
return lookupFunction<sp_fdbg_symbol_t, sp_fdbg_arraydim_t>(
debug_syms_, code_offset);
}
return lookupFunction<sp_u_fdbg_symbol_t, sp_u_fdbg_arraydim_t>(
debug_syms_unpacked_, code_offset);
}
bool
SmxV1Image::LookupLine(uint32_t addr, uint32_t *line)
{
int high = debug_lines_.length();
int low = -1;
while (high - low > 1) {
int mid = (low + high) / 2;
if (debug_lines_[mid].addr <= addr)
low = mid;
else
high = mid;
}
if (low == -1)
return false;
// Since the CIP occurs BEFORE the line, we have to add one.
*line = debug_lines_[low].line + 1;
return true;
}
+204
View File
@@ -0,0 +1,204 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2004-2015 AlliedModers LLC
//
// This file is part of SourcePawn. SourcePawn is licensed under the GNU
// General Public License, version 3.0 (GPL). If a copy of the GPL was not
// provided with this file, you can obtain it here:
// http://www.gnu.org/licenses/gpl.html
//
#ifndef _include_sourcepawn_smx_parser_h_
#define _include_sourcepawn_smx_parser_h_
#include <stdio.h>
#include <smx/smx-headers.h>
#include <smx/smx-v1.h>
#include <am-utility.h>
#include <am-string.h>
#include <am-vector.h>
#include "file-utils.h"
#include "legacy-image.h"
namespace sp {
class SmxV1Image
: public FileReader,
public LegacyImage
{
public:
SmxV1Image(FILE *fp);
// This must be called to initialize the reader.
bool validate();
const sp_file_hdr_t *hdr() const {
return hdr_;
}
const char *errorMessage() const {
return error_.chars();
}
public:
Code DescribeCode() const KE_OVERRIDE;
Data DescribeData() const KE_OVERRIDE;
size_t NumNatives() const KE_OVERRIDE;
const char *GetNative(size_t index) const KE_OVERRIDE;
bool FindNative(const char *name, size_t *indexp) const KE_OVERRIDE;
size_t NumPublics() const KE_OVERRIDE;
void GetPublic(size_t index, uint32_t *offsetp, const char **namep) const KE_OVERRIDE;
bool FindPublic(const char *name, size_t *indexp) const KE_OVERRIDE;
size_t NumPubvars() const KE_OVERRIDE;
void GetPubvar(size_t index, uint32_t *offsetp, const char **namep) const KE_OVERRIDE;
bool FindPubvar(const char *name, size_t *indexp) const KE_OVERRIDE;
size_t HeapSize() const KE_OVERRIDE;
size_t ImageSize() const KE_OVERRIDE;
const char *LookupFile(uint32_t code_offset) KE_OVERRIDE;
const char *LookupFunction(uint32_t code_offset) KE_OVERRIDE;
bool LookupLine(uint32_t code_offset, uint32_t *line) KE_OVERRIDE;
private:
struct Section
{
const char *name;
uint32_t dataoffs;
uint32_t size;
};
const Section *findSection(const char *name);
public:
template <typename T>
class Blob
{
public:
Blob()
: header_(nullptr),
section_(nullptr),
blob_(nullptr),
length_(0)
{}
Blob(const Section *header,
const T *section,
const uint8_t *blob,
size_t length)
: header_(header),
section_(section),
blob_(blob),
length_(length)
{}
size_t size() const {
return section_->size;
}
const T * operator ->() const {
return section_;
}
const uint8_t *blob() const {
return blob_;
}
size_t length() const {
return length_;
}
bool exists() const {
return !!header_;
}
private:
const Section *header_;
const T *section_;
const uint8_t *blob_;
size_t length_;
};
template <typename T>
class List
{
public:
List()
: section_(nullptr),
length_(0)
{}
List(const T *section, size_t length)
: section_(section),
length_(length)
{}
size_t length() const {
return length_;
}
const T &operator[](size_t index) const {
assert(index < length());
return section_[index];
}
bool exists() const {
return !!section_;
}
private:
const T *section_;
size_t length_;
};
public:
const Blob<sp_file_code_t> &code() const {
return code_;
}
const Blob<sp_file_data_t> &data() const {
return data_;
}
const List<sp_file_publics_t> &publics() const {
return publics_;
}
const List<sp_file_natives_t> &natives() const {
return natives_;
}
const List<sp_file_pubvars_t> &pubvars() const {
return pubvars_;
}
protected:
bool error(const char *msg) {
error_ = msg;
return false;
}
bool validateName(size_t offset);
bool validateSection(const Section *section);
bool validateCode();
bool validateData();
bool validatePublics();
bool validatePubvars();
bool validateNatives();
bool validateDebugInfo();
private:
template <typename SymbolType, typename DimType>
const char *lookupFunction(const SymbolType *syms, uint32_t addr);
private:
sp_file_hdr_t *hdr_;
ke::AString error_;
const char *header_strings_;
ke::Vector<Section> sections_;
const Section *names_section_;
const char *names_;
Blob<sp_file_code_t> code_;
Blob<sp_file_data_t> data_;
List<sp_file_publics_t> publics_;
List<sp_file_natives_t> natives_;
List<sp_file_pubvars_t> pubvars_;
const Section *debug_names_section_;
const char *debug_names_;
const sp_fdbg_info_t *debug_info_;
List<sp_fdbg_file_t> debug_files_;
List<sp_fdbg_line_t> debug_lines_;
const Section *debug_symbols_section_;
const sp_fdbg_symbol_t *debug_syms_;
const sp_u_fdbg_symbol_t *debug_syms_unpacked_;
};
} // namespace sp
#endif // _include_sourcepawn_smx_parser_h_
+227
View File
@@ -0,0 +1,227 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "environment.h"
#include "plugin-runtime.h"
#include "plugin-context.h"
#include "stack-frames.h"
#include "x86/frames-x86.h"
#include "compiled-function.h"
using namespace ke;
using namespace sp;
using namespace SourcePawn;
InvokeFrame::InvokeFrame(PluginContext *cx, ucell_t entry_cip)
: prev_(Environment::get()->top()),
cx_(cx),
prev_exit_frame_(Environment::get()->exit_frame()),
entry_cip_(0),
entry_sp_(nullptr)
{
Environment::get()->enterInvoke(this);
}
InvokeFrame::~InvokeFrame()
{
assert(Environment::get()->top() == this);
Environment::get()->leaveInvoke();
}
FrameIterator::FrameIterator()
: ivk_(Environment::get()->top()),
exit_frame_(Environment::get()->exit_frame()),
runtime_(nullptr),
sp_iter_(nullptr),
sp_stop_(nullptr),
function_cip_(kInvalidCip),
cip_(kInvalidCip),
pc_(nullptr)
{
if (!ivk_)
return;
nextInvokeFrame();
}
void
FrameIterator::nextInvokeFrame()
{
assert(exit_frame_.exit_sp());
sp_iter_ = exit_frame_.exit_sp();
// Inside an exit frame, the stack looks like this:
// .. C++ ..
// ----------- <-- entry_sp
// return addr to C++
// entry cip for frame #0
// alignment
// -----------
// return addr to frame #0
// entry cip for frame #1
// alignment
// ----------- <-- exit sp
// saved regs
// return addr
// .. InvokeNativeBoundHelper() ..
//
// We are guaranteed to always have one frame. We subtract one frame from
// the entry sp so we hit the stopping point correctly.
assert(ivk_->entry_sp());
assert(ke::IsAligned(sizeof(JitFrame), sizeof(intptr_t)));
sp_stop_ = ivk_->entry_sp() - (sizeof(JitFrame) / sizeof(intptr_t));
assert(sp_stop_ >= sp_iter_);
runtime_ = ivk_->cx()->runtime();
function_cip_ = kInvalidCip;
pc_ = nullptr;
cip_ = kInvalidCip;
if (!exit_frame_.has_exit_native()) {
// We have an exit frame, but it's not for natives. automatically advance
// to the most recent scripted frame.
const JitExitFrameForHelper *exit =
JitExitFrameForHelper::FromExitSp(exit_frame_.exit_sp());
exit_frame_ = ExitFrame();
// If we haven't compiled the function yet, but threw an error, then the
// return address will be null.
pc_ = exit->return_address;
assert(pc_ || exit->isCompileFunction());
// The function owning pc_ is in the previous frame.
const JitFrame *frame = exit->prev();
function_cip_ = frame->function_cip;
sp_iter_ = reinterpret_cast<const intptr_t *>(frame);
return;
}
}
void
FrameIterator::Next()
{
void *pc = nullptr;
if (exit_frame_.has_exit_native()) {
// If we're at an exit frame, the return address will yield the current pc.
const JitExitFrameForNative *exit =
JitExitFrameForNative::FromExitSp(exit_frame_.exit_sp());
exit_frame_ = ExitFrame();
pc_ = exit->return_address;
cip_ = kInvalidCip;
// The function owning pc_ is in the previous frame.
const JitFrame *frame = JitFrame::FromSp(sp_iter_);
function_cip_ = frame->function_cip;
return;
}
if (sp_iter_ >= sp_stop_) {
// Jump to the next invoke frame.
exit_frame_ = ivk_->prev_exit_frame();
ivk_ = ivk_->prev();
if (!ivk_)
return;
nextInvokeFrame();
return;
}
pc_ = JitFrame::FromSp(sp_iter_)->return_address;
assert(pc_);
// Advance, and find the function cip the pc belongs to.
sp_iter_ = reinterpret_cast<const intptr_t *>(JitFrame::FromSp(sp_iter_) + 1);
function_cip_ = JitFrame::FromSp(sp_iter_)->function_cip;
cip_ = kInvalidCip;
}
void
FrameIterator::Reset()
{
*this = FrameIterator();
}
cell_t
FrameIterator::findCip() const
{
CompiledFunction *fn = runtime_->GetJittedFunctionByOffset(function_cip_);
if (!fn)
return 0;
if (cip_ == kInvalidCip) {
if (pc_)
cip_ = fn->FindCipByPc(pc_);
else
cip_ = function_cip_;
}
return cip_;
}
unsigned
FrameIterator::LineNumber() const
{
ucell_t cip = findCip();
if (cip == kInvalidCip)
return 0;
uint32_t line;
if (!runtime_->image()->LookupLine(cip, &line))
return 0;
return line;
}
const char *
FrameIterator::FilePath() const
{
ucell_t cip = findCip();
if (cip == kInvalidCip)
return runtime_->image()->LookupFile(function_cip_);
return runtime_->image()->LookupFile(cip);
}
const char *
FrameIterator::FunctionName() const
{
assert(ivk_);
if (exit_frame_.has_exit_native()) {
uint32_t native_index = exit_frame_.exit_native();
const sp_native_t *native = runtime_->GetNative(native_index);
if (!native)
return nullptr;
return native->name;
}
return runtime_->image()->LookupFunction(function_cip_);
}
bool
FrameIterator::IsNativeFrame() const
{
return exit_frame_.has_exit_native();
}
bool
FrameIterator::IsScriptedFrame() const
{
return !IsNativeFrame() && ivk_;
}
IPluginContext *
FrameIterator::Context() const
{
if (!ivk_)
return nullptr;
return ivk_->cx();
}
+135
View File
@@ -0,0 +1,135 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_stack_frames_h_
#define _include_sourcepawn_vm_stack_frames_h_
#include <sp_vm_api.h>
#include <assert.h>
namespace sp {
using namespace SourcePawn;
class PluginContext;
class PluginRuntime;
// An ExitFrame represents the state of the most recent exit from VM state to
// the outside world. Because this transition is on a critical path, we declare
// exactly one ExitFrame and save/restore it in InvokeFrame(). Anytime we're in
// the VM, we are guaranteed to have an ExitFrame for each InvokeFrame().
class ExitFrame
{
public:
ExitFrame()
: exit_sp_(nullptr),
exit_native_(-1)
{}
public:
const intptr_t *exit_sp() const {
return exit_sp_;
}
bool has_exit_native() const {
return exit_native_ != -1;
}
uint32_t exit_native() const {
assert(has_exit_native());
return exit_native_;
}
public:
static inline size_t offsetOfExitSp() {
return offsetof(ExitFrame, exit_sp_);
}
static inline size_t offsetOfExitNative() {
return offsetof(ExitFrame, exit_native_);
}
private:
const intptr_t *exit_sp_;
int exit_native_;
};
// An InvokeFrame represents one activation of Execute2().
class InvokeFrame
{
public:
InvokeFrame(PluginContext *cx, ucell_t cip);
~InvokeFrame();
InvokeFrame *prev() const {
return prev_;
}
PluginContext *cx() const {
return cx_;
}
const ExitFrame &prev_exit_frame() const {
return prev_exit_frame_;
}
const intptr_t *entry_sp() const {
return entry_sp_;
}
ucell_t entry_cip() const {
return entry_cip_;
}
public:
static inline size_t offsetOfEntrySp() {
return offsetof(InvokeFrame, entry_sp_);
}
private:
InvokeFrame *prev_;
PluginContext *cx_;
ExitFrame prev_exit_frame_;
ucell_t entry_cip_;
const intptr_t *entry_sp_;
};
class FrameIterator : public SourcePawn::IFrameIterator
{
public:
FrameIterator();
bool Done() const KE_OVERRIDE {
return !ivk_;
}
void Next() KE_OVERRIDE;
void Reset() KE_OVERRIDE;
bool IsNativeFrame() const KE_OVERRIDE;
bool IsScriptedFrame() const KE_OVERRIDE;
const char *FunctionName() const KE_OVERRIDE;
const char *FilePath() const KE_OVERRIDE;
unsigned LineNumber() const KE_OVERRIDE;
IPluginContext *Context() const KE_OVERRIDE;
private:
void nextInvokeFrame();
cell_t findCip() const;
private:
InvokeFrame *ivk_;
ExitFrame exit_frame_;
PluginRuntime *runtime_;
const intptr_t *sp_iter_;
const intptr_t *sp_stop_;
ucell_t function_cip_;
mutable ucell_t cip_;
void *pc_;
};
} // namespace sp
#endif // _include_sourcepawn_vm_stack_frames_h_
+103
View File
@@ -0,0 +1,103 @@
// Microsoft Visual C++ generated resource script.
//
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
#include <sourcemod_version.h>
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION SM_VERSION_FILE
PRODUCTVERSION SM_VERSION_FILE
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", "SourcePawn JIT"
VALUE "FileDescription", "SourcePawn JIT/Virtual Machine"
VALUE "FileVersion", SM_VERSION_STRING
VALUE "InternalName", "sourcemod"
VALUE "LegalCopyright", "Copyright (c) 2004-2008, AlliedModders LLC"
VALUE "OriginalFilename", "sourcepawn.jit.x86.dll"
VALUE "ProductName", "SourcePawn JIT"
VALUE "ProductVersion", SM_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+165
View File
@@ -0,0 +1,165 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SourcePawn is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
#include "watchdog_timer.h"
#include <string.h>
#include "environment.h"
using namespace sp;
WatchdogTimer::WatchdogTimer(Environment *env)
: env_(env),
terminate_(false),
mainthread_(ke::GetCurrentThreadId()),
last_frame_id_(0),
second_timeout_(false),
timedout_(false)
{
}
WatchdogTimer::~WatchdogTimer()
{
assert(!thread_);
}
bool
WatchdogTimer::Initialize(size_t timeout_ms)
{
if (thread_)
return false;
timeout_ms_ = timeout_ms;
thread_ = new ke::Thread(this, "SM Watchdog");
if (!thread_->Succeeded())
return false;
return true;
}
void
WatchdogTimer::Shutdown()
{
if (terminate_ || !thread_)
return;
{
ke::AutoLock lock(&cv_);
terminate_ = true;
cv_.Notify();
}
thread_->Join();
thread_ = NULL;
}
void
WatchdogTimer::Run()
{
ke::AutoLock lock(&cv_);
// Initialize the frame id, so we don't have to wait longer on startup.
last_frame_id_ = env_->FrameId();
while (!terminate_) {
ke::WaitResult rv = cv_.Wait(timeout_ms_ / 2);
if (terminate_)
return;
if (rv == ke::Wait_Error)
return;
if (rv != ke::Wait_Timeout)
continue;
// We reached a timeout. If the current frame is not equal to the last
// frame, then we assume the server is still moving enough to process
// frames. We also make sure JIT code is actually on the stack, since
// our concept of frames won't move if JIT code is not running.
//
// Note that it's okay if these two race: it's just a heuristic, and
// worst case, we'll miss something that might have timed out but
// ended up resuming.
uintptr_t frame_id = env_->FrameId();
if (frame_id != last_frame_id_ || !env_->RunningCode()) {
last_frame_id_ = frame_id;
second_timeout_ = false;
continue;
}
// We woke up with the same frame. We might be timing out. Wait another
// time to see if so.
if (!second_timeout_) {
second_timeout_ = true;
continue;
}
{
// Prevent the JIT from linking or destroying runtimes and functions.
ke::AutoLock lock(env_->lock());
// Set the timeout notification bit. If this is detected before any patched
// JIT backedges are reached, the main thread will attempt to acquire the
// monitor lock, and block until we call Wait().
timedout_ = true;
// Patch all jumps. This can race with the main thread's execution since
// all code writes are 32-bit integer instruction operands, which are
// guaranteed to be atomic on x86.
env_->PatchAllJumpsForTimeout();
}
// The JIT will be free to compile new functions while we wait, but it will
// see the timeout bit set above and immediately bail out.
cv_.Wait();
second_timeout_ = false;
// Reset the last frame ID to something unlikely to be chosen again soon.
last_frame_id_--;
// It's possible that Shutdown() raced with the timeout, and if so, we
// must leave now to prevent a deadlock.
if (terminate_)
return;
}
}
bool
WatchdogTimer::NotifyTimeoutReceived()
{
// We are guaranteed that the watchdog thread is waiting for our
// notification, and is therefore blocked. We take the JIT lock
// anyway for sanity.
{
ke::AutoLock lock(env_->lock());
env_->UnpatchAllJumpsFromTimeout();
}
timedout_ = false;
// Wake up the watchdog thread, it's okay to keep processing now.
ke::AutoLock lock(&cv_);
cv_.Notify();
return false;
}
bool
WatchdogTimer::HandleInterrupt()
{
if (timedout_)
return NotifyTimeoutReceived();
return true;
}
+67
View File
@@ -0,0 +1,67 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SourcePawn is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
#ifndef _include_sourcepawn_watchdog_timer_posix_h_
#define _include_sourcepawn_watchdog_timer_posix_h_
#include <stddef.h>
#include <stdint.h>
#include <am-thread-utils.h>
namespace sp {
class Environment;
typedef bool (*WatchdogCallback)();
class WatchdogTimer : public ke::IRunnable
{
public:
WatchdogTimer(Environment *env);
~WatchdogTimer();
bool Initialize(size_t timeout_ms);
void Shutdown();
// Called from main thread.
bool NotifyTimeoutReceived();
bool HandleInterrupt();
private:
// Watchdog thread.
void Run();
private:
Environment *env_;
bool terminate_;
size_t timeout_ms_;
ke::ThreadId mainthread_;
ke::AutoPtr<ke::Thread> thread_;
ke::ConditionVariable cv_;
// Accessed only on the watchdog thread.
uintptr_t last_frame_id_;
bool second_timeout_;
// Accessed only on the main thread.
bool timedout_;
};
} // namespace sp
#endif // _include_sourcepawn_watchdog_timer_posix_h_
+141
View File
@@ -0,0 +1,141 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include <sp_vm_api.h>
#include "code-stubs.h"
#include "x86-utils.h"
#include "jit_x86.h"
#include "environment.h"
using namespace sp;
using namespace SourcePawn;
#define __ masm.
bool
CodeStubs::InitializeFeatureDetection()
{
MacroAssemblerX86 masm;
MacroAssemblerX86::GenerateFeatureDetection(masm);
void *code = LinkCode(env_, masm);
if (!code)
return false;
MacroAssemblerX86::RunFeatureDetection(code);
return true;
}
bool
CodeStubs::CompileInvokeStub()
{
AssemblerX86 masm;
__ push(ebp);
__ movl(ebp, esp);
__ push(esi); // ebp - 4
__ push(edi); // ebp - 8
__ push(ebx); // ebp - 12
__ push(esp); // ebp - 16
// ebx = cx
__ movl(ebx, Operand(ebp, 8 + 4 * 0));
// ecx = code
__ movl(ecx, Operand(ebp, 8 + 4 * 1));
// eax = cx->memory
__ movl(eax, Operand(ebx, PluginContext::offsetOfMemory()));
// Set up run-time registers.
__ movl(edi, Operand(ebx, PluginContext::offsetOfSp()));
__ addl(edi, eax);
__ movl(esi, eax);
__ movl(ebx, edi);
// Align the stack.
__ andl(esp, 0xfffffff0);
// Set up the last piece of the invoke frame. This lets us find the bounds
// of the call stack.
__ movl(eax, intptr_t(Environment::get()));
__ movl(eax, Operand(eax, Environment::offsetOfTopFrame()));
__ movl(Operand(eax, InvokeFrame::offsetOfEntrySp()), esp);
// Call into plugin (align the stack first).
__ call(ecx);
// Get input context, store rval.
__ movl(ecx, Operand(ebp, 8 + 4 * 2));
__ movl(Operand(ecx, 0), pri);
// Set no error.
__ movl(eax, SP_ERROR_NONE);
// Store latest stk. If we have an error code, we'll jump directly to here,
// so eax will already be set.
Label ret;
__ bind(&ret);
__ subl(stk, dat);
__ movl(ecx, Operand(ebp, 8 + 4 * 0));
__ movl(Operand(ecx, PluginContext::offsetOfSp()), stk);
// Restore stack.
__ movl(esp, Operand(ebp, -16));
// Restore registers and gtfo.
__ pop(ebx);
__ pop(edi);
__ pop(esi);
__ pop(ebp);
__ ret();
// The universal emergency return will jump to here.
Label error;
__ bind(&error);
__ movl(ecx, Operand(ebp, 8 + 4 * 0)); // ret-path expects ecx = ctx
__ jmp(&ret);
invoke_stub_ = LinkCode(env_, masm);
if (!invoke_stub_)
return false;
return_stub_ = reinterpret_cast<uint8_t *>(invoke_stub_) + error.offset();
return true;
}
SPVM_NATIVE_FUNC
CodeStubs::CreateFakeNativeStub(SPVM_FAKENATIVE_FUNC callback, void *pData)
{
AssemblerX86 masm;
__ push(ebx);
__ push(edi);
__ push(esi);
__ movl(edi, Operand(esp, 16)); // store ctx
__ movl(esi, Operand(esp, 20)); // store params
__ movl(ebx, esp);
__ andl(esp, 0xfffffff0);
__ subl(esp, 4);
__ push(intptr_t(pData));
__ push(esi);
__ push(edi);
__ call(ExternalAddress((void *)callback));
__ movl(esp, ebx);
__ pop(esi);
__ pop(edi);
__ pop(ebx);
__ ret();
return (SPVM_NATIVE_FUNC)LinkCode(env_, masm);
}
+83
View File
@@ -0,0 +1,83 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SourcePawn is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
#ifndef _include_sourcepawn_jit_frames_x86_h_
#define _include_sourcepawn_jit_frames_x86_h_
#include <sp_vm_types.h>
namespace sp {
using namespace SourcePawn;
class PluginContext;
// This is the layout of the stack in between each scripted function call.
struct JitFrame
{
intptr_t align0;
intptr_t align1;
ucell_t function_cip;
void *return_address;
static inline const JitFrame *FromSp(const intptr_t *sp) {
return reinterpret_cast<const JitFrame *>(sp);
}
};
// When we're about to call a native, the stack pointer we store in the exit
// frame is such that (sp + sizeof(JitExitFrameForNative)) conforms to this
// structure.
//
// Note that it looks reversed compared to JitFrame because we capture the sp
// before saving registers and pushing arguments.
struct JitExitFrameForNative
{
void *return_address;
PluginContext *cx;
union {
uint32_t native_index;
SPVM_NATIVE_FUNC fn;
} arg;
const cell_t *params;
cell_t saved_alt;
static inline const JitExitFrameForNative *FromExitSp(const intptr_t *exit_sp) {
return reinterpret_cast<const JitExitFrameForNative *>(
reinterpret_cast<const uint8_t *>(exit_sp) - sizeof(JitExitFrameForNative));
}
};
// Unlke native frames, the exit_sp for these is created at the base address.
struct JitExitFrameForHelper
{
void *return_address;
static inline const JitExitFrameForHelper *FromExitSp(const intptr_t *exit_sp) {
return reinterpret_cast<const JitExitFrameForHelper *>(exit_sp);
}
bool isCompileFunction() const {
return !!return_address;
}
const JitFrame *prev() const {
return reinterpret_cast<const JitFrame *>(this + 1);
}
};
} // namespace sp
#endif // _include_sourcepawn_jit_frames_x86_h_
File diff suppressed because it is too large Load Diff
+170
View File
@@ -0,0 +1,170 @@
// vim: set ts=8 sts=2 sw=2 tw=99 et:
//
// This file is part of SourcePawn.
//
// SourcePawn is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// SourcePawn is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SourcePawn. If not, see <http://www.gnu.org/licenses/>.
#ifndef _INCLUDE_SOURCEPAWN_JIT_X86_H_
#define _INCLUDE_SOURCEPAWN_JIT_X86_H_
#include <sp_vm_types.h>
#include <sp_vm_api.h>
#include <macro-assembler-x86.h>
#include <am-vector.h>
#include "plugin-runtime.h"
#include "plugin-context.h"
#include "compiled-function.h"
#include "opcodes.h"
using namespace SourcePawn;
namespace sp {
class LegacyImage;
class Environment;
class CompiledFunction;
struct ErrorPath
{
SilentLabel label;
const cell_t *cip;
int err;
ErrorPath(const cell_t *cip, int err)
: cip(cip),
err(err)
{}
ErrorPath()
{}
};
struct BackwardJump {
// The pc at the jump instruction (i.e. after it).
uint32_t pc;
// The cip of the jump.
const cell_t *cip;
// The offset of the timeout thunk. This is filled in at the end.
uint32_t timeout_offset;
BackwardJump()
{}
BackwardJump(uint32_t pc, const cell_t *cip)
: pc(pc),
cip(cip)
{}
};
#define JIT_INLINE_ERRORCHECKS (1<<0)
#define JIT_INLINE_NATIVES (1<<1)
#define STACK_MARGIN 64 //8 parameters of safety, I guess
#define JIT_FUNCMAGIC 0x214D4148 //magic function offset
#define JITVARS_PROFILER 2 //profiler
#define sDIMEN_MAX 5 //this must mirror what the compiler has.
struct CallThunk
{
SilentLabel call;
cell_t pcode_offset;
CallThunk(cell_t pcode_offset)
: pcode_offset(pcode_offset)
{
}
};
class Compiler
{
public:
Compiler(PluginRuntime *rt, cell_t pcode_offs);
~Compiler();
sp::CompiledFunction *emit(int *errp);
private:
bool setup(cell_t pcode_offs);
bool emitOp(sp::OPCODE op);
cell_t readCell();
private:
Label *labelAt(size_t offset);
bool emitCall();
bool emitNativeCall(sp::OPCODE op);
bool emitSwitch();
void emitGenArray(bool autozero);
void emitCallThunks();
void emitCheckAddress(Register reg);
void emitErrorPath(Label *dest, int code);
void emitErrorPaths();
void emitFloatCmp(ConditionCode cc);
void jumpOnError(ConditionCode cc, int err = 0);
void emitThrowPathIfNeeded(int err);
ExternalAddress hpAddr() {
return ExternalAddress(context_->addressOfHp());
}
ExternalAddress frmAddr() {
return ExternalAddress(context_->addressOfFrm());
}
// Map a return address (i.e. an exit point from a function) to its source
// cip. This lets us avoid tracking the cip during runtime. These are
// sorted by definition since we assemble and emit in forward order.
void emitCipMapping(const cell_t *cip) {
CipMapEntry entry;
entry.cipoffs = uintptr_t(cip) - uintptr_t(code_start_);
entry.pcoffs = masm.pc();
cip_map_.append(entry);
}
private:
AssemblerX86 masm;
Environment *env_;
PluginRuntime *rt_;
PluginContext *context_;
LegacyImage *image_;
int error_;
uint32_t pcode_start_;
const cell_t *code_start_;
const cell_t *cip_;
const cell_t *op_cip_;
const cell_t *code_end_;
Label *jump_map_;
ke::Vector<BackwardJump> backward_jumps_;
ke::Vector<CipMapEntry> cip_map_;
// Errors.
ke::Vector<ErrorPath> error_paths_;
Label throw_timeout_;
Label throw_error_code_[SP_MAX_ERROR_CODES];
Label report_error_;
Label return_reported_error_;
ke::Vector<CallThunk *> thunks_; //:TODO: free
};
const Register pri = eax;
const Register alt = edx;
const Register stk = edi;
const Register dat = esi;
const Register tmp = ecx;
const Register frm = ebx;
CompiledFunction *
CompileFunction(PluginRuntime *prt, cell_t pcode_offs, int *err);
}
#endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
+30
View File
@@ -0,0 +1,30 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#include "environment.h"
#include "x86-utils.h"
using namespace sp;
uint8_t *
sp::LinkCode(Environment *env, AssemblerX86 &masm)
{
if (masm.outOfMemory())
return nullptr;
void *code = env->AllocateCode(masm.length());
if (!code)
return nullptr;
masm.emitToExecutableMemory(code);
return reinterpret_cast<uint8_t *>(code);
}
+27
View File
@@ -0,0 +1,27 @@
// vim: set sts=2 ts=8 sw=2 tw=99 et:
//
// Copyright (C) 2006-2015 AlliedModders LLC
//
// This file is part of SourcePawn. SourcePawn is free software: you can
// redistribute it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// You should have received a copy of the GNU General Public License along with
// SourcePawn. If not, see http://www.gnu.org/licenses/.
//
#ifndef _include_sourcepawn_vm_x86_utils_h_
#define _include_sourcepawn_vm_x86_utils_h_
#include <stdint.h>
#include <macro-assembler-x86.h>
namespace sp {
class Environment;
uint8_t *LinkCode(Environment *env, AssemblerX86 &masm);
}
#endif // _include_sourcepawn_vm_x86_utils_h_
+149
View File
@@ -0,0 +1,149 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}
+79
View File
@@ -0,0 +1,79 @@
/* compress.c -- compress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Compresses the source buffer into the destination buffer. The level
parameter has the same meaning as in deflateInit. sourceLen is the byte
length of the source buffer. Upon entry, destLen is the total size of the
destination buffer, which must be at least 0.1% larger than sourceLen plus
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int level;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
#ifdef MAXSEG_64K
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
#endif
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
err = deflateInit(&stream, level);
if (err != Z_OK) return err;
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
deflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = deflateEnd(&stream);
return err;
}
/* ===========================================================================
*/
int ZEXPORT compress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
}
/* ===========================================================================
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
uLong ZEXPORT compressBound (sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
}
+424
View File
@@ -0,0 +1,424 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <[email protected]> for his contribution of faster
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
* tables for updating the shift register in one step with three exclusive-ors
* instead of four steps with four exclusive-ors. This results in about a
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/
/* @(#) $Id$ */
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
*/
#include <stdio.h>
#ifdef MAKECRCH
# include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE
# define DYNAMIC_CRC_TABLE
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
#include "zutil.h" /* for STDC and FAR definitions */
#define local static
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
#ifndef NOBYFOUR
# ifdef STDC /* need ANSI C limits.h to determine sizes */
# include <limits.h>
# define BYFOUR
# if (UINT_MAX == 0xffffffffUL)
typedef unsigned int u4;
# else
# if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long u4;
# else
# if (USHRT_MAX == 0xffffffffUL)
typedef unsigned short u4;
# else
# undef BYFOUR /* can't find a four-byte integer type! */
# endif
# endif
# endif
# endif /* STDC */
#endif /* !NOBYFOUR */
/* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
local unsigned long crc32_big OF((unsigned long,
const unsigned char FAR *, unsigned));
# define TBLS 8
#else
# define TBLS 1
#endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The first table is simply the CRC of all possible eight bit values. This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes. The remaining tables
allow for word-at-a-time CRC calculation for both big-endian and little-
endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
unsigned long c;
int n, k;
unsigned long poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL;
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
poly |= 1UL << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (unsigned long)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
}
#ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = REV(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = REV(c);
}
}
#endif /* BYFOUR */
crc_table_empty = 0;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH
/* write out CRC tables to crc32.h */
{
FILE *out;
out = fopen("crc32.h", "w");
if (out == NULL) return;
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const unsigned long FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
# ifdef BYFOUR
fprintf(out, "#ifdef BYFOUR\n");
for (k = 1; k < 8; k++) {
fprintf(out, " },\n {\n");
write_table(out, crc_table[k]);
}
fprintf(out, "#endif\n");
# endif /* BYFOUR */
fprintf(out, " }\n};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
local void write_table(out, table)
FILE *out;
const unsigned long FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const unsigned long FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const unsigned long FAR *)crc_table;
}
/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
if (buf == Z_NULL) return 0UL;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
u4 endian;
endian = 1;
if (*((unsigned char *)(&endian)))
return crc32_little(crc, buf, len);
else
return crc32_big(crc, buf, len);
}
#endif /* BYFOUR */
crc = crc ^ 0xffffffffUL;
while (len >= 8) {
DO8;
len -= 8;
}
if (len) do {
DO1;
} while (--len);
return crc ^ 0xffffffffUL;
}
#ifdef BYFOUR
/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = (u4)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
}
while (len >= 4) {
DOLIT4;
len -= 4;
}
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
} while (--len);
c = ~c;
return (unsigned long)c;
}
/* ========================================================================= */
#define DOBIG4 c ^= *++buf4; \
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = REV((u4)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
len -= 32;
}
while (len >= 4) {
DOBIG4;
len -= 4;
}
buf4++;
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(REV(c));
}
#endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}
+441
View File
@@ -0,0 +1,441 @@
/* crc32.h -- tables for rapid CRC calculation
* Generated automatically by crc32.c
*/
local const unsigned long FAR crc_table[TBLS][256] =
{
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
#ifdef BYFOUR
},
{
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
0x9324fd72UL
},
{
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
0xbe9834edUL
},
{
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
0xde0506f1UL
},
{
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
0x8def022dUL
},
{
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
0x72fd2493UL
},
{
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
0xed3498beUL
},
{
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
0xf10605deUL
#endif
}
};
File diff suppressed because it is too large Load Diff
+331
View File
@@ -0,0 +1,331 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2004 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef DEFLATE_H
#define DEFLATE_H
#include "zutil.h"
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip encoding
should be left enabled. */
#ifndef NO_GZIP
# define GZIP
#endif
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
#define EXTRA_STATE 69
#define NAME_STATE 73
#define COMMENT_STATE 91
#define HCRC_STATE 103
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
uInt pending; /* nb of bytes in the pending buffer */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
gz_headerp gzhead; /* gzip header information to write */
uInt gzindex; /* where in extra, name, or comment */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to supress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uchf *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
#ifdef DEBUG
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
void _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. _dist_code[256] and _dist_code[257] are never
* used.
*/
#ifndef DEBUG
/* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC)
extern uch _length_code[];
extern uch _dist_code[];
#else
extern const uch _length_code[];
extern const uch _dist_code[];
#endif
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->last_lit] = 0; \
s->l_buf[s->last_lit++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (length); \
ush dist = (distance); \
s->d_buf[s->last_lit] = dist; \
s->l_buf[s->last_lit++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
flush = _tr_tally(s, distance, length)
#endif
#endif /* DEFLATE_H */
File diff suppressed because it is too large Load Diff
+624
View File
@@ -0,0 +1,624 @@
/* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/*
This code is largely copied from inflate.c. Normally either infback.o or
inflate.o would be linked into an application--not both. The interface
with inffast.c is retained so that optimized assembler-coded versions of
inflate_fast() can be used with either inflate.c or infback.c.
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.
windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
int stream_size;
{
struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (int)(sizeof(z_stream)))
return Z_VERSION_ERROR;
if (strm == Z_NULL || window == Z_NULL ||
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
}
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
state->write = 0;
state->whave = 0;
return Z_OK;
}
/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
local void fixedtables(state)
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED
static int virgin = 1;
static code *lenfix, *distfix;
static code fixed[544];
/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
unsigned sym, bits;
static code *next;
/* literal/length table */
sym = 0;
while (sym < 144) state->lens[sym++] = 8;
while (sym < 256) state->lens[sym++] = 9;
while (sym < 280) state->lens[sym++] = 7;
while (sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
/* distance table */
sym = 0;
while (sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
/* do this just once */
virgin = 0;
}
#else /* !BUILDFIXED */
# include "inffixed.h"
#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}
/* Macros for inflateBack(): */
/* Load returned state from inflate_fast() */
#define LOAD() \
do { \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
} while (0)
/* Set state from registers for inflate_fast() */
#define RESTORE() \
do { \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
} while (0)
/* Clear the input bit accumulator */
#define INITBITS() \
do { \
hold = 0; \
bits = 0; \
} while (0)
/* Assure that some input is available. If input is requested, but denied,
then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
do { \
if (have == 0) { \
have = in(in_desc, &next); \
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/* Get a byte of input into the bit accumulator, or return from inflateBack()
with an error if there is no input available. */
#define PULLBYTE() \
do { \
PULL(); \
have--; \
hold += (unsigned long)(*next++) << bits; \
bits += 8; \
} while (0)
/* Assure that there are at least n bits in the bit accumulator. If there is
not enough available input to do that, then return from inflateBack() with
an error. */
#define NEEDBITS(n) \
do { \
while (bits < (unsigned)(n)) \
PULLBYTE(); \
} while (0)
/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))
/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
do { \
hold >>= (n); \
bits -= (unsigned)(n); \
} while (0)
/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
do { \
hold >>= bits & 7; \
bits -= bits & 7; \
} while (0)
/* Assure that some output space is available, by writing out the window
if it's full. If the write fails, return from inflateBack() with a
Z_BUF_ERROR. */
#define ROOM() \
do { \
if (left == 0) { \
put = state->window; \
left = state->wsize; \
state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)
/*
strm provides the memory allocation functions and window buffer on input,
and provides information on the unused input on return. For Z_DATA_ERROR
returns, strm will also provide an error message.
in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.
in() and out() are called with a descriptor parameter provided in the
inflateBack() call. This parameter can be a structure that provides the
information required to do the read or write, as well as accumulated
information on the input and output such as totals and check values.
in() should return zero on failure. out() should return non-zero on
failure. If either in() or out() fails, than inflateBack() returns a
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
was in() or out() that caused in the error. Otherwise, inflateBack()
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
error, or Z_MEM_ERROR if it could not allocate memory for the state.
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state;
unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */
code this; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
static const unsigned short order[19] = /* permutation of code lengths */
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/* Check that the strm exists and that the state was initialized */
if (strm == Z_NULL || strm->state == Z_NULL)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
/* Reset the state */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
bits = 0;
put = state->window;
left = state->wsize;
/* Inflate until end of block marked as last */
for (;;)
switch (state->mode) {
case TYPE:
/* determine and dispatch block type */
if (state->last) {
BYTEBITS();
state->mode = DONE;
break;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch (BITS(2)) {
case 0: /* stored block */
Tracev((stderr, "inflate: stored block%s\n",
state->last ? " (last)" : ""));
state->mode = STORED;
break;
case 1: /* fixed block */
fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
case 3:
strm->msg = (char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
break;
case STORED:
/* get and verify stored block length */
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();
/* copy stored block from input to output */
while (state->length != 0) {
copy = state->length;
PULL();
ROOM();
if (copy > have) copy = have;
if (copy > left) copy = left;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
}
Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;
case TABLE:
/* get dynamic table entries descriptor */
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));
/* get code length code lengths (not a typo) */
state->have = 0;
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));
/* get length and distance code code lengths */
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.val < 16) {
NEEDBITS(this.bits);
DROPBITS(this.bits);
state->lens[state->have++] = this.val;
}
else {
if (this.val == 16) {
NEEDBITS(this.bits + 2);
DROPBITS(this.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = (unsigned)(state->lens[state->have - 1]);
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (this.val == 17) {
NEEDBITS(this.bits + 3);
DROPBITS(this.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(this.bits + 7);
DROPBITS(this.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}
/* handle error breaks in while */
if (state->mode == BAD) break;
/* build code tables */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
if (state->whave < state->wsize)
state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
}
/* get a literal, length, or end-of-block code */
for (;;) {
this = state->lencode[BITS(state->lenbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if (this.op && (this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
state->length = (unsigned)this.val;
/* process literal */
if (this.op == 0) {
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", this.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
}
/* process end of block */
if (this.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
/* invalid code */
if (this.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
/* length code -- get extra bits, if any */
state->extra = (unsigned)(this.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));
/* get distance code */
for (;;) {
this = state->distcode[BITS(state->distbits)];
if ((unsigned)(this.bits) <= bits) break;
PULLBYTE();
}
if ((this.op & 0xf0) == 0) {
last = this;
for (;;) {
this = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + this.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(this.bits);
if (this.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)this.val;
/* get distance extra bits, if any */
state->extra = (unsigned)(this.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));
/* copy match from window to output */
do {
ROOM();
copy = state->wsize - state->offset;
if (copy < left) {
from = put + copy;
copy = left - copy;
}
else {
from = put - state->offset;
copy = left;
}
if (copy > state->length) copy = state->length;
state->length -= copy;
left -= copy;
do {
*put++ = *from++;
} while (--copy);
} while (state->length != 0);
break;
case DONE:
/* inflate stream terminated properly -- write leftover output */
ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;
default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}
/* Return unused input */
inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}
int ZEXPORT inflateBackEnd(strm)
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}
+319
View File
@@ -0,0 +1,319 @@
/* inffast.c -- fast decoding
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#ifndef ASMINF
/* Allow machine dependent optimization for post-increment or pre-increment.
Based on testing to date,
Pre-increment preferred for:
- PowerPC G3 (Adler)
- MIPS R5000 (Randers-Pehrson)
Post-increment preferred for:
- none
No measurable difference:
- Pentium III (Anderson)
- M68060 (Nikl)
*/
#ifdef POSTINC
# define OFF 0
# define PUP(a) *(a)++
#else
# define OFF 1
# define PUP(a) *++(a)
#endif
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
void inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
unsigned char FAR *in; /* local strm->next_in */
unsigned char FAR *last; /* while in < last, enough input available */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */
code const FAR *lcode; /* local strm->lencode */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
code this; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
unsigned char FAR *from; /* where to copy match from */
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
in = strm->next_in - OFF;
last = in + (strm->avail_in - 5);
out = strm->next_out - OFF;
beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize;
whave = state->whave;
write = state->write;
window = state->window;
hold = state->hold;
bits = state->bits;
lcode = state->lencode;
dcode = state->distcode;
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
this = lcode[hold & lmask];
dolen:
op = (unsigned)(this.bits);
hold >>= op;
bits -= op;
op = (unsigned)(this.op);
if (op == 0) { /* literal */
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", this.val));
PUP(out) = (unsigned char)(this.val);
}
else if (op & 16) { /* length base */
len = (unsigned)(this.val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
len += (unsigned)hold & ((1U << op) - 1);
hold >>= op;
bits -= op;
}
Tracevv((stderr, "inflate: length %u\n", len));
if (bits < 15) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
this = dcode[hold & dmask];
dodist:
op = (unsigned)(this.bits);
hold >>= op;
bits -= op;
op = (unsigned)(this.op);
if (op & 16) { /* distance base */
dist = (unsigned)(this.val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits;
bits += 8;
}
}
dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op;
bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist));
op = (unsigned)(out - beg); /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
from = window - OFF;
if (write == 0) { /* very common case */
from += wsize - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
else if (write < op) { /* wrap around window */
from += wsize + write - op;
op -= write;
if (op < len) { /* some from end of window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = window - OFF;
if (write < len) { /* some from start of window */
op = write;
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
}
else { /* contiguous in window */
from += write - op;
if (op < len) { /* some from window */
len -= op;
do {
PUP(out) = PUP(from);
} while (--op);
from = out - dist; /* rest from output */
}
}
while (len > 2) {
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
}
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
else {
from = out - dist; /* copy direct from output */
do { /* minimum length is three */
PUP(out) = PUP(from);
PUP(out) = PUP(from);
PUP(out) = PUP(from);
len -= 3;
} while (len > 2);
if (len) {
PUP(out) = PUP(from);
if (len > 1)
PUP(out) = PUP(from);
}
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
this = dcode[this.val + (hold & ((1U << op) - 1))];
goto dodist;
}
else {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
this = lcode[this.val + (hold & ((1U << op) - 1))];
goto dolen;
}
else if (op & 32) { /* end-of-block */
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
else {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
} while (in < last && out < end);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
in -= len;
bits -= len << 3;
hold &= (1U << bits) - 1;
/* update state and return */
strm->next_in = in + OFF;
strm->next_out = out + OFF;
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
strm->avail_out = (unsigned)(out < end ?
257 + (end - out) : 257 - (out - end));
state->hold = hold;
state->bits = bits;
return;
}
/*
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- Using bit fields for code structure
- Different op definition to avoid & for extra bits (do & for table bits)
- Three separate decoding do-loops for direct, window, and write == 0
- Special case for distance > 1 copies to do overlapped load and store copy
- Explicit branch predictions (based on measured branch probabilities)
- Deferring match copy and interspersed it with decoding subsequent codes
- Swapping literal/length else
- Swapping window/direct else
- Larger unrolled copy loops (three is about right)
- Moving len -= 3 statement into middle of loop
*/
#endif /* !ASMINF */
+11
View File
@@ -0,0 +1,11 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
void inflate_fast OF((z_streamp strm, unsigned start));
+94
View File
@@ -0,0 +1,94 @@
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/
/* WARNING: this file should *not* be used by applications. It
is part of the implementation of the compression library and
is subject to change. Applications should only use zlib.h.
*/
static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};
static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};
File diff suppressed because it is too large Load Diff
+115
View File
@@ -0,0 +1,115 @@
/* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* define NO_GZIP when compiling if you want to disable gzip header and
trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
the crc code when it is not needed. For shared libraries, gzip decoding
should be left enabled. */
#ifndef NO_GZIP
# define GUNZIP
#endif
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD, /* i: waiting for magic header */
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
EXLEN, /* i: waiting for extra length (gzip) */
EXTRA, /* i: waiting for extra bytes (gzip) */
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */
COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN, /* i: waiting for length/lit code */
LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
LENGTH, /* i: waiting for 32-bit length (gzip) */
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
SYNC /* looking for synchronization bytes to restart inflate() */
} inflate_mode;
/*
State transitions between above modes -
(most modes can go to the BAD or MEM mode -- not shown for clarity)
Process header:
HEAD -> (gzip) or (zlib)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
NAME -> COMMENT -> HCRC -> TYPE
(zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE
Read deflate blocks:
TYPE -> STORED or TABLE or LEN or CHECK
STORED -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN
Read deflate codes:
LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN
Process trailer:
CHECK -> LENGTH -> DONE
*/
/* state maintained between inflate() calls. Approximately 7K bytes. */
struct inflate_state {
inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */
unsigned long hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
/* for string and stored block copying */
unsigned length; /* literal or length of data to copy */
unsigned offset; /* distance back to copy string from */
/* for table and code decoding */
unsigned extra; /* extra bits needed */
/* fixed and dynamic code tables */
code const FAR *lencode; /* starting table for length/literal codes */
code const FAR *distcode; /* starting table for distance codes */
unsigned lenbits; /* index bits for lencode */
unsigned distbits; /* index bits for distcode */
/* dynamic table building */
unsigned ncode; /* number of code length code lengths */
unsigned nlen; /* number of length code lengths */
unsigned ndist; /* number of distance code lengths */
unsigned have; /* number of code lengths in lens[] */
code FAR *next; /* next available space in codes[] */
unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */
};
+330
View File
@@ -0,0 +1,330 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code this; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
int end; /* use base and extra for symbol > end */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
this.op = (unsigned char)64; /* invalid code marker */
this.bits = (unsigned char)1;
this.val = (unsigned short)0;
*(*table)++ = this; /* make a table to force an error */
*(*table)++ = this;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min <= MAXBITS; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked when a LENS table is being made
against the space in *table, ENOUGH, minus the maximum space needed by
the worst case distance code, MAXD. This should never happen, but the
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
This assumes that when type == LENS, bits == 9.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
end = 19;
break;
case LENS:
base = lbase;
base -= 257;
extra = lext;
extra -= 257;
end = 256;
break;
default: /* DISTS */
base = dbase;
extra = dext;
end = -1;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if (type == LENS && used >= ENOUGH - MAXD)
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
this.bits = (unsigned char)(len - drop);
if ((int)(work[sym]) < end) {
this.op = (unsigned char)0;
this.val = work[sym];
}
else if ((int)(work[sym]) > end) {
this.op = (unsigned char)(extra[work[sym]]);
this.val = base[work[sym]];
}
else {
this.op = (unsigned char)(32 + 64); /* end of block */
this.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = this;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if (type == LENS && used >= ENOUGH - MAXD)
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/*
Fill in rest of table for incomplete codes. This loop is similar to the
loop above in incrementing huff for table indices. It is assumed that
len is equal to curr + drop, so there is no loop needed to increment
through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there.
*/
this.op = (unsigned char)64; /* invalid code marker */
this.bits = (unsigned char)(len - drop);
this.val = (unsigned short)0;
while (huff != 0) {
/* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) {
drop = 0;
len = root;
next = *table;
this.bits = (unsigned char)len;
}
/* put invalid code marker in table */
next[huff >> drop] = this;
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Structure for decoding tables. Each entry provides either the
information needed to do the operation requested by the code that
indexed that table entry, or it provides a pointer to another
table that indexes more bits of the code. op indicates whether
the entry is a pointer to another table, a literal, a length or
distance, an end-of-block, or an invalid code. For a table
pointer, the low four bits of op is the number of index bits of
that table. For a length or distance, the low four bits of op
is the number of extra bits to get after the code. bits is
the number of bits in this code or part of the code to drop off
of the bit buffer. val is the actual byte to output in the case
of a literal, the base length or distance, or the offset from
the current table to the next table. Each entry is four bytes. */
typedef struct {
unsigned char op; /* operation, extra bits, table bits */
unsigned char bits; /* bits in this part of the code */
unsigned short val; /* offset in table or code value */
} code;
/* op values as set by inflate_table():
00000000 - literal
0000tttt - table link, tttt != 0 is the number of table index bits
0001eeee - length or distance, eeee is the number of extra bits
01100000 - end of block
01000000 - invalid code
*/
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1444 code structures (852 for length/literals
and 592 for distances, the latter actually the result of an
exhaustive search). The true maximum is not known, but the value
below is more than safe. */
#define ENOUGH 2048
#define MAXD 592
/* Type of code to build for inftable() */
typedef enum {
CODES,
LENS,
DISTS
} codetype;
extern int inflate_table OF((codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work));
File diff suppressed because it is too large Load Diff
+128
View File
@@ -0,0 +1,128 @@
/* header created automatically with -DGEN_TREES_H */
local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
};
local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};
const uch _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
local const int base_dist[D_CODES] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};
+61
View File
@@ -0,0 +1,61 @@
/* uncompr.c -- decompress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be large enough to hold the
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
int ZEXPORT uncompress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
err = inflateInit(&stream);
if (err != Z_OK) return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
return Z_DATA_ERROR;
return err;
}
*destLen = stream.total_out;
err = inflateEnd(&stream);
return err;
}
+281
View File
@@ -0,0 +1,281 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# ifndef WIN32
# define WIN32
# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(__OS400__)
# define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */
File diff suppressed because it is too large Load Diff
+319
View File
@@ -0,0 +1,319 @@
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include <stdio.h>
#include "zutil.h"
#ifndef NO_DUMMY_DECL
struct internal_state {int dummy;}; /* for buggy compilers */
#endif
const char * const z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
"", /* Z_OK 0 */
"file error", /* Z_ERRNO (-1) */
"stream error", /* Z_STREAM_ERROR (-2) */
"data error", /* Z_DATA_ERROR (-3) */
"insufficient memory", /* Z_MEM_ERROR (-4) */
"buffer error", /* Z_BUF_ERROR (-5) */
"incompatible version",/* Z_VERSION_ERROR (-6) */
""};
const char * ZEXPORT zlibVersion()
{
return ZLIB_VERSION;
}
uLong ZEXPORT zlibCompileFlags()
{
uLong flags;
flags = 0;
switch (sizeof(uInt)) {
case 2: break;
case 4: flags += 1; break;
case 8: flags += 2; break;
default: flags += 3;
}
switch (sizeof(uLong)) {
case 2: break;
case 4: flags += 1 << 2; break;
case 8: flags += 2 << 2; break;
default: flags += 3 << 2;
}
switch (sizeof(voidpf)) {
case 2: break;
case 4: flags += 1 << 4; break;
case 8: flags += 2 << 4; break;
default: flags += 3 << 4;
}
switch (sizeof(z_off_t)) {
case 2: break;
case 4: flags += 1 << 6; break;
case 8: flags += 2 << 6; break;
default: flags += 3 << 6;
}
#ifdef DEBUG
flags += 1 << 8;
#endif
#if defined(ASMV) || defined(ASMINF)
flags += 1 << 9;
#endif
#ifdef ZLIB_WINAPI
flags += 1 << 10;
#endif
#ifdef BUILDFIXED
flags += 1 << 12;
#endif
#ifdef DYNAMIC_CRC_TABLE
flags += 1 << 13;
#endif
#ifdef NO_GZCOMPRESS
flags += 1L << 16;
#endif
#ifdef NO_GZIP
flags += 1L << 17;
#endif
#ifdef PKZIP_BUG_WORKAROUND
flags += 1L << 20;
#endif
#ifdef FASTEST
flags += 1L << 21;
#endif
#ifdef STDC
# ifdef NO_vsnprintf
flags += 1L << 25;
# ifdef HAS_vsprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_vsnprintf_void
flags += 1L << 26;
# endif
# endif
#else
flags += 1L << 24;
# ifdef NO_snprintf
flags += 1L << 25;
# ifdef HAS_sprintf_void
flags += 1L << 26;
# endif
# else
# ifdef HAS_snprintf_void
flags += 1L << 26;
# endif
# endif
#endif
return flags;
}
#ifdef DEBUG
# ifndef verbose
# define verbose 0
# endif
int z_verbose = verbose;
void z_error (m)
char *m;
{
fprintf(stderr, "%s\n", m);
exit(1);
}
#endif
/* exported to allow conversion of error code to string for compress() and
* uncompress()
*/
const char * ZEXPORT zError(err)
int err;
{
return ERR_MSG(err);
}
#if defined(_WIN32_WCE)
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
int errno = 0;
#endif
#ifndef HAVE_MEMCPY
void zmemcpy(dest, source, len)
Bytef* dest;
const Bytef* source;
uInt len;
{
if (len == 0) return;
do {
*dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0);
}
int zmemcmp(s1, s2, len)
const Bytef* s1;
const Bytef* s2;
uInt len;
{
uInt j;
for (j = 0; j < len; j++) {
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
}
return 0;
}
void zmemzero(dest, len)
Bytef* dest;
uInt len;
{
if (len == 0) return;
do {
*dest++ = 0; /* ??? to be unrolled */
} while (--len != 0);
}
#endif
#ifdef SYS16BIT
#ifdef __TURBOC__
/* Turbo C in 16-bit mode */
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
* and farmalloc(64K) returns a pointer with an offset of 8, so we
* must fix the pointer. Warning: the pointer must be put back to its
* original form in order to free it, use zcfree().
*/
#define MAX_PTR 10
/* 10*64K = 640K */
local int next_ptr = 0;
typedef struct ptr_table_s {
voidpf org_ptr;
voidpf new_ptr;
} ptr_table;
local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
* to large buffers (64K). Such pointers are normalized with a zero offset.
* Since MSDOS is not a preemptive multitasking OS, this table is not
* protected from concurrent access. This hack doesn't work anyway on
* a protected system like OS/2. Use Microsoft C instead.
*/
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
voidpf buf = opaque; /* just to make some compilers happy */
ulg bsize = (ulg)items*size;
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
if (bsize < 65520L) {
buf = farmalloc(bsize);
if (*(ush*)&buf != 0) return buf;
} else {
buf = farmalloc(bsize + 16L);
}
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
table[next_ptr].org_ptr = buf;
/* Normalize the pointer to seg:0 */
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
*(ush*)&buf = 0;
table[next_ptr++].new_ptr = buf;
return buf;
}
void zcfree (voidpf opaque, voidpf ptr)
{
int n;
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
}
/* Find the original pointer */
for (n = 0; n < next_ptr; n++) {
if (ptr != table[n].new_ptr) continue;
farfree(table[n].org_ptr);
while (++n < next_ptr) {
table[n-1] = table[n];
}
next_ptr--;
return;
}
ptr = opaque; /* just to make some compilers happy */
Assert(0, "zcfree: ptr not found");
}
#endif /* __TURBOC__ */
#ifdef M_I86
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
# define _halloc halloc
# define _hfree hfree
#endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
if (opaque) opaque = 0; /* to make compiler happy */
return _halloc((long)items, size);
}
void zcfree (voidpf opaque, voidpf ptr)
{
if (opaque) opaque = 0; /* to make compiler happy */
_hfree(ptr);
}
#endif /* M_I86 */
#endif /* SYS16BIT */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC
extern voidp malloc OF((uInt size));
extern voidp calloc OF((uInt items, uInt size));
extern void free OF((voidpf ptr));
#endif
voidpf zcalloc (opaque, items, size)
voidpf opaque;
unsigned items;
unsigned size;
{
if (opaque) items += size - size; /* make compiler happy */
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
(voidpf)calloc(items, size);
}
void zcfree (opaque, ptr)
voidpf opaque;
voidpf ptr;
{
free(ptr);
if (opaque) return; /* make compiler happy */
}
#endif /* MY_ZCALLOC */
+269
View File
@@ -0,0 +1,269 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef ZUTIL_H
#define ZUTIL_H
#define ZLIB_INTERNAL
#include "zlib.h"
#ifdef STDC
# ifndef _WIN32_WCE
# include <stddef.h>
# endif
# include <string.h>
# include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
# ifdef _WIN32_WCE
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used. We rename it to
* avoid conflict with other libraries that use the same workaround.
*/
# define errno z_errno
# endif
extern int errno;
#else
# ifndef _WIN32_WCE
# include <errno.h>
# endif
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
# if defined(__TURBOC__) || defined(__BORLANDC__)
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
#endif
#ifdef AMIGA
# define OS_CODE 0x01
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 0x02
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 0x05
#endif
#ifdef OS2
# define OS_CODE 0x06
# ifdef M_I86
#include <malloc.h>
# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
# include <unix.h> /* for fdopen */
# else
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
# endif
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#ifdef WIN32
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
# define OS_CODE 0x0b
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define OS_CODE 0x0f
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER > 600))
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef _PTRDIFF_T_DEFINED
typedef int ptrdiff_t;
# define _PTRDIFF_T_DEFINED
# endif
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
#endif
/* common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#if defined(__CYGWIN__)
# ifndef HAVE_VSNPRINTF
# define HAVE_VSNPRINTF
# endif
#endif
#ifndef HAVE_VSNPRINTF
# ifdef MSDOS
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
but for now we just assume it doesn't. */
# define NO_vsnprintf
# endif
# ifdef __TURBOC__
# define NO_vsnprintf
# endif
# ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
# define vsnprintf _vsnprintf
# endif
# endif
# ifdef __SASC
# define NO_vsnprintf
# endif
#endif
#ifdef VMS
# define NO_vsnprintf
#endif
#if defined(pyr)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
extern void zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
#ifdef DEBUG
# include <stdio.h>
extern int z_verbose;
extern void z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
void zcfree OF((voidpf opaque, voidpf ptr));
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
#endif /* ZUTIL_H */