Hi Omar,

On Wed, 2019-07-03 at 13:03 -0700, Omar Sandoval wrote:
> I'm developing an application which uses libdwfl. When I tested it in
> our production environment, the application hit DWARF parsing errors for
> Linux kernel modules. I tracked it down to an issue that ELF relocations
> were silently not being applied because the proper libebl_CPU.so could
> not be found. That appears to be a bug in relocate_sections() or
> check_badreltype() in libdwfl

If you were on a multi-arch platform, this could have been:
https://sourceware.org/bugzilla/show_bug.cgi?id=24488
ebl_openbackend might use wrong library search path

Fixed in git commit bfcf8b
libebl: Try harder to find backend library in bin and lib origin paths.

But not yet in a released elfutils.

> but that got me looking at getting rid of
> the dlopen() entirely. IMO, it simplifies things nicely, and it makes it
> possible to use the elfutils libraries in standalone static binaries.

Very timely! This came up again recently on irc where someone else also
had something like this.

> I came across a previous discussion [1] where Mark suggested a hybrid
> approach, where one could configure which modules to compile in and
> which ones to keep separate. I tried to implement this, but it quickly
> turned into automake dependency hell: the backends subdirectory needs to
> depend on the libdw subdirectory in order to link libebl_CPU.so against
> libdw.so, but the libdw subdirectory needs to depend on the backends
> subdirectory in order to include the static backends in libdw.so.

Yes, that is unfortunate. And one of the reasons I never implemented it
myself. My own simple approach on the mjw/RH_DTS git branch also gets
this wrong (even though it doesn't do things very fancy, it just builds
a few architectures static, not all, and doesn't even try to mix static
vs shared approaches). It doesn't actually build as is. You have to
build the subdirectories in order, and then rebuild it all. It is very
messy :{

> My understanding of the benefit of separate modules is that we don't
> need to link all backend modules into every elfutils binary. I did
> some measurements to that end:
> 
> Dynamic backends (status quo):
> 44K     ./libasm/libasm.so
> 380K    ./libdw/libdw.so
> 120K    ./libelf/libelf.so
> 72K     ./src/nm
> 28K     ./src/size
> 80K     ./src/strip
> 140K    ./src/elflint
> 28K     ./src/findtextrel
> 36K     ./src/addr2line
> 52K     ./src/elfcmp
> 56K     ./src/objdump
> 32K     ./src/strings
> 48K     ./src/ar
> 60K     ./src/unstrip
> 36K     ./src/stack
> 40K     ./src/elfcompress
> 32K     ./src/ranlib
> 272K    ./src/readelf
> 68K     backends/libebl_i386.so
> 24K     backends/libebl_sh.so
> 76K     backends/libebl_x86_64.so
> 28K     backends/libebl_ia64.so
> 24K     backends/libebl_alpha.so
> 36K     backends/libebl_arm.so
> 44K     backends/libebl_aarch64.so
> 36K     backends/libebl_sparc.so
> 36K     backends/libebl_ppc.so
> 36K     backends/libebl_ppc64.so
> 32K     backends/libebl_s390.so
> 24K     backends/libebl_tilegx.so
> 20K     backends/libebl_m68k.so
> 24K     backends/libebl_bpf.so
> 32K     backends/libebl_riscv.so
> 2.1M    total

So the sum of all the backends is ~500K

> Static backends (after this series):
> 44K     ./libasm/libasm.so
> 668K    ./libdw/libdw.so
> 120K    ./libelf/libelf.so
> 356K    ./src/nm
> 28K     ./src/size
> 368K    ./src/strip
> 428K    ./src/elflint
> 28K     ./src/findtextrel
> 36K     ./src/addr2line
> 340K    ./src/elfcmp
> 348K    ./src/objdump
> 32K     ./src/strings
> 48K     ./src/ar
> 60K     ./src/unstrip
> 36K     ./src/stack
> 40K     ./src/elfcompress
> 32K     ./src/ranlib
> 560K    ./src/readelf
> 3.5M    total

But the binaries linking in the static library only grow with ~300K.
So combining them seems to reduce the size significantly. But some
binaries are now ~twice as big.

> If the size increase is a deal-breaker, one easy solution may be to
> export the libebl symbols from libdw so that libebl.a doesn't need to be
> linked into the elfutils binaries. Considering that libebl.a is already
> shipped by distributions, this doesn't increase the surface area of
> exported APIs (and the warning in libebl.h should make it clear that
> these APIs are not intended to be used).

I don't think the size increase is a deal-breaker, although it would be
nice to see if it could be reduced a little.

It probably was a mistake for distros to ship libebl.a and libebl.h
though. Even though there is a warning to not use libebl functions
directly, people will do it anyway. And get annoyed when things break.

> Thoughts? Is the size increase palatable? Should I add a third patch to
> export the libebl symbols in libdw in order to mitigate the size
> increase? Or is this a dead end?

The size increase is probably palatable. One option might be to let the
user/distributor select the backends to compile in. Or maybe we should
just drop some backends (sh, ia64, alpha and tilegx are probably not
really used).

Let me reply to the export symbols through libdw part later in the
thread (spoiler alert, I really don't like that).

Cheers,

Mark

Reply via email to