I am trying to run application which have libc component and my own golang part. I use nova kernel on x86_64 version.
I found that during the process of linker initialization of components I have uninitiated variable:
#0 Genode::Stack::size (this=0x401fef28, size=0x40000) at /media/psf/Home/gen/20.05/repos/base/src/lib/base/thread.cc:34 #1 0x00000000000fb094 in Linker::Binary::call_entry_point (env=..., this=0x15e010 <unmanaged_singleton<Linker::Binary, 8, Genode::Env&, Genode::Heap&, Linker::Config const&, char const*>(Genode::Env&, Genode::Heap&, Linker::Config const&, char const*&&)::object_space>) at /media/psf/Home/gen/20.05/repos/base/src/lib/ldso/main.cc:436 #2 Component::construct (env=...) at /media/psf/Home/gen/20.05/repos/base/src/lib/ldso/main.cc:825 #3 0x000000000007cf7f in (anonymous namespace)::Constructor_component::construct (this=0x400fec10) at /media/psf/Home/gen/20.05/repos/base/src/lib/base/entrypoint.cc:319 #4 Genode::Meta::call_member<Genode::Meta::Empty, (anonymous namespace)::Constructor_component, Genode::Meta::Empty> (func=<optimized out>, server=...) at /media/psf/Home/gen/20.05/repos/base/include/util/meta.h:464 #5 (anonymous namespace)::Constructor::Rpc_construct::serve<(anonymous namespace)::Constructor_component, Genode::Meta::Empty> (args=<synthetic pointer>..., server=...) at /media/psf/Home/gen/20.05/repos/base/src/lib/base/entrypoint.cc:293 #6 Genode::Rpc_dispatcher<(anonymous namespace)::Constructor, (anonymous namespace)::Constructor_component>::_do_serve<(anonymous namespace)::Constructor::Rpc_construct> (args=<synthetic pointer>..., this=0x400fec98) at /media/psf/Home/gen/20.05/repos/base/include/base/rpc_server.h:146 #7 Genode::Rpc_dispatcher<(anonymous namespace)::Constructor, (anonymous namespace)::Constructor_component>::_do_dispatch<Genode::Meta::Type_list<(anonymous namespace)::Constructor::Rpc_construct> > (in=..., out=..., opcode=..., this=0x400fec98) at /media/psf/Home/gen/20.05/repos/base/include/base/rpc_server.h:180 #8 Genode::Rpc_dispatcher<(anonymous namespace)::Constructor, (anonymous namespace)::Constructor_component>::dispatch (in=..., out=..., opcode=..., this=0x400fec98) at /media/psf/Home/gen/20.05/repos/base/include/base/rpc_server.h:235 #9 Genode::Rpc_object<(anonymous namespace)::Constructor, (anonymous namespace)::Constructor_component>::dispatch (this=0x400fec10, opcode=..., in=..., out=...) at /media/psf/Home/gen/20.05/repos/base/include/base/rpc_server.h:272 #10 0x000000000009d08d in Genode::Rpc_entrypoint::<lambda(Genode::Rpc_object_base*)>::operator() (obj=0x400fec10, __closure=<synthetic pointer>) at /media/psf/Home/gen/20.05/repos/base-nova/src/lib/base/rpc_entrypoint.cc:177 #11 Genode::Object_poolGenode::Rpc_object_base::apply<Genode::Rpc_entrypoint::_activation_entry()::<lambda(Genode::Rpc_object_base*)> > (func=..., capid=<optimized out>, this=0x12e4b0 Genode::bootstrap_component()::startup+528) at /media/psf/Home/gen/20.05/repos/base/include/base/object_pool.h:147 #12 Genode::Rpc_entrypoint::_activation_entry () at /media/psf/Home/gen/20.05/repos/base-nova/src/lib/base/rpc_entrypoint.cc:180 #13 0x0000000000000000 in ?? ()
code #1 contains the following: void call_entry_point(Env &env) { /* apply the component-provided stack size */ if (Elf::Addr addr = lookup_symbol("_ZN9Component10stack_sizeEv")) {
/* call 'Component::stack_size()' */ size_t const stack_size = ((size_t(*)())addr)();
/* expand stack according to the component's needs */ Thread::myself()->stack_size(stack_size); } … it found _ZN9Component10stack_sizeEv function for libc and then call the following function #0 from base/src/lib/base/thread.cc:
void Stack::size(size_t const size) { /* check if the stack needs to be enhanced */ size_t const stack_size = (addr_t)_stack - _base; if (stack_size >= size) { return; }
/* check if the stack enhancement fits the stack region */ enum { UTCB_SIZE = sizeof(Native_utcb), PAGE_SIZE_LOG2 = 12, PAGE_SIZE = (1UL << PAGE_SIZE_LOG2), }; addr_t const stack_slot_base = Stack_allocator::addr_to_base(this); size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2); if (_base - ds_size < stack_slot_base) throw Thread::Stack_too_large();
/* allocate and attach backing store for the stack enhancement */ addr_t const ds_addr = _base - ds_size - stack_area_virtual_base(); try { Ram_allocator * const ram = env_stack_area_ram_allocator; Ram_dataspace_capability const ds_cap = ram->alloc(ds_size); … here I found that env_stack_area_ram_allocator is null, not initialized!
in core base/src/core/stack_area.cc I found part which probably should be called before previous code: void Genode::init_stack_area() { static Stack_area_region_map rm; env_stack_area_region_map = &rm;
static Stack_area_ram_allocator ram; env_stack_area_ram_allocator = &ram; }
seems that this initializer should be called before libc component initializer (it belong to different component)?
Nesessary initialization probably happens in class constructor of class Genode::Core_env : public Env_deprecated, Noncopyable base/src/core/include/core_env.h
seems that something wrong in link sequence.
Question: ======== how I can fix the order of different component initialization? I probably need class Genode::Core_ to be initialized first as a part of general code of core-nova.o. may be I missed something like crt*.o in link? crt0.o definitely present in $libs/startup-nova/startup-nova.lib.a…
on previous version I found some magical sequence which works after some manipulations with link order, but now with 20.05 it is not working any more for me.
Some info about my code:
in my code dummy.cc I have function (C style) main and component constructor void Libc::Component::construct(Libc::Env &env) { // Genode::Heap heap(env.ram(), env.rm()); // _verbose = false; static int c = 1; static char * myname = "GolangApp"; int r = 0; Libc::with_libc([&r] () { r = main(c, &myname); }); env.parent().exit(r); }
my current link command line: libs=/media/psf/Home/gen/20.05/build/x86_64/var/libcache; genode-x86-gcc -B /media/psf/Home/gen/20.05/build/x86_64/../tool_chain-19.05/x86/gcc/gcc/ -Wl,-melf_x86_64 -Wl,-gc-sections -Wl,-z -Wl,max-page-size=0x1000 -Wl,--dynamic-list=/media/psf/Home/gen/20.05/repos/base/src/ld/genode_dyn.dl -nostdlib -Wl,-nostdlib -Wl,-Ttext=0x01000000 -m64 -mcmodel=large -Wl,--dynamic-linker=ld.lib.so -Wl,--eh-frame-hdr -Wl,-rpath-link=. -Wl,-T -Wl,/media/psf/Home/gen/20.05/repos/base/src/ld/genode_dyn.ld -Wl,--whole-archive -Wl,--start-group dummy.o main.o myacontext.o mycontext.o $libs/base-nova-common/base-nova-common.lib.a $libs/base-nova/base-nova.lib.a $libs/startup-nova/startup-nova.lib.a $libs/timeout/timeout.lib.a ld.lib.so libc.lib.so libm.lib.so vfs.lib.so -Wl,--no-whole-archive -Wl,--end-group /media/psf/Home/gen/20.05/build/x86_64/var/libcache/libc-gen/libc-gen.lib.a /media/psf/Home/gen/20.05/build/x86_64/var/libcache/libgo/libgobegin.a /media/psf/Home/gen/20.05/build/x86_64/var/libcache/libgo/libgolibbegin.a /media/psf/Home/gen/20.05/build/x86_64/var/libcache/libgo/libgo.a /media/psf/Home/gen/20.05/build/x86_64/var/libcache/libc-stdlib/libc-stdlib.lib.a /media/psf/Home/gen/20.05/build/x86_64/var/libcache/cxx/cxx.lib.a /media/psf/Home/gen/20.05/build/x86_64/../tool_chain-19.05/x86/gcc/x86_64-pc-elf/64/libgcc/libgcc_eh.a /media/psf/Home/gen/20.05/build/x86_64/../tool_chain-19.05/x86/gcc/x86_64-pc-elf/64/libgcc/libgcc.a
Thanks!
Hello Alexander,
it seems your component startup misses to initialize all modules correctly. While I have no idea where this stems from I have two options to proceed. First, I suggest a closer look into the changes in [1] that cleans up shared library initialization. The alternative is to use "git bisect" (maybe starting with [1]) to find the offending change in Genode 20.05.
As you have your own linker command sampled with an earlier release it only makes sense to test with your tree except you are able to isolate the issue with a minimal patch and without Go.
[1] https://github.com/chelmuth/genode/commit/42fddf8390c0436a09cf6fae3391f9a260...
Regards
Hello, Christian, and thank you for answer!
Seems that problem a bit deeper - I need to use complex application written on 4 languages (C, C++, golang and asm), each with own static objects constructors.
Frankly speaking, seems that this bug was present even in 19.08/19.11 versions. I hit in in the very beginning of my attempt to solve application link problem. I found some solution which force proper order of initialisation (libc AFTER core initialisation). It was kind of «tribe dance with drum» around: some particular order of libraries works, some - not. I hit this first for seL4 kernel, and accidentally I found proper sequence. later I moved to Nova kernel, and again I need to make kind of «MonteCarlo experiments» to find proper sequence in link command line.
Today I want to make more clear implementation based on 20.05 using defaults from genode and again start the same «dance» (I can’t reproduce it exactly as it was in my old test because it requires intensive patching of mk files - this is what I want to get rid off). I don’t think that this is exactly 20.05 changes problem...
I want to find a real reason of problem with order of dynamic library initialisation and the way to explicitly control it.
any suggestions about how to force dynamic linker to take core-nova.o in my case as the first to be initialised? I am not that proficient in link scripting...
Sincerely, Alexander
6 июля 2020 г., в 09:22, Christian Helmuth christian.helmuth@genode-labs.com написал(а):
Hello Alexander,
it seems your component startup misses to initialize all modules correctly. While I have no idea where this stems from I have two options to proceed. First, I suggest a closer look into the changes in [1] that cleans up shared library initialization. The alternative is to use "git bisect" (maybe starting with [1]) to find the offending change in Genode 20.05.
As you have your own linker command sampled with an earlier release it only makes sense to test with your tree except you are able to isolate the issue with a minimal patch and without Go.
[1] https://github.com/chelmuth/genode/commit/42fddf8390c0436a09cf6fae3391f9a260...
Regards
Christian Helmuth Genode Labs
https://www.genode-labs.com/ · https://genode.org/ https://twitter.com/GenodeLabs · /ˈdʒiː.nəʊd/
Genode Labs GmbH · Amtsgericht Dresden · HRB 28424 · Sitz Dresden Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth
Genode users mailing list users@lists.genode.org https://lists.genode.org/listinfo/users
Hi,
On Mon, Jul 06, 2020 at 11:37:09 CEST, Alexander Tormasov via users wrote:
Seems that problem a bit deeper - I need to use complex application written on 4 languages (C, C++, golang and asm), each with own static objects constructors.
I take this as: You're trying an application on top of Genode and minimalizing the issue is difficult.
I want to find a real reason of problem with order of dynamic library initialisation and the way to explicitly control it.
any suggestions about how to force dynamic linker to take core-nova.o in my case as the first to be initialised? I am not that proficient in link scripting...
I don't understand why you need to link to core-nova.o given the info above. This particular compilation unit is linked only to the core component which you don't need to change when running applications on top of Genode. You also do not need to change ld.lib.so. All your adaption should be "on top". Maybe you can have look into [1] to find out how multi-language environments could be implemented on top of Genode. Also for your issue with initialization, [2] may be relevant.
[1] https://github.com/genodelabs/genode/tree/master/repos/libports/src/test/spa... [2] https://github.com/genodelabs/genode/blob/2c47cd5c946af1ec585d2758955f8b2c4e...
Regards