I have some old programs compiled in the aout format which I would like to recompile with ELF for Linux.
I found this decompiler program (REC) which claims to be able to do the trick.
Unfortunatly, the way he has the the download setup is not very good for a direct Linux install, so I decided to use the sorce code. It comes up with a ton of warnings and an undefined reference error for the mneu variable used as a function arg.
I don't know anything about C. So I ask-Is this just bad code or it is salvagable with a few tweeks?
/* dismips.c
*
* Created by Giampiero Caprino
* Backer Street Software
*
* This software is part of REC, the reverse engineering compiler.
* You are free to use, copy, modify and distribute this software.
* If you fix bugs and or extend this software, I
* will be happy to include your changes in the
* most current version of the source.
* just send mail to caprino@netcom.com
*/
struct instr {
char *name;
unsigned long opcode;
unsigned long opcode2;
int (*optype)();
int (*op1)();
int (*op2)();
int (*op3)();
};
static char opcode[32]; /* opcode mnemonic of current instruction */
static char ops[8][32]; /* operands of current instruction */
static char *op[8]; /* pointers to operand */
static char **opp; /* pointer to current operand */
static long cur_pc; /* address of current instruction */
extern char mneu[]; /* the output string from the disassembler */
static int op26(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode)
return(1);
return(0);
}
static int op32(struct instr *ip, unsigned long val)
{
if(val == ip->opcode)
return(1);
return(0);
}
static int op26_16(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && ((val >> 16) & 0x1F) == ip->opcode2)
return(1);
return(0);
}
static int op26__16(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && (val & 0xFFFF) == ip->opcode2)
return(1);
return(0);
}
static int op21_6(struct instr *ip, unsigned long val)
{
if((val >> 21) == ip->opcode && (val & 0x3F) == ip->opcode2)
return(1);
return(0);
}
static int op5___11(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && (val & 0x7FF) == ip->opcode2)
return(1);
return(0);
}
static int op26_5(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && (val & 0x3F) == ip->opcode2)
return(1);
return(0);
}
static int op26_16_11(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && (val & 0x001F07FF) == ip->opcode2)
return(1);
return(0);
}
static int op26_21(struct instr *ip, unsigned long val)
{
if((val >> 26) == ip->opcode && (val & 0x001FFFFF) == ip->opcode2)
return(1);
return(0);
}
static int op_r21(struct instr *ip, unsigned long val)
{
sprintf(*opp, "r%d", (val >> 21) & 0x1F);
return(1);
}
static int op_r16(struct instr *ip, unsigned long val)
{
sprintf(*opp, "r%d", (val >> 16) & 0x1F);
return(1);
}
static int op_r11(struct instr *ip, unsigned long val)
{
sprintf(*opp, "r%d", (val >> 11) & 0x1F);
return(1);
}
static int op_i16(struct instr *ip, unsigned long val)
{
long lv;
lv = (long)val;
lv <<= 16;
lv >>= 16;
sprintf(*opp, "#0x%lx", lv);
return(1);
}
static int op_u16(struct instr *ip, unsigned long val)
{
sprintf(*opp, "#0x%lx", val & 0xffff);
return(1);
}
static int op_i6(struct instr *ip, unsigned long val)
{
sprintf(*opp, "#%ld", (val >> 6) & 0x1f);
return(1);
}
static int op_h16(struct instr *ip, unsigned long val)
{
sprintf(*opp, "#0x%lx", val << 16);
return(1);
}
static int op_b21(struct instr *ip, unsigned long val)
{
long lv;
lv = (long)val;
lv <<= 16;
lv >>= 16;
sprintf(*opp, "%ld(r%d)", lv, (val >> 21) & 0x1F);
return(1);
}
static int op_p16(struct instr *ip, unsigned long val)
{
long lv;
lv = (long)val;
lv <<= 16;
lv >>= 14;
lv += cur_pc + 4;
sprintf(*opp, "0x%lx", lv);
return(1);
}
static int op_p26(struct instr *ip, unsigned long val)
{
long lv;
lv = (long)val & 0x03FFFFFF;
lv <<= 2;
lv |= ((cur_pc + 4) & 0xF0000000);
sprintf(*opp, "0x%lx", lv);
return(1);
}
static int op_null(struct instr *ip, unsigned long val)
{
return(0);
}
struct instr itab[] = {
{ "add", 0, 0x20, op5___11, op_r11, op_r21, op_r16 },
{ "addi", 8, 0x00, op26, op_r16, op_r21, op_i16 },
{ "addiu", 9, 0x00, op26, op_r16, op_r21, op_i16 },
{ "addu", 0, 0x21, op5___11, op_r11, op_r21, op_r16 },
{ "and", 0, 0x24, op5___11, op_r11, op_r21, op_r16 },
{ "andi", 0xc, 0, op26, op_r16, op_r21, op_u16 },
{ "beq", 0x4, 0, op26, op_r21, op_r16, op_p16 },
{ "beql", 0x14, 0, op26, op_r21, op_r16, op_p16 },
{ "bgez", 0x1, 0x1, op26_16, op_r21, op_p16, op_null },
{ "bgezal", 0x1, 0x11, op26_16, op_r21, op_p16, op_null },
{ "bgezall", 0x1, 0x13, op26_16, op_r21, op_p16, op_null },
{ "bgezl", 0x1, 0x03, op26_16, op_r21, op_p16, op_null },
{ "bgtz", 0x7, 0x0, op26_16, op_r21, op_p16, op_null },
{ "bgtzl", 0x17, 0x0, op26_16, op_r21, op_p16, op_null },
{ "blez", 0x6, 0x0, op26_16, op_r21, op_p16, op_null },
{ "blezl", 0x16, 0x0, op26_16, op_r21, op_p16, op_null },
{ "bltz", 0x1, 0x0, op26_16, op_r21, op_p16, op_null },
{ "bltzal", 0x1, 0x10, op26_16, op_r21, op_p16, op_null },
{ "bltzall", 0x1, 0x12, op26_16, op_r21, op_p16, op_null },
{ "bne", 0x5, 0x0, op26, op_r21, op_r16, op_p16 },
{ "bnel", 0x15, 0x0, op26, op_r21, op_r16, op_p16 },
/* { "break", 0x15, 0x0, op26_16, op_r21, op_r16, op_p16 }, */
/* { "cache", 0x15, 0x0, op26_16, op_r21, op_r16, op_p16 }, */
{ "div", 0, 0x1a, op26__16, op_r21, op_r16, op_null },
{ "divu", 0, 0x1b, op26__16, op_r21, op_r16, op_null },
{ "j", 2, 0, op26, op_p26, op_null, op_null },
{ "jal", 3, 0, op26, op_p26, op_null, op_null },
{ "jalr", 0, 0x9, op26_16_11, op_r11, op_r21, op_null },
{ "jr", 0, 0x8, op26_21, op_r21, op_null, op_null },
{ "lb", 0x20, 0, op26, op_r16, op_b21, op_null },
{ "lbu", 0x24, 0, op26, op_r16, op_b21, op_null },
{ "lh", 0x21, 0, op26, op_r16, op_b21, op_null },
{ "lhu", 0x25, 0, op26, op_r16, op_b21, op_null },
{ "ll", 0x30, 0, op26, op_r16, op_b21, op_null },
{ "lui", 0x0F, 0, op26, op_r16, op_h16, op_null },
{ "lw", 0x23, 0, op26, op_r16, op_b21, op_null },
{ "lwu", 0x2F, 0, op26, op_r16, op_b21, op_null },
{ "lwl", 0x22, 0, op26, op_r16, op_b21, op_null },
{ "lwr", 0x26, 0, op26, op_r16, op_b21, op_null },
{ "mult", 0, 0x18, op26__16, op_r21, op_r16, op_null },
{ "multu", 0, 0x19, op26__16, op_r21, op_r16, op_null },
{ "nor", 0, 0x27, op5___11, op_r11, op_r21, op_r16 },
{ "or", 0, 0x25, op5___11, op_r11, op_r21, op_r16 },
{ "ori", 0xd, 0, op26, op_r16, op_r21, op_u16 },
{ "sb", 0x28, 0, op26, op_r16, op_b21, op_null },
{ "sc", 0x38, 0, op26, op_r16, op_b21, op_null },
{ "sh", 0x29, 0, op26, op_r16, op_b21, op_null },
{ "sll", 0, 0, op26_5, op_r11, op_r16, op_i6 },
{ "sllv", 0, 4, op5___11, op_r11, op_r16, op_r21 },
{ "slt", 0, 0x2a, op5___11, op_r11, op_r21, op_r16 },
{ "slti", 0xa, 0, op26, op_r16, op_r21, op_i16 },
{ "sltiu", 0xb, 0, op26, op_r16, op_r21, op_i16 },
{ "sltu", 0, 0x2b, op5___11, op_r11, op_r21, op_r16 },
{ "sra", 0, 3, op21_6, op_r11, op_r16, op_i6 },
{ "srav", 0, 7, op5___11, op_r11, op_r16, op_r21 },
{ "srl", 0, 2, op21_6, op_r11, op_r16, op_i6 },
{ "srlv", 0, 6, op5___11, op_r11, op_r16, op_r21 },
{ "sub", 0, 0x22, op5___11, op_r11, op_r21, op_r16 },
{ "subu", 0, 0x23, op5___11, op_r11, op_r21, op_r16 },
{ "sw", 0x2b, 0, op26, op_r16, op_b21, op_null },
{ "swl", 0x2a, 0, op26, op_r16, op_b21, op_null },
{ "swr", 0x2e, 0, op26, op_r16, op_b21, op_null },
{ "sync", 0xf, 0, op32, op_null, op_null, op_null },
{ "syscall", 0xc, 0, op32, op_null, op_null, op_null },
{ "xor", 0, 0x26, op5___11, op_r11, op_r21, op_r16 },
{ "xori", 0x0e, 0, op26, op_r16, op_r21, op_u16 },
{ 0 }
};
char *mips_disass(unsigned long addr, unsigned long val)
{
struct instr *ip;
int i;
char *sep;
for(i = 0; i < 8; ++i) {
ops[i][0] = 0;
op[i] = ops[i];
}
opp = op;
cur_pc = addr;
for(ip = itab; ip->name; ++ip) {
if(ip->optype && ip->optype(ip, val)) {
strcpy(opcode, ip->name);
if(ip->op1(ip, val))
++opp;
if(ip->op2(ip, val))
++opp;
if(ip->op3(ip, val))
++opp;
break;
}
}
*op = 0; /* end of arguments */
if(!ip->name) {
sprintf(opcode, "Unknown opcode");
sprintf(ops[0], "0x%08lx", val);
ops[1][0] = 0;
}
strcpy(mneu, opcode);
sep = " ";
for(i = 0; ops[i][0]; ++i) {
strcat(mneu, sep);
strcat(mneu, ops[i]);
sep = ",";
}
return(mneu);
}
Also, this looks like it can only generate the machine code, rather than C code?