2012-09-17 32 views
1

我不知道如何解釋我現在正在處理的問題,所以很抱歉,如果我在問題的標題中含糊不清。解引用一個指向一個未知類型的變量的指針

我現在擁有的是存儲在變量中的虛擬地址列表。例如,我有

0x8c334dd

存儲在char變量。這個地址是另一個有數據的變量的地址。我想要做的是去那個地址並獲取存儲在其上的數據。

我的假設是,解引用指針會是最好的方式,不幸的是我不知道地址指向的變量的類型,那麼在這種情況下解引用是如何工作的?我不能這樣做:*(char *) 8c334dd,因爲我不知道地址指向的變量的類型...

如果我把它轉換爲(int *),我得到一些變量的一些數據,指向(記住我有幾個地址),但對於其他人我只是得到一個地址,我需要的數據(這些變量是結構,字符等)。

我與ELF符號表

+1

假設你已經讀取了地址:'char a = *(char *)0x8c334dd;' – ouah

+0

我的假設是解引用指針在這裏不起作用,因爲如果我解引用具有地址的變量,那麼我會得到它的內容(這是相同的地址),而不是第二個變量的內容,對嗎?我也不知道我想從中獲取數據的變量的類型是什麼.. – attis

+1

咦?什麼「第二變量」?如果您取消引用指針,則會得到存儲在該地址的任何內容。 (另外,如果這是一個C問題,它爲什麼標記C++?) –

回答

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標準,所以如果你想用floatdouble值初始化你的結構,上面是一場噩夢。(如果將float值轉換爲一個整數,C不會只改變類型,它會將值舍入;而且我不知道如何獲得一個32位整數值,這個值正確表示一個32位漂浮在C程序編譯時。)

Compile time float packing/punning

如果您正在使用指針工作,不過,這很容易。只要將聯合中的第一個字段名稱指向一個指針類型,就可以將指針指向void *,並如上所示初始化結構(指針將在1234之上)。

如果您正在閱讀由其他人的代碼編寫的表格,並且您沒有添加類型標識符字段的方法,則我沒有針對您的一般答案。我想你可以嘗試將指針作爲不同的類型讀出來,看看哪一個工作?

+0

這很有幫助。並給了我一些好主意。不幸的是,表格值不是由我給出的。我正在使用ELF Symbol表值,這是一種「反編譯」傳遞給我的程序的任何程序的方式。通過給我ELF符號表,我需要能夠推斷出哪些變量是int類型,char類型或結構類型,然後爲每個變量獲取值。我到目前爲止是一個指向「某處」的未知類型的地址,它只是我們可以從精靈符號表中獲得的地址集合。 – attis

+0

我的確在使用別人的表,API ELF提供的更精確。事情是,試圖猜測指針的類型將是徒勞無益的,因爲編譯器不會抱怨該類型是無效的,所以如果我試圖讀指針爲char,那麼我可能會得到一個隨機的非ASCII字符值,如果我嘗試讀取它作爲int我可能會得到實際值或只是另一個地址指向值.. – attis

0

只是想添加一些東西,對於那些使用ELF符號表的人來說,我發現DWARF文件中的DIE更易於使用。您可以使用DWARF而不是ELF來獲取變量的地址,類型和名稱,而libdwarf具有良好的文檔。

相關問題