pedump 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +4 -0
- data/Gemfile +10 -6
- data/Gemfile.lock +27 -19
- data/README.md +37 -25
- data/Rakefile +45 -6
- data/VERSION +1 -1
- data/data/fs.txt +37 -1408
- data/data/jc-userdb.txt +14371 -0
- data/data/sig.bin +0 -0
- data/lib/pedump.rb +355 -618
- data/lib/pedump/cli.rb +214 -113
- data/lib/pedump/comparer.rb +147 -0
- data/lib/pedump/composite_io.rb +56 -0
- data/lib/pedump/core.rb +38 -0
- data/lib/pedump/core_ext/try.rb +57 -0
- data/lib/pedump/loader.rb +393 -0
- data/lib/pedump/loader/minidump.rb +187 -0
- data/lib/pedump/loader/section.rb +57 -0
- data/lib/pedump/logger.rb +67 -0
- data/lib/pedump/ne.rb +425 -0
- data/lib/pedump/ne/version_info.rb +171 -0
- data/lib/pedump/packer.rb +50 -2
- data/lib/pedump/pe.rb +121 -0
- data/lib/pedump/resources.rb +436 -0
- data/lib/pedump/security.rb +58 -0
- data/lib/pedump/sig_parser.rb +145 -24
- data/lib/pedump/tls.rb +17 -0
- data/lib/pedump/unpacker.rb +26 -0
- data/lib/pedump/unpacker/aspack.rb +858 -0
- data/lib/pedump/unpacker/upx.rb +13 -0
- data/lib/pedump/version.rb +1 -1
- data/lib/pedump/version_info.rb +15 -10
- data/misc/aspack/Makefile +3 -0
- data/misc/aspack/aspack_unlzx.c +92 -0
- data/misc/aspack/lzxdec.c +479 -0
- data/misc/aspack/lzxdec.h +56 -0
- data/misc/nedump.c +751 -0
- data/pedump.gemspec +75 -25
- data/samples/bad/68.exe +0 -0
- data/samples/bad/data_dir_15_entries.exe +0 -0
- data/spec/65535sects_spec.rb +8 -0
- data/spec/bad_imports_spec.rb +20 -0
- data/spec/bad_samples_spec.rb +13 -0
- data/spec/composite_io_spec.rb +122 -0
- data/spec/data/calc.exe_sections.yml +49 -0
- data/spec/data/data_dir_15_entries.exe_sections.yml +95 -0
- data/spec/dllord_spec.rb +21 -0
- data/spec/foldedhdr_spec.rb +28 -0
- data/spec/imports_badterm_spec.rb +52 -0
- data/spec/imports_vterm_spec.rb +52 -0
- data/spec/loader/names_spec.rb +24 -0
- data/spec/loader/va_spec.rb +44 -0
- data/spec/manyimportsW7_spec.rb +22 -0
- data/spec/ne_spec.rb +125 -0
- data/spec/packer_spec.rb +17 -0
- data/spec/pe_spec.rb +67 -0
- data/spec/pedump_spec.rb +16 -4
- data/spec/sections_spec.rb +11 -0
- data/spec/sig_all_packers_spec.rb +15 -5
- data/spec/sig_spec.rb +6 -1
- data/spec/spec_helper.rb +15 -3
- data/spec/support/samples.rb +24 -0
- data/spec/unpackers/aspack_spec.rb +69 -0
- data/spec/unpackers/find_spec.rb +21 -0
- data/spec/virtsectblXP_spec.rb +12 -0
- data/tmp/.keep +0 -0
- metadata +146 -35
- data/README.md.tpl +0 -90
- data/samples/calc.7z +0 -0
- data/samples/zlib.dll +0 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: binary
|
3
|
+
require 'pedump/loader'
|
4
|
+
require 'pedump/cli'
|
5
|
+
|
6
|
+
module PEdump::Unpacker; end
|
7
|
+
|
8
|
+
class PEdump::Unpacker::UPX
|
9
|
+
def self.unpack src_fname, dst_fname, log = ''
|
10
|
+
log << `upx -dqq #{src_fname} -o #{dst_fname} 2>&1`
|
11
|
+
$?.success?
|
12
|
+
end
|
13
|
+
end
|
data/lib/pedump/version.rb
CHANGED
data/lib/pedump/version_info.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class PEdump
|
2
|
-
class VS_VERSIONINFO <
|
2
|
+
class VS_VERSIONINFO < IOStruct.new( 'v3a32v',
|
3
3
|
:wLength,
|
4
4
|
:wValueLength,
|
5
5
|
:wType,
|
@@ -40,7 +40,7 @@ class PEdump
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
class VS_FIXEDFILEINFO <
|
43
|
+
class VS_FIXEDFILEINFO < IOStruct.new( 'V13',
|
44
44
|
:dwSignature,
|
45
45
|
:dwStrucVersion,
|
46
46
|
:dwFileVersionMS,
|
@@ -64,7 +64,7 @@ class PEdump
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
class StringFileInfo <
|
67
|
+
class StringFileInfo < IOStruct.new( 'v3a30',
|
68
68
|
:wLength,
|
69
69
|
:wValueLength, # always 0
|
70
70
|
:wType, # 1 => text data, 0 => binary data
|
@@ -85,7 +85,7 @@ class PEdump
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
class StringTable <
|
88
|
+
class StringTable < IOStruct.new( 'v3a16v',
|
89
89
|
:wLength, # The length, in bytes, of this StringTable structure,
|
90
90
|
# including all structures indicated by the Children member.
|
91
91
|
:wValueLength, # always 0
|
@@ -107,7 +107,7 @@ class PEdump
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
class VersionString <
|
110
|
+
class VersionString < IOStruct.new( 'v3',
|
111
111
|
:wLength, # The length, in bytes, of this String structure.
|
112
112
|
:wValueLength, # The size, in words, of the Value member
|
113
113
|
:wType, # 1 => text data, 0 => binary data
|
@@ -116,21 +116,26 @@ class PEdump
|
|
116
116
|
:Value # A zero-terminated string. See the szKey member description for more information
|
117
117
|
)
|
118
118
|
def self.read f, size = SIZE
|
119
|
+
pos = f.tell
|
119
120
|
super.tap do |x|
|
120
121
|
x.szKey = ''
|
121
122
|
x.szKey << f.read(2) until x.szKey[-2..-1] == "\x00\x00" || f.eof?
|
122
123
|
x.Padding = f.tell%4 > 0 ? f.read(4 - f.tell%4) : nil
|
123
|
-
|
124
|
+
|
125
|
+
value_len = [x.wValueLength*2, x.wLength - (f.tell-pos)].min
|
126
|
+
value_len = 0 if value_len < 0
|
127
|
+
|
128
|
+
x.Value = f.read(value_len)
|
124
129
|
if f.tell%4 > 0
|
125
130
|
f.read(4-f.tell%4) # undoc padding?
|
126
131
|
end
|
127
|
-
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000
|
128
|
-
x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000
|
132
|
+
x.szKey.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
|
133
|
+
x.Value.force_encoding('UTF-16LE').encode!('UTF-8').sub!(/\u0000+$/,'') rescue nil
|
129
134
|
end
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
133
|
-
class VarFileInfo <
|
138
|
+
class VarFileInfo < IOStruct.new( 'v3a24v',
|
134
139
|
:wLength,
|
135
140
|
:wValueLength, # always 0
|
136
141
|
:wType, # 1 => text data, 0 => binary data
|
@@ -147,7 +152,7 @@ class PEdump
|
|
147
152
|
end
|
148
153
|
end
|
149
154
|
|
150
|
-
class Var <
|
155
|
+
class Var < IOStruct.new( 'v3a24',
|
151
156
|
:wLength,
|
152
157
|
:wValueLength, # The length, in bytes, of the Value member
|
153
158
|
:wType, # 1 => text data, 0 => binary data
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <strings.h> // for bzero()
|
4
|
+
|
5
|
+
#include "lzxdec.c"
|
6
|
+
|
7
|
+
// based on ASPack Unpacker v1.00 by Dr.Golova (thx! :)
|
8
|
+
|
9
|
+
/* error codes for unpacker thread */
|
10
|
+
#define ERR_OK (0)
|
11
|
+
#define ERR_NO_FILE (1)
|
12
|
+
#define ERR_FILE_OPEN (2)
|
13
|
+
#define ERR_NO_MEM (3)
|
14
|
+
#define ERR_CANT_MAP (4)
|
15
|
+
#define ERR_FILE_CREATE (5)
|
16
|
+
#define ERR_FILE_WRITE (6)
|
17
|
+
#define ERR_COPY_OVL (7)
|
18
|
+
#define ERR_CORRUPT (8)
|
19
|
+
#define ERR_UNKNOWN (9)
|
20
|
+
#define ERR_SKIPPED (10)
|
21
|
+
#define ERR_UNPACK (11)
|
22
|
+
#define ERR_FAILED (12)
|
23
|
+
|
24
|
+
|
25
|
+
void write_result(void*buf, int size){
|
26
|
+
fwrite(buf,1,size,stdout);
|
27
|
+
}
|
28
|
+
|
29
|
+
int unpack(BYTE*packed_data, size_t packed_size, size_t unpacked_size){
|
30
|
+
LZX_CONTEXT LZX;
|
31
|
+
BYTE* unpacked_data = NULL;
|
32
|
+
size_t decoded_size;
|
33
|
+
|
34
|
+
bzero(&LZX, sizeof(LZX));
|
35
|
+
|
36
|
+
if ( NULL == (unpacked_data = calloc(1, unpacked_size + 300)) ){
|
37
|
+
perror("no mem");
|
38
|
+
return(ERR_NO_MEM);
|
39
|
+
}
|
40
|
+
|
41
|
+
decoded_size = DecodeLZX(&LZX, packed_data, unpacked_data, packed_size, unpacked_size);
|
42
|
+
if ( decoded_size < 0 || decoded_size < unpacked_size ) {
|
43
|
+
free(unpacked_data);
|
44
|
+
fprintf(stderr,"ERR_UNPACK\n");
|
45
|
+
return(ERR_UNPACK);
|
46
|
+
}
|
47
|
+
|
48
|
+
write_result(unpacked_data, decoded_size);
|
49
|
+
free(unpacked_data);
|
50
|
+
return 0;
|
51
|
+
}
|
52
|
+
|
53
|
+
int main(int argc, char*argv[]){
|
54
|
+
size_t packed_size, unpacked_size;
|
55
|
+
BYTE* packed_data = NULL;
|
56
|
+
int r;
|
57
|
+
|
58
|
+
if(argc != 3){
|
59
|
+
fprintf(stderr, "ASPack unLZX\n");
|
60
|
+
fprintf(stderr, "usage: %s <packed_size> <unpacked_size>\n", argv[0]);
|
61
|
+
fprintf(stderr, "(data is read from stdin and written to stdout)\n", argv[0]);
|
62
|
+
return 1;
|
63
|
+
}
|
64
|
+
|
65
|
+
sscanf(argv[1],"%zu",&packed_size);
|
66
|
+
if( packed_size < 1 || packed_size > 0x10000000 ){ // 256 Mb max
|
67
|
+
fprintf(stderr, "invalid packed_size: %zu\n", packed_size);
|
68
|
+
return 1;
|
69
|
+
}
|
70
|
+
|
71
|
+
sscanf(argv[2],"%zu",&unpacked_size);
|
72
|
+
if( unpacked_size < 1 || unpacked_size > 0x10000000 ){ // 256 Mb max
|
73
|
+
fprintf(stderr, "invalid unpacked_size: %zu\n", unpacked_size);
|
74
|
+
return 1;
|
75
|
+
}
|
76
|
+
|
77
|
+
/* alloc buffer */
|
78
|
+
if ( NULL == (packed_data = calloc(1, packed_size + 300)) ){
|
79
|
+
perror("no mem");
|
80
|
+
return(ERR_NO_MEM);
|
81
|
+
}
|
82
|
+
|
83
|
+
if( packed_size != fread(packed_data, 1, packed_size, stdin)){
|
84
|
+
free(packed_data);
|
85
|
+
perror("read");
|
86
|
+
return(ERR_NO_FILE);
|
87
|
+
}
|
88
|
+
|
89
|
+
r = unpack(packed_data, packed_size, unpacked_size);
|
90
|
+
free(packed_data);
|
91
|
+
return r;
|
92
|
+
}
|
@@ -0,0 +1,479 @@
|
|
1
|
+
//#include <windows.h>
|
2
|
+
|
3
|
+
typedef unsigned char BYTE;
|
4
|
+
typedef int INT;
|
5
|
+
typedef unsigned int UINT;
|
6
|
+
typedef unsigned long DWORD;
|
7
|
+
typedef int BOOL;
|
8
|
+
|
9
|
+
#define FALSE 0
|
10
|
+
#define TRUE 1
|
11
|
+
|
12
|
+
#include "lzxdec.h"
|
13
|
+
|
14
|
+
/* #define LZX_DEBUG_LOG */
|
15
|
+
|
16
|
+
#if defined _DEBUG && defined LZX_DEBUG_LOG
|
17
|
+
# include <stdio.h>
|
18
|
+
static FILE* FDebLog = NULL;
|
19
|
+
#endif
|
20
|
+
|
21
|
+
/* ##### *** COMMON FUNCTIONS *** ########################################## */
|
22
|
+
|
23
|
+
/* memset local redefinition */
|
24
|
+
static void lzx_memset(void* dst, int val, unsigned int count)
|
25
|
+
{
|
26
|
+
while( count-- )
|
27
|
+
{
|
28
|
+
*(char*)(dst) = val;
|
29
|
+
dst = (char*)(dst) + 1;
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
/* memcpy local redefinition */
|
34
|
+
static void lzx_memcpy(void* dst, void* src, unsigned int count)
|
35
|
+
{
|
36
|
+
while( count-- )
|
37
|
+
{
|
38
|
+
*(char*)(dst) = *(char*)(src);
|
39
|
+
dst = (char*)(dst) + 1;
|
40
|
+
src = (char*)(src) + 1;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
/* ##### *** BIT READER FUNCTIONS *** ###################################### */
|
45
|
+
|
46
|
+
/* init bit reader */
|
47
|
+
#define BITRDR_INIT(BitRdr, RawSrc, RawLen) { \
|
48
|
+
(BitRdr)->SrcData = (RawSrc); \
|
49
|
+
(BitRdr)->SrcSize = (RawLen); \
|
50
|
+
(BitRdr)->CurOffs = 0; \
|
51
|
+
(BitRdr)->BitBuff = 0; \
|
52
|
+
(BitRdr)->BitFree = 32; \
|
53
|
+
}
|
54
|
+
|
55
|
+
/* read input byte (can be rewritten for file io) */
|
56
|
+
#define BITRDR_GETBYTE(BitRdr, RetVal) { \
|
57
|
+
if ( (BitRdr)->CurOffs < (BitRdr)->SrcSize ) \
|
58
|
+
RetVal = (BitRdr)->SrcData[(BitRdr)->CurOffs++]; \
|
59
|
+
else \
|
60
|
+
return(-1); /* error */ \
|
61
|
+
}
|
62
|
+
|
63
|
+
/* remove number of bits from bit buffer */
|
64
|
+
#define BITRDR_DROPBITS(BitRdr, BitNum) { \
|
65
|
+
(BitRdr)->BitFree += (BitNum); \
|
66
|
+
}
|
67
|
+
|
68
|
+
/* extract integer from bit buffer */
|
69
|
+
#define BITRDR_GETINT(BitRdr, RetVal) { \
|
70
|
+
DWORD BitBuff = (BitRdr)->BitBuff; \
|
71
|
+
UINT BitFree = (BitRdr)->BitFree; \
|
72
|
+
UINT UVal; \
|
73
|
+
while( BitFree >= 8 ) { \
|
74
|
+
BITRDR_GETBYTE(BitRdr, UVal); \
|
75
|
+
BitBuff = (BitBuff << 8) | UVal; \
|
76
|
+
BitFree -= 8; \
|
77
|
+
} \
|
78
|
+
RetVal = (BitBuff >> (8 - BitFree)) & 0x00ffffff; \
|
79
|
+
(BitRdr)->BitFree = BitFree; \
|
80
|
+
(BitRdr)->BitBuff = BitBuff; \
|
81
|
+
}
|
82
|
+
|
83
|
+
/* read number of bits from bit buffer */
|
84
|
+
#define BITRDR_GETBITS(BitRdr, BitNum, RetVal) { \
|
85
|
+
DWORD BitBuff = (BitRdr)->BitBuff; \
|
86
|
+
UINT BitFree = (BitRdr)->BitFree; \
|
87
|
+
UINT UVal; \
|
88
|
+
while( BitFree >= 8 ) { \
|
89
|
+
BITRDR_GETBYTE(BitRdr, UVal); \
|
90
|
+
BitBuff = (BitBuff << 8) | UVal; \
|
91
|
+
BitFree -= 8; \
|
92
|
+
} \
|
93
|
+
RetVal = (BitBuff >> (8 - BitFree)); \
|
94
|
+
RetVal = (RetVal & 0x00ffffff) >> (24 - (BitNum)); \
|
95
|
+
(BitRdr)->BitFree = (BitFree + (BitNum)); \
|
96
|
+
(BitRdr)->BitBuff = BitBuff; \
|
97
|
+
}
|
98
|
+
|
99
|
+
/* ##### *** SLIDING WINDOW DICTIONARY FUNCTIONS *** ####################### */
|
100
|
+
|
101
|
+
/* init swd context */
|
102
|
+
#define SWD_INIT(Wnd, Mem, Len) { \
|
103
|
+
(Wnd)->Window = (Mem); \
|
104
|
+
(Wnd)->WndLen = (Len); \
|
105
|
+
(Wnd)->CurOfs = 0; \
|
106
|
+
}
|
107
|
+
|
108
|
+
/* put byte to dictionary */
|
109
|
+
#define SWD_PUTBYTE(Wnd, DVal) { \
|
110
|
+
if ( (Wnd)->CurOfs < (Wnd)->WndLen ) \
|
111
|
+
(Wnd)->Window[(Wnd)->CurOfs++] = (BYTE)(DVal); \
|
112
|
+
else \
|
113
|
+
return(-1); /* error */ \
|
114
|
+
}
|
115
|
+
|
116
|
+
/* copy lz phrase in window */
|
117
|
+
#define SWD_DELTACOPY(Wnd, DOfs, DLen) { \
|
118
|
+
BYTE* WndPtr; \
|
119
|
+
if ( (Wnd)->CurOfs < (DOfs) ) \
|
120
|
+
return(-1); /* error */ \
|
121
|
+
if ( (Wnd)->CurOfs + (DLen) > (Wnd)->WndLen ) \
|
122
|
+
return(-1); /* error */ \
|
123
|
+
WndPtr = (Wnd)->Window + (Wnd)->CurOfs; \
|
124
|
+
lzx_memcpy(WndPtr, WndPtr - (DOfs), (DLen)); \
|
125
|
+
(Wnd)->CurOfs += (DLen); \
|
126
|
+
}
|
127
|
+
|
128
|
+
/* ##### *** HUFFMAN DECODERS FUNCTIONS *** ################################ */
|
129
|
+
|
130
|
+
/* init huffman decoder, return next table address */
|
131
|
+
static BYTE* LzxHuf_Init(LZX_HUFF* Huf, LZX_BITRDR* BitRdr, UINT SymNum,
|
132
|
+
BYTE* HufTbl)
|
133
|
+
{
|
134
|
+
Huf->BitRdr = BitRdr;
|
135
|
+
Huf->SymNum = SymNum;
|
136
|
+
Huf->Symbol = (UINT*)(HufTbl);
|
137
|
+
HufTbl += (SymNum * sizeof(Huf->Symbol[0]));
|
138
|
+
Huf->Length = HufTbl;
|
139
|
+
HufTbl += (256 * sizeof(Huf->Length[0]));
|
140
|
+
return(HufTbl);
|
141
|
+
}
|
142
|
+
|
143
|
+
/* decode one huffman symbol */
|
144
|
+
static INT LzxHuf_DecodeSymbol(LZX_HUFF* Huf)
|
145
|
+
{
|
146
|
+
UINT HVal, BNum, IOfs;
|
147
|
+
|
148
|
+
BITRDR_GETINT(Huf->BitRdr, HVal);
|
149
|
+
HVal &= 0x00fffe00;
|
150
|
+
|
151
|
+
if ( HVal < Huf->SymLim[8] )
|
152
|
+
BNum = Huf->Length[HVal >> 16];
|
153
|
+
else if ( HVal < Huf->SymLim[10] )
|
154
|
+
BNum = (HVal < Huf->SymLim[9]) ? (9) : (10);
|
155
|
+
else if ( HVal < Huf->SymLim[11] )
|
156
|
+
BNum = 11;
|
157
|
+
else if ( HVal < Huf->SymLim[12] )
|
158
|
+
BNum = 12;
|
159
|
+
else if ( HVal < Huf->SymLim[13] )
|
160
|
+
BNum = 13;
|
161
|
+
else
|
162
|
+
BNum = (HVal < Huf->SymLim[14]) ? (14) : (15);
|
163
|
+
|
164
|
+
BITRDR_DROPBITS(Huf->BitRdr, BNum);
|
165
|
+
IOfs = (HVal - Huf->SymLim[BNum-1]) >> (24 - BNum);
|
166
|
+
return(Huf->Symbol[Huf->SymIdx[BNum] + IOfs]);
|
167
|
+
}
|
168
|
+
|
169
|
+
/* construct huffman tables */
|
170
|
+
static INT LzxHuf_HufTblBuild(LZX_HUFF* Huf, BYTE* CodeLen)
|
171
|
+
{
|
172
|
+
UINT LenCnt[16];
|
173
|
+
UINT CurIdx[16];
|
174
|
+
UINT SymIdx, I;
|
175
|
+
UINT Lim, Idx;
|
176
|
+
UINT Ofs;
|
177
|
+
|
178
|
+
for ( I = 0; I < 16; I++ )
|
179
|
+
LenCnt[I] = 0;
|
180
|
+
for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
|
181
|
+
LenCnt[CodeLen[SymIdx]]++;
|
182
|
+
|
183
|
+
#ifdef LZX_DEBUG_LOG
|
184
|
+
if ( NULL == FDebLog )
|
185
|
+
FDebLog = fopen("lzxdeb.log", "wt");
|
186
|
+
#endif
|
187
|
+
|
188
|
+
LenCnt[0] = 0;
|
189
|
+
CurIdx[0] = 0;
|
190
|
+
Huf->SymIdx[0] = 0;
|
191
|
+
Huf->SymLim[0] = 0;
|
192
|
+
Lim = 0;
|
193
|
+
Idx = 0;
|
194
|
+
|
195
|
+
for ( I = 1; I < 16; I++ )
|
196
|
+
{
|
197
|
+
Lim += (LenCnt[I] << (24 - I));
|
198
|
+
if ( Lim > 0x1000000 )
|
199
|
+
return(-1); /* overrun */
|
200
|
+
|
201
|
+
Huf->SymLim[I] = Lim;
|
202
|
+
Huf->SymIdx[I] = Huf->SymIdx[I-1] + LenCnt[I-1];
|
203
|
+
CurIdx[I] = Huf->SymIdx[I];
|
204
|
+
|
205
|
+
if ( I <= 8 )
|
206
|
+
{
|
207
|
+
Ofs = (Huf->SymLim[I] >> 16);
|
208
|
+
lzx_memset(&Huf->Length[Idx], I, Ofs - Idx);
|
209
|
+
Idx = Ofs;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
if ( Lim != 0x1000000 )
|
214
|
+
return(-1); /* not full set */
|
215
|
+
|
216
|
+
#ifdef LZX_DEBUG_LOG
|
217
|
+
fprintf(FDebLog, "Huf->SymNum == %u\n", Huf->SymNum);
|
218
|
+
fprintf(FDebLog, "Huf->SymIdx == ");
|
219
|
+
for ( I = 0; I < 16; I++ )
|
220
|
+
fprintf(FDebLog, "%u ", Huf->SymIdx[I]);
|
221
|
+
fprintf(FDebLog, "\n");
|
222
|
+
fprintf(FDebLog, "Huf->SymLim == ");
|
223
|
+
for ( I = 0; I < 16; I++ )
|
224
|
+
fprintf(FDebLog, "%u ", Huf->SymLim[I]);
|
225
|
+
fprintf(FDebLog, "\n");
|
226
|
+
fflush(FDebLog);
|
227
|
+
#endif
|
228
|
+
|
229
|
+
for ( SymIdx = 0; SymIdx < Huf->SymNum; SymIdx++ )
|
230
|
+
{
|
231
|
+
if ( CodeLen[SymIdx] )
|
232
|
+
{
|
233
|
+
#ifdef LZX_DEBUG_LOG
|
234
|
+
fprintf(FDebLog, "%u\n", SymIdx);
|
235
|
+
fflush(FDebLog);
|
236
|
+
#endif
|
237
|
+
Huf->Symbol[CurIdx[CodeLen[SymIdx]]++] = SymIdx;
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
return(0); /* all ok */
|
242
|
+
}
|
243
|
+
|
244
|
+
/* ##### *** LZX DECODER FUNCTIONS *** ##################################### */
|
245
|
+
|
246
|
+
/* basic lzx tables */
|
247
|
+
static const UINT LzxTblLenBits[28] = {
|
248
|
+
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
|
249
|
+
5, 5, 5, 5
|
250
|
+
};
|
251
|
+
static const UINT LzxTblLenBase[28] = {
|
252
|
+
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32,
|
253
|
+
40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224
|
254
|
+
};
|
255
|
+
static const UINT LzxTblOfsBits[58] = {
|
256
|
+
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
|
257
|
+
8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
|
258
|
+
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18,
|
259
|
+
18, 18, 18, 18
|
260
|
+
};
|
261
|
+
static const UINT LzxTblOfsBase[58] = {
|
262
|
+
0x00000000, 0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000006,
|
263
|
+
0x00000008, 0x0000000C, 0x00000010, 0x00000018, 0x00000020, 0x00000030,
|
264
|
+
0x00000040, 0x00000060, 0x00000080, 0x000000C0, 0x00000100, 0x00000180,
|
265
|
+
0x00000200, 0x00000300, 0x00000400, 0x00000600, 0x00000800, 0x00000C00,
|
266
|
+
0x00001000, 0x00001800, 0x00002000, 0x00003000, 0x00004000, 0x00006000,
|
267
|
+
0x00008000, 0x0000C000, 0x00010000, 0x00018000, 0x00020000, 0x00030000,
|
268
|
+
0x00040000, 0x00060000, 0x00080000, 0x000A0000, 0x000C0000, 0x000E0000,
|
269
|
+
0x00100000, 0x00120000, 0x00140000, 0x00160000, 0x00180000, 0x001A0000,
|
270
|
+
0x001C0000, 0x001E0000, 0x00200000, 0x00240000, 0x00280000, 0x002C0000,
|
271
|
+
0x00300000, 0x00340000, 0x00380000, 0x003C0000
|
272
|
+
};
|
273
|
+
|
274
|
+
/* ------------------------------------------------------------------------- */
|
275
|
+
|
276
|
+
/* build lzx tables */
|
277
|
+
static INT Lzx_LzxTblBuild(LZX_CONTEXT* Ctx)
|
278
|
+
{
|
279
|
+
BYTE* Heap;
|
280
|
+
BYTE LenTbl[19];
|
281
|
+
BYTE HufSym[757];
|
282
|
+
UINT Val, I, Sym;
|
283
|
+
INT ISym;
|
284
|
+
|
285
|
+
Heap = Ctx->LstMem;
|
286
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 1, Val);
|
287
|
+
if ( !Val ) lzx_memset(Heap, 0, 757);
|
288
|
+
|
289
|
+
for ( I = 0; I < 19; I++ )
|
290
|
+
{
|
291
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 4, Val);
|
292
|
+
LenTbl[I] = (BYTE)(Val);
|
293
|
+
}
|
294
|
+
|
295
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufSpec, LenTbl) )
|
296
|
+
return(-1); /* error */
|
297
|
+
|
298
|
+
I = 0;
|
299
|
+
while ( I < 757 )
|
300
|
+
{
|
301
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufSpec)) == -1 )
|
302
|
+
return(-1); /* error */
|
303
|
+
|
304
|
+
if ( (Sym = (UINT)(ISym)) < 16 )
|
305
|
+
{
|
306
|
+
HufSym[I] = (BYTE)((Heap[I] + Sym) & 15); I++;
|
307
|
+
continue;
|
308
|
+
}
|
309
|
+
|
310
|
+
if ( Sym == 16 )
|
311
|
+
{
|
312
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 2, Val); Val += 3;
|
313
|
+
while ( Val > 0 && I < 757 )
|
314
|
+
{
|
315
|
+
HufSym[I] = HufSym[I-1];
|
316
|
+
Val--; I++;
|
317
|
+
}
|
318
|
+
continue;
|
319
|
+
}
|
320
|
+
|
321
|
+
if ( Sym == 17 )
|
322
|
+
{
|
323
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 3, Val);
|
324
|
+
Val += 3;
|
325
|
+
}
|
326
|
+
else
|
327
|
+
{
|
328
|
+
BITRDR_GETBITS(&Ctx->BitRdr, 7, Val);
|
329
|
+
Val += 11;
|
330
|
+
}
|
331
|
+
|
332
|
+
while ( Val > 0 && I < 757 )
|
333
|
+
{
|
334
|
+
HufSym[I] = 0;
|
335
|
+
Val--; I++;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufBase, &HufSym[0]) )
|
340
|
+
return(-1);
|
341
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufLens, &HufSym[721]) )
|
342
|
+
return(-1);
|
343
|
+
if ( LzxHuf_HufTblBuild(&Ctx->HufOffs, &HufSym[749]) )
|
344
|
+
return(-1);
|
345
|
+
|
346
|
+
Ctx->HasOffs = FALSE;
|
347
|
+
for ( I = 0; I < 8; I++ )
|
348
|
+
{
|
349
|
+
if ( HufSym[749+I] != 3 )
|
350
|
+
{
|
351
|
+
Ctx->HasOffs = TRUE;
|
352
|
+
break;
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
lzx_memcpy(Heap, &HufSym[0], 757);
|
357
|
+
return(0); /* all ok */
|
358
|
+
}
|
359
|
+
|
360
|
+
/* ------------------------------------------------------------------------- */
|
361
|
+
|
362
|
+
INT DecodeLZX(LZX_CONTEXT* Ctx, BYTE* Src, BYTE* Dst, UINT PSize, UINT USize)
|
363
|
+
{
|
364
|
+
UINT Written;
|
365
|
+
UINT Symbol;
|
366
|
+
BYTE* HufMem;
|
367
|
+
UINT Ofs;
|
368
|
+
UINT Len;
|
369
|
+
UINT Num;
|
370
|
+
UINT Val;
|
371
|
+
INT ISym;
|
372
|
+
|
373
|
+
/* check params */
|
374
|
+
if ( !Ctx || !Src || !Dst || !USize )
|
375
|
+
return(-1); /* invalid param */
|
376
|
+
|
377
|
+
/* init lzx context */
|
378
|
+
BITRDR_INIT(&Ctx->BitRdr, Src, PSize);
|
379
|
+
SWD_INIT(&Ctx->Window, Dst, USize);
|
380
|
+
Ctx->HasOffs = FALSE;
|
381
|
+
Ctx->LstOfs[0] = 0;
|
382
|
+
Ctx->LstOfs[1] = 0;
|
383
|
+
Ctx->LstOfs[2] = 0;
|
384
|
+
|
385
|
+
/* init huffman coders */
|
386
|
+
HufMem = &Ctx->HufTbl[0];
|
387
|
+
HufMem = LzxHuf_Init(&Ctx->HufBase, &Ctx->BitRdr, 721, HufMem);
|
388
|
+
HufMem = LzxHuf_Init(&Ctx->HufLens, &Ctx->BitRdr, 28, HufMem);
|
389
|
+
HufMem = LzxHuf_Init(&Ctx->HufOffs, &Ctx->BitRdr, 8, HufMem);
|
390
|
+
HufMem = LzxHuf_Init(&Ctx->HufSpec, &Ctx->BitRdr, 19, HufMem);
|
391
|
+
lzx_memset(Ctx->LstMem = HufMem, 0, 757);
|
392
|
+
|
393
|
+
/* build lzx tables */
|
394
|
+
if ( Lzx_LzxTblBuild(Ctx) )
|
395
|
+
return(-1);
|
396
|
+
|
397
|
+
/* decode */
|
398
|
+
Written = 0;
|
399
|
+
while ( Written < USize )
|
400
|
+
{
|
401
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufBase)) == -1 )
|
402
|
+
return(-1);
|
403
|
+
|
404
|
+
if ( (Symbol = (UINT)(ISym)) < 256 )
|
405
|
+
{
|
406
|
+
/* literal */
|
407
|
+
SWD_PUTBYTE(&Ctx->Window, Symbol);
|
408
|
+
Written++;
|
409
|
+
continue;
|
410
|
+
}
|
411
|
+
|
412
|
+
if ( Symbol < 720 )
|
413
|
+
{
|
414
|
+
/* phrase */
|
415
|
+
Symbol -= 256;
|
416
|
+
Ofs = (Symbol >> 3);
|
417
|
+
Len = (Symbol & 7) + 2;
|
418
|
+
|
419
|
+
if ( Len == 9 )
|
420
|
+
{
|
421
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufLens)) == -1 )
|
422
|
+
return(-1);
|
423
|
+
|
424
|
+
Symbol = (UINT)(ISym);
|
425
|
+
Num = LzxTblLenBits[Symbol];
|
426
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
427
|
+
Len += (Val + LzxTblLenBase[Symbol]);
|
428
|
+
}
|
429
|
+
|
430
|
+
Num = LzxTblOfsBits[Ofs];
|
431
|
+
Ofs = LzxTblOfsBase[Ofs];
|
432
|
+
|
433
|
+
if ( Num < 3 || !Ctx->HasOffs )
|
434
|
+
{
|
435
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
436
|
+
Ofs += Val;
|
437
|
+
}
|
438
|
+
else
|
439
|
+
{
|
440
|
+
Num -= 3;
|
441
|
+
BITRDR_GETBITS(&Ctx->BitRdr, Num, Val);
|
442
|
+
if ( (ISym = LzxHuf_DecodeSymbol(&Ctx->HufOffs)) == -1 )
|
443
|
+
return(-1);
|
444
|
+
Ofs += ((UINT)(ISym) + (Val << 3));
|
445
|
+
}
|
446
|
+
|
447
|
+
if ( Ofs < 3 )
|
448
|
+
{
|
449
|
+
/* use saved last offset */
|
450
|
+
Ofs = Ctx->LstOfs[Num = Ofs];
|
451
|
+
if ( Num )
|
452
|
+
{
|
453
|
+
Ctx->LstOfs[Num] = Ctx->LstOfs[0];
|
454
|
+
Ctx->LstOfs[0] = Ofs;
|
455
|
+
}
|
456
|
+
}
|
457
|
+
else
|
458
|
+
{
|
459
|
+
/* update last offset */
|
460
|
+
Ctx->LstOfs[2] = Ctx->LstOfs[1];
|
461
|
+
Ctx->LstOfs[1] = Ctx->LstOfs[0];
|
462
|
+
Ctx->LstOfs[0] = (Ofs -= 3);
|
463
|
+
}
|
464
|
+
|
465
|
+
/* copy phrase */
|
466
|
+
SWD_DELTACOPY(&Ctx->Window, Ofs+1, Len);
|
467
|
+
Written += Len;
|
468
|
+
continue;
|
469
|
+
}
|
470
|
+
|
471
|
+
/* update trees */
|
472
|
+
if ( Lzx_LzxTblBuild(Ctx) )
|
473
|
+
return(-1);
|
474
|
+
}
|
475
|
+
|
476
|
+
return(Written); /* all ok */
|
477
|
+
}
|
478
|
+
|
479
|
+
/* ------------------------------------------------------------------------- */
|