示例#1
0
// Specific to BinaryFile objects that implement a "global pointer"
// Gets a pair of unsigned integers representing the address of %agp,
// and the value for GLOBALOFFSET. For Palm, the latter is the amount of
// space allocated below %a5, i.e. the difference between %a5 and %agp
// (%agp points to the bottom of the global data area).
std::pair<unsigned,unsigned> PalmBinaryFile::GetGlobalPointerInfo()
{
    unsigned agp = 0;
    const SectionInfo* ps = GetSectionInfoByName("data0");
    if (ps) agp = ps->uNativeAddr;
    std::pair<unsigned, unsigned> ret(agp, m_SizeBelowA5);
    return ret;
}
示例#2
0
// This is provided for completeness only...
std::list<SectionInfo*>& PalmBinaryFile::GetEntryPoints(const char* pEntry
        /* = "main" */)
{
    std::list<SectionInfo*>* ret = new std::list<SectionInfo*>;
    SectionInfo* pSect = GetSectionInfoByName("code1");
    if (pSect == 0)
        return *ret;               // Failed
    ret->push_back(pSect);
    return *ret;
}
示例#3
0
// This is provided for completeness only...
std::list<SectionInfo*>& ExeBinaryFile::GetEntryPoints(const char* pEntry
  /* = "main"*/) {
    std::list<SectionInfo*>* ret = new std::list<SectionInfo*>;
#if 0           // Copied from PalmBinaryFile.cc
    SectionInfo* pSect = GetSectionInfoByName("code1");
    if (pSect == 0)
        return *ret;               // Failed
    ret->push_back(pSect);
#endif
    return *ret;
}
示例#4
0
// Find the native address for the start of the main entry function.
// For Palm binaries, this is PilotMain.
ADDRESS PalmBinaryFile::GetMainEntryPoint()
{
    SectionInfo* pSect = GetSectionInfoByName("code1");
    if (pSect == 0)
        return 0;               // Failed
    // Return the start of the code1 section
    SWord* startCode = (SWord*) pSect->uHostAddr;
    ptrdiff_t delta = pSect->uHostAddr - (unsigned char *)pSect->uNativeAddr;

    // First try the CW first jump pattern
    SWord* res = findPattern(startCode, CWFirstJump,
                             sizeof(CWFirstJump) / sizeof(SWord), 1);
    if (res)
        {
            // We have the code warrior first jump. Get the addil operand
            int addilOp = (startCode[5] << 16) + startCode[6];
            SWord* startupCode = (SWord*)((unsigned char *)startCode + 10 + addilOp);
            // Now check the next 60 SWords for the call to PilotMain
            res = findPattern(startupCode, CWCallMain,
                              sizeof(CWCallMain) / sizeof(SWord), 60);
            if (res)
                {
                    // Get the addil operand
                    addilOp = (res[5] << 16) + res[6];
                    // That operand plus the address of that operand is PilotMain
                    return (ADDRESS)res + 10 + addilOp - delta;
                }
            else
                {
                    fprintf( stderr, "Could not find call to PilotMain in CW app\n" );
                    return 0;
                }
        }
    // Check for gcc call to main
    res = findPattern(startCode, GccCallMain,
                      sizeof(GccCallMain) / sizeof(SWord), 75);
    if (res)
        {
            // Get the operand to the bsr
            SWord bsrOp = res[7];
            return (ADDRESS)res + 14 + bsrOp - delta;
        }

    fprintf(stderr,"Cannot find call to PilotMain\n");
    return 0;
}
示例#5
0
ADDRESS DOS4GWBinaryFile::GetMainEntryPoint() {
    ADDRESS aMain = GetAddressByName ("main", true);
    if (aMain != NO_ADDRESS)
        return aMain;
    aMain = GetAddressByName ("__CMain", true);
    if (aMain != NO_ADDRESS)
        return aMain;

    // Search with this crude pattern: call, sub ebp, ebp, call __Cmain in the first 0x300 bytes
    // Start at program entry point
    unsigned p = LMMH(m_pLXHeader->eip);
    unsigned lim = p + 0x300;
    unsigned char op1, op2;
        ADDRESS addr;
    //unsigned lastOrdCall = 0; //TODO: identify the point of setting this variable
    bool gotSubEbp = false;            // True if see sub ebp, ebp
    bool lastWasCall = false;        // True if the last instruction was a call

    SectionInfo* si = GetSectionInfoByName("seg0");        // Assume the first section is text
    if (si == nullptr) si = GetSectionInfoByName(".text");
    if (si == nullptr) si = GetSectionInfoByName("CODE");
    assert(si);
    ADDRESS nativeOrigin = si->uNativeAddr;
    unsigned textSize = si->uSectionSize;
    if (textSize < 0x300)
        lim = p + textSize;

    while (p < lim) {
        op1 = *(unsigned char*)(p + base);
        op2 = *(unsigned char*)(p + base + 1);
        //std::cerr << std::hex << "At " << p << ", ops " << (unsigned)op1 << ", " << (unsigned)op2 << std::dec << "\n";
        switch (op1) {
            case 0xE8: {
                // An ordinary call
                if (gotSubEbp) {
                    // This is the call we want. Get the offset from the call instruction
                    addr = nativeOrigin + p + 5 + LMMH(*(p + base + 1));
                    // std::cerr << "__CMain at " << std::hex << addr << "\n";
                    return addr;
                }
                //lastOrdCall = p;
                lastWasCall = true;
                break;
            }
            case 0x2B:            // 0x2B 0xED is sub ebp,ebp
                if (op2 == 0xED && lastWasCall)
                    gotSubEbp = true;
                lastWasCall = false;
                break;
            default:
                gotSubEbp = false;
                lastWasCall = false;
                break;
            case 0xEB:                     // Short relative jump
                if (op2 >= 0x80)        // Branch backwards?
                    break;                // Yes, just ignore it
                // Otherwise, actually follow the branch. May have to modify this some time...
                p += op2+2;                // +2 for the instruction itself, and op2 for the displacement
                continue;                // Don't break, we have the new "pc" set already
        }
        int size = microX86Dis(p + base);
        if (size == 0x40) {
            fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
            size = 1;
        }
        p += size;
    }
    return NO_ADDRESS;
}
示例#6
0
bool PalmBinaryFile::RealLoad(const char* sName)
{
    FILE    *fp;
    char    buf[32];

    m_pFileName = sName;

    if ((fp = fopen(sName, "rb")) == NULL)
        {
            fprintf(stderr, "Could not open binary file %s\n", sName);
            return false;
        }

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);

    // Allocate a buffer for the image
    m_pImage = new unsigned char[size];
    if (m_pImage == 0)
        {
            fprintf(stderr, "Could not allocate %ld bytes for image\n", size);
            return false;
        }
    memset(m_pImage, size, 0);

    fseek(fp, 0, SEEK_SET);
    if (fread(m_pImage, 1, size, fp) != (unsigned)size)
        {
            fprintf(stderr, "Error reading binary file %s\n", sName);
            return false;
        }

    // Check type at offset 0x3C; should be "appl" (or "palm"; ugh!)
    if ((strncmp((char*)(m_pImage+0x3C), "appl", 4) != 0) &&
            (strncmp((char*)(m_pImage+0x3C), "panl", 4) != 0) &&
            (strncmp((char*)(m_pImage+0x3C), "libr", 4) != 0))
        {
            fprintf(stderr, "%s is not a standard .prc file\n", sName);
            return false;
        }

    // Get the number of resource headers (one section per resource)
    m_iNumSections = (m_pImage[0x4C] << 8) + m_pImage[0x4D];

    // Allocate the section information
    m_pSections = new SectionInfo[m_iNumSections];
    if (m_pSections == 0)
        {
            fprintf(stderr, "Could not allocate section info array of %d items\n",
                    m_iNumSections);
            if (m_pImage)
                {
                    delete m_pImage;
                    m_pImage = 0;
                }
        }

    // Iterate through the resource headers (generating section info structs)
    unsigned char* p = m_pImage + 0x4E;          // First resource header
    unsigned off = 0;
    for (int i=0; i < m_iNumSections; i++)
        {
            // First get the name (4 alpha)
            strncpy(buf, (char*)p, 4);
            buf[4] = '\0';
            std::string name(buf);
            // Now get the identifier (2 byte binary)
            unsigned id = (p[4] << 8) + p[5];
            sprintf(buf, "%d", id);
            // Join the id to the name, e.g. code0, data12
            name += buf;
            m_pSections[i].pSectionName = new char[name.size()+1];
            strcpy(m_pSections[i].pSectionName, name.c_str());
            p += 4+2;
            off = UINT4(p);
            p += 4;
            m_pSections[i].uNativeAddr = off;
            m_pSections[i].uHostAddr = off + m_pImage;

            // Guess the length
            if (i > 0)
                {
                    m_pSections[i-1].uSectionSize = off - m_pSections[i-1].uNativeAddr;
                    m_pSections[i].uSectionEntrySize = 1;        // No info available
                }

            // Decide if code or data; note that code0 is a special case (not code)
            m_pSections[i].bCode =
                (name != "code0") && (name.substr(0, 4) == "code");
            m_pSections[i].bData = name.substr(0, 4) == "data";

        }

    // Set the length for the last section
    m_pSections[m_iNumSections-1].uSectionSize = size - off;

    // Create a separate, uncompressed, initialised data section
    SectionInfo* pData = GetSectionInfoByName("data0");
    if (pData == 0)
        {
            fprintf(stderr, "No data section!\n");
            return false;
        }

    SectionInfo* pCode0 = GetSectionInfoByName("code0");
    if (pCode0 == 0)
        {
            fprintf(stderr, "No code 0 section!\n");
            return false;
        }

    // When the info is all boiled down, the two things we need from the
    // code 0 section are at offset 0, the size of data above a5, and at
    // offset 4, the size below. Save the size below as a member variable
    m_SizeBelowA5 = UINT4(pCode0->uHostAddr+4);
    // Total size is this plus the amount above (>=) a5
    unsigned sizeData = m_SizeBelowA5 + UINT4(pCode0->uHostAddr);

    // Allocate a new data section
    m_pData = new unsigned char[sizeData];
    if (m_pData == 0)
        {
            fprintf(stderr, "Could not allocate %u bytes for data section\n",
                    sizeData);
        }

    // Uncompress the data. Skip first long (offset of CODE1 "xrefs")
    p = (unsigned char*)(pData->uHostAddr+4);
    int start = (int) UINT4(p);
    p += 4;
    unsigned char* q = (m_pData + m_SizeBelowA5 + start);
    bool done = false;
    while (!done && (p < (unsigned char*)(pData->uHostAddr +
                                          pData->uSectionSize)))
        {
            unsigned char rle = *p++;
            if (rle == 0)
                {
                    done = true;
                    break;
                }
            else if (rle == 1)
                {
                    // 0x01 b_0 b_1
                    // => 0x00 0x00 0x00 0x00 0xFF 0xFF b_0 b_1
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0xFF;
                    *q++ = 0xFF;
                    *q++ = *p++;
                    *q++ = *p++;
                }
            else if (rle == 2)
                {
                    // 0x02 b_0 b_1 b_2
                    // => 0x00 0x00 0x00 0x00 0xFF b_0 b_1 b_2
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = 0xFF;
                    *q++ = *p++;
                    *q++ = *p++;
                    *q++ = *p++;
                }
            else if (rle == 3)
                {
                    // 0x03 b_0 b_1 b_2
                    // => 0xA9 0xF0 0x00 0x00 b_0 b_1 0x00 b_2
                    *q++ = 0xA9;
                    *q++ = 0xF0;
                    *q++ = 0;
                    *q++ = 0;
                    *q++ = *p++;
                    *q++ = *p++;
                    *q++ = 0;
                    *q++ = *p++;
                }
            else if (rle == 4)
                {
                    // 0x04 b_0 b_1 b_2 b_3
                    // => 0xA9 axF0 0x00 b_0 b_1 b_3 0x00 b_3
                    *q++ = 0xA9;
                    *q++ = 0xF0;
                    *q++ = 0;
                    *q++ = *p++;
                    *q++ = *p++;
                    *q++ = *p++;
                    *q++ = 0;
                    *q++ = *p++;
                }
            else if (rle < 0x10)
                {
                    // 5-0xF are invalid.
                    assert(0);
                }
            else if (rle >= 0x80)
                {
                    // n+1 bytes of literal data
                    for (int k=0; k <= (rle-0x80); k++)
                        *q++ = *p++;
                }
            else if (rle >= 40)
                {
                    // n+1 repetitions of 0
                    for (int k=0; k <= (rle-0x40); k++)
                        *q++ = 0;
                }
            else if (rle >= 20)
                {
                    // n+2 repetitions of b
                    unsigned char b = *p++;
                    for (int k=0; k < (rle-0x20+2); k++)
                        *q++ = b;
                }
            else
                {
                    // 0x10: n+1 repetitions of 0xFF
                    for (int k=0; k <= (rle-0x10); k++)
                        *q++ = 0xFF;
                }
        }

    if (!done)
        fprintf(stderr, "Warning! Compressed data section premature end\n");
//printf("Used %u bytes of %u in decompressing data section\n",
//p-(unsigned char*)pData->uHostAddr, pData->uSectionSize);

    // Replace the data pointer and size with the uncompressed versions
    pData->uHostAddr = m_pData;
    pData->uSectionSize = sizeData;
    // May as well make the native address zero; certainly the offset in the
    // file is no longer appropriate (and is confusing)
    pData->uNativeAddr = 0;

    return true;
}