2015-04-21 57 views
1

我寫了一個簡單的C程序,帶有一些全局和靜態變量。一些代碼和輸出可以在下面顯示。/proc/pid/stat錯誤條目?

源代碼示例:

#include <stdio.h> 

int g1, g2; 

int main(){ 

    printf("g1:%p g2:%p\n", &g1, &g2); 

    return 0; 
} 

輸出:

g1:0x6061b0 g2:0x6061c0 

這樣的變量落在數據段。他們可能在初始化的小節中,或者在未初始化的(bss)小節中。我打印他們的地址以檢查它們在內存中的位置,然後將這些值與/proc/<pid>/stat僞文件的start_dataend_data條目的值進行比較。我的變量不在屬於該區域。

限制了/ proc /進程/ STAT給我:

start_data: 604e10 
end_data: 605180 

documentation

45)start_data%LU(因爲Linux 3.3) 地址高於該程序初始化和 未初始化(BSS)數據被放置。

(46)end_data%LU(因爲Linux 3.3) 地址低於該程序初始化並 未初始化(BSS)的數據被放置。

我設法得到使用由linker產生map file,但是通過使用proc接口這將是更清潔的(更容易,更快,..)的data segment的正確區域。

正確的限制,我發現使用映射文件從鏈接:

start: 605168 
end: 606290 

我使用Ubuntu服務器版x64,Linux的3.13。

統計的完整輸出:

29505 (myexec) R 29504 29504 1438 34822 29504 24640 52 0 0 0 0 0 0 0 20 0 1 0 55253161 4308992 24 18446744073709551615 4194304 4210644 140737488347232 140737488337560 140737348896784 0 0 0 0 0 0 0 17 0 0 0 0 0 0 6311440 6312320 6320128 140737488347816 140737488347831 140737488347831 140737488351209 0 

輸出map_files的:

total 0 
lr-------- 1 root root 64 Apr 21 22:32 400000-41a000 -> /bin/ls 
lr-------- 1 root root 64 Apr 21 22:32 619000-61a000 -> /bin/ls 
lr-------- 1 root root 64 Apr 21 22:32 61a000-61b000 -> /bin/ls 
lr-------- 1 root root 64 Apr 21 22:32 7ffff649e000-7ffff64a9000 -> /lib/x86_64-linux-gnu/libnss_files-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff64a9000-7ffff66a8000 -> /lib/x86_64-linux-gnu/libnss_files-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff66a8000-7ffff66a9000 -> /lib/x86_64-linux-gnu/libnss_files-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff66a9000-7ffff66aa000 -> /lib/x86_64-linux-gnu/libnss_files-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff66aa000-7ffff66b5000 -> /lib/x86_64-linux-gnu/libnss_nis-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff66b5000-7ffff68b4000 -> /lib/x86_64-linux-gnu/libnss_nis-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff68b4000-7ffff68b5000 -> /lib/x86_64-linux-gnu/libnss_nis-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff68b5000-7ffff68b6000 -> /lib/x86_64-linux-gnu/libnss_nis-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff68b6000-7ffff68cd000 -> /lib/x86_64-linux-gnu/libnsl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff68cd000-7ffff6acc000 -> /lib/x86_64-linux-gnu/libnsl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6acc000-7ffff6acd000 -> /lib/x86_64-linux-gnu/libnsl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6acd000-7ffff6ace000 -> /lib/x86_64-linux-gnu/libnsl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6ad0000-7ffff6ad9000 -> /lib/x86_64-linux-gnu/libnss_compat-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6ad9000-7ffff6cd8000 -> /lib/x86_64-linux-gnu/libnss_compat-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6cd8000-7ffff6cd9000 -> /lib/x86_64-linux-gnu/libnss_compat-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6cd9000-7ffff6cda000 -> /lib/x86_64-linux-gnu/libnss_compat-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6cda000-7ffff6fa3000 -> /usr/lib/locale/locale-archive 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6fa3000-7ffff6fa7000 -> /lib/x86_64-linux-gnu/libattr.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff6fa7000-7ffff71a6000 -> /lib/x86_64-linux-gnu/libattr.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff71a6000-7ffff71a7000 -> /lib/x86_64-linux-gnu/libattr.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff71a7000-7ffff71a8000 -> /lib/x86_64-linux-gnu/libattr.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff71a8000-7ffff71ab000 -> /lib/x86_64-linux-gnu/libdl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff71ab000-7ffff73aa000 -> /lib/x86_64-linux-gnu/libdl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff73aa000-7ffff73ab000 -> /lib/x86_64-linux-gnu/libdl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff73ab000-7ffff73ac000 -> /lib/x86_64-linux-gnu/libdl-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff73ac000-7ffff73e9000 -> /lib/x86_64-linux-gnu/libpcre.so.3.13.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff73e9000-7ffff75e8000 -> /lib/x86_64-linux-gnu/libpcre.so.3.13.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff75e8000-7ffff75e9000 -> /lib/x86_64-linux-gnu/libpcre.so.3.13.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff75e9000-7ffff75ea000 -> /lib/x86_64-linux-gnu/libpcre.so.3.13.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff75ea000-7ffff77a5000 -> /lib/x86_64-linux-gnu/libc-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff77a5000-7ffff79a4000 -> /lib/x86_64-linux-gnu/libc-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff79a4000-7ffff79a8000 -> /lib/x86_64-linux-gnu/libc-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff79a8000-7ffff79aa000 -> /lib/x86_64-linux-gnu/libc-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff79af000-7ffff79b6000 -> /lib/x86_64-linux-gnu/libacl.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff79b6000-7ffff7bb5000 -> /lib/x86_64-linux-gnu/libacl.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7bb5000-7ffff7bb6000 -> /lib/x86_64-linux-gnu/libacl.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7bb6000-7ffff7bb7000 -> /lib/x86_64-linux-gnu/libacl.so.1.1.0 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7bb7000-7ffff7bd7000 -> /lib/x86_64-linux-gnu/libselinux.so.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7bd7000-7ffff7dd6000 -> /lib/x86_64-linux-gnu/libselinux.so.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7dd6000-7ffff7dd7000 -> /lib/x86_64-linux-gnu/libselinux.so.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7dd7000-7ffff7dd8000 -> /lib/x86_64-linux-gnu/libselinux.so.1 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7dda000-7ffff7dfd000 -> /lib/x86_64-linux-gnu/ld-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7ffc000-7ffff7ffd000 -> /lib/x86_64-linux-gnu/ld-2.19.so 
lr-------- 1 root root 64 Apr 21 22:32 7ffff7ffd000-7ffff7ffe000 -> /lib/x86_64-linux-gnu/ld-2.19.so 

有什麼想法? 乾杯。

+0

procfs內容在內核版本之間發生變化。你使用的是什麼版本的內核?你確定你正在尋找正確的領域,你有內核> = 3.3(它支持start_data和end_data)? –

+0

@BlueMoon對兩者都是!查看更新的問題! – Paschalis

+0

它在我的ubuntu 3.11,i686上顯示正確(即與地圖匹配的範圍)您的代碼。你能發佈'stat'和'ls -l ../ map_files'的確切內容嗎? –

回答

3

似乎是(或不正確的文件)。

ELF使用一個小竅門用於指定BSS(I切割前導零):

$ objdump -x ./a.out 

LOAD off 0x00000e00 vaddr 0x00600e00 paddr 0x00600e00 align 2**21 
    filesz 0x00000258 memsz 0x00000268 flags rw- 

對於PT_LOAD:

vaddr = 0x00600e00 
vaddr + filesz = 0x00601058 
vaddr + memsz = 0x00601068 

所以字節[0x00600e00; 0x00601058)被裝載到從文件存儲器,而最後的0x10字節也應該存在於內存中,但不能從ELF文件加載 - 它們歸零,因爲它是BSS。您可以檢查與objdump的太多:

25 .bss 00000010 00601058 00601058 00001058 2**2 
     ^size ^base address 

然而,binfmt裝載機ELF裏面,只有vaddr + filesz計爲end_data(見fs/binfmt_elf.c):

k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 

if (k > elf_bss) 
    elf_bss = k; 
if ((elf_ppnt->p_flags & PF_X) && end_code < k) 
    end_code = k; 
if (end_data < k) 
    end_data = k; 
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; 
if (k > elf_brk) 
    elf_brk = k; 

所以:

  • end_data指向從文件加載的最後一個字節
  • elf_bss指向f BSS的IRST字節(不暴露,內部使用)
  • elf_brk點BSS的最後一個字節(不暴露,內部使用)

您可以檢查/proc/PID/maps - 它應該表現出更可靠的結果。

P.S.看來,內核文檔已被隨機陌生人更改:https://lkml.org/lkml/2011/12/6/604

+0

不錯的答案。感謝您花時間解釋它!但是,爲什麼'start_data'也是錯的? 至於你最後的建議,我希望/ proc/PID/maps更可靠。看看我昨天的問題:http://stackoverflow.com/questions/29681712/why-global-variables-are-stored-in-heap/29683894#29683894 – Paschalis

+1

@Paschalis,有超過_your data_下降到數據段。用objdump檢查一下,你可以找到類似'.got'和'.jcr'的服務部分。 – myaut

+1

根據您的建議,似乎文檔不正確。 –