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?

Recommended Answers

All 3 Replies

its nearly impossible to take a compiled executable and reconstruct the c program. how is a decompiler even supposed to know the original source was written in c, or c++, or basic, or fortran, or ... ? Also it is not possible for it to reconstruct the structures that may have been used. So I think you are wasting your time if you expect the decompiler to generate c code for you. Just not going to happen.

It would be nearly imposible to reconstruct C code as all compilers will compile it slightly different. Also, the same compiler might do it differently twice.

> Also, this looks like it can only generate the machine code, rather than C code?
True, and it's also specific to the MIPS processor as well, which means that at best, it will only turn a MIPS a.out file back into MIPS assembly, which might give you a chance to reassemble it to MIPS elf format.

> It comes up with a ton of warnings and an undefined reference error for the mneu variable
This file is most likely just one of MANY files in the whole project. It also lacks a main() for example.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.