⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stabs.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
    memset(srcpath, 0, sizeof(srcpath));
    memset(stabs_basic, 0, sizeof(stabs_basic));

    /*
     * Allocate a buffer into which we can build stab strings for cases
     * where the stab is continued over multiple lines.
     */
    stabbufflen = 65536;
    stabbuff = HeapAlloc(GetProcessHeap(), 0, stabbufflen);

    strtabinc = 0;
    stabbuff[0] = '\0';
    for (i = 0; i < nstab; i++, stab_ptr++)
    {
        ptr = strs + stab_ptr->n_un.n_strx;
        if ((ptr > strs_end) || (ptr + strlen(ptr) > strs_end))
        {
            WARN("Bad stabs string %p\n", ptr);
            continue;
        }
        if (ptr[strlen(ptr) - 1] == '\\')
        {
            /*
             * Indicates continuation.  Append this to the buffer, and go onto the
             * next record.  Repeat the process until we find a stab without the
             * '/' character, as this indicates we have the whole thing.
             */
            unsigned    len = strlen(ptr);
            if (strlen(stabbuff) + len > stabbufflen)
            {
                stabbufflen += 65536;
                stabbuff = HeapReAlloc(GetProcessHeap(), 0, stabbuff, stabbufflen);
            }
            strncat(stabbuff, ptr, len - 1);
            continue;
        }
        else if (stabbuff[0] != '\0')
        {
            strcat(stabbuff, ptr);
            ptr = stabbuff;
        }

        /* only symbol entries contain a typedef */
        switch (stab_ptr->n_type)
        {
        case N_GSYM:
        case N_LCSYM:
        case N_STSYM:
        case N_RSYM:
        case N_LSYM:
        case N_ROSYM:
            if (strchr(ptr, '=') != NULL)
            {
                /*
                 * The stabs aren't in writable memory, so copy it over so we are
                 * sure we can scribble on it.
                 */
                if (ptr != stabbuff)
                {
                    strcpy(stabbuff, ptr);
                    ptr = stabbuff;
                }
                stab_strcpy(symname, sizeof(symname), ptr);
                if (!stabs_parse_typedef(module, ptr, symname))
                {
                    /* skip this definition */
                    stabbuff[0] = '\0';
                    continue;
                }
            }
        }

#if 0
        const char* defs[] = {"","","","",                      /* 00 */
                              "","","","",                      /* 08 */
                              "","","","",                      /* 10 */
                              "","","","",                      /* 18 */
                              "gsym","","fun","stsym",          /* 20 */
                              "lcsym","main","rosym","",        /* 28 */
                              "","","","",                      /* 30 */
                              "","","opt","",                   /* 38 */
                              "rsym","","sline","",             /* 40 */
                              "","","","",                      /* 48 */
                              "","","","",                      /* 50 */
                              "","","","",                      /* 58 */
                              "","","so","",                    /* 60 */
                              "","","","",                      /* 68 */
                              "","","","",                      /* 70 */
                              "","","","",                      /* 78 */
                              "lsym","bincl","sol","",          /* 80 */
                              "","","","",                      /* 88 */
                              "","","","",                      /* 90 */
                              "","","","",                      /* 98 */
                              "psym","eincl","","",             /* a0 */
                              "","","","",                      /* a8 */
                              "","","","",                      /* b0 */
                              "","","","",                      /* b8 */
                              "lbrac","excl","","",             /* c0 */
                              "","","","",                      /* c8 */
                              "","","","",                      /* d0 */
                              "","","","",                      /* d8 */
                              "rbrac","","","",                 /* e0 */
        };

        FIXME("Got %s<%u> %u/%lu (%s)\n", 
              defs[stab_ptr->n_type / 2], stab_ptr->n_type, stab_ptr->n_desc, stab_ptr->n_value, debugstr_a(ptr));
#endif

        switch (stab_ptr->n_type)
        {
        case N_GSYM:
            /*
             * These are useless with ELF.  They have no value, and you have to
             * read the normal symbol table to get the address.  Thus we
             * ignore them, and when we process the normal symbol table
             * we should do the right thing.
             *
             * With a.out or mingw, they actually do make some amount of sense.
             */
            stab_strcpy(symname, sizeof(symname), ptr);
            symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
                                     load_offset + stab_ptr->n_value, 0,
                                     stabs_parse_type(ptr));
            break;
        case N_LCSYM:
        case N_STSYM:
            /* These are static symbols and BSS symbols. */
            stab_strcpy(symname, sizeof(symname), ptr);
            symt_new_global_variable(module, compiland, symname, TRUE /* FIXME */,
                                     load_offset + stab_ptr->n_value, 0,
                                     stabs_parse_type(ptr));
            break;
        case N_LBRAC:
            block = symt_open_func_block(module, curr_func, block,
                                         stab_ptr->n_value, 0);
            for (j = 0; j < num_pending_vars; j++)
            {
                symt_add_func_local(module, curr_func, pending_vars[j].regno, 
                                    pending_vars[j].offset,
                                    block, pending_vars[j].type, pending_vars[j].name);
            }
            num_pending_vars = 0;
            break;
        case N_RBRAC:
            block = symt_close_func_block(module, curr_func, block,
                                          stab_ptr->n_value);
            break;
        case N_PSYM:
            /* These are function parameters. */
            if (curr_func != NULL)
            {
                struct symt*    param_type = stabs_parse_type(ptr);
                stab_strcpy(symname, sizeof(symname), ptr);
                symt_add_func_local(module, curr_func, 0, stab_ptr->n_value, 
                                    NULL, param_type, symname);
                symt_add_function_signature_parameter(module, 
                                                      (struct symt_function_signature*)curr_func->type, 
                                                      param_type);
            }
            break;
        case N_RSYM:
            /* These are registers (as local variables) */
            if (curr_func != NULL)
            {
                unsigned reg;

                if (num_pending_vars == num_allocated_pending_vars)
                {
                    num_allocated_pending_vars += 8;
                    if (!pending_vars)
                        pending_vars = HeapAlloc(GetProcessHeap(), 0, 
                                                 num_allocated_pending_vars * sizeof(pending_vars[0]));
                    else
                        pending_vars = HeapReAlloc(GetProcessHeap(), 0, pending_vars,
                                                   num_allocated_pending_vars * sizeof(pending_vars[0]));
                }
                switch (stab_ptr->n_value)
                {
                case  0: reg = CV_REG_EAX; break;
                case  1: reg = CV_REG_ECX; break;
                case  2: reg = CV_REG_EDX; break;
                case  3: reg = CV_REG_EBX; break;
                case  4: reg = CV_REG_ESP; break;
                case  5: reg = CV_REG_EBP; break;
                case  6: reg = CV_REG_ESI; break;
                case  7: reg = CV_REG_EDI; break;
                case 11:
                case 12:
                case 13:
                case 14:
                case 15:
                case 16:
                case 17:
                case 18:
                case 19: reg = CV_REG_ST0 + stab_ptr->n_value - 12; break;
                default:
                    FIXME("Unknown register value (%lu)\n", stab_ptr->n_value);
                    reg = CV_REG_NONE;
                    break;
                }

                stab_strcpy(pending_vars[num_pending_vars].name, 
                            sizeof(pending_vars[num_pending_vars].name), ptr);
                pending_vars[num_pending_vars].type   = stabs_parse_type(ptr);
                pending_vars[num_pending_vars].offset = 0;
                pending_vars[num_pending_vars].regno  = reg;
                num_pending_vars++;
            }
            break;
        case N_LSYM:
            /* These are local variables */
            if (curr_func != NULL)
            {
                if (num_pending_vars == num_allocated_pending_vars)
                {
                    num_allocated_pending_vars += 8;
                    if (!pending_vars)
                        pending_vars = HeapAlloc(GetProcessHeap(), 0, 
                                                 num_allocated_pending_vars * sizeof(pending_vars[0]));
                    else
                        pending_vars = HeapReAlloc(GetProcessHeap(), 0, pending_vars,
                                                   num_allocated_pending_vars * sizeof(pending_vars[0]));
                }                        
                stab_strcpy(pending_vars[num_pending_vars].name, 
                            sizeof(pending_vars[num_pending_vars].name), ptr);
                pending_vars[num_pending_vars].type   = stabs_parse_type(ptr);
                pending_vars[num_pending_vars].offset = stab_ptr->n_value;
                pending_vars[num_pending_vars].regno  = 0;
                num_pending_vars++;
            }
            break;
        case N_SLINE:
            /*
             * This is a line number.  These are always relative to the start
             * of the function (N_FUN), and this makes the lookup easier.
             */
            if (curr_func != NULL)
            {
                assert(source_idx >= 0);
                symt_add_func_line(module, curr_func, source_idx, 
                                   stab_ptr->n_desc, stab_ptr->n_value);
            }
            break;
        case N_FUN:
            /* First, clean up the previous function we were working on. */
            stabs_finalize_function(module, curr_func, 
                                    stab_ptr->n_value ? load_offset + stab_ptr->n_value : 0);

            /*
             * For now, just declare the various functions.  Later
             * on, we will add the line number information and the
             * local symbols.
             */
            /*
             * Copy the string to a temp buffer so we
             * can kill everything after the ':'.  We do
             * it this way because otherwise we end up dirtying
             * all of the pages related to the stabs, and that
             * sucks up swap space like crazy.
             */
            stab_strcpy(symname, sizeof(symname), ptr);
            if (*symname)
            {
                struct symt_function_signature* func_type;
                func_type = symt_new_function_signature(module, 
                                                        stabs_parse_type(ptr));
                curr_func = symt_new_function(module, compiland, symname, 
                                              load_offset + stab_ptr->n_value, 0,
                                              &func_type->symt);
            }
            else
            {
                /* some GCC seem to use a N_FUN "" to mark the end of a function */
                curr_func = NULL;
            }
            break;
        case N_SO:
            /*
             * This indicates a new source file.  Append the records
             * together, to build the correct path name.
             */
            if (*ptr == '\0') /* end of N_SO file */
            {
                /* Nuke old path. */
                srcpath[0] = '\0';
                stabs_finalize_function(module, curr_func, 
                                        stab_ptr->n_value ? load_offset + stab_ptr->n_value : 0);
                curr_func = NULL;
                source_idx = -1;
                incl_stk = -1;
                assert(block == NULL);
                compiland = NULL;
            }
            else
            {
                int len = strlen(ptr);
                if (ptr[len-1] != '/')
                {
                    strcpy(currpath, srcpath);
                    strcat(currpath, ptr);
                    stabs_reset_includes();
                    compiland = symt_new_compiland(module, currpath);
                    source_idx = source_new(module, currpath);
                }
                else
                    strcpy(srcpath, ptr);
            }
            break;
        case N_SOL:
            if (*ptr != '/')
            {
                strcpy(currpath, srcpath);
                strcat(currpath, ptr);
            }
            else
                strcpy(currpath, ptr);
            source_idx = source_new(module, currpath);
            break;
        case N_UNDF:
            strs += strtabinc;
            strtabinc = stab_ptr->n_value;
            /* I'm not sure this is needed, so trace it before we obsolete it */
            if (curr_func) FIXME("UNDF: curr_func %s\n", curr_func->hash_elt.name);
            stabs_finalize_function(module, curr_func, 0); /* FIXME */
            curr_func = NULL;
            break;
        case N_OPT:
            /* Ignore this. We don't care what it points to. */
            break;
        case N_BINCL:
            stabs_add_include(stabs_new_include(ptr, stab_ptr->n_value));
            assert(incl_stk < (int)(sizeof(incl) / sizeof(incl[0])) - 1);
            incl[++incl_stk] = source_idx;
            source_idx = source_new(module, ptr);
            break;
        case N_EINCL:
            assert(incl_stk >= 0);
            source_idx = incl[incl_stk--];
            break;
	case N_EXCL:
            if (stabs_add_include(stabs_find_include(ptr, stab_ptr->n_value)) < 0)
            {
                ERR("Excluded header not found (%s,%ld)\n", ptr, stab_ptr->n_value);
                module_reset_debug_info(module);
                ret = FALSE;
                goto done;
            }
            break;
        case N_MAIN:
            /* Always ignore these. GCC doesn't even generate them. */
            break;
        default:
            ERR("Unknown stab type 0x%02x\n", stab_ptr->n_type);
            break;
        }
        stabbuff[0] = '\0';
        TRACE("0x%02x %lx %s\n", 
              stab_ptr->n_type, stab_ptr->n_value, debugstr_a(strs + stab_ptr->n_un.n_strx));
    }
    module->module.SymType = SymDia;
done:
    HeapFree(GetProcessHeap(), 0, stabbuff);
    stabs_free_includes();
    if (pending_vars) HeapFree(GetProcessHeap(), 0, pending_vars);

    return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -