diff leo-obj/tool/disasm.c @ 136:81fc8da9a29c

tiobjd: disasm hints work now
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 07 Apr 2014 04:56:29 +0000
parents df432a4b1b84
children acdf75463e30
line wrap: on
line diff
--- a/leo-obj/tool/disasm.c	Mon Apr 07 04:06:17 2014 +0000
+++ b/leo-obj/tool/disasm.c	Mon Apr 07 04:56:29 2014 +0000
@@ -118,14 +118,57 @@
 }
 
 void
+disasm_emit_asciz(sec, pos, len)
+	struct internal_scnhdr *sec;
+	unsigned pos, len;
+{
+	int c;
+	unsigned endpos = pos + len;
+
+	fputs("\t.asciz\t\"", stdout);
+	for (; pos < endpos; pos++) {
+		c = filemap[sec->data_offset + pos];
+		switch (c) {
+		case '\b':
+			fputs("\\b", stdout);
+			continue;
+		case '\t':
+			fputs("\\t", stdout);
+			continue;
+		case '\n':
+			fputs("\\n", stdout);
+			continue;
+		case '\r':
+			fputs("\\r", stdout);
+			continue;
+		case '"':
+			fputs("\\\"", stdout);
+			continue;
+		case '\\':
+			fputs("\\\\", stdout);
+			continue;
+		}
+		if (c >= ' ' && c <= '~')
+			putchar(c);
+		else
+			printf("\\%03o", c);
+	}
+	putchar('"');
+	putchar('\n');
+}
+
+void
 disasm_codedata_section(sec)
 	struct internal_scnhdr *sec;
 {
 	unsigned symnum, relnum;
 	unsigned pos, incr, headroom;
-	int state = -1, linebrk = 0;
+	int state = -1, linebrk = 0, gothint;
 	struct internal_syment *sym;
 	struct internal_reloc *rel;
+	struct hint *hint = sec->hints;
+	u_char *asciz_end;
+	unsigned asciz_len;
 
 	if (sec->nreloc)
 		get_relocs_of_sec(sec);
@@ -154,7 +197,54 @@
 			}
 		} else
 			rel = 0;
+		if (hint) {
+			if (pos >= hint->pos)
+				gothint++;
+			else {
+				gothint = 0;
+				if (hint->pos - pos < headroom)
+					headroom = hint->pos - pos;
+			}
+		} else
+			gothint = 0;
+		if (gothint && pos == hint->pos && hint->linebrk)
+			putchar('\n');
 		printf("%8x:\t", pos);
+		if (gothint && hint->type) {
+			if (rel) {
+				printf("error: hint/reloc conflict\n");
+				return;
+			}
+			switch (hint->type) {
+			case HINT_D8:
+				printf("%02x\n",
+					filemap[sec->data_offset + pos]);
+				incr = 1;
+				break;
+			case HINT_D16:
+				printf("%04x\n",
+					get_u16(filemap+sec->data_offset+pos));
+				incr = 2;
+				break;
+			case HINT_D32:
+				printf("%08x\n",
+					get_u32(filemap+sec->data_offset+pos));
+				incr = 4;
+				break;
+			case HINT_ASCIZ:
+				asciz_end = memchr(filemap+sec->data_offset+pos,
+							0, headroom);
+				if (!asciz_end) {
+					printf("bad asciz hint: no 0 found\n");
+					return;
+				}
+				asciz_len = asciz_end - filemap -
+						sec->data_offset - pos;
+				disasm_emit_asciz(sec, pos, asciz_len);
+				incr = asciz_len + 1;
+			}
+			goto next;
+		}
 		if (rel) {
 			if (rel->type == RTYPE_LONG) {
 				if (pos & 3) {
@@ -235,6 +325,8 @@
 				incr, headroom);
 			return;
 		}
+		if (hint && pos >= hint->endpos)
+			hint = hint->next;
 	}
 	if (symnum == sec->nsymbols)
 		return;