Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 19 Dec 2017 16:27:09 +0100
From: Szabolcs Nagy <>
Subject: Re: [PATCH] split __libc_start_main.c into two files (Wasm)

* Nicholas Wilson <> [2017-12-19 11:04:33 +0000]:
> On 19 December 2017 01:08, Rich Felker wrote:
> > I still don't see any good reason to call __init_libc instead of
> > __libc_start_main. While the crt1 entry point (_start) itself is a not
> > a normal C function but something specific to the ELF entry
> > conventions, __libc_start_main is a perfectly good C function that is
> > not "ELF specific".
> There are two ELF-specific bits to __libc_start_main:
> 1) The first thing is that it calls main and exit! Wasm users don't want to call exit. (This is different from the discussion we had before as to whether it's OK to *link in* exit when it's never called. This is about whether it's actually OK to call exit.) exit destroys C++ global variables, and Wasm users don't want that. We need to able to call into the Wasm module repeatedly from a JavaScript web page.

i don't know much about the wasm environment, but surely
there are many ways to map c concepts to the wasm ones.
you should choose a mapping that makes wasm less different
from other targets.

> Maybe think of a Wasm (statically-linked) binary as being a bit more like a shared library: instead of exporting a single "entrypoint" for the kernel to run (like a Unix process), it exports a list of functions for the JavaScript environment to run repeatedly. We're not using the language of "shared library" though, because we're using that terminology to mean Wasm libraries calling each other, and we don't have all the tooling in place for that in web browsers yet.
> 2) This second point is just for your interest. It doesn't affect the rest of Musl, since Wasm can provide its own crt/wasm/crt1.c.  (See:

the correctness of the runtime is only guaranteed if you
go via the symbol __libc_start_main otherwise future
changes to that function can easily break your wasm port.

> Another difference is that __libc_start_init uses the __init_array_start/end symbols, which come from special compiler-provided crtbegin.o/crtend.o objects on ELF platforms. The linker has to arrange for a table of function pointers for Musl to call, and it does that using the magic .init_array ELF section (plus some priority fiddling).
> In Wasm, most functions are not callable by pointer: a function pointer is only assigned to code that has its address taken. For security, a decision was taken *not* to use a table of function pointers for the startup code, since that would mean taking the address of those functions, and they otherwise would be unlikely to need to go in the function pointer table. It's a hardening measure, to reduce the number of functions that can be used as the target of an indirect call.
> Hence, the linker synthesises the init-function as a list of call-instructions, rather than synthesising a list of function pointers for a pre-written function to iterate over.

you can use a single function pointer in init_array (to the
linker generated magic init function) or override _init or
let the wasm environment provide main which does the init.
in any case there seems to be no need to do things
differently on wasm (at least for an initial port)

> This decision wasn't mine, but I'm sympathetic to it. We did discuss whether it would be unhelpful to diverge from ELF like this, but the consensus was that keeping the table of function pointers small was more worthwhile.
> Note - I realise that we could override the ELF-y __libc_start_init since it's weak. However, given that we need to call __init_libc directly anyway, we may as well save some code and just register __init_libc with the Wasm start mechanism.

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.