2013-02-06 46 views
3

有影響,設置或定義一個函數的(相對)地址的方法?也許在鏈接器腳本中有任何可能性來確保函數abc()始終駐留在OFFSET + 0x0034C0處(僅舉例)。 我想以某種方式「控制」的記憶裏面函數的位置,使這些地方的某種參數化的。 目前我正在使用gcc在我的x86上尋找一種方法。但是,真正的應用程序應該在嵌入式設備上運行。如何影響功能的地址?

問候

+0

IMO,如果應用程序在嵌入式設備上運行,我假設某種類型的自定義操作系統,不要試圖使它在x86上工作,然後找出它不能在設備上完成。 (好奇,爲什麼?) – Max

+0

你看過存儲數據結構中函數的指針嗎? – Nocturno

+3

這聽起來非常像一個XY問題,你試圖解決問題X,所以你認爲解決方案涉及Y,所以你問如何去做Y.你能解釋一下你實際上想要做什麼嗎?我認爲使用函數指針或類似的東西是一個很有可能的候選者,但是如果沒有真正理解「我需要我的函數在特殊地址上」的真實想法,很難知道建議的解決方案。 –

回答

8

你或許可以做到這一點使用linker script magic與海灣合作委員會,是的。看看如何定義section placement,然後把指令在源放功能在您所選擇的部分(一個或多個)。

不能肯定是否會在x86機器的工作,雖然,因爲操作系統可能有...異議。這更直接用於嵌入式應用。

在完整的操作系統上控制代碼位置的是什麼?

+0

其實我想創建一些Software-Hardware-Binding-Scheme。某些功能的位置應在軟件開發過程中定義。在執行軟件時,它從用於指導軟件控制流的硬件讀取認證信息。 只有從硬件讀取正確的憑證時,連續的函數調用纔會指向正確的內存地址。否則,他們指向內存中的錯誤位置,軟件停止執行/軟件崩潰。 – user1192748

+0

@ user1192748,我只是通過存儲特定硬件地址(如中斷向量)內容的校驗和來看到類似的結果。 –

+3

@ user1192748 CRC校驗的優點是您可以簡單地檢查該值並在不匹配時不運行。調用未定義的行爲只是一種災難性的方法(即,如果「停止」,您無法控制軟件「停止」的時間/地點/方式) –

1

一個典型的廣義實施,這將是一個矢量表(我也聽說過這個叫補丁表)。

首先,在你的C文件,寫功能:

void my_first_function(int){ /* do something */ } 
void my_second_function(int){ /* do something */ } 

然後,在你的C文件創建定義表格的佈局結構:

struct MyVectorTable 
{ 
    void (*first_function)(int); 
    int (*second_function)(float, char); 

    // all the rest 
}; 

接下來,在你的C文件創建一個靜態表:

static struct MyVectorTable my_vector_table = { 
    my_first_function, 
    my_second_function, 
}; 

最後露出地址作爲一個void *

void* get_table_base_address(void) { return &my_vector_table; } 

現在你應該能夠得到所有的函數作爲基地址的偏移量。

如果所有的函數具有相同的調用簽名,你可以通過具有函數指針,而不是結構的數組簡化這個。但是,數組和結構都會保存指針,所以指針數學基本相同。

這也允許您使用鏈接器在特定地址找到您的補丁表。

1

要做到這一點,IMO的最佳方法是將函數放入用戶定義的部分中,如展開已在上面提及。你可以找到一個簡單的例子,在低於4K字節邊界放置一個功能myFunc

通過修改鏈接腳本來創建在你的記憶一個新的部分:

/* .my_section will be the name of the section in the final executable */ 
.my_section : ALIGN (8) 
{ 
    . = ALIGN (0x1000); 

    KEEP(*(.mysection)) /* The section will be called ".mysection" in the 
           compiled translation unit (.obj) */ 

    . = ALIGN (8); 
} >rom 

現在,使用gcc的attribute功能放置功能爲我們剛剛創建的部分:

void myFunc(void) __attribute__ ((section(".mysection"))); // The section name to use 
                  // here is ".mysection", 
                  // not ".my_section" 

// Looks like you need to use __attribute__ along with function declaration, rather 
// than with the function definition, though I'm not sure why 

void myFunc(void) 
{ 
    // ... 
} 

如果你這樣做objdump現在,你會被持有myFunc代碼地址0名.my_section看到部分,而不是在0x12e8

Disassembly of section .my_section: 

000012e8 <myFunc-0xd18>: 
     ... 

00002000 <myFunc>: 
    2000:  b508   push {r3, lr} 
    ... 

該代碼可以使用Codesourcey gcc套件ARM皮質。我不太確定x86 ...