📄 stabs.c
字号:
static int stabs_pts_read_number(struct ParseTypedefData* ptd, long* v)
{
char* last;
*v = strtol(ptd->ptr, &last, 10);
PTS_ABORTIF(ptd, last == ptd->ptr);
ptd->ptr = last;
return 0;
}
static int stabs_pts_read_type_reference(struct ParseTypedefData* ptd,
long* filenr, long* subnr)
{
if (*ptd->ptr == '(')
{
/* '(' <int> ',' <int> ')' */
ptd->ptr++;
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, filenr) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ')');
}
else
{
*filenr = 0;
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, subnr) == -1);
}
return 0;
}
struct pts_range_value
{
unsigned long long val;
int sign;
};
static int stabs_pts_read_range_value(struct ParseTypedefData* ptd, struct pts_range_value* prv)
{
char* last;
switch (*ptd->ptr)
{
case '0':
while (*ptd->ptr == '0') ptd->ptr++;
if (*ptd->ptr >= '1' && *ptd->ptr <= '7')
{
switch (ptd->ptr[1])
{
case '0':
PTS_ABORTIF(ptd, ptd->ptr[0] != '1');
prv->sign = -1;
prv->val = 0;
while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
break;
case '7':
prv->sign = 1;
prv->val = 0;
while (isdigit(*ptd->ptr)) prv->val = (prv->val << 3) + *ptd->ptr++ - '0';
break;
default: PTS_ABORTIF(ptd, 1); break;
}
} else prv->sign = 0;
break;
case '-':
prv->sign = -1;
prv->val = strtoull(++ptd->ptr, &last, 10);
ptd->ptr = last;
break;
case '+':
default:
prv->sign = 1;
prv->val = strtoull(ptd->ptr, &last, 10);
ptd->ptr = last;
break;
}
return 0;
}
static int stabs_pts_read_range(struct ParseTypedefData* ptd, const char* typename,
struct symt** dt)
{
struct symt* ref;
struct pts_range_value lo;
struct pts_range_value hi;
unsigned size;
enum BasicType bt;
int i;
unsigned long long v;
/* type ';' <int> ';' <int> ';' */
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &ref) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';'); /* ';' */
PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &lo) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';'); /* ';' */
PTS_ABORTIF(ptd, stabs_pts_read_range_value(ptd, &hi) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';'); /* ';' */
/* basically, we don't use ref... in some cases, for example, float is declared
* as a derivated type of int... which won't help us... so we guess the types
* from the various formats
*/
if (lo.sign == 0 && hi.sign < 0)
{
bt = btUInt;
size = hi.val;
}
else if (lo.sign < 0 && hi.sign == 0)
{
bt = btUInt;
size = lo.val;
}
else if (lo.sign > 0 && hi.sign == 0)
{
bt = btFloat;
size = lo.val;
}
else if (lo.sign < 0 && hi.sign > 0)
{
v = 1 << 7;
for (i = 7; i < 64; i += 8)
{
if (lo.val == v && hi.val == v - 1)
{
bt = btInt;
size = (i + 1) / 8;
break;
}
v <<= 8;
}
PTS_ABORTIF(ptd, i >= 64);
}
else if (lo.sign == 0 && hi.sign > 0)
{
if (hi.val == 127) /* specific case for char... */
{
bt = btChar;
size = 1;
}
else
{
v = 1;
for (i = 8; i <= 64; i += 8)
{
v <<= 8;
if (hi.val + 1 == v)
{
bt = btUInt;
size = (i + 1) / 8;
break;
}
}
PTS_ABORTIF(ptd, i > 64);
}
}
else PTS_ABORTIF(ptd, 1);
*dt = &symt_new_basic(ptd->module, bt, typename, size)->symt;
return 0;
}
static __inline int stabs_pts_read_method_info(struct ParseTypedefData* ptd)
{
struct symt* dt;
char* tmp;
char mthd;
do
{
/* get type of return value */
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
if (*ptd->ptr == ';') ptd->ptr++;
/* get types of parameters */
if (*ptd->ptr == ':')
{
PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr + 1, ';')));
ptd->ptr = tmp + 1;
}
PTS_ABORTIF(ptd, !(*ptd->ptr >= '0' && *ptd->ptr <= '9'));
ptd->ptr++;
PTS_ABORTIF(ptd, !(ptd->ptr[0] >= 'A' && *ptd->ptr <= 'D'));
mthd = *++ptd->ptr;
PTS_ABORTIF(ptd, mthd != '.' && mthd != '?' && mthd != '*');
ptd->ptr++;
if (mthd == '*')
{
long int ofs;
struct symt* dt;
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
}
} while (*ptd->ptr != ';');
ptd->ptr++;
return 0;
}
static __inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd,
struct symt_udt* sdt)
{
long sz, ofs;
struct symt* adt;
struct symt* dt = NULL;
int idx;
int doadd;
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
doadd = symt_set_udt_size(ptd->module, sdt, sz);
if (*ptd->ptr == '!') /* C++ inheritence */
{
long num_classes;
ptd->ptr++;
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &num_classes) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
while (--num_classes >= 0)
{
ptd->ptr += 2; /* skip visibility and inheritence */
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
if (doadd)
{
char tmp[256];
WCHAR* name;
DWORD size;
symt_get_info(adt, TI_GET_SYMNAME, &name);
strcmp(tmp, "__inherited_class_");
WideCharToMultiByte(CP_ACP, 0, name, -1,
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
NULL, NULL);
HeapFree(GetProcessHeap(), 0, name);
/* FIXME: TI_GET_LENGTH will not always work, especially when adt
* has just been seen as a forward definition and not the real stuff
* yet.
* As we don't use much the size of members in structs, this may not
* be much of a problem
*/
symt_get_info(adt, TI_GET_LENGTH, &size);
symt_add_udt_element(ptd->module, sdt, tmp, adt, ofs, size * 8);
}
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
}
}
/* if the structure has already been filled, just redo the parsing
* but don't store results into the struct
* FIXME: there's a quite ugly memory leak in there...
*/
/* Now parse the individual elements of the structure/union. */
while (*ptd->ptr != ';')
{
/* agg_name : type ',' <int:offset> ',' <int:size> */
idx = ptd->idx;
if (ptd->ptr[0] == '$' && ptd->ptr[1] == 'v')
{
long x;
if (ptd->ptr[2] == 'f')
{
/* C++ virtual method table */
ptd->ptr += 3;
stabs_read_type_enum(&ptd->ptr);
PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
ptd->idx = idx;
continue;
}
else if (ptd->ptr[2] == 'b')
{
ptd->ptr += 3;
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &x) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
ptd->idx = idx;
continue;
}
}
PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
/* Ref. TSDF R2.130 Section 7.4. When the field name is a method name
* it is followed by two colons rather than one.
*/
if (*ptd->ptr == ':')
{
ptd->ptr++;
stabs_pts_read_method_info(ptd);
ptd->idx = idx;
continue;
}
else
{
/* skip C++ member protection /0 /1 or /2 */
if (*ptd->ptr == '/') ptd->ptr += 2;
}
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
switch (*ptd->ptr++)
{
case ',':
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &ofs) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &sz) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
if (doadd) symt_add_udt_element(ptd->module, sdt, ptd->buf + idx, adt, ofs, sz);
break;
case ':':
{
char* tmp;
/* method parameters... terminated by ';' */
PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr, ';')));
ptd->ptr = tmp + 1;
}
break;
default:
PTS_ABORTIF(ptd, TRUE);
}
ptd->idx = idx;
}
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
if (*ptd->ptr == '~')
{
ptd->ptr++;
PTS_ABORTIF(ptd, *ptd->ptr++ != '%');
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &dt) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
}
return 0;
}
static __inline int stabs_pts_read_enum(struct ParseTypedefData* ptd,
struct symt_enum* edt)
{
long value;
int idx;
while (*ptd->ptr != ';')
{
idx = ptd->idx;
PTS_ABORTIF(ptd, stabs_pts_read_id(ptd) == -1);
PTS_ABORTIF(ptd, stabs_pts_read_number(ptd, &value) == -1);
PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
symt_add_enum_element(ptd->module, edt, ptd->buf + idx, value);
ptd->idx = idx;
}
ptd->ptr++;
return 0;
}
static __inline int stabs_pts_read_array(struct ParseTypedefData* ptd,
struct symt** adt)
{
long lo, hi;
struct symt* rdt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -