Home | History | Annotate | Line # | Download | only in simple
      1 // SPDX-License-Identifier: 0BSD
      2 
      3 ///////////////////////////////////////////////////////////////////////////////
      4 //
      5 /// \file       armthumb.c
      6 /// \brief      Filter for ARM-Thumb binaries
      7 ///
      8 //  Authors:    Igor Pavlov
      9 //              Lasse Collin
     10 //
     11 ///////////////////////////////////////////////////////////////////////////////
     12 
     13 #include "simple_private.h"
     14 
     15 
     16 static size_t
     17 armthumb_code(void *simple lzma_attribute((__unused__)),
     18 		uint32_t now_pos, bool is_encoder,
     19 		uint8_t *buffer, size_t size)
     20 {
     21 	if (size < 4)
     22 		return 0;
     23 
     24 	size -= 4;
     25 
     26 	size_t i;
     27 	for (i = 0; i <= size; i += 2) {
     28 		if ((buffer[i + 1] & 0xF8) == 0xF0
     29 				&& (buffer[i + 3] & 0xF8) == 0xF8) {
     30 			uint32_t src = (((uint32_t)(buffer[i + 1]) & 7) << 19)
     31 				| ((uint32_t)(buffer[i + 0]) << 11)
     32 				| (((uint32_t)(buffer[i + 3]) & 7) << 8)
     33 				| (uint32_t)(buffer[i + 2]);
     34 
     35 			src <<= 1;
     36 
     37 			uint32_t dest;
     38 			if (is_encoder)
     39 				dest = now_pos + (uint32_t)(i) + 4 + src;
     40 			else
     41 				dest = src - (now_pos + (uint32_t)(i) + 4);
     42 
     43 			dest >>= 1;
     44 			buffer[i + 1] = 0xF0 | ((dest >> 19) & 0x7);
     45 			buffer[i + 0] = (dest >> 11);
     46 			buffer[i + 3] = 0xF8 | ((dest >> 8) & 0x7);
     47 			buffer[i + 2] = (dest);
     48 			i += 2;
     49 		}
     50 	}
     51 
     52 	return i;
     53 }
     54 
     55 
     56 static lzma_ret
     57 armthumb_coder_init(lzma_next_coder *next, const lzma_allocator *allocator,
     58 		const lzma_filter_info *filters, bool is_encoder)
     59 {
     60 	return lzma_simple_coder_init(next, allocator, filters,
     61 			&armthumb_code, 0, 4, 2, is_encoder);
     62 }
     63 
     64 
     65 #ifdef HAVE_ENCODER_ARMTHUMB
     66 extern lzma_ret
     67 lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
     68 		const lzma_allocator *allocator,
     69 		const lzma_filter_info *filters)
     70 {
     71 	return armthumb_coder_init(next, allocator, filters, true);
     72 }
     73 #endif
     74 
     75 
     76 #ifdef HAVE_DECODER_ARMTHUMB
     77 extern lzma_ret
     78 lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
     79 		const lzma_allocator *allocator,
     80 		const lzma_filter_info *filters)
     81 {
     82 	return armthumb_coder_init(next, allocator, filters, false);
     83 }
     84 #endif
     85