2012年3月4日 星期日

bss section (2)

env: in 32bit linux, 64 bit 似乎有點不同??

在沒有 os 的環境下搞懂 bss 有點麻煩嗎?這次提供在 os 環境下, 看看 bss。
首先找出 bss 開始和結束的地方。先來看看 default linker script。

ld --verbose
  1 GNU ld (GNU Binutils for Debian) 2.22
  2   Supported emulations:
  3    elf_i386
  4    i386linux
  5    elf32_x86_64
  6    elf_x86_64
  7    elf_l1om
  8    elf_k1om
  9 using internal linker script:
 10 ==================================================
 11 /* Script for -z combreloc: combine and sort reloc sections */
 12 OUTPUT_FORMAT("elf32-i386", "elf32-i386",
 13        "elf32-i386")
 14 OUTPUT_ARCH(i386)
 15 ENTRY(_start)
 16 SEARCH_DIR("/usr/i486-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32"); 
SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); 
SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); 
SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/lib"); 
SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib");
 17 SECTIONS
 18 {
 19   /* Read-only sections, merged into text segment: */
 20   PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); 
. = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;
 21   .interp         : { *(.interp) }
 22   .note.gnu.build-id : { *(.note.gnu.build-id) }
 23   .hash           : { *(.hash) }
 24   .gnu.hash       : { *(.gnu.hash) }
 25   .dynsym         : { *(.dynsym) }
 26   .dynstr         : { *(.dynstr) }
 27   .gnu.version    : { *(.gnu.version) }
 28   .gnu.version_d  : { *(.gnu.version_d) }
 29   .gnu.version_r  : { *(.gnu.version_r) }
 30   .rel.dyn        :
 31     {
 32       *(.rel.init)
 33       *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
 34       *(.rel.fini)
 35       *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
 36       *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
 37       *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
 38       *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
 39       *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
 40       *(.rel.ctors)
 41       *(.rel.dtors)
 42       *(.rel.got)
 43       *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
 44       *(.rel.ifunc)
 45     }
 46   .rel.plt        :
 47     {
 48       *(.rel.plt)
 49       PROVIDE_HIDDEN (__rel_iplt_start = .);
 50       *(.rel.iplt)
 51       PROVIDE_HIDDEN (__rel_iplt_end = .);
 52     }
 53   .init           :
 54   {
 55     KEEP (*(.init))
 56   } =0x90909090
 57   .plt            : { *(.plt) *(.iplt) }
 58   .text           :
 59   {
 60     *(.text.unlikely .text.*_unlikely)
 61     *(.text.exit .text.exit.*)
 62     *(.text.startup .text.startup.*)
 63     *(.text.hot .text.hot.*)
 64     *(.text .stub .text.* .gnu.linkonce.t.*)
 65     /* .gnu.warning sections are handled specially by elf32.em.  */
 66     *(.gnu.warning)
 67   } =0x90909090
 68   .fini           :
 69   {
 70     KEEP (*(.fini))
 71   } =0x90909090
 72   PROVIDE (__etext = .);
 73   PROVIDE (_etext = .);
 74   PROVIDE (etext = .);
 75   .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
 76   .rodata1        : { *(.rodata1) }
 77   .eh_frame_hdr : { *(.eh_frame_hdr) }
 78   .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
 79   .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
 80   .gcc_except_table.*) }
 81   /* These sections are generated by the Sun/Oracle C++ compiler.  */
 82   .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
 83   .exception_ranges*) }
 84   /* Adjust the address for the data segment.  We want to adjust up to
 85      the same address within the page on the next page up.  */
 86   . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) 
& (CONSTANT (MAXPAGESIZE) - 1)); 
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
 87   /* Exception handling  */
 88   .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
 89   .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
 90   .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
 91   /* Thread Local Storage sections  */
 92   .tdata   : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
 93   .tbss    : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
 94   .preinit_array     :
 95   {
 96     PROVIDE_HIDDEN (__preinit_array_start = .);
 97     KEEP (*(.preinit_array))
 98     PROVIDE_HIDDEN (__preinit_array_end = .);
 99   }
100   .init_array     :
101   {
102     PROVIDE_HIDDEN (__init_array_start = .);
103     KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
104     KEEP (*(.init_array))
105     KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
106     PROVIDE_HIDDEN (__init_array_end = .);
107   }
108   .fini_array     :
109   {
110     PROVIDE_HIDDEN (__fini_array_start = .);
111     KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
112     KEEP (*(.fini_array))
113     KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
114     PROVIDE_HIDDEN (__fini_array_end = .);
115   }
116   .ctors          :
117   {
118     /* gcc uses crtbegin.o to find the start of
119        the constructors, so we make sure it is
120        first.  Because this is a wildcard, it
121        doesn't matter if the user does not
122        actually link against crtbegin.o; the
123        linker won't look for a file to match a
124        wildcard.  The wildcard also means that it
125        doesn't matter which directory crtbegin.o
126        is in.  */
127     KEEP (*crtbegin.o(.ctors))
128     KEEP (*crtbegin?.o(.ctors))
129     /* We don't want to include the .ctor section from
130        the crtend.o file until after the sorted ctors.
131        The .ctor section from the crtend file contains the
132        end of ctors marker and it must be last */
133     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
134     KEEP (*(SORT(.ctors.*)))
135     KEEP (*(.ctors))
136   }
137   .dtors          :
138   {
139     KEEP (*crtbegin.o(.dtors))
140     KEEP (*crtbegin?.o(.dtors))
141     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
142     KEEP (*(SORT(.dtors.*)))
143     KEEP (*(.dtors))
144   }
145   .jcr            : { KEEP (*(.jcr)) }
146   .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) 
*(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
147   .dynamic        : { *(.dynamic) }
148   .got            : { *(.got) *(.igot) }
149   . = DATA_SEGMENT_RELRO_END (12, .);
150   .got.plt        : { *(.got.plt)  *(.igot.plt) }
151   .data           :
152   {
153     *(.data .data.* .gnu.linkonce.d.*)
154     SORT(CONSTRUCTORS)
155   }
156   .data1          : { *(.data1) }
157   _edata = .; PROVIDE (edata = .);
158   __bss_start = .;
159   .bss            :
160   {
161    *(.dynbss)
162    *(.bss .bss.* .gnu.linkonce.b.*)
163    *(COMMON)
164    /* Align here to ensure that the .bss section occupies space up to
165       _end.  Align after .bss to ensure correct alignment even if the
166       .bss section disappears because there are no input sections.
167       FIXME: Why do we need it? When there is no .bss section, we don't
168       pad the .data section.  */
169    . = ALIGN(. != 0 ? 32 / 8 : 1);
170   }
171   . = ALIGN(32 / 8);
172   . = ALIGN(32 / 8);
173   _end = .; PROVIDE (end = .);
174   . = DATA_SEGMENT_END (.);
175   /* Stabs debugging sections.  */
176   .stab          0 : { *(.stab) }
177   .stabstr       0 : { *(.stabstr) }
178   .stab.excl     0 : { *(.stab.excl) }
179   .stab.exclstr  0 : { *(.stab.exclstr) }
180   .stab.index    0 : { *(.stab.index) }
181   .stab.indexstr 0 : { *(.stab.indexstr) }
182   .comment       0 : { *(.comment) }
183   /* DWARF debug sections.
184      Symbols in the DWARF debugging sections are relative to the beginning
185      of the section so we begin them at 0.  */
186   /* DWARF 1 */
187   .debug          0 : { *(.debug) }
188   .line           0 : { *(.line) }
189   /* GNU DWARF 1 extensions */
190   .debug_srcinfo  0 : { *(.debug_srcinfo) }
191   .debug_sfnames  0 : { *(.debug_sfnames) }
192   /* DWARF 1.1 and DWARF 2 */
193   .debug_aranges  0 : { *(.debug_aranges) }
194   .debug_pubnames 0 : { *(.debug_pubnames) }
195   /* DWARF 2 */
196   .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
197   .debug_abbrev   0 : { *(.debug_abbrev) }
198   .debug_line     0 : { *(.debug_line) }
199   .debug_frame    0 : { *(.debug_frame) }
200   .debug_str      0 : { *(.debug_str) }
201   .debug_loc      0 : { *(.debug_loc) }
202   .debug_macinfo  0 : { *(.debug_macinfo) }
203   /* SGI/MIPS DWARF 2 extensions */
204   .debug_weaknames 0 : { *(.debug_weaknames) }
205   .debug_funcnames 0 : { *(.debug_funcnames) }
206   .debug_typenames 0 : { *(.debug_typenames) }
207   .debug_varnames  0 : { *(.debug_varnames) }
208   /* DWARF 3 */
209   .debug_pubtypes 0 : { *(.debug_pubtypes) }
210   .debug_ranges   0 : { *(.debug_ranges) }
211   .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
212   /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
213 }
214 
215 
216 ==================================================

我知道很長, 我和你一樣大部份有看沒有懂, 只看 L158 ~ L173 就好。

158   __bss_start = .;
159   .bss            :
160   {
161    *(.dynbss)
162    *(.bss .bss.* .gnu.linkonce.b.*)
163    *(COMMON)
164    /* Align here to ensure that the .bss section occupies space up to
165       _end.  Align after .bss to ensure correct alignment even if the
166       .bss section disappears because there are no input sections.
167       FIXME: Why do we need it? When there is no .bss section, we don't
168       pad the .data section.  */
169    . = ALIGN(. != 0 ? 32 / 8 : 1);
170   }
171   . = ALIGN(32 / 8);
172   . = ALIGN(32 / 8);
173   _end = .; PROVIDE (end = .);

_end, __bss_start 這兩個 symbol 就是 bss section 的開始和結束。先來看看程式執行結果。

i: 0x8049734
i: 0x8049738
&__bss_start: 0x8049734
&_end: 0x804973c
ABCDEF: 11223344

bss 從  0x8049734 ~ 0x804973c 佔了 8 byte。

ABCDEF 不是預期的 0。表示成功改變 bss 這個區域。這應該簡單多了, 而且也可以馬上在 linux 上實驗。

b.c
 1 #include <stdio.h>
 2 
 3 int ABCDEF;
 4 extern int _end;
 5 extern int __bss_start;
 6 
 7 void fill_bss(void)
 8 {
 9   int *i=0;
10   for (i = &__bss_start ; i != &_end ; ++i)
11   {
12     printf("i: %p\n", i);
13     *i = 0x11223344;
14   }
15 
16 }
17 
18 int main(void)
19 {
20   fill_bss();
21   printf("&__bss_start: %p\n", &__bss_start);
22   printf("&_end: %p\n", &_end);
23   printf("ABCDEF: %x\n", ABCDEF);
24   return 0;
25 }

看看 elf 裡頭的資訊:
[26] .bss NOBITS 08049734 000734 000008 00  WA  0   0  4
63: 08049738     4 OBJECT  GLOBAL DEFAULT   26 ABCDEF
bss 佔 8 byte, ABCDEF 則位於 0x08049738

source code:
git clone git@github.com:descent/progs.git'
cd bss

ref:
linux kernel 完全剖析 (3.5.4 p 96)

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。