C++ Constructors missing from .ctors section
Posted: Sun Dec 06, 2015 7:21 am
I'm back after a long hiatus, and after going through the rusty dusty gross codebase that I call a kernel, I realised that constructors... were never being called properly. The linker was somehow throwing away the .ctors and .dtors sections. To fix this, I put them in their own section in the output script, as such:
I can thus confirm that is a section that appears in the final ELF file:
It contains a nice list of 10 pointers to functions. Unfortunately, after using addr2line, I realised all 10 functions were coming from this, somehow:
I use rdestl for some of its datastructures. This is all fine, except of course other constructors never appear in the list. A quick example I put in a cpp file somewhere like this:
never creates any constructors in the list. Here's how I'm calling the constructors (it shouldn't matter since the binary file shows only 10 entries, but just in case):
Thanks.
Code: Select all
ENTRY(KernelBootstrap)
OUTPUT_FORMAT(elf64-x86-64)
SECTIONS
{
Kernel_VMA = 0xFFFFFFFF80000000;
. = Kernel_VMA;
.text ALIGN(0x1000) : AT(ADDR(.text) - Kernel_VMA)
{
*(.text*)
*(.gnu.linkonce.t*)
}
.rodata ALIGN(0x1000) : AT(ADDR(.rodata) - Kernel_VMA)
{
*(.rodata*)
*(.gnu.linkonce.r*)
}
.stuff ALIGN(0x1000) : AT(ADDR(.stuff) - Kernel_VMA)
{
start_ctors = .;
*(SORT(.ctors))
*(SORT(.ctors*))
end_ctors = .;
start_dtors = .;
*(SORT(.dtors))
end_dtors = .;
}
.data ALIGN(0x1000) : AT(ADDR(.data) - Kernel_VMA)
{
*(.data*)
*(.gnu.linkonce.d*)
}
.bss ALIGN(0x1000) : AT(ADDR(.bss) - Kernel_VMA)
{
StartBSS = .;
*(COMMON)
*(.bss*)
*(.gnu.linkonce.b*)
EndBSS = .;
}
KernelEnd = .;
}
I can thus confirm that
Code: Select all
.stuff
Code: Select all
$ ~/D/S/O/mx> tools/od -s -j .stuff build/kernel64.elf
build/kernel64.elf: file format elf64-x86-64
Contents of section .stuff:
ffffffff80042000 20170080 ffffffff 802d0080 ffffffff ........-......
ffffffff80042010 a0da0080 ffffffff 00140180 ffffffff ................
ffffffff80042020 408a0180 ffffffff b0aa0180 ffffffff @...............
ffffffff80042030 40c40180 ffffffff 20e20180 ffffffff @....... .......
ffffffff80042040 40fa0180 ffffffff f0230280 ffffffff @........#......
$ ~/D/S/O/mx>
Code: Select all
// Holy ...
template<typename TKey, typename TValue,
class THashFunc,
int TLoadFactor4,
class TKeyEqualFunc,
class TAllocator>
typename hash_map<TKey, TValue, THashFunc, TLoadFactor4, TKeyEqualFunc, TAllocator>::node hash_map<TKey, TValue, THashFunc, TLoadFactor4, TKeyEqualFunc, TAllocator>::ms_emptyNode;
Code: Select all
struct Foo
{
Foo()
{
HALT("");
}
int bar = 40;
};
struct Bar
{
Foo f;
};
static Bar g;
Code: Select all
uint64_t* ctorListBegin = &start_ctors;
uint64_t* ctorListEnd = &end_ctors;
Log("Calling Constructors:");
size_t i = 0;
while(ctorListBegin != ctorListEnd)
{
Log("%d: %p", i, *ctorListBegin);
void (*fn)() = (void(*)()) (*ctorListBegin);
fn();
ctorListBegin++, i++;
}
Thanks.