📄 msc.c
字号:
const unsigned int* filetab;
const struct p_string* p_fn;
int i;
int k;
struct codeview_linetab* lt_hdr;
const unsigned int* lt_ptr;
int nfile;
int nseg;
union any_size pnt;
union any_size pnt2;
const struct startend* start;
int this_seg;
struct symt_compiland* compiland;
/*
* Now get the important bits.
*/
pnt.c = linetab;
nfile = *pnt.s++;
nseg = *pnt.s++;
filetab = (const unsigned int*) pnt.c;
/*
* Now count up the number of segments in the file.
*/
nseg = 0;
for (i = 0; i < nfile; i++)
{
pnt2.c = linetab + filetab[i];
nseg += *pnt2.s;
}
/*
* Next allocate the header we will be returning.
* There is one header for each segment, so that we can reach in
* and pull bits as required.
*/
lt_hdr = (struct codeview_linetab*)
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nseg + 1) * sizeof(*lt_hdr));
if (lt_hdr == NULL)
{
goto leave;
}
/*
* Now fill the header we will be returning, one for each segment.
* Note that this will basically just contain pointers into the existing
* line table, and we do not actually copy any additional information
* or allocate any additional memory.
*/
this_seg = 0;
for (i = 0; i < nfile; i++)
{
/*
* Get the pointer into the segment information.
*/
pnt2.c = linetab + filetab[i];
file_segcount = *pnt2.s;
pnt2.ui++;
lt_ptr = (const unsigned int*) pnt2.c;
start = (const struct startend*)(lt_ptr + file_segcount);
/*
* Now snarf the filename for all of the segments for this file.
*/
if (pascal_str)
{
p_fn = (const struct p_string*)(start + file_segcount);
memset(filename, 0, sizeof(filename));
memcpy(filename, p_fn->name, p_fn->namelen);
compiland = symt_new_compiland(module, filename);
}
else
compiland = symt_new_compiland(module, (const char*)(start + file_segcount));
for (k = 0; k < file_segcount; k++, this_seg++)
{
pnt2.c = linetab + lt_ptr[k];
lt_hdr[this_seg].start = start[k].start;
lt_hdr[this_seg].end = start[k].end;
lt_hdr[this_seg].compiland = compiland;
lt_hdr[this_seg].segno = *pnt2.s++;
lt_hdr[this_seg].nline = *pnt2.s++;
lt_hdr[this_seg].offtab = pnt2.ui;
lt_hdr[this_seg].linetab = (const unsigned short*)(pnt2.ui + lt_hdr[this_seg].nline);
}
}
leave:
return lt_hdr;
}
/*========================================================================
* Process CodeView symbol information.
*/
static unsigned int codeview_map_offset(const struct msc_debug_info* msc_dbg,
unsigned int offset)
{
int nomap = msc_dbg->nomap;
const OMAP_DATA* omapp = msc_dbg->omapp;
int i;
if (!nomap || !omapp) return offset;
/* FIXME: use binary search */
for (i = 0; i < nomap - 1; i++)
if (omapp[i].from <= offset && omapp[i+1].from > offset)
return !omapp[i].to ? 0 : omapp[i].to + (offset - omapp[i].from);
return 0;
}
static const struct codeview_linetab*
codeview_get_linetab(const struct codeview_linetab* linetab,
unsigned seg, unsigned offset)
{
/*
* Check whether we have line number information
*/
if (linetab)
{
for (; linetab->linetab; linetab++)
if (linetab->segno == seg &&
linetab->start <= offset && linetab->end > offset)
break;
if (!linetab->linetab) linetab = NULL;
}
return linetab;
}
static unsigned codeview_get_address(const struct msc_debug_info* msc_dbg,
unsigned seg, unsigned offset)
{
int nsect = msc_dbg->nsect;
const IMAGE_SECTION_HEADER* sectp = msc_dbg->sectp;
if (!seg || seg > nsect) return 0;
return msc_dbg->module->module.BaseOfImage +
codeview_map_offset(msc_dbg, sectp[seg-1].VirtualAddress + offset);
}
static void codeview_add_func_linenum(struct module* module,
struct symt_function* func,
const struct codeview_linetab* linetab,
unsigned offset, unsigned size)
{
unsigned int i;
if (!linetab) return;
for (i = 0; i < linetab->nline; i++)
{
if (linetab->offtab[i] >= offset && linetab->offtab[i] < offset + size)
{
symt_add_func_line(module, func, linetab->compiland->source,
linetab->linetab[i], linetab->offtab[i] - offset);
}
}
}
static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root,
int offset, int size,
struct codeview_linetab* linetab)
{
struct symt_function* curr_func = NULL;
int i, length;
const struct codeview_linetab* flt;
struct symt_block* block = NULL;
struct symt* symt;
const char* name;
/*
* Loop over the different types of records and whenever we
* find something we are interested in, record it and move on.
*/
for (i = offset; i < size; i += length)
{
const union codeview_symbol* sym = (const union codeview_symbol*)(root + i);
length = sym->generic.len + 2;
if (length & 3) FIXME("unpadded len %u\n", length + 2);
switch (sym->generic.id)
{
/*
* Global and local data symbols. We don't associate these
* with any given source file.
*/
case S_GDATA_V1:
case S_LDATA_V1:
flt = codeview_get_linetab(linetab, sym->data_v1.segment, sym->data_v1.offset);
symt_new_global_variable(msc_dbg->module,
flt ? flt->compiland : NULL,
terminate_string(&sym->data_v1.p_name), sym->generic.id == S_LDATA_V1,
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
0,
codeview_get_type(sym->data_v1.symtype, FALSE));
break;
case S_GDATA_V2:
case S_LDATA_V2:
flt = codeview_get_linetab(linetab, sym->data_v2.segment, sym->data_v2.offset);
name = terminate_string(&sym->data_v2.p_name);
if (name)
symt_new_global_variable(msc_dbg->module, flt ? flt->compiland : NULL,
name, sym->generic.id == S_LDATA_V2,
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
0,
codeview_get_type(sym->data_v2.symtype, FALSE));
break;
case S_GDATA_V3:
case S_LDATA_V3:
flt = codeview_get_linetab(linetab, sym->data_v3.segment, sym->data_v3.offset);
if (*sym->data_v3.name)
symt_new_global_variable(msc_dbg->module, flt ? flt->compiland : NULL,
sym->data_v3.name,
sym->generic.id == S_LDATA_V3,
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
0,
codeview_get_type(sym->data_v3.symtype, FALSE));
break;
case S_PUB_V1: /* FIXME is this really a 'data_v1' structure ?? */
if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
{
flt = codeview_get_linetab(linetab, sym->data_v1.segment, sym->data_v1.offset);
symt_new_public(msc_dbg->module, flt ? flt->compiland : NULL,
terminate_string(&sym->data_v1.p_name),
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
0, TRUE /* FIXME */, TRUE /* FIXME */);
}
break;
case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
if (!(dbghelp_options & SYMOPT_NO_PUBLICS))
{
flt = codeview_get_linetab(linetab, sym->data_v2.segment, sym->data_v2.offset);
symt_new_public(msc_dbg->module, flt ? flt->compiland : NULL,
terminate_string(&sym->data_v2.p_name),
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
0, TRUE /* FIXME */, TRUE /* FIXME */);
}
break;
/*
* Sort of like a global function, but it just points
* to a thunk, which is a stupid name for what amounts to
* a PLT slot in the normal jargon that everyone else uses.
*/
case S_THUNK_V1:
flt = codeview_get_linetab(linetab, sym->thunk_v1.segment, sym->thunk_v1.offset);
symt_new_thunk(msc_dbg->module, flt ? flt->compiland : NULL,
terminate_string(&sym->thunk_v1.p_name), sym->thunk_v1.thtype,
codeview_get_address(msc_dbg, sym->thunk_v1.segment, sym->thunk_v1.offset),
sym->thunk_v1.thunk_len);
break;
case S_THUNK_V3:
flt = codeview_get_linetab(linetab, sym->thunk_v3.segment, sym->thunk_v3.offset);
symt_new_thunk(msc_dbg->module, flt ? flt->compiland : NULL,
sym->thunk_v3.name, sym->thunk_v3.thtype,
codeview_get_address(msc_dbg, sym->thunk_v3.segment, sym->thunk_v3.offset),
sym->thunk_v3.thunk_len);
break;
/*
* Global and static functions.
*/
case S_GPROC_V1:
case S_LPROC_V1:
flt = codeview_get_linetab(linetab, sym->proc_v1.segment, sym->proc_v1.offset);
if (curr_func) FIXME("nested function\n");
curr_func = symt_new_function(msc_dbg->module,
flt ? flt->compiland : NULL,
terminate_string(&sym->proc_v1.p_name),
codeview_get_address(msc_dbg, sym->proc_v1.segment, sym->proc_v1.offset),
sym->proc_v1.proc_len,
codeview_get_type(sym->proc_v1.proctype, FALSE));
codeview_add_func_linenum(msc_dbg->module, curr_func, flt,
sym->proc_v1.offset, sym->proc_v1.proc_len);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc_v1.debug_start, NULL);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc_v1.debug_end, NULL);
break;
case S_GPROC_V2:
case S_LPROC_V2:
flt = codeview_get_linetab(linetab, sym->proc_v2.segment, sym->proc_v2.offset);
if (curr_func) FIXME("nested function\n");
curr_func = symt_new_function(msc_dbg->module,
flt ? flt->compiland : NULL,
terminate_string(&sym->proc_v2.p_name),
codeview_get_address(msc_dbg, sym->proc_v2.segment, sym->proc_v2.offset),
sym->proc_v2.proc_len,
codeview_get_type(sym->proc_v2.proctype, FALSE));
codeview_add_func_linenum(msc_dbg->module, curr_func, flt,
sym->proc_v2.offset, sym->proc_v2.proc_len);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc_v2.debug_start, NULL);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc_v2.debug_end, NULL);
break;
case S_GPROC_V3:
case S_LPROC_V3:
flt = codeview_get_linetab(linetab, sym->proc_v3.segment, sym->proc_v3.offset);
if (curr_func) FIXME("nested function\n");
curr_func = symt_new_function(msc_dbg->module,
flt ? flt->compiland : NULL,
sym->proc_v3.name,
codeview_get_address(msc_dbg, sym->proc_v3.segment, sym->proc_v3.offset),
sym->proc_v3.proc_len,
codeview_get_type(sym->proc_v3.proctype, FALSE));
codeview_add_func_linenum(msc_dbg->module, curr_func, flt,
sym->proc_v3.offset, sym->proc_v3.proc_len);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugStart, sym->proc_v3.debug_start, NULL);
symt_add_function_point(msc_dbg->module, curr_func, SymTagFuncDebugEnd, sym->proc_v3.debug_end, NULL);
break;
/*
* Function parameters and stack variables.
*/
case S_BPREL_V1:
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack_v1.offset,
block, codeview_get_type(sym->stack_v1.symtype, FALSE),
terminate_string(&sym->stack_v1.p_name));
break;
case S_BPREL_V2:
symt_add_func_local(msc_dbg->module, curr_func, 0, sym->stack_v2.offset,
block, codeview_get_type(sym->stack_v2.symtype, FALSE),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -