Lost .ctors section from a static library

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Lost .ctors section from a static library

Post by torshie »

I created a new staticly library libtest.a and linked it to my kernel. The static library will create some global objects. I found that the global objects from the static library are not constructed, but the global objects in the kernel are still constructed correctly. I also checked the elf files: the .ctors section of the kernel object file is 8 bytes, .ctors section of the static library(only one object file of the static library has a .ctors section) is 8 bytes. The .ctors section of the final executable is still 8 bytes. So I guess the .ctors section from the static library is lost somehow. The following is my linker script and the code used to initialize global objects. Do I missed anything in the linker script or my code used for construct global objects is wrong?

Code: Select all

typedef void (*Initializer)(void);

/* These two are defined in ld script */
extern "C" Initializer __wtn_ctors_begin__, __wtn_ctors_end__;

void initGlobalObjects() {
	for (Initializer* init = &__wtn_ctors_begin__; init < &__wtn_ctors_end__;
			++init) {
		(*init)();
	}
}

Code: Select all

OUTPUT_ARCH(i386:x86-64)
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(__wtn_start)
PROVIDE(runAllTestCase = 0);
GROUP(-ltest -lcxxrt -lcrt-x64 -lunwind)

SECTIONS {
	. = 0xFFFFFFFF80000000 + 0x100000 + 0x100000;

	__wtn_stack_bottom__ = .;

	.init : ALIGN(16) {
		*(.init)
	}

	.text : ALIGN(16) {
		*(.text .text.*)
	}

	. = ALIGN(4096);

	.rodata : {
		*(.rodata .rodata.*)
	}

	.eh_frame_hdr : ALIGN(16) {
		*(.eh_frame_hdr)
	}
	.eh_frame : ONLY_IF_RO {
		__wtn_eh_frame_start__ = .;
		*(.eh_frame)
	}
	.gcc_except_table : ONLY_IF_RO {
		*(.gcc_except_table .gcc_except_table.*)
	}

	.ctors : ALIGN(16) {
		__wtn_ctors_begin__ = .;
		KEEP(*(SORT(.ctors.*)))
		KEEP(*(.ctors))
		__wtn_ctors_end__ = .;
	}

	.dtors : ALIGN(16) {
		KEEP(*(SORT(.dtors.*)))
		KEEP(*(.dtors))
	}

	.note : ALIGN(16) {
		*(.note.gnu.build-id)
	}

	. = ALIGN(4096);

	.eh_frame : ONLY_IF_RW {
		*(.eh_frame)
	}
	.gcc_except_table : ONLY_IF_RW {
		*(.gcc_except_table .gcc_except_table.*)
	}

	.data : ALIGN(16) {
		*(.data .data.*);
	}

	.bss : ALIGN(16) {
		*(.bss .bss.*)
		*(COMMON)
	}

	. = ALIGN(4096);
	__wtn_image_end__ = .;

	/DISCARD/ : {
		*(.comment)
	}
}
Thanks
-torshie
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Lost .ctors section from a static library

Post by Combuster »

If your code does not include portions of static libraries, it usually means they are not referenced: For instance, if you don't use cout/cin/cerr, there's no need at all to create those objects at startup, and therefore their ctors/dtors are not needed.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: Lost .ctors section from a static library

Post by torshie »

These global objects are NOT referenced directly. But these objects have non-trivial constructors, in the constructors, one global variable will be changed, and the global variable will be referenced.
I also tried partial library(ld -r), when a partial library instead of a static library is created, the executable runs as expected.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Lost .ctors section from a static library

Post by Combuster »

But that still means nothing depends on the object file with the constructors. You apparently require KDE to run a mount command just because KDE depends on it :wink:
Last edited by Combuster on Tue Jul 19, 2011 3:49 am, edited 1 time in total.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Lost .ctors section from a static library

Post by Owen »

Static libraries are designed so that the linker only pulls out the objects which contain symbols referenced by objects already linked. You can think of the process traditional LD uses as follows:
  1. Create an empty internal representation of an object
  2. foreach input in inputs {
  3. Look at an imput file (whether supplied as a path or a -l parameter)
  4. If its an object, merge it with the ones already processed
  5. If its a static library, look up each undefined symbol against the library symbol table. If a symbol is found, pull in that object. This process is repeated for any undefined symbols introduced by the object being pulled in
  6. Move to the next input
  7. }
A more modern linker, like ObjectTools' OT::Linker class (ObjectTools being the set of libraries and tools I'm working on; sorry, not yet released) may do this process in a more advanced and more friendly format (For example, I link all passed object files together and then do multiple passes over the libraries until either a symbol is declared undefined, which raises an error, or the symbol is successfully linked) when not operating in a strict compatibility mode. However, the core of it is still the same.

ld -r just merges the passed objects into a single relocatable object file. You can think of this as being the internal form that the object takes before an image writer proceeds to write it out to a file. This is certainly how ObjectTools does things, though this all happens with the internal representation. It is not a "partial library"; it is just a way of merging relocatable objects.
Post Reply