# HG changeset patch # User Michael Spacefalcon # Date 1396822479 0 # Node ID 87b82398a08be5dda37310eb2c786d9a99952e39 # Parent 597143ba1c37509cd3fc409cdf9b66a329e3a078 leo-obj project subtree started, tiobjd tool moved into it diff -r 597143ba1c37 -r 87b82398a08b .hgignore --- a/.hgignore Sun Apr 06 20:20:39 2014 +0000 +++ b/.hgignore Sun Apr 06 22:14:39 2014 +0000 @@ -10,6 +10,8 @@ ^compal/c156-boot\. ^compal/osmovoodoo +^leo-obj/tool/tiobjd$ + ^miscprog/atsc$ ^miscprog/factdiff$ ^miscprog/imeibrute$ @@ -31,5 +33,3 @@ ^pirollback/dumpjournal$ ^pirollback/inopath$ ^pirollback/rollback$ - -^ticoff/tiobjd$ diff -r 597143ba1c37 -r 87b82398a08b leo-obj/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/README Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,11 @@ +TI's TCS211 aka Leonardo firmware is a mixture of C sources and linkable object +modules (packaged into archive libraries) in the COFF format used by TI's TMS470 +compiler toolchain. One of the goals of the FreeCalypso project is to transform +this firmware into full C source by analyzing the COFF object blobs with a tool +that groks the symbolic information present therein, then replacing each blob +either with a matching source piece from another TI firmware leak (e.g., the one +in ftp.ifctf.org:/pub/GSM/LoCosto) or with newly written C code that exports +the same functions and global variables etc, with logic inside matching the +disassembly of the original. + +The present directory tree will hold the just-described project. diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/Makefile Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,19 @@ +CC= gcc +CFLAGS= -O2 +PROG= tiobjd +OBJS= armdis.o atcommon.o basics.o disasm.o globals.o hints.o lowlevel.o \ + main.o profile.o reloc.o symtab.o tables.o thumbdis.o +HDRS= coffconst.h filestruct.h globals.h intstruct.h + +all: ${PROG} + +${PROG}: ${OBJS} + ${CC} -o $@ ${OBJS} + +${OBJS}: ${HDRS} + +install: + install -c -o bin -g bin -m 755 ${PROG} /usr/local/bin + +clean: + rm -f *.o ${PROG} *err diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/README Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,6 @@ +Here I'm going to build a standalone tool that reads linkable (not final) +object modules produced by TI's TMS470 toolchain, as found in GSM firmware +semi-sources, and produces disassembly listings that are well-fit for +understanding the function and interfaces of each object blob, and ultimately +replacing each of these blobs with functionally and interface-equivalent +new C code. diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/armdis.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/armdis.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,522 @@ +/* + * ARM state disassembly + */ + +#include +#include +#include +#include +#include +#include "intstruct.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); +extern struct internal_reloc *find_word32_reloc(); + +extern char *regnames[16], *condition_decode[16], *shift_types[4]; + +static char *dataproc_ops[16] = {"and", "eor", "sub", "rsb", + "add", "adc", "sbc", "rsc", + "tst", "teq", "cmp", "cmn", + "orr", "mov", "bic", "mvn"}; + +static void +arm_branch(off, word) + unsigned off, word; +{ + unsigned dest; + + dest = (word & 0x00FFFFFF) << 2; + if (dest & 0x02000000) + dest |= 0xFC000000; + dest += off + 8; + printf("b%s%s\t0x%x\n", word&0x1000000 ? "l" : "", + condition_decode[word>>28], dest); +} + +static void +op2_immed(word) + unsigned word; +{ + unsigned low8, rot, val; + + low8 = word & 0xFF; + rot = (word & 0xF00) >> 7; + val = (low8 << (32 - rot)) | (low8 >> rot); + if (val <= 9) + printf("#%u\n", val); + else + printf("#%u\t; 0x%x\n", val, val); +} + +static void +op2_regbyconst(word) + unsigned word; +{ + unsigned c, t; + + c = (word >> 7) & 0x1F; + t = (word >> 5) & 3; + if (!c) { + switch (t) { + case 0: + printf("%s", regnames[word&0xF]); + return; + case 3: + printf("%s, rrx", regnames[word&0xF]); + return; + default: + c = 32; + } + } + printf("%s, %s #%u", regnames[word&0xF], shift_types[t], c); +} + +static void +op2_regbyreg(word) + unsigned word; +{ + printf("%s, %s %s", regnames[word&0xF], shift_types[(word>>5)&3], + regnames[(word>>8)&0xF]); +} + +static void +op2_regshift(word) + unsigned word; +{ + if (word & 0x10) + op2_regbyreg(word); + else + op2_regbyconst(word); + putchar('\n'); +} + +static void +dataproc_op2(word) + unsigned word; +{ + if (word & 0x02000000) + op2_immed(word); + else + op2_regshift(word); +} + +static void +dataproc_tstcmp_overlay(word) + unsigned word; +{ + char msrmask[5], *cp; + + if ((word & 0x0FFFFFF0) == 0x012FFF10) { + printf("bx%s\t%s\n", condition_decode[word>>28], + regnames[word&0xF]); + return; + } else if ((word & 0x0FBF0FFF) == 0x010F0000) { + printf("mrs%s\t%s, %cPSR\n", condition_decode[word>>28], + regnames[(word>>12)&0xF], word&0x400000 ? 'S' : 'C'); + return; + } else if ((word & 0x0DB0F000) == 0x0120F000) { + if (!(word & 0x02000000) && (word & 0xFF0)) { + printf("\n"); + return; + } + if (word & 0xF0000) { + cp = msrmask; + if (word & 0x80000) + *cp++ = 'f'; + if (word & 0x40000) + *cp++ = 's'; + if (word & 0x20000) + *cp++ = 'x'; + if (word & 0x10000) + *cp++ = 'c'; + *cp = '\0'; + } else + strcpy(msrmask, "null"); + printf("msr%s\t%cPSR_%s, ", condition_decode[word>>28], + word&0x400000 ? 'S' : 'C', msrmask); + dataproc_op2(word); + return; + } + printf("\n"); +} + +static void +dataproc(word) + unsigned word; +{ + unsigned opc; + + opc = (word >> 21) & 0xF; + switch (opc) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 0xC: + case 0xE: + printf("%s%s%s\t%s, %s, ", dataproc_ops[opc], + condition_decode[word>>28], word&0x100000 ? "s" : "", + regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); + dataproc_op2(word); + return; + case 0xD: + case 0xF: + printf("%s%s%s\t%s, ", dataproc_ops[opc], + condition_decode[word>>28], word&0x100000 ? "s" : "", + regnames[(word>>12)&0xF]); + dataproc_op2(word); + return; + case 8: + case 9: + case 0xA: + case 0xB: + if (word & 0x100000) { + printf("%s%s\t%s, ", dataproc_ops[opc], + condition_decode[word>>28], + regnames[(word>>16)&0xF]); + dataproc_op2(word); + } else + dataproc_tstcmp_overlay(word); + return; + } +} + +static void +multiply(word) + unsigned word; +{ + if ((word & 0x0FE000F0) == 0x90) + printf("mul%s%s\t%s, %s, %s\n", condition_decode[word>>28], + word&0x100000 ? "s" : "", regnames[(word>>16)&0xF], + regnames[word&0xF], regnames[(word>>8)&0xF]); + else if ((word & 0x0FE000F0) == 0x00200090) + printf("mla%s%s\t%s, %s, %s, %s\n", condition_decode[word>>28], + word&0x100000 ? "s" : "", regnames[(word>>16)&0xF], + regnames[word&0xF], regnames[(word>>8)&0xF], + regnames[(word>>12)&0xF]); + else if ((word & 0x0F8000F0) == 0x00800090) + printf("%c%sl%s%s\t%s, %s, %s, %s\n", + word&0x400000 ? 's' : 'u', + word&0x200000 ? "mla" : "mul", + condition_decode[word>>28], + word&0x100000 ? "s" : "", + regnames[(word>>12)&0xF], regnames[(word>>16)&0xF], + regnames[word&0xF], regnames[(word>>8)&0xF]); + else if ((word & 0x0FB00FF0) == 0x01000090) + printf("swp%s%s\t%s, %s, [%s]\n", condition_decode[word>>28], + word&0x400000, "b", "", regnames[(word>>12)&0xF], + regnames[word&0xF], regnames[(word>>16)&0xF]); + else + printf("\n"); +} + +static int +check_ldr_litpool(sec, off, word, loff, size) + struct internal_scnhdr *sec; + unsigned off, word, loff; +{ + unsigned litoff, datum; + struct internal_reloc *rel; + + /* base reg must be 15 */ + if (((word >> 16) & 0xF) != 15) + return(0); + /* must be a load */ + if (!(word & 0x100000)) + return(0); + /* no writeback allowed */ + if (word & 0x200000) + return(0); + /* alignment */ + if (loff & (size - 1)) + return(0); + /* range */ + off += 8; + if (word & 0x800000) + litoff = off + loff; + else { + if (loff > off) + return(0); + litoff = off - loff; + } + if (litoff >= sec->size) + return(0); + /* all checks passed, proceed */ + rel = find_word32_reloc(sec, litoff); + switch (size) { + case 1: + datum = filemap[sec->data_offset + litoff]; + break; + case 2: + datum = get_u16(filemap + sec->data_offset + litoff); + break; + case 4: + datum = get_u32(filemap + sec->data_offset + litoff); + break; + } + putchar('='); + if (rel) + disasm_reloc_target(sec, rel, datum); + else + printf("0x%x", datum); + printf("\t; via 0x%x\n", litoff); + return(1); +} + +static void +ldr_str_imm_pre(sec, off, word) + struct internal_scnhdr *sec; + unsigned off, word; +{ + unsigned loff = word & 0xFFF; + + printf("%s%s%s\t%s, ", word&0x100000 ? "ldr" : "str", + condition_decode[word>>28], word&0x400000 ? "b" : "", + regnames[(word>>12)&0xF]); + if (check_ldr_litpool(sec, off, word, loff, word&0x400000 ? 1 : 4)) + return; + printf("[%s", regnames[(word>>16)&0xF]); + if (loff || word&0x200000) + printf(", #%s%u", word&0x800000 ? "" : "-", loff); + putchar(']'); + if (word & 0x200000) + putchar('!'); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +ldr_str_imm_post(word) + unsigned word; +{ + unsigned loff = word & 0xFFF; + + printf("%s%s%s%s\t%s, [%s], #%s%u", word&0x100000 ? "ldr" : "str", + condition_decode[word>>28], word&0x400000 ? "b" : "", + word&0x200000 ? "t" : "", + regnames[(word>>12)&0xF], regnames[(word>>16)&0xF], + word&0x800000 ? "" : "-", loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +ldr_str_reg_pre(word) + unsigned word; +{ + if (word & 0x10) { + printf("\n"); + return; + } + printf("%s%s%s\t%s, [%s, ", word&0x100000 ? "ldr" : "str", + condition_decode[word>>28], word&0x400000 ? "b" : "", + regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); + if (!(word & 0x800000)) + putchar('-'); + op2_regbyconst(word); + putchar(']'); + if (word & 0x200000) + putchar('!'); + putchar('\n'); +} + +static void +ldr_str_reg_post(word) + unsigned word; +{ + if (word & 0x10) { + printf("\n"); + return; + } + printf("%s%s%s%s\t%s, [%s], ", word&0x100000 ? "ldr" : "str", + condition_decode[word>>28], word&0x400000 ? "b" : "", + word&0x200000 ? "t" : "", + regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); + if (!(word & 0x800000)) + putchar('-'); + op2_regbyconst(word); + putchar('\n'); +} + +static void +ldr_str_ext(sec, off, word) + struct internal_scnhdr *sec; + unsigned off, word; +{ + unsigned loff; + + if (!(word&0x01000000) && word&0x200000) { + printf("\n"); + return; + } + if (!(word&0x400000) && word&0xF00) { + printf("\n"); + return; + } + printf("%s%s%s%c\t%s, ", word&0x100000 ? "ldr" : "str", + condition_decode[word>>28], + word&0x40 ? "s" : "", + word&0x20 ? 'h' : 'b', + regnames[(word>>12)&0xF]); + if (word & 0x400000) + loff = ((word & 0xF00) >> 4) | (word & 0xF); + switch (word & 0x01400000) { + case 0: + /* reg post */ + printf("[%s], %s%s", regnames[(word>>16)&0xF], + word&0x800000 ? "" : "-", regnames[word&0xF]); + break; + case 0x400000: + /* imm post */ + printf("[%s], #%s%u", regnames[(word>>16)&0xF], + word&0x800000 ? "" : "-", loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + break; + case 0x01000000: + /* reg pre */ + printf("[%s, %s%s]%s", regnames[(word>>16)&0xF], + word&0x800000 ? "" : "-", regnames[word&0xF], + word&0x200000 ? "!" : ""); + break; + case 0x01400000: + /* imm pre */ + if (check_ldr_litpool(sec, off, word, loff, word&0x20 ? 2 : 1)) + return; + printf("[%s", regnames[(word>>16)&0xF]); + if (loff || word&0x200000) + printf(", #%s%u", word&0x800000 ? "" : "-", loff); + putchar(']'); + if (word & 0x200000) + putchar('!'); + if (loff >= 10) + printf("\t; 0x%x", loff); + break; + } + putchar('\n'); +} + +static void +dataproc_74_overlay(sec, off, word) + struct internal_scnhdr *sec; + unsigned off, word; +{ + if (word & 0x60) + ldr_str_ext(sec, off, word); + else + multiply(word); +} + +static void +ldm_stm(word) + unsigned word; +{ + int r, flag; + + printf("%s%s%c%c\t%s", word&0x100000 ? "ldm" : "stm", + condition_decode[word>>28], + word&0x800000 ? 'i' : 'd', word&0x01000000 ? 'b' : 'a', + regnames[(word>>16)&0xF]); + if (word & 0x200000) + putchar('!'); + fputs(", {", stdout); + flag = 0; + for (r = 0; r < 16; r++) + if (word & (1 << r)) { + if (flag) + fputs(", ", stdout); + fputs(regnames[r], stdout); + flag = 1; + } + putchar('}'); + if (word & 0x400000) + putchar('^'); + putchar('\n'); +} + +void +arm_disasm_line(sec, off) + struct internal_scnhdr *sec; + unsigned off; +{ + unsigned word; + + word = get_u32(filemap + sec->data_offset + off); + printf("%08x\t", word); + if ((word >> 28) == 0xF) { + printf("\n"); + return; + } + switch ((word >> 24) & 0xF) { + case 0: + case 1: + if ((word & 0x90) == 0x90) + dataproc_74_overlay(sec, off, word); + else + dataproc(word); + return; + case 2: + case 3: + dataproc(word); + return; + case 4: + ldr_str_imm_post(word); + return; + case 5: + ldr_str_imm_pre(sec, off, word); + return; + case 6: + ldr_str_reg_post(word); + return; + case 7: + ldr_str_reg_pre(word); + return; + case 8: + case 9: + ldm_stm(word); + return; + case 0xA: + case 0xB: + arm_branch(off, word); + return; + case 0xC: + case 0xD: + case 0xE: + printf("\n"); + return; + case 0xF: + printf("swi%s\t0x%x\n", condition_decode[word>>28], + word & 0xFFFFFF); + return; + } +} + +void +arm_branch_reloc(sec, rel) + struct internal_scnhdr *sec; + struct internal_reloc *rel; +{ + unsigned word, dest; + + word = get_u32(filemap + sec->data_offset + rel->location); + printf("%08x R\t", word); + if ((word & 0x0E000000) != 0x0A000000) { + printf("\n"); + return; + } + dest = (word & 0x00FFFFFF) << 2; + if (dest & 0x02000000) + dest |= 0xFC000000; + dest += rel->location + 8; + printf("b%s%s\t", word&0x1000000 ? "l" : "", + condition_decode[word>>28]); + disasm_reloc_target(sec, rel, dest); + putchar('\n'); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/atcommon.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/atcommon.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,14 @@ +/* + * Lean and mean ARM7TDMI disassembler + * Written by Spacefalcon the Outlaw + */ + +/* a few disassembly bits common between ARM and Thumb */ + +char *regnames[16] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"}; + +char *condition_decode[16] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "", "INV"}; + +char *shift_types[4] = {"lsl", "lsr", "asr", "ror"}; diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/basics.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/basics.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,74 @@ +/* + * This C module implements some "basic" dump commands + */ + +#include +#include +#include +#include +#include "filestruct.h" +#include "intstruct.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); + +dump_filehdr_info() +{ + time_t timestamp; + struct tm *timedec; + + timestamp = get_u32(filehdr_struct->f_timdat); + timedec = gmtime(×tamp); + printf("timestamp: %d-%02d-%02dT%02d:%02d:%02dZ\n", + timedec->tm_year + 1900, timedec->tm_mon + 1, timedec->tm_mday, + timedec->tm_hour, timedec->tm_min, timedec->tm_sec); + printf("file flags: 0x%x\n", get_u16(filehdr_struct->f_flags)); + printf("%u sections, %u symtab entries\n", nsections, nsymtab); + return(0); +} + +dump_sechdr() +{ + unsigned n; + struct internal_scnhdr *inf; + + for (n = 0; n < nsections; n++) { + inf = sections + n; + printf("#%d: %s size=%u, flags=0x%x\n", n, inf->name, + inf->size, inf->flags); + printf("\t%u reloc, %u line entries\n", + inf->nreloc, inf->nlineent); + } + return(0); +} + +cmd_sechdr() +{ + get_int_section_table(); + dump_sechdr(); + exit(0); +} + +cmd_symtab() +{ + get_int_section_table(); + get_int_symbol_table(); + dump_symtab(); + exit(0); +} + +cmd_basics() +{ + printf("%s:\n", objfilename); + dump_filehdr_info(); + putchar('\n'); + get_int_section_table(); + printf("Sections:\n\n"); + dump_sechdr(); + putchar('\n'); + get_int_symbol_table(); + printf("Symbol table:\n\n"); + dump_symtab(); + putchar('\n'); + exit(0); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/coffconst.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/coffconst.h Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,37 @@ +/********************** STORAGE CLASSES **********************/ + +#define C_NULL 0 +#define C_AUTO 1 /* automatic variable */ +#define C_EXT 2 /* external symbol */ +#define C_STAT 3 /* static */ +#define C_REG 4 /* register variable */ +#define C_EXTREF 5 /* external reference */ +#define C_LABEL 6 /* label */ +#define C_ULABEL 7 /* undefined label */ +#define C_MOS 8 /* member of structure */ +#define C_ARG 9 /* function argument */ +#define C_STRTAG 10 /* structure tag */ +#define C_MOU 11 /* member of union */ +#define C_UNTAG 12 /* union tag */ +#define C_TPDEF 13 /* type definition */ +#define C_USTATIC 14 /* undefined static */ +#define C_ENTAG 15 /* enumeration tag */ +#define C_MOE 16 /* member of enumeration */ +#define C_REGPARM 17 /* register parameter */ +#define C_FIELD 18 /* bit field */ +#define C_UEXT 19 /* Tentative external definition */ +#define C_STATLAB 20 /* Static load time label */ +#define C_EXTLAB 21 /* External load time label */ +#define C_SYSTEM 23 /* System Wide variable */ +#define C_VARARG 27 /* from TI's spraao8.pdf */ +#define C_BLOCK 100 /* ".bb" or ".eb" */ +#define C_FCN 101 /* ".bf" or ".ef" */ +#define C_EOS 102 /* end of structure */ +#define C_FILE 103 /* file name */ +#define C_LINE 104 /* line # reformatted as symbol table entry */ + +/* Reloc types */ + +#define RTYPE_LONG 0x11 +#define RTYPE_THUMB_BL 0x16 +#define RTYPE_ARM_B 0x17 diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/disasm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/disasm.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,414 @@ +/* + * Putting it all together: section-, symbol- and reloc-aware disassembly + */ + +#include +#include +#include +#include +#include +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); +extern char *storage_class_to_string(); + +static int auto_xlat_section_relocs = 1; + +static void +find_better_symbol(sec, symp, addp) + struct internal_scnhdr *sec; + struct internal_syment **symp; + unsigned *addp; +{ + unsigned addr, delta; + struct internal_syment *sym; + unsigned n; + + addr = *addp; + for (n = 0; n < sec->nsymbols; n++) { + sym = sec->sorted_symbols[n]; + if (sym->value > addr) + return; + if (sym->class != C_EXT && sym->class != C_STAT) + continue; + delta = addr - sym->value; + if (sym->name[0] == '_' && !delta || + sym->name[0] == '$' && delta <= 1) { + *symp = sym; + *addp = delta; + } + } +} + +void +disasm_reloc_target(sec, rel, addend) + struct internal_scnhdr *sec; + struct internal_reloc *rel; + unsigned addend; +{ + struct internal_syment *sym = rel->sym; + + if (sym) + addend -= sym->value; + if (auto_xlat_section_relocs && + (!sym || sym->section && !strcmp(sym->name, sym->section->name))) + find_better_symbol(sym ? sym->section : sec, &sym, &addend); + if (sym) + fputs(sym->name, stdout); + else + fputs(sec->name, stdout); + if (addend >= 10) + printf("+0x%x", addend); + else if (addend) + printf("+%u", addend); +} + +void +disasm_word32_reloc(sec, rel) + struct internal_scnhdr *sec; + struct internal_reloc *rel; +{ + unsigned word; + + word = get_u32(filemap + sec->data_offset + rel->location); + printf("%08x R\t.word\t", word); + disasm_reloc_target(sec, rel, word); + putchar('\n'); +} + +void +disasm_end_of_section(sec, symnum) + struct internal_scnhdr *sec; + unsigned symnum; +{ + struct internal_syment *sym; + char *sym_comment; + + putchar('\n'); + while (symnum < sec->nsymbols) { + sym = sec->sorted_symbols[symnum]; + if (sym->value != sec->size) { + printf("error: expecting symbol at end of section\n"); + return; + } + switch (sym->class) { + case C_EXT: + sym_comment = "Global"; + break; + case C_STAT: + sym_comment = "static"; + break; + case C_LABEL: + sym_comment = "label"; + break; + default: + sym_comment = "unexpected class!"; + } + printf("%s:\t; %s\n", sym->name, sym_comment); + symnum++; + } + printf("%8x:\t\n", sec->size); +} + +void +disasm_text_section(sec) + struct internal_scnhdr *sec; +{ + unsigned symnum, relnum; + unsigned pos, incr, headroom; + int state = -1, linebrk = 0; + struct internal_syment *sym; + struct internal_reloc *rel; + char *sym_comment; + + printf("Disassembling code section:\n"); + if (sec->nsymbols) + sort_symbols_of_sec(sec); + if (sec->nreloc) + get_relocs_of_sec(sec); + symnum = relnum = 0; + for (pos = 0; pos < sec->size; pos += incr) { + headroom = sec->size - pos; + while (symnum < sec->nsymbols) { + sym = sec->sorted_symbols[symnum]; + if (sym->value > pos) { + if (sym->value - pos < headroom) + headroom = sym->value - pos; + break; + } + /* hit symbol */ + if (!linebrk) { + putchar('\n'); + linebrk = 1; + } + switch (sym->class) { + case C_EXT: + sym_comment = "Global"; + break; + case C_STAT: + sym_comment = "static"; + break; + case C_LABEL: + sym_comment = "label"; + if (!strcmp(sym->name, "$CODE16")) + state = 1; + else if (!strcmp(sym->name, "$CODE32")) + state = 0; + break; + default: + sym_comment = "unexpected class!"; + } + printf("%s:\t; %s\n", sym->name, sym_comment); + symnum++; + } + if (relnum < sec->nreloc) { + rel = sec->int_relocs + relnum; + if (rel->location == pos) + relnum++; /* it's ours */ + else { + if (rel->location - pos < headroom) + headroom = rel->location - pos; + rel = 0; /* no reloc for current pos */ + } + } else + rel = 0; + printf("%8x:\t", pos); + if (rel && rel->type == RTYPE_LONG) { + if (pos & 3) { + printf("MISALIGNED pos for word32 reloc, aborting\n"); + return; + } + disasm_word32_reloc(sec, rel); + incr = 4; + goto next; + } + if (pos & 1 || headroom < 2) { + if (rel) { + printf("error: reloc at byte pos, aborting\n"); + return; + } + printf("%02x\n", filemap[sec->data_offset + pos]); + incr = 1; + goto next; + } + switch (state) { + case 0: /* ARM */ + if (pos & 3) { + printf("MISALIGNED pos in CODE32 state, aborting\n"); + return; + } + if (rel) { + if (rel->type != RTYPE_ARM_B) { + printf("Wrong reloc type in CODE32 state, aborting\n"); + return; + } + arm_branch_reloc(sec, rel); + } else + arm_disasm_line(sec, pos); + incr = 4; + break; + case 1: /* Thumb */ + if (pos & 1) { + printf("MISALIGNED pos in CODE16 state, aborting\n"); + return; + } + if (rel) { + if (rel->type != RTYPE_THUMB_BL) { + printf("Wrong reloc type in CODE16 state, aborting\n"); + return; + } + thumb_bl_reloc(sec, rel); + incr = 4; + } else if (headroom >= 4 && thumb_check_bl(sec, pos)) + incr = 4; + else { + thumb_disasm_line(sec, pos); + incr = 2; + } + break; + default: + printf("UNKNOWN T state, aborting\n"); + return; + } +next: linebrk = 0; + if (incr > headroom) { + printf("error: increment %u > headroom %u, aborting\n", + incr, headroom); + return; + } + } + if (symnum < sec->nsymbols) + disasm_end_of_section(sec, symnum); +} + +void +disasm_data_section(sec) + struct internal_scnhdr *sec; +{ + unsigned symnum, relnum; + unsigned pos, incr, headroom; + int linebrk = 0; + struct internal_syment *sym; + struct internal_reloc *rel; + char *sym_comment; + + printf("Disassembling data section:\n"); + if (sec->nsymbols) + sort_symbols_of_sec(sec); + if (sec->nreloc) + get_relocs_of_sec(sec); + symnum = relnum = 0; + for (pos = 0; pos < sec->size; pos += incr) { + headroom = sec->size - pos; + while (symnum < sec->nsymbols) { + sym = sec->sorted_symbols[symnum]; + if (sym->value > pos) { + if (sym->value - pos < headroom) + headroom = sym->value - pos; + break; + } + /* hit symbol */ + if (!linebrk) { + putchar('\n'); + linebrk = 1; + } + switch (sym->class) { + case C_EXT: + sym_comment = "Global"; + break; + case C_STAT: + sym_comment = "static"; + break; + case C_LABEL: + sym_comment = "label"; + break; + default: + sym_comment = "unexpected class!"; + } + printf("%s:\t; %s\n", sym->name, sym_comment); + symnum++; + } + if (relnum < sec->nreloc) { + rel = sec->int_relocs + relnum; + if (rel->location == pos) + relnum++; /* it's ours */ + else { + if (rel->location - pos < headroom) + headroom = rel->location - pos; + rel = 0; /* no reloc for current pos */ + } + } else + rel = 0; + printf("%8x:\t", pos); + if (rel) { + if (rel->type != RTYPE_LONG) { + printf("error: reloc other than word32 in data section\n"); + return; + } + if (pos & 3) { + printf("MISALIGNED pos for word32 reloc, aborting\n"); + return; + } + disasm_word32_reloc(sec, rel); + incr = 4; + } else if (pos & 1 || headroom < 2) { + printf("%02x\n", filemap[sec->data_offset + pos]); + incr = 1; + } else if (pos & 2 || headroom < 4) { + printf("%04x\n", + get_u16(filemap + sec->data_offset + pos)); + incr = 2; + } else { + printf("%08x\n", + get_u32(filemap + sec->data_offset + pos)); + incr = 4; + } + linebrk = 0; + if (incr > headroom) { + printf("error: increment %u > headroom %u, aborting\n", + incr, headroom); + return; + } + } + if (symnum < sec->nsymbols) + disasm_end_of_section(sec, symnum); +} + +void +disasm_bss(sec) + struct internal_scnhdr *sec; +{ + unsigned m; + struct internal_syment *sym; + char classbuf[8]; + + putchar('\n'); + for (m = 0; m < sec->nsymbols; m++) { + sym = sec->sorted_symbols[m]; + printf("%08X %-7s %s\n", sym->value, + storage_class_to_string(sym->class, classbuf), + sym->name); + } + printf("%08X \n", sec->size); +} + +void +disasm_sec_by_type(sec) + struct internal_scnhdr *sec; +{ + switch (sec->disasm_mode) { + case DISASM_MODE_CODE: + disasm_text_section(sec); + return; + case DISASM_MODE_DATA: + disasm_data_section(sec); + return; + case DISASM_MODE_BSS: + disasm_bss(sec); + return; + default: + printf("Unrecognized section type, skipped\n"); + } +} + +cmd_disasm(argc, argv) + char **argv; +{ + extern char *optarg; + char *hintsfile = 0; + struct internal_scnhdr *sec; + unsigned secnum; + int c; + + while ((c = getopt(argc, argv, "h:s")) != EOF) + switch (c) { + case 'h': + hintsfile = optarg; + continue; + case 's': + auto_xlat_section_relocs = 0; + continue; + default: + /* error msg already printed */ + exit(1); + } + + printf("%s:\n", objfilename); + dump_filehdr_info(); + putchar('\n'); + get_int_section_table(); + get_int_symbol_table(); + if (hintsfile) + read_hints_file(hintsfile); + extern_profile_report("Module"); + sort_symbols_of_all_sec(); + for (secnum = 0; secnum < nsections; secnum++) { + sec = sections + secnum; + printf("=== %s ===\n", sec->name); + disasm_sec_by_type(sec); + putchar('\n'); + } + exit(0); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/filestruct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/filestruct.h Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,46 @@ +/* + * Here we are going to define the structures found in the COFF artifact + * file to be analyzed. + */ + +struct external_filehdr { + u_char f_magic[2]; /* magic number */ + u_char f_nscns[2]; /* number of sections */ + u_char f_timdat[4]; /* time & date stamp */ + u_char f_symptr[4]; /* file pointer to symtab */ + u_char f_nsyms[4]; /* number of symtab entries */ + u_char f_opthdr[2]; /* sizeof(optional hdr) */ + u_char f_flags[2]; /* flags */ + u_char f_target_id[2]; /* magic no. (TI COFF-specific) */ +}; + +struct external_scnhdr { + u_char s_name[8]; /* section name */ + u_char s_paddr[4]; /* physical address, aliased s_nlib */ + u_char s_vaddr[4]; /* virtual address */ + u_char s_size[4]; /* section size (in WORDS) */ + u_char s_scnptr[4]; /* file ptr to raw data for section */ + u_char s_relptr[4]; /* file ptr to relocation */ + u_char s_lnnoptr[4]; /* file ptr to line numbers */ + u_char s_nreloc[4]; /* number of relocation entries */ + u_char s_nlnno[4]; /* number of line number entries*/ + u_char s_flags[4]; /* flags */ + u_char s_reserved[2]; /* reserved */ + u_char s_page[2]; /* section page number (LOAD) */ +}; + +struct external_syment { + u_char e_name[8]; + u_char e_value[4]; + u_char e_scnum[2]; + u_char e_type[2]; + u_char e_sclass; + u_char e_numaux; +}; + +struct external_reloc { + u_char r_vaddr[4]; + u_char r_symndx[4]; + u_char r_reserved[2]; /* extended pmad byte for COFF2 */ + u_char r_type[2]; +}; diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/globals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/globals.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,19 @@ +/* + * Definitions of global vars for the tiobjd program. + */ + +#include + +char *objfilename; +u_char *filemap; +size_t objfile_tot_size; + +struct external_filehdr *filehdr_struct; +struct external_scnhdr *sections_raw; +unsigned nsections; +struct external_syment *symtab_raw; +unsigned nsymtab; +unsigned strtab_offset; + +struct internal_scnhdr *sections; +struct internal_syment **symtab; diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/globals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/globals.h Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,17 @@ +/* + * extern declarations of global vars for the tiobjd program. + */ + +extern char *objfilename; +extern u_char *filemap; +extern size_t objfile_tot_size; + +extern struct external_filehdr *filehdr_struct; +extern struct external_scnhdr *sections_raw; +extern unsigned nsections; +extern struct external_syment *symtab_raw; +extern unsigned nsymtab; +extern unsigned strtab_offset; + +extern struct internal_scnhdr *sections; +extern struct internal_syment **symtab; diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/hints.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/hints.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,131 @@ +/* + * Parsing of the disassembly hints file + */ + +#include +#include +#include +#include +#include +#include +#include "intstruct.h" +#include "globals.h" + +static char *filename_for_err; +static int lineno; +static struct internal_scnhdr *section; +static struct hint *lasthint; + +static void +set_section(name) + char *name; +{ + unsigned n; + struct internal_scnhdr *sec = 0; + + for (n = 0; n < nsections; n++) + if (!strcmp(sections[n].name, name)) { + sec = sections + n; + break; + } + if (!sec) { + fprintf(stderr, "%s line %d: no section named \"%s\" in %s\n", + filename_for_err, lineno, name, objfilename); + exit(1); + } + if (sec->hints) { + fprintf(stderr, "%s line %d: [%s] given more than once\n", + filename_for_err, lineno, name); + exit(1); + } + section = sec; + lasthint = 0; +} + +static void +set_mode(arg) + char *arg; +{ + char *cp; + + if (!section) { + fprintf(stderr, + "%s line %d: error: mode line outside of section\n", + filename_for_err, lineno); + exit(1); + } + while (isspace(*arg)) + arg++; + if (!*arg) { + fprintf(stderr, "%s line %d: mode line: missing argument\n", + filename_for_err, lineno); + exit(1); + } + for (cp = arg; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(arg, "code")) + section->disasm_mode = DISASM_MODE_CODE; + else if (!strcmp(arg, "data")) + section->disasm_mode = DISASM_MODE_DATA; + else if (!strcmp(arg, "bss")) + section->disasm_mode = DISASM_MODE_BSS; + else { + fprintf(stderr, "%s line %d: unknown mode \"%s\"\n", + filename_for_err, lineno, arg); + exit(1); + } +} + +static void +regular_hint(arg1, arg2) + char *arg1, *arg2; +{ + fprintf(stderr, "error: regular hints not implemented yet\n"); + exit(1); +} + +read_hints_file(filename) + char *filename; +{ + FILE *f; + char linebuf[128], *cp, *np; + + f = fopen(filename, "r"); + if (!f) { + perror(filename); + exit(1); + } + filename_for_err = filename; + for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) { + for (cp = linebuf; isspace(*cp); cp++) + ; + if (!*cp || *cp == '#') + continue; + if (*cp == '[') { + np = ++cp; + cp = index(cp, ']'); + if (!cp) { + fprintf(stderr, + "%s line %d: invalid section syntax\n", + filename, lineno); + exit(1); + } + *cp = '\0'; + set_section(np); + continue; + } + for (np = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + if (!strcmp(np, "mode")) { + set_mode(cp); + continue; + } + regular_hint(np, cp); + } + fclose(f); + return(0); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/intstruct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/intstruct.h Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,56 @@ +/* + * The structures defined in this header file + * are internal to our utility. + */ + +struct internal_scnhdr { + char *name; + unsigned size; + unsigned data_offset; + unsigned reloc_offset; + unsigned line_offset; + unsigned nreloc; + unsigned nlineent; + unsigned flags; + unsigned nsymbols; + struct internal_syment **sorted_symbols; + struct internal_reloc *int_relocs; + int disasm_mode; + struct hint *hints; +}; + +#define DISASM_MODE_UNKNOWN 0 +#define DISASM_MODE_CODE 1 +#define DISASM_MODE_DATA 2 +#define DISASM_MODE_BSS 3 + +struct internal_syment { + unsigned number; + char *name; + unsigned value; + int scnum; + int type; + int class; + u_char *aux; + struct internal_scnhdr *section; +}; + +struct internal_reloc { + unsigned location; + struct internal_syment *sym; + int type; + char *typestr; +}; + +struct hint { + unsigned pos; + int type; + unsigned nitems; + int linebrk; + struct hint *next; +}; + +#define HINT_D8 1 +#define HINT_D16 2 +#define HINT_ASCIZ 3 +#define HINT_D32 4 diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/lowlevel.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/lowlevel.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,94 @@ +/* + * This C module implements the low-level steps of TI COFF image analysis. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "filestruct.h" +#include "globals.h" + +mmap_objfile() +{ + int fd; + struct stat st; + + fd = open(objfilename, O_RDONLY); + if (fd < 0) { + perror(objfilename); + exit(1); + } + fstat(fd, &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "error: %s is not a regular file\n", + objfilename); + exit(1); + } + objfile_tot_size = st.st_size; + filemap = mmap(NULL, objfile_tot_size, PROT_READ, MAP_PRIVATE, fd, 0L); + if (filemap == MAP_FAILED) { + perror("mmap"); + exit(1); + } + close(fd); +} + +unsigned +get_u16(ptr) + u_char *ptr; +{ + return ptr[0] | ptr[1] << 8; +} + +get_s16(ptr) + u_char *ptr; +{ + int i; + + i = ptr[0] | ptr[1] << 8; + if (i >= 32768) + i -= 65536; + return(i); +} + +unsigned +get_u32(ptr) + u_char *ptr; +{ + return ptr[0] | ptr[1] << 8 | ptr[2] << 16 | ptr[3] << 24; +} + +initial_parse_hdr() +{ + unsigned symtab_offset; + + filehdr_struct = (struct external_filehdr *) filemap; + if (get_u16(filehdr_struct->f_magic) != 0xC2) { + fprintf(stderr, "error: %s is not a TI COFF2 object\n", + objfilename); + exit(1); + } + if (get_u16(filehdr_struct->f_target_id) != 0x97) { + fprintf(stderr, "error: TI COFF object %s is not for TMS470\n", + objfilename); + exit(1); + } + if (get_u16(filehdr_struct->f_opthdr)) { + fprintf(stderr, + "error: %s has the \"optional\" header present\n", + objfilename); + exit(1); + } + sections_raw = (struct external_scnhdr *) + (filemap + sizeof(struct external_filehdr)); + nsections = get_u16(filehdr_struct->f_nscns); + symtab_offset = get_u32(filehdr_struct->f_symptr); + symtab_raw = (struct external_syment *)(filemap + symtab_offset); + nsymtab = get_u32(filehdr_struct->f_nsyms); + strtab_offset = symtab_offset + + sizeof(struct external_syment) * nsymtab; +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/main.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,60 @@ +/* + * tiobjd main() function and command dispatch + */ + +#include +#include +#include +#include +#include +#include "globals.h" + +extern int cmd_basics(); +extern int cmd_disasm(); +extern int cmd_nm(); +extern int cmd_profile(); +extern int cmd_rawrel(); +extern int cmd_reloc(); +extern int cmd_sechdr(); +extern int cmd_symtab(); +extern int dump_filehdr_info(); + +static struct cmdtab { + char *cmd; + int (*func)(); +} cmdtab[] = { + {"basics", cmd_basics}, + {"disasm", cmd_disasm}, + {"dumpsym", cmd_symtab}, /* backward compat */ + {"hdr", dump_filehdr_info}, + {"nm", cmd_nm}, + {"profile", cmd_profile}, + {"rawrel", cmd_rawrel}, + {"reloc", cmd_reloc}, + {"sechdr", cmd_sechdr}, + {"symtab", cmd_symtab}, + {0, 0} +}; + +main(argc, argv) + char **argv; +{ + struct cmdtab *tp; + + if (argc < 3) { + fprintf(stderr, "usage: %s [args]\n", argv[0]); + exit(1); + } + objfilename = argv[1]; + mmap_objfile(); + initial_parse_hdr(); + for (tp = cmdtab; tp->cmd; tp++) + if (!strcmp(tp->cmd, argv[2])) + break; + if (!tp->func) { + fprintf(stderr, "\"%s\": unknown or unimplemented command\n", + argv[2]); + exit(1); + } + return tp->func(argc - 2, argv + 2); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/profile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/profile.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,158 @@ +/* + * It is handy to have a "profile" of what functions and variables + * a given module defines (presents to the rest of the fw) and what + * it references. This profile is constructed from the symbol table. + * + * Experience indicates that the order of these symbols in the + * artifact symtab is often "random", and an alphabetic sort is + * expected to improve readability. This module contains the + * messy code. + */ + +#include +#include +#include +#include +#include +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +static int +is_symbol_text_def(sym) + struct internal_syment *sym; +{ + if (!sym->section) + return(0); + if (!strncmp(sym->section->name, ".text", 5)) + return(1); + else + return(0); +} + +static int +is_symbol_nontext_def(sym) + struct internal_syment *sym; +{ + if (!sym->section) + return(0); + if (!strncmp(sym->section->name, ".text", 5)) + return(0); + else + return(1); +} + +static int +is_symbol_extref(sym) + struct internal_syment *sym; +{ + if (sym->section) + return(0); + else + return(1); +} + +static int +compare_for_sort(p1, p2) + struct internal_syment **p1, **p2; +{ + return strcmp((*p1)->name, (*p2)->name); +} + +static void +list_class(firstidx, lastidx, total, checkfunc, printsec) + unsigned firstidx, lastidx, total; + int (*checkfunc)(); +{ + struct internal_syment **array, *sym; + unsigned n, m; + + array = malloc(sizeof(void *) * total); + if (!array) { + perror("malloc"); + exit(1); + } + m = 0; + for (n = firstidx; n <= lastidx; n++) { + sym = symtab[n]; + if (!sym) + continue; + if (sym->class != C_EXT) + continue; + if (!checkfunc(sym)) + continue; + array[m++] = sym; + } + if (m != total) { + fprintf(stderr, "BUG: symbol class miscount in profile gen\n"); + exit(1); + } + qsort(array, total, sizeof(void *), compare_for_sort); + for (n = 0; n < total; n++) { + sym = array[n]; + if (printsec) + printf("%s (%s)\n", sym->name, sym->section->name); + else + printf("%s\n", sym->name); + } + free(array); + putchar('\n'); +} + +extern_profile_report(heading) + char *heading; +{ + unsigned n; + int first_extern = -1, last_extern; + struct internal_syment *sym; + unsigned defs_text = 0, defs_nontext = 0, extrefs = 0; + + for (n = 0; n < nsymtab; n++) { + sym = symtab[n]; + if (!sym) + continue; + if (sym->class != C_EXT) + continue; + if (first_extern < 0) + first_extern = n; + last_extern = n; + if (sym->scnum < 0) { + fprintf(stderr, + "symbol entry #%u: unexpected negative scnum for C_EXT\n", n); + exit(1); + } + if (sym->scnum == 0) + extrefs++; + else if (!strncmp(sym->section->name, ".text", 5)) + defs_text++; + else + defs_nontext++; + } + if (first_extern < 0) { + printf("%s has no external symbols!\n", heading); + return(1); + } + if (defs_text || defs_nontext) { + printf("%s defines:\n\n", heading); + if (defs_text) + list_class(first_extern, last_extern, defs_text, + is_symbol_text_def, 1); + if (defs_nontext) + list_class(first_extern, last_extern, defs_nontext, + is_symbol_nontext_def, 1); + } + if (extrefs) { + printf("%s references:\n\n", heading); + list_class(first_extern, last_extern, extrefs, + is_symbol_extref, 0); + } + return(0); +} + +cmd_profile() +{ + get_int_section_table(); + get_int_symbol_table(); + extern_profile_report(objfilename); + exit(0); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/reloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/reloc.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,164 @@ +/* + * Handling of relocation records + */ + +#include +#include +#include +#include "filestruct.h" +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); + +cmd_rawrel() +{ + unsigned n, m; + struct internal_scnhdr *sec; + struct external_reloc *rel; + + get_int_section_table(); + for (n = 0; n < nsections; n++) { + sec = sections + n; + if (!sec->nreloc) + continue; + printf("%s:\n\n", sec->name); + rel = (struct external_reloc *)(filemap + sec->reloc_offset); + printf("Location SymIndex Rsvd Type\n"); + for (m = 0; m < sec->nreloc; m++, rel++) + printf("%08X %08X %04X %04X\n", + get_u32(rel->r_vaddr), get_u32(rel->r_symndx), + get_u16(rel->r_reserved), get_u16(rel->r_type)); + putchar('\n'); + } + exit(0); +} + +void +get_relocs_of_sec(sec) + struct internal_scnhdr *sec; +{ + unsigned n; + struct external_reloc *extrel; + struct internal_reloc *intrel; + unsigned lastloc, symidx; + + if (sec->int_relocs) + return; + if (!sec->nreloc) { + fprintf(stderr, + "BUG: get_relocs_of_sec() called for section \"%s\" w/o relocs\n", + sec->name); + exit(1); + } + intrel = malloc(sizeof(struct internal_reloc) * sec->nreloc); + if (!intrel) { + perror("malloc"); + exit(1); + } + sec->int_relocs = intrel; + extrel = (struct external_reloc *)(filemap + sec->reloc_offset); + for (n = 0; n < sec->nreloc; n++, extrel++, intrel++) { + intrel->location = get_u32(extrel->r_vaddr); + if (n && intrel->location <= lastloc) { + fprintf(stderr, + "error: non-increasing reloc order in section \"%s\"\n", + sec->name); + exit(1); + } + lastloc = intrel->location; + symidx = get_u32(extrel->r_symndx); + if (symidx == 0xFFFFFFFF) + intrel->sym = 0; + else if (symidx >= nsymtab || !symtab[symidx]) { + fprintf(stderr, + "error: reloc references invalid symbol #%u in section \"%s\"\n", + symidx, sec->name); + exit(1); + } else + intrel->sym = symtab[symidx]; + intrel->type = get_u16(extrel->r_type); + switch (intrel->type) { + case RTYPE_LONG: + intrel->typestr = "Word32"; + break; + case RTYPE_THUMB_BL: + intrel->typestr = "Thumb_BL"; + break; + case RTYPE_ARM_B: + intrel->typestr = "ARM_B"; + break; + default: + fprintf(stderr, + "error: reloc in section \"%s\" of unexpected type 0x%x\n", + sec->name, intrel->type); + exit(1); + } + if (get_u16(extrel->r_reserved)) + fprintf(stderr, + "warning: reloc in section \"%s\" has non-zero reserved field\n", + sec->name); + } +} + +cmd_reloc() +{ + unsigned n, m; + struct internal_scnhdr *sec; + struct internal_reloc *rel; + char *symname; + + get_int_section_table(); + get_int_symbol_table(); + for (n = 0; n < nsections; n++) { + sec = sections + n; + if (!sec->nreloc) + continue; + printf("%s:\n\n", sec->name); + get_relocs_of_sec(sec); + rel = sec->int_relocs; + printf("Location Type Symbol relative to\n"); + for (m = 0; m < sec->nreloc; m++, rel++) { + if (rel->sym) + symname = rel->sym->name; + else + symname = ""; + printf("%08X %-8s %s\n", rel->location, rel->typestr, + symname); + } + putchar('\n'); + } + exit(0); +} + +struct internal_reloc * +find_reloc(sec, loc) + struct internal_scnhdr *sec; + unsigned loc; +{ + struct internal_reloc *rel; + unsigned m; + + rel = sec->int_relocs; + for (m = 0; m < sec->nreloc; m++, rel++) { + if (rel->location == loc) + return(rel); + if (rel->location > loc) + return(0); + } + return(0); +} + +struct internal_reloc * +find_word32_reloc(sec, loc) + struct internal_scnhdr *sec; + unsigned loc; +{ + struct internal_reloc *rel; + + rel = find_reloc(sec, loc); + if (rel && rel->type != RTYPE_LONG) + rel = 0; + return(rel); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/symtab.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/symtab.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,185 @@ +/* + * Code for working with the symbol table + */ + +#include +#include +#include +#include "filestruct.h" +#include "intstruct.h" +#include "coffconst.h" +#include "globals.h" + +static struct classmap { + int code; + char *str; +} classtab[] = { + {C_NULL, "NULL"}, + {C_AUTO, "AUTO"}, + {C_EXT, "EXT"}, + {C_STAT, "STAT"}, + {C_REG, "REG"}, + {C_EXTREF, "EXTREF"}, + {C_LABEL, "LABEL"}, + {C_ULABEL, "ULABEL"}, + {C_MOS, "MOS"}, + {C_ARG, "ARG"}, + {C_STRTAG, "STRTAG"}, + {C_MOU, "MOU"}, + {C_UNTAG, "UNTAG"}, + {C_TPDEF, "TPDEF"}, + {C_USTATIC, "USTATIC"}, + {C_ENTAG, "ENTAG"}, + {C_MOE, "MOE"}, + {C_REGPARM, "REGPARM"}, + {C_FIELD, "FIELD"}, + {C_UEXT, "UEXT"}, + {C_STATLAB, "STATLAB"}, + {C_EXTLAB, "EXTLAB"}, + {C_SYSTEM, "SYSTEM"}, + {C_VARARG, "VARARG"}, + {C_BLOCK, "BLOCK"}, + {C_FCN, "FCN"}, + {C_EOS, "EOS"}, + {C_FILE, "FILE"}, + {C_LINE, "LINE"}, + {0, 0} +}; + +char * +storage_class_to_string(code, numbuf) + char *numbuf; +{ + struct classmap *tp; + + for (tp = classtab; tp->str; tp++) + if (tp->code == code) + return(tp->str); + sprintf(numbuf, "%d", code); + return(numbuf); +} + +dump_symtab() +{ + unsigned n; + struct internal_syment *sym; + char *sec, secstr[8]; + char *class, classbuf[8]; + + printf("%-5s %-30s %-4s %-7s %-12s %-8s\n", + "Num", "Name", "Type", "Class", "Section", "Value"); + for (n = 0; n < nsymtab; n++) { + sym = symtab[n]; + if (!sym) + continue; + if (sym->section) + sec = sym->section->name; + else { + sprintf(secstr, "%d", sym->scnum); + sec = secstr; + } + class = storage_class_to_string(sym->class, classbuf); + printf("%-5u %-30s %04X %-7s %-12s %08X%s\n", + n, sym->name, sym->type, class, + sec, sym->value, sym->aux ? " Aux" : ""); + } + return(0); +} + +static void +initial_fill_for_sort(sec) + struct internal_scnhdr *sec; +{ + unsigned n, m; + struct internal_syment *sym; + + m = 0; + for (n = 0; n < nsymtab; n++) { + sym = symtab[n]; + if (!sym) + continue; + if (sym->section != sec) + continue; + sec->sorted_symbols[m++] = sym; + } +} + +static int +compare_for_sort(p1, p2) + struct internal_syment **p1, **p2; +{ + /* sort by value first */ + if ((*p1)->value < (*p2)->value) + return(-1); + if ((*p1)->value > (*p2)->value) + return(1); + /* if same value, retain the original symtab order */ + if ((*p1)->number < (*p2)->number) + return(-1); + if ((*p1)->number > (*p2)->number) + return(1); + else + return(0); +} + +void +sort_symbols_of_sec(sec) + struct internal_scnhdr *sec; +{ + if (sec->sorted_symbols) + return; + if (!sec->nsymbols) { + fprintf(stderr, + "BUG: sort_symbols_of_sec() called for section \"%s\" w/o symbols\n", + sec->name); + exit(1); + } + sec->sorted_symbols = malloc(sizeof(void *) * sec->nsymbols); + if (!sec->sorted_symbols) { + perror("malloc"); + exit(1); + } + initial_fill_for_sort(sec); + qsort(sec->sorted_symbols, sec->nsymbols, sizeof(void *), + compare_for_sort); +} + +void +sort_symbols_of_all_sec() +{ + unsigned n; + struct internal_scnhdr *sec; + + for (n = 0; n < nsections; n++) { + sec = sections + n; + if (!sec->nsymbols) + continue; + sort_symbols_of_sec(sec); + } +} + +cmd_nm() +{ + unsigned n, m; + struct internal_scnhdr *sec; + struct internal_syment *sym; + char classbuf[8]; + + get_int_section_table(); + get_int_symbol_table(); + for (n = 0; n < nsections; n++) { + sec = sections + n; + if (!sec->nsymbols) + continue; + printf("%s:\n\n", sec->name); + sort_symbols_of_sec(sec); + for (m = 0; m < sec->nsymbols; m++) { + sym = sec->sorted_symbols[m]; + printf("%08X %-7s %s\n", sym->value, + storage_class_to_string(sym->class, classbuf), + sym->name); + } + putchar('\n'); + } + exit(0); +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/tables.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/tables.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,155 @@ +/* + * This C module will contain functions for the initial parsing + * of the section and symbol tables. + */ + +#include +#include +#include +#include +#include +#include "filestruct.h" +#include "intstruct.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); + +static char * +get_secorsym_name(ptr) + u_char *ptr; +{ + char *alloc; + + if (ptr[0]) { + if (ptr[7]) { + alloc = malloc(9); + if (!alloc) { + perror("malloc"); + exit(1); + } + bcopy(ptr, alloc, 8); + alloc[8] = '\0'; + return(alloc); + } else + return((char *) ptr); + } + if (ptr[1] || ptr[2] || ptr[3]) { + fprintf(stderr, "error: malformed name in %s at offset 0x%x\n", + objfilename, ptr - filemap); + exit(1); + } + return(filemap + strtab_offset + get_u32(ptr+4)); +} + +get_int_section_table() +{ + unsigned n; + + sections = malloc(sizeof(struct internal_scnhdr) * nsections); + if (!sections) { + perror("malloc"); + exit(1); + } + for (n = 0; n < nsections; n++) { + sections[n].name = get_secorsym_name(sections_raw[n].s_name); + if (get_u32(sections_raw[n].s_paddr)) + fprintf(stderr, + "warning: section #%u (%s) has nonzero paddr\n", + n, sections[n].name); + if (get_u32(sections_raw[n].s_vaddr)) + fprintf(stderr, + "warning: section #%u (%s) has nonzero vaddr\n", + n, sections[n].name); + sections[n].size = get_u32(sections_raw[n].s_size); + sections[n].data_offset = get_u32(sections_raw[n].s_scnptr); + sections[n].reloc_offset = get_u32(sections_raw[n].s_relptr); + sections[n].line_offset = get_u32(sections_raw[n].s_lnnoptr); + sections[n].nreloc = get_u32(sections_raw[n].s_nreloc); + sections[n].nlineent = get_u32(sections_raw[n].s_nlnno); + sections[n].flags = get_u32(sections_raw[n].s_flags); + if (get_u16(sections_raw[n].s_reserved)) + fprintf(stderr, + "warning: section #%u (%s): some nonzero value in s_reserved bytes\n", + n, sections[n].name); + if (get_u16(sections_raw[n].s_page)) + fprintf(stderr, + "warning: section #%u (%s): some nonzero value in s_page bytes\n", + n, sections[n].name); + sections[n].nsymbols = 0; + sections[n].sorted_symbols = 0; + sections[n].int_relocs = 0; + if (!strncmp(sections[n].name, ".text", 5)) + sections[n].disasm_mode = DISASM_MODE_CODE; + else if (!strcmp(sections[n].name, ".const")) + sections[n].disasm_mode = DISASM_MODE_DATA; + else if (!strcmp(sections[n].name, ".cinit")) + sections[n].disasm_mode = DISASM_MODE_DATA; + else if (!strcmp(sections[n].name, ".data")) + sections[n].disasm_mode = DISASM_MODE_DATA; + else if (!strcmp(sections[n].name, ".bss")) + sections[n].disasm_mode = DISASM_MODE_BSS; + else + sections[n].disasm_mode = DISASM_MODE_UNKNOWN; + sections[n].hints = 0; + } +} + +get_int_symbol_table() +{ + unsigned n; + struct internal_syment *in; + + symtab = malloc(sizeof(struct internal_syment *) * nsymtab); + if (!symtab) { + perror("malloc"); + exit(1); + } + for (n = 0; n < nsymtab; ) { + in = malloc(sizeof(struct internal_syment)); + if (!in) { + perror("malloc"); + exit(1); + } + symtab[n] = in; + in->number = n; + in->name = get_secorsym_name(symtab_raw[n].e_name); + in->value = get_u32(symtab_raw[n].e_value); + in->scnum = get_s16(symtab_raw[n].e_scnum); + if (in->scnum > 0) { + if (in->scnum > nsections) { + fprintf(stderr, + "symtab entry #%u: scnum too big\n", n); + exit(1); + } + in->section = sections + in->scnum - 1; + in->section->nsymbols++; + } else if (in->scnum < -2) { + fprintf(stderr, + "symtab entry #%u: scnum < -2\n", n); + exit(1); + } else + in->section = 0; + in->type = get_u16(symtab_raw[n].e_type); + in->class = symtab_raw[n].e_sclass; + switch (symtab_raw[n++].e_numaux) { + case 0: + in->aux = 0; + continue; + case 1: + if (n >= nsymtab) { + fprintf(stderr, + "error: last symbol's aux spills over\n"); + exit(1); + } + symtab[n] = 0; + in->aux = (u_char *)(symtab_raw + n); + n++; + continue; + default: + n--; + fprintf(stderr, "symtab entry #%u: invalid numaux\n", + n); + exit(1); + } + } +} diff -r 597143ba1c37 -r 87b82398a08b leo-obj/tool/thumbdis.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/leo-obj/tool/thumbdis.c Sun Apr 06 22:14:39 2014 +0000 @@ -0,0 +1,436 @@ +/* + * Thumb state disassembly + */ + +#include +#include +#include +#include +#include +#include "intstruct.h" +#include "globals.h" + +extern unsigned get_u16(), get_u32(); +extern struct internal_reloc *find_word32_reloc(); + +extern char *regnames[16], *condition_decode[16], *shift_types[4]; + +static void +format_1_2(word) + unsigned word; +{ + unsigned op, imm; + + op = (word >> 11) & 3; + if (op != 3) { + /* format 1 */ + imm = (word >> 6) & 0x1F; + if (op != 0 && imm == 0) + imm = 32; + printf("%s\t%s, %s, #%u\n", shift_types[op], regnames[word&7], + regnames[(word>>3)&7], imm); + return; + } + /* format 2 */ + printf("%s\t%s, %s, ", word&0x200 ? "sub" : "add", regnames[word&7], + regnames[(word>>3)&7]); + if (word & 0x400) + printf("#%u\n", (word >> 6) & 7); + else + printf("%s\n", regnames[(word >> 6) & 7]); +} + +static void +format_3(word) + unsigned word; +{ + static char *opctab[4] = {"mov", "cmp", "add", "sub"}; + unsigned imm; + + imm = word & 0xFF; + printf("%s\t%s, #%u", opctab[(word>>11)&3], regnames[(word>>8)&7], imm); + if (imm > 9) + printf("\t; 0x%x", imm); + putchar('\n'); +} + +static void +format_4(word) + unsigned word; +{ + static char *opc[16] = {"and", "eor", "lsl", "lsr", + "asr", "adc", "sbc", "ror", + "tst", "neg", "cmp", "cmn", + "orr", "mul", "bic", "mvn"}; + + printf("%s\t%s, %s\n", opc[(word>>6)&0xF], regnames[word&7], + regnames[(word>>3)&7]); +} + +static void +format_5_bx(word) + unsigned word; +{ + if (word & 0x80) + printf("\n"); + else + printf("bx\t%s\n", regnames[(word>>3)&0xF]); +} + +static void +format_5_hiops(word) + unsigned word; +{ + static char *opctab[3] = {"add", "cmp", "mov"}; + int reg1, reg2, op; + + if (word & 0xC0) { + reg1 = word & 7; + if (word & 0x80) + reg1 += 8; + reg2 = (word >> 3) & 0xF; + op = (word >> 8) & 3; + if (op == 2 && reg1 == reg2 && reg1 != 15) + printf("nop\t\t\t(mov %s, %s)\n", + regnames[reg1], regnames[reg2]); + else + printf("%s\t%s, %s\n", opctab[op], + regnames[reg1], regnames[reg2]); + } else + printf("\n"); +} + +static void +format_5(word) + unsigned word; +{ + if ((word & 0x300) == 0x300) + format_5_bx(word); + else + format_5_hiops(word); +} + +static void +format_6(sec, off, word) + struct internal_scnhdr *sec; + unsigned off, word; +{ + unsigned loff, litoff, datum; + struct internal_reloc *rel; + + loff = (word & 0xFF) << 2; + off &= ~3; + off += 4; + litoff = off + loff; + if (litoff+4 <= sec->size) { + rel = find_word32_reloc(sec, litoff); + datum = get_u32(filemap + sec->data_offset + litoff); + printf("ldr\t%s, =", regnames[(word>>8)&7]); + if (rel) + disasm_reloc_target(sec, rel, datum); + else + printf("0x%x", datum); + printf("\t; via 0x%x\n", litoff); + } else + printf("ldr\t%s, [pc, #%u]\t(0x%x)\n", regnames[(word>>8)&7], + loff, litoff); +} + +static void +format_7(word) + unsigned word; +{ + printf("%s%s\t%s, [%s, %s]\n", word&0x800 ? "ldr" : "str", + word&0x400 ? "b" : "", regnames[word&7], + regnames[(word>>3)&7], regnames[(word>>6)&7]); +} + +static void +format_8(word) + unsigned word; +{ + static char *opc[4] = {"strh", "ldrsb", "ldrh", "ldrsh"}; + + printf("%s\t%s, [%s, %s]\n", opc[(word>>10)&3], regnames[word&7], + regnames[(word>>3)&7], regnames[(word>>6)&7]); +} + +static void +format_9(word) + unsigned word; +{ + unsigned loff; + + loff = (word >> 6) & 0x1F; + if (!(word & 0x1000)) + loff <<= 2; + printf("%s%s\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", + word&0x1000 ? "b" : "", regnames[word&7], + regnames[(word>>3)&7], loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +format_10(word) + unsigned word; +{ + unsigned loff; + + loff = (word >> 6) & 0x1F; + loff <<= 1; + printf("%sh\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", + regnames[word&7], regnames[(word>>3)&7], loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +format_11(word) + unsigned word; +{ + unsigned loff; + + loff = (word & 0xFF) << 2; + printf("%s\t%s, [sp, #%u]", word&0x800 ? "ldr" : "str", + regnames[(word>>8)&7], loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +format_12(off, word) + unsigned off, word; +{ + unsigned loff; + + loff = (word & 0xFF) << 2; + printf("add\t%s, ", regnames[(word>>8)&7]); + if (word & 0x800) { + printf("sp, #%u", loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); + } else { + off &= ~3; + printf("pc, #%u\t; 0x%x\n", loff, off + 4 + loff); + } +} + +static void +format_13(word) + unsigned word; +{ + unsigned loff; + + if ((word & 0xFF00) != 0xB000) { + printf("\n"); + return; + } + loff = (word & 0x7F) << 2; + printf("%s\tsp, #%u", word&0x80 ? "sub" : "add", loff); + if (loff >= 10) + printf("\t; 0x%x", loff); + putchar('\n'); +} + +static void +format_14(word) + unsigned word; +{ + int r, flag; + + if ((word & 0xF600) != 0xB400) { + printf("\n"); + return; + } + printf("%s\t{", word&0x800 ? "pop" : "push"); + flag = 0; + for (r = 0; r < 9; r++) + if (word & (1 << r)) { + if (flag) + fputs(", ", stdout); + if (r == 8) + fputs(word&0x800 ? "pc" : "lr", stdout); + else + fputs(regnames[r], stdout); + flag = 1; + } + putchar('}'); + putchar('\n'); +} + +static void +format_15(word) + unsigned word; +{ + int r, flag; + + printf("%sia\t%s!, {", word&0x800 ? "ldm" : "stm", + regnames[(word>>8)&7]); + flag = 0; + for (r = 0; r < 8; r++) + if (word & (1 << r)) { + if (flag) + fputs(", ", stdout); + fputs(regnames[r], stdout); + flag = 1; + } + putchar('}'); + putchar('\n'); +} + +static void +format_16_17(off, word) + unsigned off, word; +{ + unsigned cond; + unsigned dest; + + cond = (word >> 8) & 0xF; + switch (cond) { + case 0xE: + printf("\n"); + return; + case 0xF: + printf("swi\t0x%x\n", word & 0xFF); + return; + } + dest = (word & 0xFF) << 1; + if (dest & 0x00000100) + dest |= 0xFFFFFE00; + dest += off + 4; + printf("b%s\t0x%x\n", condition_decode[cond], dest); +} + +static void +format_18(off, word) + unsigned off, word; +{ + unsigned dest; + + if (word & 0x800) { + printf("\n"); + return; + } + dest = (word & 0x7FF) << 1; + if (dest & 0x00000800) + dest |= 0xFFFFF000; + dest += off + 4; + printf("b\t0x%x\n", dest); +} + +void +thumb_disasm_line(sec, off) + struct internal_scnhdr *sec; + unsigned off; +{ + unsigned word; + + word = get_u16(filemap + sec->data_offset + off); + printf("%04x\t\t", word); + switch (word >> 12) { + case 0: + case 1: + format_1_2(word); + return; + case 2: + case 3: + format_3(word); + return; + case 4: + if (word & 0x800) + format_6(sec, off, word); + else if (word & 0x400) + format_5(word); + else + format_4(word); + return; + case 5: + if (word & 0x200) + format_8(word); + else + format_7(word); + return; + case 6: + case 7: + format_9(word); + return; + case 8: + format_10(word); + return; + case 9: + format_11(word); + return; + case 0xA: + format_12(off, word); + return; + case 0xB: + if (word & 0x400) + format_14(word); + else + format_13(word); + return; + case 0xC: + format_15(word); + return; + case 0xD: + format_16_17(off, word); + return; + case 0xE: + format_18(off, word); + return; + case 0xF: + printf("\n"); + return; + } +} + +thumb_check_bl(sec, off) + struct internal_scnhdr *sec; + unsigned off; +{ + unsigned ins1, ins2; + unsigned dest; + + ins1 = get_u16(filemap + sec->data_offset + off); + if ((ins1 & 0xF800) != 0xF000) + return(0); + ins2 = get_u16(filemap + sec->data_offset + off + 2); + if ((ins2 & 0xF800) != 0xF800) + return(0); + /* match */ + dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); + if (dest & 0x00400000) + dest |= 0xFF800000; + dest += off + 4; + printf("%04x %04x\tbl\t0x%x\n", ins1, ins2, dest); + return(1); +} + +void +thumb_bl_reloc(sec, rel) + struct internal_scnhdr *sec; + struct internal_reloc *rel; +{ + unsigned ins1, ins2; + unsigned dest; + + ins1 = get_u16(filemap + sec->data_offset + rel->location); + ins2 = get_u16(filemap + sec->data_offset + rel->location + 2); + printf("%04x %04x R\t", ins1, ins2); + if ((ins1 & 0xF800) != 0xF000 || (ins2 & 0xF800) != 0xF800) { + printf("\n"); + return; + } + dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); + if (dest & 0x00400000) + dest |= 0xFF800000; + dest += rel->location + 4; + fputs("bl\t", stdout); + disasm_reloc_target(sec, rel, dest); + putchar('\n'); +} diff -r 597143ba1c37 -r 87b82398a08b ticoff/Makefile --- a/ticoff/Makefile Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -CC= gcc -CFLAGS= -O2 -PROG= tiobjd -OBJS= armdis.o atcommon.o basics.o disasm.o globals.o hints.o lowlevel.o \ - main.o profile.o reloc.o symtab.o tables.o thumbdis.o -HDRS= coffconst.h filestruct.h globals.h intstruct.h - -all: ${PROG} - -${PROG}: ${OBJS} - ${CC} -o $@ ${OBJS} - -${OBJS}: ${HDRS} - -install: - install -c -o bin -g bin -m 755 ${PROG} /usr/local/bin - -clean: - rm -f *.o ${PROG} *err diff -r 597143ba1c37 -r 87b82398a08b ticoff/README --- a/ticoff/README Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Here I'm going to build a standalone tool that reads linkable (not final) -object modules produced by TI's TMS470 toolchain, as found in GSM firmware -semi-sources, and produces disassembly listings that are well-fit for -understanding the function and interfaces of each object blob, and ultimately -replacing each of these blobs with functionally and interface-equivalent -new C code. diff -r 597143ba1c37 -r 87b82398a08b ticoff/armdis.c --- a/ticoff/armdis.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,522 +0,0 @@ -/* - * ARM state disassembly - */ - -#include -#include -#include -#include -#include -#include "intstruct.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); -extern struct internal_reloc *find_word32_reloc(); - -extern char *regnames[16], *condition_decode[16], *shift_types[4]; - -static char *dataproc_ops[16] = {"and", "eor", "sub", "rsb", - "add", "adc", "sbc", "rsc", - "tst", "teq", "cmp", "cmn", - "orr", "mov", "bic", "mvn"}; - -static void -arm_branch(off, word) - unsigned off, word; -{ - unsigned dest; - - dest = (word & 0x00FFFFFF) << 2; - if (dest & 0x02000000) - dest |= 0xFC000000; - dest += off + 8; - printf("b%s%s\t0x%x\n", word&0x1000000 ? "l" : "", - condition_decode[word>>28], dest); -} - -static void -op2_immed(word) - unsigned word; -{ - unsigned low8, rot, val; - - low8 = word & 0xFF; - rot = (word & 0xF00) >> 7; - val = (low8 << (32 - rot)) | (low8 >> rot); - if (val <= 9) - printf("#%u\n", val); - else - printf("#%u\t; 0x%x\n", val, val); -} - -static void -op2_regbyconst(word) - unsigned word; -{ - unsigned c, t; - - c = (word >> 7) & 0x1F; - t = (word >> 5) & 3; - if (!c) { - switch (t) { - case 0: - printf("%s", regnames[word&0xF]); - return; - case 3: - printf("%s, rrx", regnames[word&0xF]); - return; - default: - c = 32; - } - } - printf("%s, %s #%u", regnames[word&0xF], shift_types[t], c); -} - -static void -op2_regbyreg(word) - unsigned word; -{ - printf("%s, %s %s", regnames[word&0xF], shift_types[(word>>5)&3], - regnames[(word>>8)&0xF]); -} - -static void -op2_regshift(word) - unsigned word; -{ - if (word & 0x10) - op2_regbyreg(word); - else - op2_regbyconst(word); - putchar('\n'); -} - -static void -dataproc_op2(word) - unsigned word; -{ - if (word & 0x02000000) - op2_immed(word); - else - op2_regshift(word); -} - -static void -dataproc_tstcmp_overlay(word) - unsigned word; -{ - char msrmask[5], *cp; - - if ((word & 0x0FFFFFF0) == 0x012FFF10) { - printf("bx%s\t%s\n", condition_decode[word>>28], - regnames[word&0xF]); - return; - } else if ((word & 0x0FBF0FFF) == 0x010F0000) { - printf("mrs%s\t%s, %cPSR\n", condition_decode[word>>28], - regnames[(word>>12)&0xF], word&0x400000 ? 'S' : 'C'); - return; - } else if ((word & 0x0DB0F000) == 0x0120F000) { - if (!(word & 0x02000000) && (word & 0xFF0)) { - printf("\n"); - return; - } - if (word & 0xF0000) { - cp = msrmask; - if (word & 0x80000) - *cp++ = 'f'; - if (word & 0x40000) - *cp++ = 's'; - if (word & 0x20000) - *cp++ = 'x'; - if (word & 0x10000) - *cp++ = 'c'; - *cp = '\0'; - } else - strcpy(msrmask, "null"); - printf("msr%s\t%cPSR_%s, ", condition_decode[word>>28], - word&0x400000 ? 'S' : 'C', msrmask); - dataproc_op2(word); - return; - } - printf("\n"); -} - -static void -dataproc(word) - unsigned word; -{ - unsigned opc; - - opc = (word >> 21) & 0xF; - switch (opc) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 0xC: - case 0xE: - printf("%s%s%s\t%s, %s, ", dataproc_ops[opc], - condition_decode[word>>28], word&0x100000 ? "s" : "", - regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); - dataproc_op2(word); - return; - case 0xD: - case 0xF: - printf("%s%s%s\t%s, ", dataproc_ops[opc], - condition_decode[word>>28], word&0x100000 ? "s" : "", - regnames[(word>>12)&0xF]); - dataproc_op2(word); - return; - case 8: - case 9: - case 0xA: - case 0xB: - if (word & 0x100000) { - printf("%s%s\t%s, ", dataproc_ops[opc], - condition_decode[word>>28], - regnames[(word>>16)&0xF]); - dataproc_op2(word); - } else - dataproc_tstcmp_overlay(word); - return; - } -} - -static void -multiply(word) - unsigned word; -{ - if ((word & 0x0FE000F0) == 0x90) - printf("mul%s%s\t%s, %s, %s\n", condition_decode[word>>28], - word&0x100000 ? "s" : "", regnames[(word>>16)&0xF], - regnames[word&0xF], regnames[(word>>8)&0xF]); - else if ((word & 0x0FE000F0) == 0x00200090) - printf("mla%s%s\t%s, %s, %s, %s\n", condition_decode[word>>28], - word&0x100000 ? "s" : "", regnames[(word>>16)&0xF], - regnames[word&0xF], regnames[(word>>8)&0xF], - regnames[(word>>12)&0xF]); - else if ((word & 0x0F8000F0) == 0x00800090) - printf("%c%sl%s%s\t%s, %s, %s, %s\n", - word&0x400000 ? 's' : 'u', - word&0x200000 ? "mla" : "mul", - condition_decode[word>>28], - word&0x100000 ? "s" : "", - regnames[(word>>12)&0xF], regnames[(word>>16)&0xF], - regnames[word&0xF], regnames[(word>>8)&0xF]); - else if ((word & 0x0FB00FF0) == 0x01000090) - printf("swp%s%s\t%s, %s, [%s]\n", condition_decode[word>>28], - word&0x400000, "b", "", regnames[(word>>12)&0xF], - regnames[word&0xF], regnames[(word>>16)&0xF]); - else - printf("\n"); -} - -static int -check_ldr_litpool(sec, off, word, loff, size) - struct internal_scnhdr *sec; - unsigned off, word, loff; -{ - unsigned litoff, datum; - struct internal_reloc *rel; - - /* base reg must be 15 */ - if (((word >> 16) & 0xF) != 15) - return(0); - /* must be a load */ - if (!(word & 0x100000)) - return(0); - /* no writeback allowed */ - if (word & 0x200000) - return(0); - /* alignment */ - if (loff & (size - 1)) - return(0); - /* range */ - off += 8; - if (word & 0x800000) - litoff = off + loff; - else { - if (loff > off) - return(0); - litoff = off - loff; - } - if (litoff >= sec->size) - return(0); - /* all checks passed, proceed */ - rel = find_word32_reloc(sec, litoff); - switch (size) { - case 1: - datum = filemap[sec->data_offset + litoff]; - break; - case 2: - datum = get_u16(filemap + sec->data_offset + litoff); - break; - case 4: - datum = get_u32(filemap + sec->data_offset + litoff); - break; - } - putchar('='); - if (rel) - disasm_reloc_target(sec, rel, datum); - else - printf("0x%x", datum); - printf("\t; via 0x%x\n", litoff); - return(1); -} - -static void -ldr_str_imm_pre(sec, off, word) - struct internal_scnhdr *sec; - unsigned off, word; -{ - unsigned loff = word & 0xFFF; - - printf("%s%s%s\t%s, ", word&0x100000 ? "ldr" : "str", - condition_decode[word>>28], word&0x400000 ? "b" : "", - regnames[(word>>12)&0xF]); - if (check_ldr_litpool(sec, off, word, loff, word&0x400000 ? 1 : 4)) - return; - printf("[%s", regnames[(word>>16)&0xF]); - if (loff || word&0x200000) - printf(", #%s%u", word&0x800000 ? "" : "-", loff); - putchar(']'); - if (word & 0x200000) - putchar('!'); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -ldr_str_imm_post(word) - unsigned word; -{ - unsigned loff = word & 0xFFF; - - printf("%s%s%s%s\t%s, [%s], #%s%u", word&0x100000 ? "ldr" : "str", - condition_decode[word>>28], word&0x400000 ? "b" : "", - word&0x200000 ? "t" : "", - regnames[(word>>12)&0xF], regnames[(word>>16)&0xF], - word&0x800000 ? "" : "-", loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -ldr_str_reg_pre(word) - unsigned word; -{ - if (word & 0x10) { - printf("\n"); - return; - } - printf("%s%s%s\t%s, [%s, ", word&0x100000 ? "ldr" : "str", - condition_decode[word>>28], word&0x400000 ? "b" : "", - regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); - if (!(word & 0x800000)) - putchar('-'); - op2_regbyconst(word); - putchar(']'); - if (word & 0x200000) - putchar('!'); - putchar('\n'); -} - -static void -ldr_str_reg_post(word) - unsigned word; -{ - if (word & 0x10) { - printf("\n"); - return; - } - printf("%s%s%s%s\t%s, [%s], ", word&0x100000 ? "ldr" : "str", - condition_decode[word>>28], word&0x400000 ? "b" : "", - word&0x200000 ? "t" : "", - regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); - if (!(word & 0x800000)) - putchar('-'); - op2_regbyconst(word); - putchar('\n'); -} - -static void -ldr_str_ext(sec, off, word) - struct internal_scnhdr *sec; - unsigned off, word; -{ - unsigned loff; - - if (!(word&0x01000000) && word&0x200000) { - printf("\n"); - return; - } - if (!(word&0x400000) && word&0xF00) { - printf("\n"); - return; - } - printf("%s%s%s%c\t%s, ", word&0x100000 ? "ldr" : "str", - condition_decode[word>>28], - word&0x40 ? "s" : "", - word&0x20 ? 'h' : 'b', - regnames[(word>>12)&0xF]); - if (word & 0x400000) - loff = ((word & 0xF00) >> 4) | (word & 0xF); - switch (word & 0x01400000) { - case 0: - /* reg post */ - printf("[%s], %s%s", regnames[(word>>16)&0xF], - word&0x800000 ? "" : "-", regnames[word&0xF]); - break; - case 0x400000: - /* imm post */ - printf("[%s], #%s%u", regnames[(word>>16)&0xF], - word&0x800000 ? "" : "-", loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - break; - case 0x01000000: - /* reg pre */ - printf("[%s, %s%s]%s", regnames[(word>>16)&0xF], - word&0x800000 ? "" : "-", regnames[word&0xF], - word&0x200000 ? "!" : ""); - break; - case 0x01400000: - /* imm pre */ - if (check_ldr_litpool(sec, off, word, loff, word&0x20 ? 2 : 1)) - return; - printf("[%s", regnames[(word>>16)&0xF]); - if (loff || word&0x200000) - printf(", #%s%u", word&0x800000 ? "" : "-", loff); - putchar(']'); - if (word & 0x200000) - putchar('!'); - if (loff >= 10) - printf("\t; 0x%x", loff); - break; - } - putchar('\n'); -} - -static void -dataproc_74_overlay(sec, off, word) - struct internal_scnhdr *sec; - unsigned off, word; -{ - if (word & 0x60) - ldr_str_ext(sec, off, word); - else - multiply(word); -} - -static void -ldm_stm(word) - unsigned word; -{ - int r, flag; - - printf("%s%s%c%c\t%s", word&0x100000 ? "ldm" : "stm", - condition_decode[word>>28], - word&0x800000 ? 'i' : 'd', word&0x01000000 ? 'b' : 'a', - regnames[(word>>16)&0xF]); - if (word & 0x200000) - putchar('!'); - fputs(", {", stdout); - flag = 0; - for (r = 0; r < 16; r++) - if (word & (1 << r)) { - if (flag) - fputs(", ", stdout); - fputs(regnames[r], stdout); - flag = 1; - } - putchar('}'); - if (word & 0x400000) - putchar('^'); - putchar('\n'); -} - -void -arm_disasm_line(sec, off) - struct internal_scnhdr *sec; - unsigned off; -{ - unsigned word; - - word = get_u32(filemap + sec->data_offset + off); - printf("%08x\t", word); - if ((word >> 28) == 0xF) { - printf("\n"); - return; - } - switch ((word >> 24) & 0xF) { - case 0: - case 1: - if ((word & 0x90) == 0x90) - dataproc_74_overlay(sec, off, word); - else - dataproc(word); - return; - case 2: - case 3: - dataproc(word); - return; - case 4: - ldr_str_imm_post(word); - return; - case 5: - ldr_str_imm_pre(sec, off, word); - return; - case 6: - ldr_str_reg_post(word); - return; - case 7: - ldr_str_reg_pre(word); - return; - case 8: - case 9: - ldm_stm(word); - return; - case 0xA: - case 0xB: - arm_branch(off, word); - return; - case 0xC: - case 0xD: - case 0xE: - printf("\n"); - return; - case 0xF: - printf("swi%s\t0x%x\n", condition_decode[word>>28], - word & 0xFFFFFF); - return; - } -} - -void -arm_branch_reloc(sec, rel) - struct internal_scnhdr *sec; - struct internal_reloc *rel; -{ - unsigned word, dest; - - word = get_u32(filemap + sec->data_offset + rel->location); - printf("%08x R\t", word); - if ((word & 0x0E000000) != 0x0A000000) { - printf("\n"); - return; - } - dest = (word & 0x00FFFFFF) << 2; - if (dest & 0x02000000) - dest |= 0xFC000000; - dest += rel->location + 8; - printf("b%s%s\t", word&0x1000000 ? "l" : "", - condition_decode[word>>28]); - disasm_reloc_target(sec, rel, dest); - putchar('\n'); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/atcommon.c --- a/ticoff/atcommon.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -/* - * Lean and mean ARM7TDMI disassembler - * Written by Spacefalcon the Outlaw - */ - -/* a few disassembly bits common between ARM and Thumb */ - -char *regnames[16] = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"}; - -char *condition_decode[16] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", "gt", "le", "", "INV"}; - -char *shift_types[4] = {"lsl", "lsr", "asr", "ror"}; diff -r 597143ba1c37 -r 87b82398a08b ticoff/basics.c --- a/ticoff/basics.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * This C module implements some "basic" dump commands - */ - -#include -#include -#include -#include -#include "filestruct.h" -#include "intstruct.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); - -dump_filehdr_info() -{ - time_t timestamp; - struct tm *timedec; - - timestamp = get_u32(filehdr_struct->f_timdat); - timedec = gmtime(×tamp); - printf("timestamp: %d-%02d-%02dT%02d:%02d:%02dZ\n", - timedec->tm_year + 1900, timedec->tm_mon + 1, timedec->tm_mday, - timedec->tm_hour, timedec->tm_min, timedec->tm_sec); - printf("file flags: 0x%x\n", get_u16(filehdr_struct->f_flags)); - printf("%u sections, %u symtab entries\n", nsections, nsymtab); - return(0); -} - -dump_sechdr() -{ - unsigned n; - struct internal_scnhdr *inf; - - for (n = 0; n < nsections; n++) { - inf = sections + n; - printf("#%d: %s size=%u, flags=0x%x\n", n, inf->name, - inf->size, inf->flags); - printf("\t%u reloc, %u line entries\n", - inf->nreloc, inf->nlineent); - } - return(0); -} - -cmd_sechdr() -{ - get_int_section_table(); - dump_sechdr(); - exit(0); -} - -cmd_symtab() -{ - get_int_section_table(); - get_int_symbol_table(); - dump_symtab(); - exit(0); -} - -cmd_basics() -{ - printf("%s:\n", objfilename); - dump_filehdr_info(); - putchar('\n'); - get_int_section_table(); - printf("Sections:\n\n"); - dump_sechdr(); - putchar('\n'); - get_int_symbol_table(); - printf("Symbol table:\n\n"); - dump_symtab(); - putchar('\n'); - exit(0); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/coffconst.h --- a/ticoff/coffconst.h Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/********************** STORAGE CLASSES **********************/ - -#define C_NULL 0 -#define C_AUTO 1 /* automatic variable */ -#define C_EXT 2 /* external symbol */ -#define C_STAT 3 /* static */ -#define C_REG 4 /* register variable */ -#define C_EXTREF 5 /* external reference */ -#define C_LABEL 6 /* label */ -#define C_ULABEL 7 /* undefined label */ -#define C_MOS 8 /* member of structure */ -#define C_ARG 9 /* function argument */ -#define C_STRTAG 10 /* structure tag */ -#define C_MOU 11 /* member of union */ -#define C_UNTAG 12 /* union tag */ -#define C_TPDEF 13 /* type definition */ -#define C_USTATIC 14 /* undefined static */ -#define C_ENTAG 15 /* enumeration tag */ -#define C_MOE 16 /* member of enumeration */ -#define C_REGPARM 17 /* register parameter */ -#define C_FIELD 18 /* bit field */ -#define C_UEXT 19 /* Tentative external definition */ -#define C_STATLAB 20 /* Static load time label */ -#define C_EXTLAB 21 /* External load time label */ -#define C_SYSTEM 23 /* System Wide variable */ -#define C_VARARG 27 /* from TI's spraao8.pdf */ -#define C_BLOCK 100 /* ".bb" or ".eb" */ -#define C_FCN 101 /* ".bf" or ".ef" */ -#define C_EOS 102 /* end of structure */ -#define C_FILE 103 /* file name */ -#define C_LINE 104 /* line # reformatted as symbol table entry */ - -/* Reloc types */ - -#define RTYPE_LONG 0x11 -#define RTYPE_THUMB_BL 0x16 -#define RTYPE_ARM_B 0x17 diff -r 597143ba1c37 -r 87b82398a08b ticoff/disasm.c --- a/ticoff/disasm.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ -/* - * Putting it all together: section-, symbol- and reloc-aware disassembly - */ - -#include -#include -#include -#include -#include -#include "intstruct.h" -#include "coffconst.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); -extern char *storage_class_to_string(); - -static int auto_xlat_section_relocs = 1; - -static void -find_better_symbol(sec, symp, addp) - struct internal_scnhdr *sec; - struct internal_syment **symp; - unsigned *addp; -{ - unsigned addr, delta; - struct internal_syment *sym; - unsigned n; - - addr = *addp; - for (n = 0; n < sec->nsymbols; n++) { - sym = sec->sorted_symbols[n]; - if (sym->value > addr) - return; - if (sym->class != C_EXT && sym->class != C_STAT) - continue; - delta = addr - sym->value; - if (sym->name[0] == '_' && !delta || - sym->name[0] == '$' && delta <= 1) { - *symp = sym; - *addp = delta; - } - } -} - -void -disasm_reloc_target(sec, rel, addend) - struct internal_scnhdr *sec; - struct internal_reloc *rel; - unsigned addend; -{ - struct internal_syment *sym = rel->sym; - - if (sym) - addend -= sym->value; - if (auto_xlat_section_relocs && - (!sym || sym->section && !strcmp(sym->name, sym->section->name))) - find_better_symbol(sym ? sym->section : sec, &sym, &addend); - if (sym) - fputs(sym->name, stdout); - else - fputs(sec->name, stdout); - if (addend >= 10) - printf("+0x%x", addend); - else if (addend) - printf("+%u", addend); -} - -void -disasm_word32_reloc(sec, rel) - struct internal_scnhdr *sec; - struct internal_reloc *rel; -{ - unsigned word; - - word = get_u32(filemap + sec->data_offset + rel->location); - printf("%08x R\t.word\t", word); - disasm_reloc_target(sec, rel, word); - putchar('\n'); -} - -void -disasm_end_of_section(sec, symnum) - struct internal_scnhdr *sec; - unsigned symnum; -{ - struct internal_syment *sym; - char *sym_comment; - - putchar('\n'); - while (symnum < sec->nsymbols) { - sym = sec->sorted_symbols[symnum]; - if (sym->value != sec->size) { - printf("error: expecting symbol at end of section\n"); - return; - } - switch (sym->class) { - case C_EXT: - sym_comment = "Global"; - break; - case C_STAT: - sym_comment = "static"; - break; - case C_LABEL: - sym_comment = "label"; - break; - default: - sym_comment = "unexpected class!"; - } - printf("%s:\t; %s\n", sym->name, sym_comment); - symnum++; - } - printf("%8x:\t\n", sec->size); -} - -void -disasm_text_section(sec) - struct internal_scnhdr *sec; -{ - unsigned symnum, relnum; - unsigned pos, incr, headroom; - int state = -1, linebrk = 0; - struct internal_syment *sym; - struct internal_reloc *rel; - char *sym_comment; - - printf("Disassembling code section:\n"); - if (sec->nsymbols) - sort_symbols_of_sec(sec); - if (sec->nreloc) - get_relocs_of_sec(sec); - symnum = relnum = 0; - for (pos = 0; pos < sec->size; pos += incr) { - headroom = sec->size - pos; - while (symnum < sec->nsymbols) { - sym = sec->sorted_symbols[symnum]; - if (sym->value > pos) { - if (sym->value - pos < headroom) - headroom = sym->value - pos; - break; - } - /* hit symbol */ - if (!linebrk) { - putchar('\n'); - linebrk = 1; - } - switch (sym->class) { - case C_EXT: - sym_comment = "Global"; - break; - case C_STAT: - sym_comment = "static"; - break; - case C_LABEL: - sym_comment = "label"; - if (!strcmp(sym->name, "$CODE16")) - state = 1; - else if (!strcmp(sym->name, "$CODE32")) - state = 0; - break; - default: - sym_comment = "unexpected class!"; - } - printf("%s:\t; %s\n", sym->name, sym_comment); - symnum++; - } - if (relnum < sec->nreloc) { - rel = sec->int_relocs + relnum; - if (rel->location == pos) - relnum++; /* it's ours */ - else { - if (rel->location - pos < headroom) - headroom = rel->location - pos; - rel = 0; /* no reloc for current pos */ - } - } else - rel = 0; - printf("%8x:\t", pos); - if (rel && rel->type == RTYPE_LONG) { - if (pos & 3) { - printf("MISALIGNED pos for word32 reloc, aborting\n"); - return; - } - disasm_word32_reloc(sec, rel); - incr = 4; - goto next; - } - if (pos & 1 || headroom < 2) { - if (rel) { - printf("error: reloc at byte pos, aborting\n"); - return; - } - printf("%02x\n", filemap[sec->data_offset + pos]); - incr = 1; - goto next; - } - switch (state) { - case 0: /* ARM */ - if (pos & 3) { - printf("MISALIGNED pos in CODE32 state, aborting\n"); - return; - } - if (rel) { - if (rel->type != RTYPE_ARM_B) { - printf("Wrong reloc type in CODE32 state, aborting\n"); - return; - } - arm_branch_reloc(sec, rel); - } else - arm_disasm_line(sec, pos); - incr = 4; - break; - case 1: /* Thumb */ - if (pos & 1) { - printf("MISALIGNED pos in CODE16 state, aborting\n"); - return; - } - if (rel) { - if (rel->type != RTYPE_THUMB_BL) { - printf("Wrong reloc type in CODE16 state, aborting\n"); - return; - } - thumb_bl_reloc(sec, rel); - incr = 4; - } else if (headroom >= 4 && thumb_check_bl(sec, pos)) - incr = 4; - else { - thumb_disasm_line(sec, pos); - incr = 2; - } - break; - default: - printf("UNKNOWN T state, aborting\n"); - return; - } -next: linebrk = 0; - if (incr > headroom) { - printf("error: increment %u > headroom %u, aborting\n", - incr, headroom); - return; - } - } - if (symnum < sec->nsymbols) - disasm_end_of_section(sec, symnum); -} - -void -disasm_data_section(sec) - struct internal_scnhdr *sec; -{ - unsigned symnum, relnum; - unsigned pos, incr, headroom; - int linebrk = 0; - struct internal_syment *sym; - struct internal_reloc *rel; - char *sym_comment; - - printf("Disassembling data section:\n"); - if (sec->nsymbols) - sort_symbols_of_sec(sec); - if (sec->nreloc) - get_relocs_of_sec(sec); - symnum = relnum = 0; - for (pos = 0; pos < sec->size; pos += incr) { - headroom = sec->size - pos; - while (symnum < sec->nsymbols) { - sym = sec->sorted_symbols[symnum]; - if (sym->value > pos) { - if (sym->value - pos < headroom) - headroom = sym->value - pos; - break; - } - /* hit symbol */ - if (!linebrk) { - putchar('\n'); - linebrk = 1; - } - switch (sym->class) { - case C_EXT: - sym_comment = "Global"; - break; - case C_STAT: - sym_comment = "static"; - break; - case C_LABEL: - sym_comment = "label"; - break; - default: - sym_comment = "unexpected class!"; - } - printf("%s:\t; %s\n", sym->name, sym_comment); - symnum++; - } - if (relnum < sec->nreloc) { - rel = sec->int_relocs + relnum; - if (rel->location == pos) - relnum++; /* it's ours */ - else { - if (rel->location - pos < headroom) - headroom = rel->location - pos; - rel = 0; /* no reloc for current pos */ - } - } else - rel = 0; - printf("%8x:\t", pos); - if (rel) { - if (rel->type != RTYPE_LONG) { - printf("error: reloc other than word32 in data section\n"); - return; - } - if (pos & 3) { - printf("MISALIGNED pos for word32 reloc, aborting\n"); - return; - } - disasm_word32_reloc(sec, rel); - incr = 4; - } else if (pos & 1 || headroom < 2) { - printf("%02x\n", filemap[sec->data_offset + pos]); - incr = 1; - } else if (pos & 2 || headroom < 4) { - printf("%04x\n", - get_u16(filemap + sec->data_offset + pos)); - incr = 2; - } else { - printf("%08x\n", - get_u32(filemap + sec->data_offset + pos)); - incr = 4; - } - linebrk = 0; - if (incr > headroom) { - printf("error: increment %u > headroom %u, aborting\n", - incr, headroom); - return; - } - } - if (symnum < sec->nsymbols) - disasm_end_of_section(sec, symnum); -} - -void -disasm_bss(sec) - struct internal_scnhdr *sec; -{ - unsigned m; - struct internal_syment *sym; - char classbuf[8]; - - putchar('\n'); - for (m = 0; m < sec->nsymbols; m++) { - sym = sec->sorted_symbols[m]; - printf("%08X %-7s %s\n", sym->value, - storage_class_to_string(sym->class, classbuf), - sym->name); - } - printf("%08X \n", sec->size); -} - -void -disasm_sec_by_type(sec) - struct internal_scnhdr *sec; -{ - switch (sec->disasm_mode) { - case DISASM_MODE_CODE: - disasm_text_section(sec); - return; - case DISASM_MODE_DATA: - disasm_data_section(sec); - return; - case DISASM_MODE_BSS: - disasm_bss(sec); - return; - default: - printf("Unrecognized section type, skipped\n"); - } -} - -cmd_disasm(argc, argv) - char **argv; -{ - extern char *optarg; - char *hintsfile = 0; - struct internal_scnhdr *sec; - unsigned secnum; - int c; - - while ((c = getopt(argc, argv, "h:s")) != EOF) - switch (c) { - case 'h': - hintsfile = optarg; - continue; - case 's': - auto_xlat_section_relocs = 0; - continue; - default: - /* error msg already printed */ - exit(1); - } - - printf("%s:\n", objfilename); - dump_filehdr_info(); - putchar('\n'); - get_int_section_table(); - get_int_symbol_table(); - if (hintsfile) - read_hints_file(hintsfile); - extern_profile_report("Module"); - sort_symbols_of_all_sec(); - for (secnum = 0; secnum < nsections; secnum++) { - sec = sections + secnum; - printf("=== %s ===\n", sec->name); - disasm_sec_by_type(sec); - putchar('\n'); - } - exit(0); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/filestruct.h --- a/ticoff/filestruct.h Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Here we are going to define the structures found in the COFF artifact - * file to be analyzed. - */ - -struct external_filehdr { - u_char f_magic[2]; /* magic number */ - u_char f_nscns[2]; /* number of sections */ - u_char f_timdat[4]; /* time & date stamp */ - u_char f_symptr[4]; /* file pointer to symtab */ - u_char f_nsyms[4]; /* number of symtab entries */ - u_char f_opthdr[2]; /* sizeof(optional hdr) */ - u_char f_flags[2]; /* flags */ - u_char f_target_id[2]; /* magic no. (TI COFF-specific) */ -}; - -struct external_scnhdr { - u_char s_name[8]; /* section name */ - u_char s_paddr[4]; /* physical address, aliased s_nlib */ - u_char s_vaddr[4]; /* virtual address */ - u_char s_size[4]; /* section size (in WORDS) */ - u_char s_scnptr[4]; /* file ptr to raw data for section */ - u_char s_relptr[4]; /* file ptr to relocation */ - u_char s_lnnoptr[4]; /* file ptr to line numbers */ - u_char s_nreloc[4]; /* number of relocation entries */ - u_char s_nlnno[4]; /* number of line number entries*/ - u_char s_flags[4]; /* flags */ - u_char s_reserved[2]; /* reserved */ - u_char s_page[2]; /* section page number (LOAD) */ -}; - -struct external_syment { - u_char e_name[8]; - u_char e_value[4]; - u_char e_scnum[2]; - u_char e_type[2]; - u_char e_sclass; - u_char e_numaux; -}; - -struct external_reloc { - u_char r_vaddr[4]; - u_char r_symndx[4]; - u_char r_reserved[2]; /* extended pmad byte for COFF2 */ - u_char r_type[2]; -}; diff -r 597143ba1c37 -r 87b82398a08b ticoff/globals.c --- a/ticoff/globals.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -/* - * Definitions of global vars for the tiobjd program. - */ - -#include - -char *objfilename; -u_char *filemap; -size_t objfile_tot_size; - -struct external_filehdr *filehdr_struct; -struct external_scnhdr *sections_raw; -unsigned nsections; -struct external_syment *symtab_raw; -unsigned nsymtab; -unsigned strtab_offset; - -struct internal_scnhdr *sections; -struct internal_syment **symtab; diff -r 597143ba1c37 -r 87b82398a08b ticoff/globals.h --- a/ticoff/globals.h Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -/* - * extern declarations of global vars for the tiobjd program. - */ - -extern char *objfilename; -extern u_char *filemap; -extern size_t objfile_tot_size; - -extern struct external_filehdr *filehdr_struct; -extern struct external_scnhdr *sections_raw; -extern unsigned nsections; -extern struct external_syment *symtab_raw; -extern unsigned nsymtab; -extern unsigned strtab_offset; - -extern struct internal_scnhdr *sections; -extern struct internal_syment **symtab; diff -r 597143ba1c37 -r 87b82398a08b ticoff/hints.c --- a/ticoff/hints.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Parsing of the disassembly hints file - */ - -#include -#include -#include -#include -#include -#include -#include "intstruct.h" -#include "globals.h" - -static char *filename_for_err; -static int lineno; -static struct internal_scnhdr *section; -static struct hint *lasthint; - -static void -set_section(name) - char *name; -{ - unsigned n; - struct internal_scnhdr *sec = 0; - - for (n = 0; n < nsections; n++) - if (!strcmp(sections[n].name, name)) { - sec = sections + n; - break; - } - if (!sec) { - fprintf(stderr, "%s line %d: no section named \"%s\" in %s\n", - filename_for_err, lineno, name, objfilename); - exit(1); - } - if (sec->hints) { - fprintf(stderr, "%s line %d: [%s] given more than once\n", - filename_for_err, lineno, name); - exit(1); - } - section = sec; - lasthint = 0; -} - -static void -set_mode(arg) - char *arg; -{ - char *cp; - - if (!section) { - fprintf(stderr, - "%s line %d: error: mode line outside of section\n", - filename_for_err, lineno); - exit(1); - } - while (isspace(*arg)) - arg++; - if (!*arg) { - fprintf(stderr, "%s line %d: mode line: missing argument\n", - filename_for_err, lineno); - exit(1); - } - for (cp = arg; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - if (!strcmp(arg, "code")) - section->disasm_mode = DISASM_MODE_CODE; - else if (!strcmp(arg, "data")) - section->disasm_mode = DISASM_MODE_DATA; - else if (!strcmp(arg, "bss")) - section->disasm_mode = DISASM_MODE_BSS; - else { - fprintf(stderr, "%s line %d: unknown mode \"%s\"\n", - filename_for_err, lineno, arg); - exit(1); - } -} - -static void -regular_hint(arg1, arg2) - char *arg1, *arg2; -{ - fprintf(stderr, "error: regular hints not implemented yet\n"); - exit(1); -} - -read_hints_file(filename) - char *filename; -{ - FILE *f; - char linebuf[128], *cp, *np; - - f = fopen(filename, "r"); - if (!f) { - perror(filename); - exit(1); - } - filename_for_err = filename; - for (lineno = 1; fgets(linebuf, sizeof linebuf, f); lineno++) { - for (cp = linebuf; isspace(*cp); cp++) - ; - if (!*cp || *cp == '#') - continue; - if (*cp == '[') { - np = ++cp; - cp = index(cp, ']'); - if (!cp) { - fprintf(stderr, - "%s line %d: invalid section syntax\n", - filename, lineno); - exit(1); - } - *cp = '\0'; - set_section(np); - continue; - } - for (np = cp; *cp && !isspace(*cp); cp++) - ; - if (*cp) - *cp++ = '\0'; - if (!strcmp(np, "mode")) { - set_mode(cp); - continue; - } - regular_hint(np, cp); - } - fclose(f); - return(0); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/intstruct.h --- a/ticoff/intstruct.h Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * The structures defined in this header file - * are internal to our utility. - */ - -struct internal_scnhdr { - char *name; - unsigned size; - unsigned data_offset; - unsigned reloc_offset; - unsigned line_offset; - unsigned nreloc; - unsigned nlineent; - unsigned flags; - unsigned nsymbols; - struct internal_syment **sorted_symbols; - struct internal_reloc *int_relocs; - int disasm_mode; - struct hint *hints; -}; - -#define DISASM_MODE_UNKNOWN 0 -#define DISASM_MODE_CODE 1 -#define DISASM_MODE_DATA 2 -#define DISASM_MODE_BSS 3 - -struct internal_syment { - unsigned number; - char *name; - unsigned value; - int scnum; - int type; - int class; - u_char *aux; - struct internal_scnhdr *section; -}; - -struct internal_reloc { - unsigned location; - struct internal_syment *sym; - int type; - char *typestr; -}; - -struct hint { - unsigned pos; - int type; - unsigned nitems; - int linebrk; - struct hint *next; -}; - -#define HINT_D8 1 -#define HINT_D16 2 -#define HINT_ASCIZ 3 -#define HINT_D32 4 diff -r 597143ba1c37 -r 87b82398a08b ticoff/lowlevel.c --- a/ticoff/lowlevel.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * This C module implements the low-level steps of TI COFF image analysis. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "filestruct.h" -#include "globals.h" - -mmap_objfile() -{ - int fd; - struct stat st; - - fd = open(objfilename, O_RDONLY); - if (fd < 0) { - perror(objfilename); - exit(1); - } - fstat(fd, &st); - if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "error: %s is not a regular file\n", - objfilename); - exit(1); - } - objfile_tot_size = st.st_size; - filemap = mmap(NULL, objfile_tot_size, PROT_READ, MAP_PRIVATE, fd, 0L); - if (filemap == MAP_FAILED) { - perror("mmap"); - exit(1); - } - close(fd); -} - -unsigned -get_u16(ptr) - u_char *ptr; -{ - return ptr[0] | ptr[1] << 8; -} - -get_s16(ptr) - u_char *ptr; -{ - int i; - - i = ptr[0] | ptr[1] << 8; - if (i >= 32768) - i -= 65536; - return(i); -} - -unsigned -get_u32(ptr) - u_char *ptr; -{ - return ptr[0] | ptr[1] << 8 | ptr[2] << 16 | ptr[3] << 24; -} - -initial_parse_hdr() -{ - unsigned symtab_offset; - - filehdr_struct = (struct external_filehdr *) filemap; - if (get_u16(filehdr_struct->f_magic) != 0xC2) { - fprintf(stderr, "error: %s is not a TI COFF2 object\n", - objfilename); - exit(1); - } - if (get_u16(filehdr_struct->f_target_id) != 0x97) { - fprintf(stderr, "error: TI COFF object %s is not for TMS470\n", - objfilename); - exit(1); - } - if (get_u16(filehdr_struct->f_opthdr)) { - fprintf(stderr, - "error: %s has the \"optional\" header present\n", - objfilename); - exit(1); - } - sections_raw = (struct external_scnhdr *) - (filemap + sizeof(struct external_filehdr)); - nsections = get_u16(filehdr_struct->f_nscns); - symtab_offset = get_u32(filehdr_struct->f_symptr); - symtab_raw = (struct external_syment *)(filemap + symtab_offset); - nsymtab = get_u32(filehdr_struct->f_nsyms); - strtab_offset = symtab_offset + - sizeof(struct external_syment) * nsymtab; -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/main.c --- a/ticoff/main.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * tiobjd main() function and command dispatch - */ - -#include -#include -#include -#include -#include -#include "globals.h" - -extern int cmd_basics(); -extern int cmd_disasm(); -extern int cmd_nm(); -extern int cmd_profile(); -extern int cmd_rawrel(); -extern int cmd_reloc(); -extern int cmd_sechdr(); -extern int cmd_symtab(); -extern int dump_filehdr_info(); - -static struct cmdtab { - char *cmd; - int (*func)(); -} cmdtab[] = { - {"basics", cmd_basics}, - {"disasm", cmd_disasm}, - {"dumpsym", cmd_symtab}, /* backward compat */ - {"hdr", dump_filehdr_info}, - {"nm", cmd_nm}, - {"profile", cmd_profile}, - {"rawrel", cmd_rawrel}, - {"reloc", cmd_reloc}, - {"sechdr", cmd_sechdr}, - {"symtab", cmd_symtab}, - {0, 0} -}; - -main(argc, argv) - char **argv; -{ - struct cmdtab *tp; - - if (argc < 3) { - fprintf(stderr, "usage: %s [args]\n", argv[0]); - exit(1); - } - objfilename = argv[1]; - mmap_objfile(); - initial_parse_hdr(); - for (tp = cmdtab; tp->cmd; tp++) - if (!strcmp(tp->cmd, argv[2])) - break; - if (!tp->func) { - fprintf(stderr, "\"%s\": unknown or unimplemented command\n", - argv[2]); - exit(1); - } - return tp->func(argc - 2, argv + 2); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/profile.c --- a/ticoff/profile.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* - * It is handy to have a "profile" of what functions and variables - * a given module defines (presents to the rest of the fw) and what - * it references. This profile is constructed from the symbol table. - * - * Experience indicates that the order of these symbols in the - * artifact symtab is often "random", and an alphabetic sort is - * expected to improve readability. This module contains the - * messy code. - */ - -#include -#include -#include -#include -#include -#include "intstruct.h" -#include "coffconst.h" -#include "globals.h" - -static int -is_symbol_text_def(sym) - struct internal_syment *sym; -{ - if (!sym->section) - return(0); - if (!strncmp(sym->section->name, ".text", 5)) - return(1); - else - return(0); -} - -static int -is_symbol_nontext_def(sym) - struct internal_syment *sym; -{ - if (!sym->section) - return(0); - if (!strncmp(sym->section->name, ".text", 5)) - return(0); - else - return(1); -} - -static int -is_symbol_extref(sym) - struct internal_syment *sym; -{ - if (sym->section) - return(0); - else - return(1); -} - -static int -compare_for_sort(p1, p2) - struct internal_syment **p1, **p2; -{ - return strcmp((*p1)->name, (*p2)->name); -} - -static void -list_class(firstidx, lastidx, total, checkfunc, printsec) - unsigned firstidx, lastidx, total; - int (*checkfunc)(); -{ - struct internal_syment **array, *sym; - unsigned n, m; - - array = malloc(sizeof(void *) * total); - if (!array) { - perror("malloc"); - exit(1); - } - m = 0; - for (n = firstidx; n <= lastidx; n++) { - sym = symtab[n]; - if (!sym) - continue; - if (sym->class != C_EXT) - continue; - if (!checkfunc(sym)) - continue; - array[m++] = sym; - } - if (m != total) { - fprintf(stderr, "BUG: symbol class miscount in profile gen\n"); - exit(1); - } - qsort(array, total, sizeof(void *), compare_for_sort); - for (n = 0; n < total; n++) { - sym = array[n]; - if (printsec) - printf("%s (%s)\n", sym->name, sym->section->name); - else - printf("%s\n", sym->name); - } - free(array); - putchar('\n'); -} - -extern_profile_report(heading) - char *heading; -{ - unsigned n; - int first_extern = -1, last_extern; - struct internal_syment *sym; - unsigned defs_text = 0, defs_nontext = 0, extrefs = 0; - - for (n = 0; n < nsymtab; n++) { - sym = symtab[n]; - if (!sym) - continue; - if (sym->class != C_EXT) - continue; - if (first_extern < 0) - first_extern = n; - last_extern = n; - if (sym->scnum < 0) { - fprintf(stderr, - "symbol entry #%u: unexpected negative scnum for C_EXT\n", n); - exit(1); - } - if (sym->scnum == 0) - extrefs++; - else if (!strncmp(sym->section->name, ".text", 5)) - defs_text++; - else - defs_nontext++; - } - if (first_extern < 0) { - printf("%s has no external symbols!\n", heading); - return(1); - } - if (defs_text || defs_nontext) { - printf("%s defines:\n\n", heading); - if (defs_text) - list_class(first_extern, last_extern, defs_text, - is_symbol_text_def, 1); - if (defs_nontext) - list_class(first_extern, last_extern, defs_nontext, - is_symbol_nontext_def, 1); - } - if (extrefs) { - printf("%s references:\n\n", heading); - list_class(first_extern, last_extern, extrefs, - is_symbol_extref, 0); - } - return(0); -} - -cmd_profile() -{ - get_int_section_table(); - get_int_symbol_table(); - extern_profile_report(objfilename); - exit(0); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/reloc.c --- a/ticoff/reloc.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +0,0 @@ -/* - * Handling of relocation records - */ - -#include -#include -#include -#include "filestruct.h" -#include "intstruct.h" -#include "coffconst.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); - -cmd_rawrel() -{ - unsigned n, m; - struct internal_scnhdr *sec; - struct external_reloc *rel; - - get_int_section_table(); - for (n = 0; n < nsections; n++) { - sec = sections + n; - if (!sec->nreloc) - continue; - printf("%s:\n\n", sec->name); - rel = (struct external_reloc *)(filemap + sec->reloc_offset); - printf("Location SymIndex Rsvd Type\n"); - for (m = 0; m < sec->nreloc; m++, rel++) - printf("%08X %08X %04X %04X\n", - get_u32(rel->r_vaddr), get_u32(rel->r_symndx), - get_u16(rel->r_reserved), get_u16(rel->r_type)); - putchar('\n'); - } - exit(0); -} - -void -get_relocs_of_sec(sec) - struct internal_scnhdr *sec; -{ - unsigned n; - struct external_reloc *extrel; - struct internal_reloc *intrel; - unsigned lastloc, symidx; - - if (sec->int_relocs) - return; - if (!sec->nreloc) { - fprintf(stderr, - "BUG: get_relocs_of_sec() called for section \"%s\" w/o relocs\n", - sec->name); - exit(1); - } - intrel = malloc(sizeof(struct internal_reloc) * sec->nreloc); - if (!intrel) { - perror("malloc"); - exit(1); - } - sec->int_relocs = intrel; - extrel = (struct external_reloc *)(filemap + sec->reloc_offset); - for (n = 0; n < sec->nreloc; n++, extrel++, intrel++) { - intrel->location = get_u32(extrel->r_vaddr); - if (n && intrel->location <= lastloc) { - fprintf(stderr, - "error: non-increasing reloc order in section \"%s\"\n", - sec->name); - exit(1); - } - lastloc = intrel->location; - symidx = get_u32(extrel->r_symndx); - if (symidx == 0xFFFFFFFF) - intrel->sym = 0; - else if (symidx >= nsymtab || !symtab[symidx]) { - fprintf(stderr, - "error: reloc references invalid symbol #%u in section \"%s\"\n", - symidx, sec->name); - exit(1); - } else - intrel->sym = symtab[symidx]; - intrel->type = get_u16(extrel->r_type); - switch (intrel->type) { - case RTYPE_LONG: - intrel->typestr = "Word32"; - break; - case RTYPE_THUMB_BL: - intrel->typestr = "Thumb_BL"; - break; - case RTYPE_ARM_B: - intrel->typestr = "ARM_B"; - break; - default: - fprintf(stderr, - "error: reloc in section \"%s\" of unexpected type 0x%x\n", - sec->name, intrel->type); - exit(1); - } - if (get_u16(extrel->r_reserved)) - fprintf(stderr, - "warning: reloc in section \"%s\" has non-zero reserved field\n", - sec->name); - } -} - -cmd_reloc() -{ - unsigned n, m; - struct internal_scnhdr *sec; - struct internal_reloc *rel; - char *symname; - - get_int_section_table(); - get_int_symbol_table(); - for (n = 0; n < nsections; n++) { - sec = sections + n; - if (!sec->nreloc) - continue; - printf("%s:\n\n", sec->name); - get_relocs_of_sec(sec); - rel = sec->int_relocs; - printf("Location Type Symbol relative to\n"); - for (m = 0; m < sec->nreloc; m++, rel++) { - if (rel->sym) - symname = rel->sym->name; - else - symname = ""; - printf("%08X %-8s %s\n", rel->location, rel->typestr, - symname); - } - putchar('\n'); - } - exit(0); -} - -struct internal_reloc * -find_reloc(sec, loc) - struct internal_scnhdr *sec; - unsigned loc; -{ - struct internal_reloc *rel; - unsigned m; - - rel = sec->int_relocs; - for (m = 0; m < sec->nreloc; m++, rel++) { - if (rel->location == loc) - return(rel); - if (rel->location > loc) - return(0); - } - return(0); -} - -struct internal_reloc * -find_word32_reloc(sec, loc) - struct internal_scnhdr *sec; - unsigned loc; -{ - struct internal_reloc *rel; - - rel = find_reloc(sec, loc); - if (rel && rel->type != RTYPE_LONG) - rel = 0; - return(rel); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/symtab.c --- a/ticoff/symtab.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -/* - * Code for working with the symbol table - */ - -#include -#include -#include -#include "filestruct.h" -#include "intstruct.h" -#include "coffconst.h" -#include "globals.h" - -static struct classmap { - int code; - char *str; -} classtab[] = { - {C_NULL, "NULL"}, - {C_AUTO, "AUTO"}, - {C_EXT, "EXT"}, - {C_STAT, "STAT"}, - {C_REG, "REG"}, - {C_EXTREF, "EXTREF"}, - {C_LABEL, "LABEL"}, - {C_ULABEL, "ULABEL"}, - {C_MOS, "MOS"}, - {C_ARG, "ARG"}, - {C_STRTAG, "STRTAG"}, - {C_MOU, "MOU"}, - {C_UNTAG, "UNTAG"}, - {C_TPDEF, "TPDEF"}, - {C_USTATIC, "USTATIC"}, - {C_ENTAG, "ENTAG"}, - {C_MOE, "MOE"}, - {C_REGPARM, "REGPARM"}, - {C_FIELD, "FIELD"}, - {C_UEXT, "UEXT"}, - {C_STATLAB, "STATLAB"}, - {C_EXTLAB, "EXTLAB"}, - {C_SYSTEM, "SYSTEM"}, - {C_VARARG, "VARARG"}, - {C_BLOCK, "BLOCK"}, - {C_FCN, "FCN"}, - {C_EOS, "EOS"}, - {C_FILE, "FILE"}, - {C_LINE, "LINE"}, - {0, 0} -}; - -char * -storage_class_to_string(code, numbuf) - char *numbuf; -{ - struct classmap *tp; - - for (tp = classtab; tp->str; tp++) - if (tp->code == code) - return(tp->str); - sprintf(numbuf, "%d", code); - return(numbuf); -} - -dump_symtab() -{ - unsigned n; - struct internal_syment *sym; - char *sec, secstr[8]; - char *class, classbuf[8]; - - printf("%-5s %-30s %-4s %-7s %-12s %-8s\n", - "Num", "Name", "Type", "Class", "Section", "Value"); - for (n = 0; n < nsymtab; n++) { - sym = symtab[n]; - if (!sym) - continue; - if (sym->section) - sec = sym->section->name; - else { - sprintf(secstr, "%d", sym->scnum); - sec = secstr; - } - class = storage_class_to_string(sym->class, classbuf); - printf("%-5u %-30s %04X %-7s %-12s %08X%s\n", - n, sym->name, sym->type, class, - sec, sym->value, sym->aux ? " Aux" : ""); - } - return(0); -} - -static void -initial_fill_for_sort(sec) - struct internal_scnhdr *sec; -{ - unsigned n, m; - struct internal_syment *sym; - - m = 0; - for (n = 0; n < nsymtab; n++) { - sym = symtab[n]; - if (!sym) - continue; - if (sym->section != sec) - continue; - sec->sorted_symbols[m++] = sym; - } -} - -static int -compare_for_sort(p1, p2) - struct internal_syment **p1, **p2; -{ - /* sort by value first */ - if ((*p1)->value < (*p2)->value) - return(-1); - if ((*p1)->value > (*p2)->value) - return(1); - /* if same value, retain the original symtab order */ - if ((*p1)->number < (*p2)->number) - return(-1); - if ((*p1)->number > (*p2)->number) - return(1); - else - return(0); -} - -void -sort_symbols_of_sec(sec) - struct internal_scnhdr *sec; -{ - if (sec->sorted_symbols) - return; - if (!sec->nsymbols) { - fprintf(stderr, - "BUG: sort_symbols_of_sec() called for section \"%s\" w/o symbols\n", - sec->name); - exit(1); - } - sec->sorted_symbols = malloc(sizeof(void *) * sec->nsymbols); - if (!sec->sorted_symbols) { - perror("malloc"); - exit(1); - } - initial_fill_for_sort(sec); - qsort(sec->sorted_symbols, sec->nsymbols, sizeof(void *), - compare_for_sort); -} - -void -sort_symbols_of_all_sec() -{ - unsigned n; - struct internal_scnhdr *sec; - - for (n = 0; n < nsections; n++) { - sec = sections + n; - if (!sec->nsymbols) - continue; - sort_symbols_of_sec(sec); - } -} - -cmd_nm() -{ - unsigned n, m; - struct internal_scnhdr *sec; - struct internal_syment *sym; - char classbuf[8]; - - get_int_section_table(); - get_int_symbol_table(); - for (n = 0; n < nsections; n++) { - sec = sections + n; - if (!sec->nsymbols) - continue; - printf("%s:\n\n", sec->name); - sort_symbols_of_sec(sec); - for (m = 0; m < sec->nsymbols; m++) { - sym = sec->sorted_symbols[m]; - printf("%08X %-7s %s\n", sym->value, - storage_class_to_string(sym->class, classbuf), - sym->name); - } - putchar('\n'); - } - exit(0); -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/tables.c --- a/ticoff/tables.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * This C module will contain functions for the initial parsing - * of the section and symbol tables. - */ - -#include -#include -#include -#include -#include -#include "filestruct.h" -#include "intstruct.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); - -static char * -get_secorsym_name(ptr) - u_char *ptr; -{ - char *alloc; - - if (ptr[0]) { - if (ptr[7]) { - alloc = malloc(9); - if (!alloc) { - perror("malloc"); - exit(1); - } - bcopy(ptr, alloc, 8); - alloc[8] = '\0'; - return(alloc); - } else - return((char *) ptr); - } - if (ptr[1] || ptr[2] || ptr[3]) { - fprintf(stderr, "error: malformed name in %s at offset 0x%x\n", - objfilename, ptr - filemap); - exit(1); - } - return(filemap + strtab_offset + get_u32(ptr+4)); -} - -get_int_section_table() -{ - unsigned n; - - sections = malloc(sizeof(struct internal_scnhdr) * nsections); - if (!sections) { - perror("malloc"); - exit(1); - } - for (n = 0; n < nsections; n++) { - sections[n].name = get_secorsym_name(sections_raw[n].s_name); - if (get_u32(sections_raw[n].s_paddr)) - fprintf(stderr, - "warning: section #%u (%s) has nonzero paddr\n", - n, sections[n].name); - if (get_u32(sections_raw[n].s_vaddr)) - fprintf(stderr, - "warning: section #%u (%s) has nonzero vaddr\n", - n, sections[n].name); - sections[n].size = get_u32(sections_raw[n].s_size); - sections[n].data_offset = get_u32(sections_raw[n].s_scnptr); - sections[n].reloc_offset = get_u32(sections_raw[n].s_relptr); - sections[n].line_offset = get_u32(sections_raw[n].s_lnnoptr); - sections[n].nreloc = get_u32(sections_raw[n].s_nreloc); - sections[n].nlineent = get_u32(sections_raw[n].s_nlnno); - sections[n].flags = get_u32(sections_raw[n].s_flags); - if (get_u16(sections_raw[n].s_reserved)) - fprintf(stderr, - "warning: section #%u (%s): some nonzero value in s_reserved bytes\n", - n, sections[n].name); - if (get_u16(sections_raw[n].s_page)) - fprintf(stderr, - "warning: section #%u (%s): some nonzero value in s_page bytes\n", - n, sections[n].name); - sections[n].nsymbols = 0; - sections[n].sorted_symbols = 0; - sections[n].int_relocs = 0; - if (!strncmp(sections[n].name, ".text", 5)) - sections[n].disasm_mode = DISASM_MODE_CODE; - else if (!strcmp(sections[n].name, ".const")) - sections[n].disasm_mode = DISASM_MODE_DATA; - else if (!strcmp(sections[n].name, ".cinit")) - sections[n].disasm_mode = DISASM_MODE_DATA; - else if (!strcmp(sections[n].name, ".data")) - sections[n].disasm_mode = DISASM_MODE_DATA; - else if (!strcmp(sections[n].name, ".bss")) - sections[n].disasm_mode = DISASM_MODE_BSS; - else - sections[n].disasm_mode = DISASM_MODE_UNKNOWN; - sections[n].hints = 0; - } -} - -get_int_symbol_table() -{ - unsigned n; - struct internal_syment *in; - - symtab = malloc(sizeof(struct internal_syment *) * nsymtab); - if (!symtab) { - perror("malloc"); - exit(1); - } - for (n = 0; n < nsymtab; ) { - in = malloc(sizeof(struct internal_syment)); - if (!in) { - perror("malloc"); - exit(1); - } - symtab[n] = in; - in->number = n; - in->name = get_secorsym_name(symtab_raw[n].e_name); - in->value = get_u32(symtab_raw[n].e_value); - in->scnum = get_s16(symtab_raw[n].e_scnum); - if (in->scnum > 0) { - if (in->scnum > nsections) { - fprintf(stderr, - "symtab entry #%u: scnum too big\n", n); - exit(1); - } - in->section = sections + in->scnum - 1; - in->section->nsymbols++; - } else if (in->scnum < -2) { - fprintf(stderr, - "symtab entry #%u: scnum < -2\n", n); - exit(1); - } else - in->section = 0; - in->type = get_u16(symtab_raw[n].e_type); - in->class = symtab_raw[n].e_sclass; - switch (symtab_raw[n++].e_numaux) { - case 0: - in->aux = 0; - continue; - case 1: - if (n >= nsymtab) { - fprintf(stderr, - "error: last symbol's aux spills over\n"); - exit(1); - } - symtab[n] = 0; - in->aux = (u_char *)(symtab_raw + n); - n++; - continue; - default: - n--; - fprintf(stderr, "symtab entry #%u: invalid numaux\n", - n); - exit(1); - } - } -} diff -r 597143ba1c37 -r 87b82398a08b ticoff/thumbdis.c --- a/ticoff/thumbdis.c Sun Apr 06 20:20:39 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,436 +0,0 @@ -/* - * Thumb state disassembly - */ - -#include -#include -#include -#include -#include -#include "intstruct.h" -#include "globals.h" - -extern unsigned get_u16(), get_u32(); -extern struct internal_reloc *find_word32_reloc(); - -extern char *regnames[16], *condition_decode[16], *shift_types[4]; - -static void -format_1_2(word) - unsigned word; -{ - unsigned op, imm; - - op = (word >> 11) & 3; - if (op != 3) { - /* format 1 */ - imm = (word >> 6) & 0x1F; - if (op != 0 && imm == 0) - imm = 32; - printf("%s\t%s, %s, #%u\n", shift_types[op], regnames[word&7], - regnames[(word>>3)&7], imm); - return; - } - /* format 2 */ - printf("%s\t%s, %s, ", word&0x200 ? "sub" : "add", regnames[word&7], - regnames[(word>>3)&7]); - if (word & 0x400) - printf("#%u\n", (word >> 6) & 7); - else - printf("%s\n", regnames[(word >> 6) & 7]); -} - -static void -format_3(word) - unsigned word; -{ - static char *opctab[4] = {"mov", "cmp", "add", "sub"}; - unsigned imm; - - imm = word & 0xFF; - printf("%s\t%s, #%u", opctab[(word>>11)&3], regnames[(word>>8)&7], imm); - if (imm > 9) - printf("\t; 0x%x", imm); - putchar('\n'); -} - -static void -format_4(word) - unsigned word; -{ - static char *opc[16] = {"and", "eor", "lsl", "lsr", - "asr", "adc", "sbc", "ror", - "tst", "neg", "cmp", "cmn", - "orr", "mul", "bic", "mvn"}; - - printf("%s\t%s, %s\n", opc[(word>>6)&0xF], regnames[word&7], - regnames[(word>>3)&7]); -} - -static void -format_5_bx(word) - unsigned word; -{ - if (word & 0x80) - printf("\n"); - else - printf("bx\t%s\n", regnames[(word>>3)&0xF]); -} - -static void -format_5_hiops(word) - unsigned word; -{ - static char *opctab[3] = {"add", "cmp", "mov"}; - int reg1, reg2, op; - - if (word & 0xC0) { - reg1 = word & 7; - if (word & 0x80) - reg1 += 8; - reg2 = (word >> 3) & 0xF; - op = (word >> 8) & 3; - if (op == 2 && reg1 == reg2 && reg1 != 15) - printf("nop\t\t\t(mov %s, %s)\n", - regnames[reg1], regnames[reg2]); - else - printf("%s\t%s, %s\n", opctab[op], - regnames[reg1], regnames[reg2]); - } else - printf("\n"); -} - -static void -format_5(word) - unsigned word; -{ - if ((word & 0x300) == 0x300) - format_5_bx(word); - else - format_5_hiops(word); -} - -static void -format_6(sec, off, word) - struct internal_scnhdr *sec; - unsigned off, word; -{ - unsigned loff, litoff, datum; - struct internal_reloc *rel; - - loff = (word & 0xFF) << 2; - off &= ~3; - off += 4; - litoff = off + loff; - if (litoff+4 <= sec->size) { - rel = find_word32_reloc(sec, litoff); - datum = get_u32(filemap + sec->data_offset + litoff); - printf("ldr\t%s, =", regnames[(word>>8)&7]); - if (rel) - disasm_reloc_target(sec, rel, datum); - else - printf("0x%x", datum); - printf("\t; via 0x%x\n", litoff); - } else - printf("ldr\t%s, [pc, #%u]\t(0x%x)\n", regnames[(word>>8)&7], - loff, litoff); -} - -static void -format_7(word) - unsigned word; -{ - printf("%s%s\t%s, [%s, %s]\n", word&0x800 ? "ldr" : "str", - word&0x400 ? "b" : "", regnames[word&7], - regnames[(word>>3)&7], regnames[(word>>6)&7]); -} - -static void -format_8(word) - unsigned word; -{ - static char *opc[4] = {"strh", "ldrsb", "ldrh", "ldrsh"}; - - printf("%s\t%s, [%s, %s]\n", opc[(word>>10)&3], regnames[word&7], - regnames[(word>>3)&7], regnames[(word>>6)&7]); -} - -static void -format_9(word) - unsigned word; -{ - unsigned loff; - - loff = (word >> 6) & 0x1F; - if (!(word & 0x1000)) - loff <<= 2; - printf("%s%s\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", - word&0x1000 ? "b" : "", regnames[word&7], - regnames[(word>>3)&7], loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -format_10(word) - unsigned word; -{ - unsigned loff; - - loff = (word >> 6) & 0x1F; - loff <<= 1; - printf("%sh\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", - regnames[word&7], regnames[(word>>3)&7], loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -format_11(word) - unsigned word; -{ - unsigned loff; - - loff = (word & 0xFF) << 2; - printf("%s\t%s, [sp, #%u]", word&0x800 ? "ldr" : "str", - regnames[(word>>8)&7], loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -format_12(off, word) - unsigned off, word; -{ - unsigned loff; - - loff = (word & 0xFF) << 2; - printf("add\t%s, ", regnames[(word>>8)&7]); - if (word & 0x800) { - printf("sp, #%u", loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); - } else { - off &= ~3; - printf("pc, #%u\t; 0x%x\n", loff, off + 4 + loff); - } -} - -static void -format_13(word) - unsigned word; -{ - unsigned loff; - - if ((word & 0xFF00) != 0xB000) { - printf("\n"); - return; - } - loff = (word & 0x7F) << 2; - printf("%s\tsp, #%u", word&0x80 ? "sub" : "add", loff); - if (loff >= 10) - printf("\t; 0x%x", loff); - putchar('\n'); -} - -static void -format_14(word) - unsigned word; -{ - int r, flag; - - if ((word & 0xF600) != 0xB400) { - printf("\n"); - return; - } - printf("%s\t{", word&0x800 ? "pop" : "push"); - flag = 0; - for (r = 0; r < 9; r++) - if (word & (1 << r)) { - if (flag) - fputs(", ", stdout); - if (r == 8) - fputs(word&0x800 ? "pc" : "lr", stdout); - else - fputs(regnames[r], stdout); - flag = 1; - } - putchar('}'); - putchar('\n'); -} - -static void -format_15(word) - unsigned word; -{ - int r, flag; - - printf("%sia\t%s!, {", word&0x800 ? "ldm" : "stm", - regnames[(word>>8)&7]); - flag = 0; - for (r = 0; r < 8; r++) - if (word & (1 << r)) { - if (flag) - fputs(", ", stdout); - fputs(regnames[r], stdout); - flag = 1; - } - putchar('}'); - putchar('\n'); -} - -static void -format_16_17(off, word) - unsigned off, word; -{ - unsigned cond; - unsigned dest; - - cond = (word >> 8) & 0xF; - switch (cond) { - case 0xE: - printf("\n"); - return; - case 0xF: - printf("swi\t0x%x\n", word & 0xFF); - return; - } - dest = (word & 0xFF) << 1; - if (dest & 0x00000100) - dest |= 0xFFFFFE00; - dest += off + 4; - printf("b%s\t0x%x\n", condition_decode[cond], dest); -} - -static void -format_18(off, word) - unsigned off, word; -{ - unsigned dest; - - if (word & 0x800) { - printf("\n"); - return; - } - dest = (word & 0x7FF) << 1; - if (dest & 0x00000800) - dest |= 0xFFFFF000; - dest += off + 4; - printf("b\t0x%x\n", dest); -} - -void -thumb_disasm_line(sec, off) - struct internal_scnhdr *sec; - unsigned off; -{ - unsigned word; - - word = get_u16(filemap + sec->data_offset + off); - printf("%04x\t\t", word); - switch (word >> 12) { - case 0: - case 1: - format_1_2(word); - return; - case 2: - case 3: - format_3(word); - return; - case 4: - if (word & 0x800) - format_6(sec, off, word); - else if (word & 0x400) - format_5(word); - else - format_4(word); - return; - case 5: - if (word & 0x200) - format_8(word); - else - format_7(word); - return; - case 6: - case 7: - format_9(word); - return; - case 8: - format_10(word); - return; - case 9: - format_11(word); - return; - case 0xA: - format_12(off, word); - return; - case 0xB: - if (word & 0x400) - format_14(word); - else - format_13(word); - return; - case 0xC: - format_15(word); - return; - case 0xD: - format_16_17(off, word); - return; - case 0xE: - format_18(off, word); - return; - case 0xF: - printf("\n"); - return; - } -} - -thumb_check_bl(sec, off) - struct internal_scnhdr *sec; - unsigned off; -{ - unsigned ins1, ins2; - unsigned dest; - - ins1 = get_u16(filemap + sec->data_offset + off); - if ((ins1 & 0xF800) != 0xF000) - return(0); - ins2 = get_u16(filemap + sec->data_offset + off + 2); - if ((ins2 & 0xF800) != 0xF800) - return(0); - /* match */ - dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); - if (dest & 0x00400000) - dest |= 0xFF800000; - dest += off + 4; - printf("%04x %04x\tbl\t0x%x\n", ins1, ins2, dest); - return(1); -} - -void -thumb_bl_reloc(sec, rel) - struct internal_scnhdr *sec; - struct internal_reloc *rel; -{ - unsigned ins1, ins2; - unsigned dest; - - ins1 = get_u16(filemap + sec->data_offset + rel->location); - ins2 = get_u16(filemap + sec->data_offset + rel->location + 2); - printf("%04x %04x R\t", ins1, ins2); - if ((ins1 & 0xF800) != 0xF000 || (ins2 & 0xF800) != 0xF800) { - printf("\n"); - return; - } - dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); - if (dest & 0x00400000) - dest |= 0xFF800000; - dest += rel->location + 4; - fputs("bl\t", stdout); - disasm_reloc_target(sec, rel, dest); - putchar('\n'); -}