129 lines
2.8 KiB
C
129 lines
2.8 KiB
C
/*
|
|
* xlat.c
|
|
*
|
|
* Translate
|
|
*/
|
|
#include "decoder.h"
|
|
|
|
|
|
void NEAR init_decoder_translation(t_decoder_context *context)
|
|
{
|
|
context->dec_instr_pos = 0;
|
|
}
|
|
|
|
|
|
#ifdef ASM_TRANSLATE_E8
|
|
ulong asm_decoder_translate_e8(ulong instr_pos, ulong file_size, byte *mem, long bytes);
|
|
|
|
void NEAR decoder_translate_e8(t_decoder_context *context, byte *mem, long bytes)
|
|
{
|
|
/*
|
|
* We don't want the ASM code to have to worry about where in the
|
|
* context structure a particular element is
|
|
*/
|
|
context->dec_instr_pos = asm_decoder_translate_e8(
|
|
context->dec_instr_pos,
|
|
context->dec_current_file_size,
|
|
mem,
|
|
bytes
|
|
);
|
|
}
|
|
|
|
#else /* !ASM_TRANSLATE_E8 */
|
|
|
|
void NEAR decoder_translate_e8(t_decoder_context *context, byte *mem, long bytes)
|
|
{
|
|
ulong end_instr_pos;
|
|
byte temp[6];
|
|
byte *mem_backup;
|
|
|
|
if (bytes <= 6)
|
|
{
|
|
context->dec_instr_pos += bytes;
|
|
return;
|
|
}
|
|
|
|
mem_backup = mem;
|
|
|
|
/* backup these bytes */
|
|
memcpy(temp, &mem[bytes-6], 6);
|
|
|
|
/* overwrite them with 0xE8 */
|
|
memset(&mem[bytes-6], 0xE8, 6);
|
|
|
|
end_instr_pos = context->dec_instr_pos + bytes - 6;
|
|
|
|
while (1)
|
|
{
|
|
unsigned long absolute;
|
|
#if !defined(_X86_)
|
|
unsigned long offset;
|
|
#endif
|
|
|
|
/*
|
|
* We are guaranteed to hit one of the 6 0xE8's we stuck at the
|
|
* end of the buffer, even if we ran into some corrupted data
|
|
* that resulted in our jumping over 5 bytes due to a translation
|
|
*/
|
|
while (*mem++ != 0xE8)
|
|
context->dec_instr_pos++;
|
|
|
|
if (context->dec_instr_pos >= end_instr_pos)
|
|
break;
|
|
|
|
/*
|
|
* There are 5 or more bytes in the buffer
|
|
* (i.e. E8 xx xx xx xx)
|
|
*
|
|
* We have a complete offset available to (potentially) translate
|
|
*/
|
|
|
|
#if defined(_X86_)
|
|
absolute = *(ulong *) mem;
|
|
#else
|
|
absolute = ( (ulong)mem[0]) |
|
|
(((ulong)mem[1])<<8) |
|
|
(((ulong)mem[2])<<16)|
|
|
(((ulong)mem[3])<<24);
|
|
#endif
|
|
|
|
if (absolute < context->dec_current_file_size)
|
|
{
|
|
/* absolute >= 0 && absolute < dec_current_file_size */
|
|
|
|
#if defined(_X86_)
|
|
*(ulong *) mem = absolute - context->dec_instr_pos;
|
|
#else
|
|
offset = absolute - context->dec_instr_pos;
|
|
mem[0] = (byte) (offset & 255);
|
|
mem[1] = (byte) ((offset >> 8) & 255);
|
|
mem[2] = (byte) ((offset >> 16) & 255);
|
|
mem[3] = (byte) ((offset >> 24) & 255);
|
|
#endif
|
|
}
|
|
else if ((ulong) (-(long) absolute) <= context->dec_instr_pos)
|
|
{
|
|
/* absolute >= -instr_pos && absolute < 0 */
|
|
|
|
#if defined(_X86_)
|
|
*(ulong *) mem = absolute + context->dec_current_file_size;
|
|
#else
|
|
offset = absolute + context->dec_current_file_size;
|
|
mem[0] = (byte) (offset & 255);
|
|
mem[1] = (byte) (offset >> 8) & 255;
|
|
mem[2] = (byte) (offset >> 16) & 255;
|
|
mem[3] = (byte) (offset >> 24) & 255;
|
|
#endif
|
|
}
|
|
|
|
mem += 4;
|
|
context->dec_instr_pos += 5;
|
|
}
|
|
|
|
context->dec_instr_pos = end_instr_pos + 6;
|
|
|
|
/* restore these bytes */
|
|
memcpy(&mem_backup[bytes-6], temp, 6);
|
|
}
|
|
#endif
|