(root)/
xz-5.4.5/
src/
liblzma/
simple/
x86.c
       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 ^ ((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
     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  #ifdef HAVE_ENCODER_X86
     145  extern lzma_ret
     146  lzma_simple_x86_encoder_init(lzma_next_coder *next,
     147  		const lzma_allocator *allocator,
     148  		const lzma_filter_info *filters)
     149  {
     150  	return x86_coder_init(next, allocator, filters, true);
     151  }
     152  #endif
     153  
     154  
     155  #ifdef HAVE_DECODER_X86
     156  extern lzma_ret
     157  lzma_simple_x86_decoder_init(lzma_next_coder *next,
     158  		const lzma_allocator *allocator,
     159  		const lzma_filter_info *filters)
     160  {
     161  	return x86_coder_init(next, allocator, filters, false);
     162  }
     163  #endif