components sequence and libc

Alexander Tormasov a.tormasov at innopolis.ru
Sun Jul 5 01:07:55 CEST 2020


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_pool<Genode::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!



More information about the users mailing list