1 /////////////////////////////////////////////////////////////////////////////// 2 // 3 /// \file x86.c 4 /// \brief Filter for x86 binaries (BCJ filter) 5 /// 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 // 12 /////////////////////////////////////////////////////////////////////////////// 13 14 #include "simple_private.h" 15 16 17 #define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) 18 19 20 typedef struct { 21 uint32_t prev_mask; 22 uint32_t prev_pos; 23 } lzma_simple_x86; 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 ^ ((1 << (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 127 x86_coder_init(lzma_next_coder *next, const lzma_allocator *allocator, 128 const lzma_filter_info *filters, bool is_encoder) 129 { 130 const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters, 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 145 lzma_simple_x86_encoder_init(lzma_next_coder *next, 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 154 lzma_simple_x86_decoder_init(lzma_next_coder *next, 155 const lzma_allocator *allocator, 156 const lzma_filter_info *filters) 157 { 158 return x86_coder_init(next, allocator, filters, false); 159 } 160