- class1.cpp
- #include <iostream>
- class class1_t
- {
- public:
- class1_t ()
- {
- std::cout << "class1_t::class1_t ()" << std::endl;
- }
- };
- static class1_t s_class1;
- main.cpp
- #include <iostream>
- class class2_t
- {
- public:
- class2_t ()
- {
- std::cout << "class2_t::class2_t ()" << std::endl;
- }
- };
- static class2_t s_class2;
- int main ()
- {
- return 0;
- }
- $ g++ main.cpp class1.cpp -o example
- $ ./example.exe
- class1_t::class1_t ()
- class2_t::class2_t ()
- $ g++ class1.cpp main.cpp -o example
- $ ./example.exe
- class2_t::class2_t ()
- class1_t::class1_t ()
- $ ld --verbose > ldscript
- ldscript
- /* Script for ld --enable-auto-import: Like the default script except
- read only data is placed into .data */
- SECTIONS
- {
- /* Make the virtual address and file offset synced if the
- alignment is lower than the target page size. */
- . = SIZEOF_HEADERS;
- . = ALIGN(__section_alignment__);
- .text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :
- {
- *(.init)
- *(.text)
- *(SORT(.text$*))
- *(.text.*)
- *(.glue_7t)
- *(.glue_7)
- ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
- LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);
- ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
- LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);
- *(.fini)
- /* ??? Why is .gcc_exc here? */
- *(.gcc_exc)
- PROVIDE (etext = .);
- *(.gcc_except_table)
- }
- ……
- }
- gbl-ctors.h
- typedef void (*func_ptr) (void);
- extern func_ptr __CTOR_LIST__[];
- extern func_ptr __DTOR_LIST__[];
- #define DO_GLOBAL_CTORS_BODY \
- do { \
- unsigned long nptrs = (unsigned long) __CTOR_LIST__[0]; \
- unsigned i; \
- if (nptrs == (unsigned long)-1) \
- for (nptrs = 0; __CTOR_LIST__[nptrs + 1] != 0; nptrs++); \
- for (i = nptrs; i >= 1; i--) \
- __CTOR_LIST__[i] (); \
- } while (0)
- libgcc2.c
- void __do_global_dtors (void)
- {
- static func_ptr *p = __DTOR_LIST__ + 1;
- while (*p) {
- p++;
- (*(p-1)) ();
- }
- }
- void __do_global_ctors (void)
- {
- DO_GLOBAL_CTORS_BODY;
- atexit (__do_global_dtors);
- }
- $ g++ -c –g class1.cpp
- $ objdump -S -d --demangle=gnu-v3 class1.o
- class1.o: file format pe-i386
- Disassembly of section .text:
- ……内容有删减……
- 0000004a <global destructors keyed to class1.cpp>:
- 4a: 55 push %ebp
- 4b: 89 e5 mov %esp,%ebp
- 4d: 83 ec 08 sub $0x8,%esp
- 50: c7 44 24 04 ff ff 00 movl $0xffff,0x4(%esp)
- 57: 00
- 58: c7 04 24 00 00 00 00 movl $0x0,(%esp)
- 5f: e8 9c ff ff ff call 0
- 64: c9 leave
- 65: c3 ret
- 00000066 <global constructors keyed to class1.cpp>:
- 66: 55 push %ebp
- 67: 89 e5 mov %esp,%ebp
- 69: 83 ec 08 sub $0x8,%esp
- 6c: c7 44 24 04 ff ff 00 movl $0xffff,0x4(%esp)
- 73: 00
- 74: c7 04 24 01 00 00 00 movl $0x1,(%esp)
- 7b: e8 80 ff ff ff call 0
- 80: c9 leave
- 81: c3 ret
- 82: 90 nop
- 83: 90 nop
图 7示例了如何通过objdump工具查看class1.o文件中.ctors和.dtors段中的内容。从内容中可以看到存在前面提到的4a和66两个值,而这两个值会最终被ld链接器分别放入__CTOR_LIST__和__DTOR_LIST__数组中。
- $ objdump -s -j .ctors class1.o
- class1.o: file format pe-i386
- Contents of section .ctors:
- 0000 66000000 f...
- $ objdump -s -j .dtors class1.o
- class1.o: file format pe-i386
- Contents of section .dtors:
- 0000 4a000000 J...