Example #1
0
int
ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
{
    char *pc, *pcLine;
    int nLine;
    EXPORT exp;
    int included;

    //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);

    /* Loop all lines */
    nLine = 1;
    exp.nNumber = 0;
    for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
    {
        pc = pcLine;

        exp.nArgCount = 0;
        exp.uFlags = 0;
        exp.nNumber++;

        //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
        //        nLine, TokenLength(pcLine), pcLine);

        /* Skip white spaces */
        while (*pc == ' ' || *pc == '\t') pc++;

        /* Skip empty lines, stop at EOF */
        if (*pc == ';' || *pc <= '#') continue;
        if (*pc == 0) return 0;

        //fprintf(stderr, "info: line %d, token:'%.*s'\n",
        //        nLine, TokenLength(pc), pc);

        /* Now we should get either an ordinal or @ */
        if (*pc == '@') exp.nOrdinal = -1;
        else exp.nOrdinal = atol(pc);

        /* Go to next token (type) */
        if (!(pc = NextToken(pc)))
        {
            fprintf(stderr, "error: line %d, unexpected end of line\n", nLine);
            return -10;
        }

        //fprintf(stderr, "info: Token:'%.10s'\n", pc);

        /* Now we should get the type */
        if (CompareToken(pc, "stdcall"))
        {
            exp.nCallingConvention = CC_STDCALL;
        }
        else if (CompareToken(pc, "cdecl") ||
                 CompareToken(pc, "varargs"))
        {
            exp.nCallingConvention = CC_CDECL;
        }
        else if (CompareToken(pc, "fastcall"))
        {
            exp.nCallingConvention = CC_FASTCALL;
        }
        else if (CompareToken(pc, "thiscall"))
        {
            exp.nCallingConvention = CC_THISCALL;
        }
        else if (CompareToken(pc, "extern"))
        {
            exp.nCallingConvention = CC_EXTERN;
        }
        else if (CompareToken(pc, "stub"))
        {
            exp.nCallingConvention = CC_STUB;
        }
        else
        {
            fprintf(stderr, "error: line %d, expected type, got '%.*s' %d\n",
                    nLine, TokenLength(pc), pc, *pc);
            return -11;
        }

        //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);

        /* Go to next token (options or name) */
        if (!(pc = NextToken(pc)))
        {
            fprintf(stderr, "fail2\n");
            return -12;
        }

        /* Handle options */
        included = 1;
        while (*pc == '-')
        {
            if (CompareToken(pc, "-arch"))
            {
                /* Default to not included */
                included = 0;
                pc += 5;

                /* Look if we are included */
                while (*pc == '=' || *pc == ',')
                {
                    pc++;
                    if (CompareToken(pc, pszArchString) ||
                        CompareToken(pc, pszArchString2))
                    {
                        included = 1;
                    }

                    /* Skip to next arch or end */
                    while (*pc > ',') pc++;
                }
            }
            else if (CompareToken(pc, "-i386"))
            {
                if (giArch != ARCH_X86) included = 0;
            }
            else if (CompareToken(pc, "-private"))
            {
                exp.uFlags |= FL_PRIVATE;
            }
            else if (CompareToken(pc, "-noname") ||
                     CompareToken(pc, "-ordinal"))
            {
                exp.uFlags |= FL_NONAME;
            }
            else if (CompareToken(pc, "-stub"))
            {
                exp.uFlags |= FL_STUB;
            }
            else if (CompareToken(pc, "-norelay") ||
                     CompareToken(pc, "-register") ||
                     CompareToken(pc, "-ret64"))
            {
                /* silently ignore these */
            }
            else
            {
                fprintf(stderr, "info: ignored option: '%.*s'\n",
                        TokenLength(pc), pc);
            }

            /* Go to next token */
            pc = NextToken(pc);
        }

        //fprintf(stderr, "info: Name:'%.10s'\n", pc);

        /* If arch didn't match ours, skip this entry */
        if (!included) continue;

        /* Get name */
        exp.pcName = pc;
        exp.nNameLength = TokenLength(pc);

        /* Handle parameters */
        exp.nStackBytes = 0;
        if (exp.nCallingConvention != CC_EXTERN &&
            exp.nCallingConvention != CC_STUB)
        {
            //fprintf(stderr, "info: options:'%.10s'\n", pc);
            /* Go to next token */
            if (!(pc = NextToken(pc)))
            {
                fprintf(stderr, "fail4\n");
                return -13;
            }

            /* Verify syntax */
            if (*pc++ != '(')
            {
                fprintf(stderr, "error: line %d, expected '('\n", nLine);
                return -14;
            }

            /* Skip whitespaces */
            while (*pc == ' ' || *pc == '\t') pc++;

            exp.nStackBytes = 0;
            while (*pc >= '0')
            {
                if (CompareToken(pc, "long"))
                {
                    exp.nStackBytes += 4;
                    exp.anArgs[exp.nArgCount] = ARG_LONG;
                }
                else if (CompareToken(pc, "double"))
                {
                    exp.nStackBytes += 8;
                    exp.anArgs[exp.nArgCount] = ARG_DBL;
                }
                else if (CompareToken(pc, "ptr") ||
                         CompareToken(pc, "str") ||
                         CompareToken(pc, "wstr"))
                {
                    exp.nStackBytes += 4; // sizeof(void*) on x86
                    exp.anArgs[exp.nArgCount] = ARG_PTR; // FIXME: handle strings
                }
                else if (CompareToken(pc, "int64"))
                {
                    exp.nStackBytes += 8;
                    exp.anArgs[exp.nArgCount] = ARG_INT64;
                }
                else if (CompareToken(pc, "int128"))
                {
                    exp.nStackBytes += 16;
                    exp.anArgs[exp.nArgCount] = ARG_INT128;
                }
                else if (CompareToken(pc, "float"))
                {
                    exp.nStackBytes += 4;
                    exp.anArgs[exp.nArgCount] = ARG_FLOAT;
                }
                else
                    fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc);

                exp.nArgCount++;

                /* Go to next parameter */
                if (!(pc = NextToken(pc)))
                {
                    fprintf(stderr, "fail5\n");
                    return -15;
                }
            }

            /* Check syntax */
            if (*pc++ != ')')
            {
                fprintf(stderr, "error: line %d, expected ')'\n", nLine);
                return -16;
            }
        }

        /* Handle special stub cases */
        if (exp.nCallingConvention == CC_STUB)
        {
            /* Check for c++ mangled name */
            if (pc[0] == '?')
            {
                //printf("Found c++ mangled name...\n");
                //
            }
            else
            {
                /* Check for stdcall name */
                char *p = strchr(pc, '@');
                if (p && ((size_t)(p - pc) < exp.nNameLength))
                {
                    int i;
                    exp.nNameLength = p - pc;
                    if (exp.nNameLength < 1)
                    {
                        fprintf(stderr, "error, @ in line %d\n", nLine);
                        return -1;
                    }
                    exp.nStackBytes = atoi(p + 1);
                    exp.nArgCount =  exp.nStackBytes / 4;
                    exp.nCallingConvention = CC_STDCALL;
                    exp.uFlags |= FL_STUB;
                    for (i = 0; i < exp.nArgCount; i++)
                        exp.anArgs[i] = ARG_LONG;
                }
            }
        }

        /* Get optional redirection */
        if ((pc = NextToken(pc)))
        {
            exp.pcRedirection = pc;
            exp.nRedirectionLength = TokenLength(pc);

            /* Check syntax (end of line) */
            if (NextToken(pc))
            {
                 fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine);
                 return -17;
            }
        }
        else
        {
            exp.pcRedirection = 0;
            exp.nRedirectionLength = 0;
        }

        OutputLine(fileDest, &exp);
    }

    return 0;
}
Example #2
0
int
ParseFile(char* pcStart, FILE *fileDest, PFNOUTLINE OutputLine)
{
    char *pc, *pcLine;
    int nLine;
    EXPORT exp;
    int included;
    char namebuffer[16];

    //fprintf(stderr, "info: line %d, pcStart:'%.30s'\n", nLine, pcStart);

    /* Loop all lines */
    nLine = 1;
    exp.nNumber = 0;
    for (pcLine = pcStart; *pcLine; pcLine = NextLine(pcLine), nLine++)
    {
        pc = pcLine;

        exp.nArgCount = 0;
        exp.uFlags = 0;
        exp.nNumber++;


        //if (!strncmp(pcLine, "22 stdcall @(long) MPR_Alloc",28))
        //    gbDebug = 1;

        //fprintf(stderr, "info: line %d, token:'%d, %.20s'\n",
        //        nLine, TokenLength(pcLine), pcLine);

        /* Skip white spaces */
        while (*pc == ' ' || *pc == '\t') pc++;

        /* Skip empty lines, stop at EOF */
        if (*pc == ';' || *pc <= '#') continue;
        if (*pc == 0) return 0;

        //fprintf(stderr, "info: line %d, token:'%.*s'\n",
        //        nLine, TokenLength(pc), pc);

        /* Now we should get either an ordinal or @ */
        if (*pc == '@')
            exp.nOrdinal = -1;
        else
        {
            exp.nOrdinal = atol(pc);
            /* The import lib should contain the ordinal only if -ordinal was specified */
            if (!gbImportLib)
                exp.uFlags |= FL_ORDINAL;
        }

        /* Go to next token (type) */
        if (!(pc = NextToken(pc)))
        {
            fprintf(stderr, "error: line %d, unexpected end of line\n", nLine);
            return -10;
        }

        //fprintf(stderr, "info: Token:'%.*s'\n", TokenLength(pc), pc);

        /* Now we should get the type */
        if (CompareToken(pc, "stdcall"))
        {
            exp.nCallingConvention = CC_STDCALL;
        }
        else if (CompareToken(pc, "cdecl") ||
                 CompareToken(pc, "varargs"))
        {
            exp.nCallingConvention = CC_CDECL;
        }
        else if (CompareToken(pc, "fastcall"))
        {
            exp.nCallingConvention = CC_FASTCALL;
        }
        else if (CompareToken(pc, "thiscall"))
        {
            exp.nCallingConvention = CC_THISCALL;
        }
        else if (CompareToken(pc, "extern"))
        {
            exp.nCallingConvention = CC_EXTERN;
        }
        else if (CompareToken(pc, "stub"))
        {
            exp.nCallingConvention = CC_STUB;
        }
        else
        {
            fprintf(stderr, "error: line %d, expected callconv, got '%.*s' %d\n",
                    nLine, TokenLength(pc), pc, *pc);
            return -11;
        }

        //fprintf(stderr, "info: nCallingConvention: %d\n", exp.nCallingConvention);

        /* Go to next token (options or name) */
        if (!(pc = NextToken(pc)))
        {
            fprintf(stderr, "fail2\n");
            return -12;
        }

        /* Handle options */
        included = 1;
        while (*pc == '-')
        {
            if (CompareToken(pc, "-arch"))
            {
                /* Default to not included */
                included = 0;
                pc += 5;

                /* Look if we are included */
                while (*pc == '=' || *pc == ',')
                {
                    pc++;
                    if (CompareToken(pc, pszArchString) ||
                        CompareToken(pc, pszArchString2))
                    {
                        included = 1;
                    }

                    /* Skip to next arch or end */
                    while (*pc > ',') pc++;
                }
            }
            else if (CompareToken(pc, "-i386"))
            {
                if (giArch != ARCH_X86) included = 0;
            }
            else if (CompareToken(pc, "-private"))
            {
                exp.uFlags |= FL_PRIVATE;
            }
            else if (CompareToken(pc, "-noname"))
            {
                exp.uFlags |= FL_ORDINAL | FL_NONAME;
            }
            else if (CompareToken(pc, "-ordinal"))
            {
                exp.uFlags |= FL_ORDINAL;
                /* GCC doesn't automatically import by ordinal if an ordinal
                 * is found in the def file. Force it. */
                if (gbImportLib && !gbMSComp)
                    exp.uFlags |= FL_NONAME;
            }
            else if (CompareToken(pc, "-stub"))
            {
                exp.uFlags |= FL_STUB;
            }
            else if (CompareToken(pc, "-norelay"))
            {
                exp.uFlags |= FL_NORELAY;
            }
            else if (CompareToken(pc, "-ret64"))
            {
                exp.uFlags |= FL_RET64;
            }
            else if (CompareToken(pc, "-register"))
            {
                exp.uFlags |= FL_REGISTER;
            }
            else
            {
                fprintf(stderr, "info: ignored option: '%.*s'\n",
                        TokenLength(pc), pc);
            }

            /* Go to next token */
            pc = NextToken(pc);
        }

        //fprintf(stderr, "info: Name:'%.10s'\n", pc);

        /* If arch didn't match ours, skip this entry */
        if (!included) continue;

        /* Get name */
        exp.strName.buf = pc;
        exp.strName.len = TokenLength(pc);
        DbgPrint("Got name: '%.*s'\n", exp.strName.len, exp.strName.buf);

        /* Check for autoname */
        if ((exp.strName.len == 1) && (exp.strName.buf[0] == '@'))
        {
            sprintf(namebuffer, "ordinal%d", exp.nOrdinal);
            exp.strName.len = strlen(namebuffer);
            exp.strName.buf = namebuffer;
            exp.uFlags |= FL_ORDINAL | FL_NONAME;
        }

        /* Handle parameters */
        exp.nStackBytes = 0;
        if (exp.nCallingConvention != CC_EXTERN &&
            exp.nCallingConvention != CC_STUB)
        {
            /* Go to next token */
            if (!(pc = NextToken(pc)))
            {
                fprintf(stderr, "fail4\n");
                return -13;
            }

            /* Verify syntax */
            if (*pc++ != '(')
            {
                fprintf(stderr, "error: line %d, expected '('\n", nLine);
                return -14;
            }

            /* Skip whitespaces */
            while (*pc == ' ' || *pc == '\t') pc++;

            exp.nStackBytes = 0;
            while (*pc >= '0')
            {
                if (CompareToken(pc, "long"))
                {
                    exp.nStackBytes += 4;
                    exp.anArgs[exp.nArgCount] = ARG_LONG;
                }
                else if (CompareToken(pc, "double"))
                {
                    exp.nStackBytes += 8;
                    exp.anArgs[exp.nArgCount] = ARG_DBL;
                }
                else if (CompareToken(pc, "ptr"))
                {
                    exp.nStackBytes += 4; // sizeof(void*) on x86
                    exp.anArgs[exp.nArgCount] = ARG_PTR;
                }
                else if (CompareToken(pc, "str"))
                {
                    exp.nStackBytes += 4; // sizeof(void*) on x86
                    exp.anArgs[exp.nArgCount] = ARG_STR;
                }
                else if (CompareToken(pc, "wstr"))
                {
                    exp.nStackBytes += 4; // sizeof(void*) on x86
                    exp.anArgs[exp.nArgCount] = ARG_WSTR;
                }
                else if (CompareToken(pc, "int64"))
                {
                    exp.nStackBytes += 8;
                    exp.anArgs[exp.nArgCount] = ARG_INT64;
                }
                else if (CompareToken(pc, "int128"))
                {
                    exp.nStackBytes += 16;
                    exp.anArgs[exp.nArgCount] = ARG_INT128;
                }
                else if (CompareToken(pc, "float"))
                {
                    exp.nStackBytes += 4;
                    exp.anArgs[exp.nArgCount] = ARG_FLOAT;
                }
                else
                    fprintf(stderr, "error: line %d, expected type, got: %.10s\n", nLine, pc);

                exp.nArgCount++;

                /* Go to next parameter */
                if (!(pc = NextToken(pc)))
                {
                    fprintf(stderr, "fail5\n");
                    return -15;
                }
            }

            /* Check syntax */
            if (*pc++ != ')')
            {
                fprintf(stderr, "error: line %d, expected ')'\n", nLine);
                return -16;
            }
        }

        /* Handle special stub cases */
        if (exp.nCallingConvention == CC_STUB)
        {
            /* Check for c++ mangled name */
            if (pc[0] == '?')
            {
                //printf("Found c++ mangled name...\n");
                //
            }
            else
            {
                /* Check for stdcall name */
                const char *p = ScanToken(pc, '@');
                if (p && (p - pc < exp.strName.len))
                {
                    int i;

                    /* Truncate the name to before the @ */
                    exp.strName.len = (int)(p - pc);
                    if (exp.strName.len < 1)
                    {
                        fprintf(stderr, "error, @ in line %d\n", nLine);
                        return -1;
                    }
                    exp.nStackBytes = atoi(p + 1);
                    exp.nArgCount =  exp.nStackBytes / 4;
                    exp.nCallingConvention = CC_STDCALL;
                    exp.uFlags |= FL_STUB;
                    for (i = 0; i < exp.nArgCount; i++)
                        exp.anArgs[i] = ARG_LONG;
                }
            }
        }

        /* Get optional redirection */
        pc = NextToken(pc);
        if (pc)
        {
            exp.strTarget.buf = pc;
            exp.strTarget.len = TokenLength(pc);

            /* Check syntax (end of line) */
            if (NextToken(pc))
            {
                 fprintf(stderr, "error: line %d, additional tokens after ')'\n", nLine);
                 return -17;
            }

            /* Don't relay-trace forwarded functions */
            exp.uFlags |= FL_NORELAY;
        }
        else
        {
            exp.strTarget.buf = 0;
            exp.strTarget.len = 0;
        }

        /* Check for no-name without ordinal */
        if ((exp.uFlags & FL_ORDINAL) && (exp.nOrdinal == -1))
        {
            fprintf(stderr, "error: line %d, ordinal export without ordinal!\n", nLine);
            return -1;
        }

        OutputLine(fileDest, &exp);
        gbDebug = 0;
    }

    return 0;
}