Rizin
unix-like reverse engineering framework and cli tools
x86.c
Go to the documentation of this file.
1 //
6 // Authors: Igor Pavlov
7 // Lasse Collin
8 //
9 // This file has been put into the public domain.
10 // You can do whatever you want with this file.
11 //
13 
14 #include "simple_private.h"
15 
16 
17 #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
18 
19 
20 typedef struct {
24 
25 
26 static size_t
27 x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder,
28  uint8_t *buffer, size_t size)
29 {
30  static const bool MASK_TO_ALLOWED_STATUS[8]
31  = { true, true, true, false, true, false, false, false };
32 
33  static const uint32_t MASK_TO_BIT_NUMBER[8]
34  = { 0, 1, 2, 2, 3, 3, 3, 3 };
35 
36  lzma_simple_x86 *simple = simple_ptr;
37  uint32_t prev_mask = simple->prev_mask;
38  uint32_t prev_pos = simple->prev_pos;
39 
40  if (size < 5)
41  return 0;
42 
43  if (now_pos - prev_pos > 5)
44  prev_pos = now_pos - 5;
45 
46  const size_t limit = size - 5;
47  size_t buffer_pos = 0;
48 
49  while (buffer_pos <= limit) {
50  uint8_t b = buffer[buffer_pos];
51  if (b != 0xE8 && b != 0xE9) {
52  ++buffer_pos;
53  continue;
54  }
55 
56  const uint32_t offset = now_pos + (uint32_t)(buffer_pos)
57  - prev_pos;
58  prev_pos = now_pos + (uint32_t)(buffer_pos);
59 
60  if (offset > 5) {
61  prev_mask = 0;
62  } else {
63  for (uint32_t i = 0; i < offset; ++i) {
64  prev_mask &= 0x77;
65  prev_mask <<= 1;
66  }
67  }
68 
69  b = buffer[buffer_pos + 4];
70 
71  if (Test86MSByte(b)
72  && MASK_TO_ALLOWED_STATUS[(prev_mask >> 1) & 0x7]
73  && (prev_mask >> 1) < 0x10) {
74 
75  uint32_t src = ((uint32_t)(b) << 24)
76  | ((uint32_t)(buffer[buffer_pos + 3]) << 16)
77  | ((uint32_t)(buffer[buffer_pos + 2]) << 8)
78  | (buffer[buffer_pos + 1]);
79 
80  uint32_t dest;
81  while (true) {
82  if (is_encoder)
83  dest = src + (now_pos + (uint32_t)(
84  buffer_pos) + 5);
85  else
86  dest = src - (now_pos + (uint32_t)(
87  buffer_pos) + 5);
88 
89  if (prev_mask == 0)
90  break;
91 
92  const uint32_t i = MASK_TO_BIT_NUMBER[
93  prev_mask >> 1];
94 
95  b = (uint8_t)(dest >> (24 - i * 8));
96 
97  if (!Test86MSByte(b))
98  break;
99 
100  src = dest ^ ((1U << (32 - i * 8)) - 1);
101  }
102 
103  buffer[buffer_pos + 4]
104  = (uint8_t)(~(((dest >> 24) & 1) - 1));
105  buffer[buffer_pos + 3] = (uint8_t)(dest >> 16);
106  buffer[buffer_pos + 2] = (uint8_t)(dest >> 8);
107  buffer[buffer_pos + 1] = (uint8_t)(dest);
108  buffer_pos += 5;
109  prev_mask = 0;
110 
111  } else {
112  ++buffer_pos;
113  prev_mask |= 1;
114  if (Test86MSByte(b))
115  prev_mask |= 0x10;
116  }
117  }
118 
119  simple->prev_mask = prev_mask;
120  simple->prev_pos = prev_pos;
121 
122  return buffer_pos;
123 }
124 
125 
126 static lzma_ret
128  const lzma_filter_info *filters, bool is_encoder)
129 {
131  &x86_code, sizeof(lzma_simple_x86), 5, 1, is_encoder);
132 
133  if (ret == LZMA_OK) {
134  lzma_simple_coder *coder = next->coder;
135  lzma_simple_x86 *simple = coder->simple;
136  simple->prev_mask = 0;
137  simple->prev_pos = (uint32_t)(-5);
138  }
139 
140  return ret;
141 }
142 
143 
144 extern lzma_ret
146  const lzma_allocator *allocator,
147  const lzma_filter_info *filters)
148 {
149  return x86_coder_init(next, allocator, filters, true);
150 }
151 
152 
153 extern lzma_ret
155  const lzma_allocator *allocator,
156  const lzma_filter_info *filters)
157 {
158  return x86_coder_init(next, allocator, filters, false);
159 }
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
const lzma_allocator * allocator
Definition: block.h:377
const lzma_filter * filters
Definition: container.h:315
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
char * dest
Definition: lz4.h:697
static uint32_t const uint8_t uint32_t uint32_t limit
Definition: memcmplen.h:45
unsigned int uint32_t
Definition: sftypes.h:29
unsigned char uint8_t
Definition: sftypes.h:31
#define b(i)
Definition: sha256.c:42
lzma_ret lzma_simple_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter_info *filters, size_t(*filter)(void *simple, uint32_t now_pos, bool is_encoder, uint8_t *buffer, size_t size), size_t simple_size, size_t unfiltered_max, uint32_t alignment, bool is_encoder)
Definition: simple_coder.c:235
Private definitions for so called simple filters.
Definition: buffer.h:15
Custom functions for memory handling.
Definition: base.h:372
Hold data and function pointers of the next filter in the chain.
Definition: common.h:135
void * coder
Pointer to coder-specific data.
Definition: common.h:137
uint32_t prev_pos
Definition: x86.c:22
uint32_t prev_mask
Definition: x86.c:21
static lzma_ret x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter_info *filters, bool is_encoder)
Definition: x86.c:127
lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter_info *filters)
Definition: x86.c:145
lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter_info *filters)
Definition: x86.c:154
#define Test86MSByte(b)
Definition: x86.c:17
static size_t x86_code(void *simple_ptr, uint32_t now_pos, bool is_encoder, uint8_t *buffer, size_t size)
Definition: x86.c:27
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58