我的程序正在使用gcc的linux上工作。通過手冊頁,我發現edata,它代表初始化數據段的第一個地址過去結束。
但我想知道初始化數據段的首地址
我該如何得到它?如何獲得初始化數據段的首地址
我試過把etext作爲初始化數據段的第一個地址。然後,當我增加地址並訪問存儲在其中的變量時,我遇到了段錯誤。我認爲etext和edata之間的一些地址空間沒有映射到虛擬內存中。是對的嗎?
我的程序正在使用gcc的linux上工作。通過手冊頁,我發現edata,它代表初始化數據段的第一個地址過去結束。
但我想知道初始化數據段的首地址
我該如何得到它?如何獲得初始化數據段的首地址
我試過把etext作爲初始化數據段的第一個地址。然後,當我增加地址並訪問存儲在其中的變量時,我遇到了段錯誤。我認爲etext和edata之間的一些地址空間沒有映射到虛擬內存中。是對的嗎?
這取決於你的鏈接腳本。例如,在某些平臺上,您在BSS的開始處有符號__bss_start
。這是一個沒有任何數據關聯的符號,你可以通過extern
得到一個指向它的指針,聲明一個具有該名稱的變量(僅用於獲取該變量的地址)。例如:
#include <stdio.h>
extern char __bss_start;
int main()
{
printf("%p\n", &__bss_start);
return 0;
}
您在/usr/lib/ldscripts/elf_x64_64.x
看在鏈接腳本,例如發現這一點:
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
__bss_start = .; /* <<<<< this is what you're looking for /*
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64/8 : 1);
}
你也可以看到你所提到的edata
,但edata
不預留用於實施(PROVIDE
的意思是隻有創建這個符號,否則不使用),你應該使用_edata
來代替。
如果你想將地址data
部分,您可以修改鏈接腳本的開始:
__data_start = . ;
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
_edata = .; PROVIDE (edata = .);
__bss_start = .; /* <<<<< this is what you're looking for /*
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 64/8 : 1);
}
你可能想使鏈接腳本的副本(在/usr/lib/ldscripts
尋找合適的一個,它們是不同,這取決於什麼樣的你的目標輸出),並提供它,當你編譯:
gcc -o execfile source.c -Wl,-T ldscript
,如果你不想修改鏈接腳本可以使用__executable_start
的另一種選擇d解析ELF頭文件(希望可執行文件被線性映射)
至於_etext
,它是text
部分的結尾(您也可以在鏈接描述文件中閱讀它,但我沒有包含它在摘錄中),但text
部分後面跟着rodata
,試圖寫入可能會出現段錯誤。
您可以使用linux工具size
(Debian/Ubuntu中的binutils軟件包)。
例
size -A /usr/bin/gcc
結果
/usr/bin/gcc :
section size addr
.interp 28 4194928
.note.ABI-tag 32 4194956
.note.gnu.build-id 36 4194988
.gnu.hash 240 4195024
.dynsym 4008 4195264
.dynstr 2093 4199272
.gnu.version 334 4201366
.gnu.version_r 160 4201704
.rela.dyn 720 4201864
.rela.plt 3240 4202584
.init 14 4205824
.plt 2176 4205840
.text 384124 4208016
.fini 9 4592140
.rodata 303556 4592160
.eh_frame_hdr 8540 4895716
.eh_frame 50388 4904256
.gcc_except_table 264 4954644
.tbss 16 7052632
.init_array 16 7052632
.fini_array 8 7052648
.jcr 8 7052656
.data.rel.ro 3992 7052672
.dynamic 480 7056664
.got 216 7057144
.got.plt 1104 7057384
.data 2520 7058496
.bss 80976 7061024
.gnu_debuglink 12 0
Total 849310
你如何找到'edata'?你不能使用相同的技術來查找數據嗎?爲什麼不簡單地閱讀二進制文件並找到'data'段?我最感興趣的是*爲什麼*你需要它?你試圖解決什麼是原始問題?(相關閱讀:[「什麼是XY問題」](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)) –
@JoachimPileborg。我搜索這個問題,只找到edata,etext,結束。這就是爲什麼我在這裏尋求幫助。 – fanux
@JoachimPileborg不是我的問題清楚嗎?我已閱讀相關文件並進行搜索。如果你不能回答,就走開。或者,我會感謝你。不要評價我或者問我爲什麼想知道它。那是愚蠢的 – fanux