This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Is init_priority file scope or global scope?
On 12/12/2010 06:54, H.J. Lu wrote:
[ off-list, but it's not personal, so let's Cc the list back in, someone might
find this explanation of the mechanism useful in the archives. ]
> Can you check the assembly output? Since
>
> ----
> Note that the particular values of PRIORITY do not matter; only
> their relative ordering.
> ---
>
> on Linux, the numeric string in section name isn't the same as
> PRIORITY in source file. That means on Linux, the order
> of .ctors sections in 2 files isn't the relative ordering of PRIORITY
> of those 2 files.
Well, at least on PE-COFF, the numeric string is (65536-priority). It is
zero padded to five digits, so that the linker's alphabetical sort effectively
becomes a numeric sort, and the reason for the inverting the numeric order of
priorities is because .ctors gets read backwards at startup.
I did actually check the assembly somewhere between writing "IIRC" and
finishing my email as it happens. For a testcase based on your example:
class Some_Class {
int x;
public:
Some_Class();
~Some_Class();
};
Some_Class A __attribute__ ((init_priority (2000)));
Some_Class B __attribute__ ((init_priority (543)));
... what we get is a static_initialization_and_destruction function that takes
the init priority level as an argument and constructs or destroys (per a
second argument) everything at that level only:
.file "clas.c"
.globl _A
.bss
.align 4
_A:
.space 4
.globl _B
.align 4
_B:
.space 4
.text
.def __Z41__static_initialization_and_destruction_0ii; .scl 3; .type 32; .endef
__Z41__static_initialization_and_destruction_0ii:
LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
cmpl $1, 8(%ebp)
jne L2
cmpl $2000, 12(%ebp)
^^^^^^^^^^^^^^^^^^^^^^^
jne L3
^^^^^^^^^^
movl $_A, (%esp)
call __ZN10Some_ClassC1Ev
L3:
cmpl $543, 12(%ebp)
^^^^^^^^^^^^^^^^^^^^^^
jne L2
^^^^^^^^^^
movl $_B, (%esp)
call __ZN10Some_ClassC1Ev
L2:
cmpl $0, 8(%ebp)
jne L1
cmpl $543, 12(%ebp)
^^^^^^^^^^^^^^^^^^^^^^
jne L5
^^^^^^^^^^
movl $_B, (%esp)
call __ZN10Some_ClassD1Ev
L5:
cmpl $2000, 12(%ebp)
^^^^^^^^^^^^^^^^^^^^^^^
jne L1
^^^^^^^^^^
movl $_A, (%esp)
call __ZN10Some_ClassD1Ev
L1:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE0:
Then we have __GLOBAL__[I/D] functions for each priority level, which load
the appropriate priority and construct/destruct argument and call that:
.def __GLOBAL__I.00543_A; .scl 3; .type 32; .endef
__GLOBAL__I.00543_A:
LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $543, 4(%esp)
^^^^^^^^^^^^^^^^^^^^^
movl $1, (%esp)
^^^^^^^^^^^^^^^^^^
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE1:
.def __GLOBAL__D.00543_A; .scl 3; .type 32; .endef
__GLOBAL__D.00543_A:
LFB2:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $543, 4(%esp)
^^^^^^^^^^^^^^^^^^^^^
movl $0, (%esp)
^^^^^^^^^^^^^^^^^^
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE2:
.def __GLOBAL__I.02000_A; .scl 3; .type 32; .endef
__GLOBAL__I.02000_A:
LFB3:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $2000, 4(%esp)
^^^^^^^^^^^^^^^^^^^^^^
movl $1, (%esp)
^^^^^^^^^^^^^^^^^^
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE3:
.def __GLOBAL__D.02000_A; .scl 3; .type 32; .endef
__GLOBAL__D.02000_A:
LFB4:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $2000, 4(%esp)
^^^^^^^^^^^^^^^^^^^^^^
movl $0, (%esp)
^^^^^^^^^^^^^^^^^^
call __Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE4:
... and it is these routines that are inserted in reverse-priority order into
the .ctors and .dtors tables (don't forget that the .ctors table is run
backward, the .dtors is run forward):
.section .ctors.64992,"w"
.align 4
.long __GLOBAL__I.00543_A
.text
.section .dtors.64992,"w"
.align 4
.long __GLOBAL__D.00543_A
.text
.section .ctors.63535,"w"
.align 4
.long __GLOBAL__I.02000_A
.text
.section .dtors.63535,"w"
.align 4
.long __GLOBAL__D.02000_A
So that ought to be entirely global ordering at final-link time. I don't
know if ELF does it differently.
cheers,
DaveK