我不知道如何解释我现在遇到的问题,如果我对问题的标题含糊不清,那就很抱歉。
我现在所拥有的是存储在变量中的虚拟地址列表。例如,我有
0x8c334dd
存储在char变量中。该地址是另一个包含数据的变量的地址。我想要做的是转到该地址并获取存储在其上的数据。
我的假设是取消引用指针本来是最好的方法,遗憾的是我不知道地址指向的变量的类型,那么解除引用在这种情况下如何工作?我不能这样做:*(char *) 8c334dd
因为我不知道地址所指向的变量的类型......
如果我将其转换为(int *)
,我会得到一些地址所指向的某些变量的数据(请记住我有几个地址)但是对于其他人我只是得到一个地址,我需要数据(这个变量是结构,字符等)。
我正在使用ELF符号表
答案 0 :(得分:3)
通常,C ++或C无法知道你的指针类型。
解决此问题的常用方法是使指针指向结构,并在结构中具有已知位置以指示数据的类型。通常,已知位置是结构中的第一个位置。
示例:
// signature value; use any value unlikely to happen by chance
#define VAR_SIG 0x11223344
typedef enum
{
vartypeInvalid = 0,
vartypeInt,
vartypeFloat,
vartypeDouble,
vartypeString,
vartypeMax // not a valid vartype
} VARTYPE;
typedef struct
{
VARTYPE type;
#ifdef DEBUG
uint32_t sig;
#endif // DEBUG
union data
{
int i;
float f;
double d;
char *s;
};
} VAR;
然后,您可以进行完整性检查:您可以查看type
字段的值是否大于vartypeInvalid
且小于vartypeMax
(并且您永远不需要编辑这些名称在完整性检查代码中;如果添加更多类型,则在列表中的vartypeMax
之前添加它们。此外,对于DEBUG
版本,您可以检查签名字段sig
是否包含某些特定的签名值。 (这意味着初始化VAR
实例的初始化代码需要始终设置sig
字段。)
如果您执行此类操作,那么如何初始化它?运行时代码将始终有效:
VAR v;
#ifdef DEBUG
v.sig = VAR_SIG;
#endif // DEBUG
v.type = vartypeFloat;
v.data = 3.14f;
如果要在编译时初始化它怎么办?如果你想用整数值初始化它很容易,因为int
类型是union
中的第一个类型:
VAR v =
{
vartypeInt,
#ifdef DEBUG
VAR_SIG,
#endif // DEBUG
1234
};
如果您使用的是C99兼容版本的C,您实际上可以使用字段名称初始化结构并让它指定任何类型。但是Microsoft C不符合C99,所以如果你想用float
或double
值初始化你的结构,上面就是一场噩梦。 (如果将浮点值转换为整数,C不会只改变类型,它将对值进行舍入;并且我不知道可以获得一个正确表示32位的32位整数值的技巧在C程序中编译时浮动。)
Compile time float packing/punning
如果你正在使用指针,那很容易。只需使联合中的第一个字段名称为指针类型,将指针强制转换为void *
并按上面的方式初始化结构(指针将转到1234
上面的位置)。
如果您正在阅读由其他人的代码编写的表格,并且您无法添加类型标识符字段,那么我没有一般的答案。我想你可以尝试将指针读出来作为不同的类型,看哪哪个工作?
答案 1 :(得分:0)
只是想添加一些东西,对于那些使用ELF符号表的人来说,我发现DWARF文件中的DIE更容易使用。您可以使用DWARF而不是ELF来获取变量的地址,类型和名称,并且libdwarf具有良好的文档。