public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* [RFC PATCH 1/2] libcpu: merge libcpu_{i386,x86_64,bpf} into one library
  2019-07-03 20:04 [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules Omar Sandoval
@ 2019-07-03 20:04 ` Omar Sandoval
  2019-07-03 20:04 ` [RFC PATCH 2/2] Don't use dlopen() for libebl modules Omar Sandoval
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Omar Sandoval @ 2019-07-03 20:04 UTC (permalink / raw)
  To: elfutils-devel

From: Omar Sandoval <osandov@fb.com>

In preparation for combining the libebl backend modules, combine all of
the libcpu backends into libcpu.a.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 backends/ChangeLog   |  4 ++++
 backends/Makefile.am | 12 +++---------
 libcpu/ChangeLog     |  4 ++++
 libcpu/Makefile.am   | 12 +++++-------
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/backends/ChangeLog b/backends/ChangeLog
index 6c2b47a9..b40a4c8e 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,7 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Use combined libcpu.a library.
+
 2019-04-14  Mark Wielaard  <mark@klomp.org>
 
 	* riscv_cfi.c: Fix BACKEND define.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 2126a2ec..0307da07 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -43,6 +43,7 @@ noinst_LIBRARIES = $(libebl_pic)
 noinst_DATA = $(libebl_pic:_pic.a=.so)
 
 
+libcpu = ../libcpu/libcpu.a
 libelf = ../libelf/libelf.so
 libdw = ../libdw/libdw.so
 libeu = ../lib/libeu.a
@@ -50,7 +51,6 @@ libeu = ../lib/libeu.a
 i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
 	    i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c \
 	    i386_initreg.c i386_unwind.c
-cpu_i386 = ../libcpu/libcpu_i386.a
 libebl_i386_pic_a_SOURCES = $(i386_SRCS)
 am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
 
@@ -61,7 +61,6 @@ am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
 x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_cfi.c \
 	      x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c \
 	      x86_64_initreg.c x86_64_unwind.c x32_corenote.c
-cpu_x86_64 = ../libcpu/libcpu_x86_64.a
 libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
 am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
 
@@ -127,7 +126,6 @@ am_libebl_m68k_pic_a_OBJECTS = $(m68k_SRCS:.c=.os)
 m68k_corenote_no_Wpacked_not_aligned = yes
 
 bpf_SRCS = bpf_init.c bpf_regs.c bpf_symbol.c
-cpu_bpf = ../libcpu/libcpu_bpf.a
 libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
 am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
 
@@ -137,20 +135,16 @@ libebl_riscv_pic_a_SOURCES = $(riscv_SRCS)
 am_libebl_riscv_pic_a_OBJECTS = $(riscv_SRCS:.c=.os)
 
 
-libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw) $(libeu)
+libebl_%.so libebl_%.map: libebl_%_pic.a $(libcpu) $(libelf) $(libdw) $(libeu)
 	@rm -f $(@:.so=.map)
 	$(AM_V_at)echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' \
 	  > $(@:.so=.map)
 	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $(@:.map=.so) \
-		-Wl,--whole-archive $< $(cpu_$*) -Wl,--no-whole-archive \
+		-Wl,--whole-archive $< $(libcpu) -Wl,--no-whole-archive \
 		-Wl,--version-script,$(@:.so=.map),--no-undefined \
 		-Wl,--as-needed $(libelf) $(libdw) $(libeu)
 	@$(textrel_check)
 
-libebl_i386.so: $(cpu_i386)
-libebl_x86_64.so: $(cpu_x86_64)
-libebl_bpf.so: $(cpu_bpf)
-
 install: install-am install-ebl-modules
 install-ebl-modules:
 	$(mkinstalldirs) $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
index adebbef8..0075a793 100644
--- a/libcpu/ChangeLog
+++ b/libcpu/ChangeLog
@@ -1,3 +1,7 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Combine backends into libcpu.a.
+
 2018-11-04  Mark Wielaard  <mark@klomp.org>
 
 	* bpf_disasm.c (bpf_disasm): Recognize BPF_JLT, BPF_JLE, BPF_JSLT
diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am
index 4c8778d1..a7d9f6fd 100644
--- a/libcpu/Makefile.am
+++ b/libcpu/Makefile.am
@@ -35,20 +35,16 @@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$(<F:lex.l=)
 LEX_OUTPUT_ROOT = lex.$(<F:lex.l=)
 AM_YFLAGS = -p$(<F:parse.y=)
 
-noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a
+noinst_LIBRARIES = libcpu.a
 
-libcpu_i386_a_SOURCES = i386_disasm.c i386_dis.h
-libcpu_x86_64_a_SOURCES = x86_64_disasm.c x86_64_dis.h
+libcpu_a_SOURCES = i386_disasm.c i386_dis.h x86_64_disasm.c x86_64_dis.h \
+		   bpf_disasm.c
 
 i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y
 
 i386_disasm.o: i386.mnemonics $(srcdir)/i386_dis.h
 x86_64_disasm.o: x86_64.mnemonics $(srcdir)/x86_64_dis.h
 
-noinst_LIBRARIES += libcpu_bpf.a
-libcpu_bpf_a_SOURCES = bpf_disasm.c
-libcpu_bpf_a_CFLAGS = $(AM_CFLAGS) -Wno-format-nonliteral
-
 %_defs: $(srcdir)/defs/i386
 	$(AM_V_GEN)m4 -D$* -DDISASSEMBLER $< > $@T
 	$(AM_V_at)mv -f $@T $@
@@ -86,6 +82,8 @@ i386_gendis_LDADD = $(libeu) -lm
 
 i386_parse.h: i386_parse.c ;
 
+bpf_disasm_CFLAGS = -Wno-format-nonliteral
+
 EXTRA_DIST = defs/i386
 
 CLEANFILES += $(foreach P,i386 x86_64,$P_defs $P.mnemonics)
-- 
2.22.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFC PATCH 2/2] Don't use dlopen() for libebl modules
  2019-07-03 20:04 [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules Omar Sandoval
  2019-07-03 20:04 ` [RFC PATCH 1/2] libcpu: merge libcpu_{i386,x86_64,bpf} into one library Omar Sandoval
@ 2019-07-03 20:04 ` Omar Sandoval
  2019-07-03 21:33 ` [RFC PATCH 0/2] elfutils: don't " Frank Ch. Eigler
  2019-07-08 20:33 ` Mark Wielaard
  3 siblings, 0 replies; 15+ messages in thread
From: Omar Sandoval @ 2019-07-03 20:04 UTC (permalink / raw)
  To: elfutils-devel

From: Omar Sandoval <osandov@fb.com>

Currently, architecture-specific code for libebl exists in separate
libebl_$ARCH.so libraries which libebl loads with dlopen() at runtime.
This makes it impossible to have standalone, statically-linked binaries
which use libdwfl if they depend on any architecture-specific
functionality. Additionally, when these libraries cannot be found, the
failure modes are non-obvious. So, let's get rid of libebl_$arch.so and
move it all into libebl.a, which simplifies things considerably.

Signed-off-by: Omar Sandoval <osandov@fb.com>
---
 ChangeLog                |   6 +
 Makefile.am              |   4 +-
 backends/ChangeLog       |   1 +
 backends/Makefile.am     |  93 ++------------
 configure.ac             |  12 +-
 libdw/ChangeLog          |   7 +
 libdw/Makefile.am        |  11 +-
 libebl/ChangeLog         |  11 ++
 libebl/Makefile.am       |   7 +-
 libebl/eblclosebackend.c |   4 -
 libebl/eblopenbackend.c  | 267 +++++++++++++++------------------------
 libebl/libeblP.h         |   3 -
 src/ChangeLog            |   7 +
 src/Makefile.am          |  18 +--
 tests/ChangeLog          |   5 +
 tests/Makefile.am        |  34 ++---
 tests/test-subr.sh       |   4 +-
 17 files changed, 195 insertions(+), 299 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5c45cccf..ff12ee27 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* configure.ac: Get rid of --enable-libebl-subdir.
+	* Makefile.am: Reorder backends and libcpu before libebl in SUBDIRS to
+	satisfy build dependencies.
+
 2019-02-14  Mark Wielaard  <mark@klomp.org>
 
 	* configure.ac: Set version to 0.176.
diff --git a/Makefile.am b/Makefile.am
index 2ff444e7..51f54552 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,8 +27,8 @@ AM_MAKEFLAGS = --no-print-directory
 pkginclude_HEADERS = version.h
 
 # Add doc back when we have some real content.
-SUBDIRS = config m4 lib libelf libebl libdwelf libdwfl libdw libcpu libasm \
-	  backends src po tests
+SUBDIRS = config m4 lib libelf libcpu backends libebl libdwelf libdwfl libdw \
+	  libasm src po tests
 
 EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING \
 	     COPYING COPYING-GPLV2 COPYING-LGPLV3
diff --git a/backends/ChangeLog b/backends/ChangeLog
index b40a4c8e..11f513c1 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,6 +1,7 @@
 2019-07-02  Omar Sandoval  <osandov@fb.com>
 
 	* Makefile.am: Use combined libcpu.a library.
+	Combine modules into libebl_backends.a.
 
 2019-04-14  Mark Wielaard  <mark@klomp.org>
 
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 0307da07..733c8623 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -28,95 +28,58 @@
 ## the GNU Lesser General Public License along with this program.  If
 ## not, see <http://www.gnu.org/licenses/>.
 include $(top_srcdir)/config/eu.am
+AM_CFLAGS += $(fpic_CFLAGS)
 AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
 	   -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
 
+noinst_LIBRARIES = libebl_backends.a
 
 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
 	  tilegx m68k bpf riscv
-libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a    \
-	     libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a    \
-	     libebl_aarch64_pic.a libebl_sparc_pic.a libebl_ppc_pic.a \
-	     libebl_ppc64_pic.a libebl_s390_pic.a libebl_tilegx_pic.a \
-	     libebl_m68k_pic.a libebl_bpf_pic.a libebl_riscv_pic.a
-noinst_LIBRARIES = $(libebl_pic)
-noinst_DATA = $(libebl_pic:_pic.a=.so)
-
-
-libcpu = ../libcpu/libcpu.a
-libelf = ../libelf/libelf.so
-libdw = ../libdw/libdw.so
-libeu = ../lib/libeu.a
 
 i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
 	    i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c \
 	    i386_initreg.c i386_unwind.c
-libebl_i386_pic_a_SOURCES = $(i386_SRCS)
-am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
 
 sh_SRCS = sh_init.c sh_symbol.c sh_corenote.c sh_regs.c sh_retval.c
-libebl_sh_pic_a_SOURCES = $(sh_SRCS)
-am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
 
 x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_cfi.c \
-	      x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c \
-	      x86_64_initreg.c x86_64_unwind.c x32_corenote.c
-libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
-am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
+	      x86_64_retval.c x86_64_regs.c x86_64_syscall.c x86_64_initreg.c \
+	      x86_64_unwind.c x32_corenote.c
+
 
 ia64_SRCS = ia64_init.c ia64_symbol.c ia64_regs.c ia64_retval.c
-libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
-am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
 
 alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
 	     alpha_corenote.c alpha_auxv.c
-libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
-am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
 
 arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \
 	   arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c arm_initreg.c
-libebl_arm_pic_a_SOURCES = $(arm_SRCS)
-am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
 
 aarch64_SRCS = aarch64_init.c aarch64_regs.c aarch64_symbol.c	\
 	       aarch64_corenote.c aarch64_retval.c aarch64_cfi.c \
 	       aarch64_initreg.c aarch64_unwind.c
-libebl_aarch64_pic_a_SOURCES = $(aarch64_SRCS)
-am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
 
 sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c sparc_retval.c \
 	     sparc_corenote.c sparc64_corenote.c sparc_auxv.c sparc_attrs.c \
              sparc_cfi.c sparc_initreg.c
-libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
-am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
 
 ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
 	   ppc_corenote.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
 	   ppc_cfi.c ppc_initreg.c
-libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
-am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
 
-ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
-	     ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
-	     ppc_cfi.c ppc_initreg.c ppc64_unwind.c ppc64_resolve_sym.c
-libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
-am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
+ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c ppc64_corenote.c \
+	     ppc64_unwind.c ppc64_resolve_sym.c
 
 s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
 	    s390_corenote.c s390x_corenote.c s390_cfi.c s390_initreg.c \
 	    s390_unwind.c
-libebl_s390_pic_a_SOURCES = $(s390_SRCS)
-am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
 
 tilegx_SRCS = tilegx_init.c tilegx_symbol.c tilegx_regs.c \
               tilegx_retval.c tilegx_corenote.c
-libebl_tilegx_pic_a_SOURCES = $(tilegx_SRCS)
-am_libebl_tilegx_pic_a_OBJECTS = $(tilegx_SRCS:.c=.os)
 
 m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
 	    m68k_retval.c m68k_corenote.c m68k_cfi.c m68k_initreg.c
-libebl_m68k_pic_a_SOURCES = $(m68k_SRCS)
-am_libebl_m68k_pic_a_OBJECTS = $(m68k_SRCS:.c=.os)
 
 # m68k prstatus core notes are described by a packed structure
 # which has not naturally aligned fields. Since we don't access
@@ -126,43 +89,15 @@ am_libebl_m68k_pic_a_OBJECTS = $(m68k_SRCS:.c=.os)
 m68k_corenote_no_Wpacked_not_aligned = yes
 
 bpf_SRCS = bpf_init.c bpf_regs.c bpf_symbol.c
-libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
-am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
 
 riscv_SRCS = riscv_init.c riscv_symbol.c riscv_cfi.c riscv_regs.c \
 	     riscv_initreg.c riscv_corenote.c riscv64_corenote.c riscv_retval.c
-libebl_riscv_pic_a_SOURCES = $(riscv_SRCS)
-am_libebl_riscv_pic_a_OBJECTS = $(riscv_SRCS:.c=.os)
-
-
-libebl_%.so libebl_%.map: libebl_%_pic.a $(libcpu) $(libelf) $(libdw) $(libeu)
-	@rm -f $(@:.so=.map)
-	$(AM_V_at)echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' \
-	  > $(@:.so=.map)
-	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $(@:.map=.so) \
-		-Wl,--whole-archive $< $(libcpu) -Wl,--no-whole-archive \
-		-Wl,--version-script,$(@:.so=.map),--no-undefined \
-		-Wl,--as-needed $(libelf) $(libdw) $(libeu)
-	@$(textrel_check)
-
-install: install-am install-ebl-modules
-install-ebl-modules:
-	$(mkinstalldirs) $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
-	for m in $(modules); do \
-	  $(INSTALL_PROGRAM) libebl_$${m}.so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
-	  ln -fs libebl_$${m}-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
-	done
-
-uninstall: uninstall-am
-	for m in $(modules); do \
-	  rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
-	  rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
-	done
-	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
 
-noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
-EXTRA_DIST = $(foreach m,$(modules),$($(m)_SRCS)) $(modules:=_reloc.def)
+libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
+			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
+			    $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \
+			    $(ppc64_SRCS) $(s390_SRCS) $(tilegx_SRCS) \
+			    $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS)
 
-CLEANFILES += $(foreach m,$(modules),\
-			libebl_$(m).map libebl_$(m).so \
-			$(am_libebl_$(m)_pic_a_OBJECTS))
+noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
+EXTRA_DIST = $(modules:=_reloc.def)
diff --git a/configure.ac b/configure.ac
index b4e012de..72d7f126 100644
--- a/configure.ac
+++ b/configure.ac
@@ -336,15 +336,6 @@ AS_HELP_STRING([--enable-tests-rpath],[build $ORIGIN-using rpath into tests]),
 	       [tests_use_rpath=$enableval], [tests_use_rpath=no])
 AM_CONDITIONAL(TESTS_RPATH, test "$tests_use_rpath" = yes)
 
-LIBEBL_SUBDIR="$PACKAGE"
-AC_ARG_ENABLE([libebl-subdir],
-AS_HELP_STRING([--enable-libebl-subdir=DIR],
-[install libebl_CPU modules in $(libdir)/DIR]), [dnl
-LIBEBL_SUBDIR="$enable_libebl_subdir"])
-AC_SUBST([LIBEBL_SUBDIR])
-AC_DEFINE_UNQUOTED(LIBEBL_SUBDIR, "$LIBEBL_SUBDIR")
-AH_TEMPLATE([LIBEBL_SUBDIR], [$libdir subdirectory containing libebl modules.])
-
 dnl zlib is mandatory.
 save_LIBS="$LIBS"
 LIBS=
@@ -585,7 +576,7 @@ esac
 eu_version=$(( (eu_version + 999) / 1000 ))
 
 dnl Unique ID for this build.
-MODVERSION="Build for ${LIBEBL_SUBDIR} ${eu_version} ${ac_cv_build}"
+MODVERSION="Build for ${eu_version} ${ac_cv_build}"
 AC_SUBST([MODVERSION])
 AC_DEFINE_UNQUOTED(MODVERSION, "$MODVERSION")
 AH_TEMPLATE([MODVERSION], [Identifier for modules in the build.])
@@ -650,7 +641,6 @@ AC_MSG_NOTICE([
     Program prefix ("eu-" recommended) : ${program_prefix}
     Source code location               : ${srcdir}
     Maintainer mode                    : ${enable_maintainer_mode}
-    libebl modules subdirectory        : ${LIBEBL_SUBDIR}
     build arch                         : ${ac_cv_build}
 
   RECOMMENDED FEATURES (should all be yes)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 4760f9de..ff0fda54 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,10 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am (libdw_so_LIBS): Move libebl.a to the beginning so that
+	libdw symbols are resolved.
+	(libdw_so_LDLIBS): Remove -ldl.
+	(libdw.so): Remove -rpath.
+
 2019-05-16  Mark Wielaard  <mark@klomp.org>
 
 	* dwarf.h: Add DW_AT_GNU_numerator, DW_AT_GNU_denominator and
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 7a3d5322..a2c82495 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -105,17 +105,14 @@ endif
 libdw_pic_a_SOURCES =
 am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
 
-libdw_so_LIBS = libdw_pic.a ../libdwelf/libdwelf_pic.a \
-	  ../libdwfl/libdwfl_pic.a ../libebl/libebl.a
+libdw_so_LIBS = ../libebl/libebl.a libdw_pic.a ../libdwelf/libdwelf_pic.a \
+		../libdwfl/libdwfl_pic.a
 libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so
-libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(zip_LIBS)
+libdw_so_LDLIBS = $(libdw_so_DEPS) -lz $(argp_LDADD) $(zip_LIBS)
 libdw_so_SOURCES =
 libdw.so$(EXEEXT): $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS)
-# The rpath is necessary for libebl because its $ORIGIN use will
-# not fly in a setuid executable that links in libdw.
 	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
-		-Wl,--soname,$@.$(VERSION) \
-		-Wl,--enable-new-dtags,-rpath,$(pkglibdir) \
+		-Wl,--soname,$@.$(VERSION),--enable-new-dtags \
 		-Wl,--version-script,$<,--no-undefined \
 		-Wl,--whole-archive $(libdw_so_LIBS) -Wl,--no-whole-archive \
 		$(libdw_so_LDLIBS)
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 8a7d177f..e7d2dfbe 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,14 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am (libebl_a_LIBADD): Add libcpu.a and libebl_backends.a
+	objects.
+	* libeblP.h (struct ebl): Remove dlhandle member.
+	* eblopenbackend.c (machines): Replace dsoname with init callback.
+	(try_dlopen): Remove.
+	(openbackend): Use machine callback instead of try_dlopen().
+	Don't assign result->dlhandle.
+	* eblclosebackend.c (ebl_closebackend): Remove dlclose() call.
+
 2019-05-30  Mark Wielaard  <mark@klomp.org>
 
 	* eblopenbackend.c (try_dlopen): New function extracted from
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 737de6b0..e1adee64 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -31,7 +31,6 @@ include $(top_srcdir)/config/eu.am
 AM_CFLAGS += $(fpic_CFLAGS)
 AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libdw -I$(srcdir)/../libasm
 VERSION = 1
-LIBEBL_SUBDIR = @LIBEBL_SUBDIR@
 
 lib_LIBRARIES = libebl.a
 
@@ -58,6 +57,12 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c \
 
 libebl_a_SOURCES = $(gen_SOURCES)
 
+libcpu_objects = $(shell $(AR) t ../libcpu/libcpu.a)
+libebl_a_LIBADD = $(addprefix ../libcpu/,$(libcpu_objects))
+
+backends_objects = $(shell $(AR) t ../backends/libebl_backends.a)
+libebl_a_LIBADD += $(addprefix ../backends/,$(backends_objects))
+
 noinst_HEADERS = libeblP.h ebl-hooks.h
 
 CLEANFILES += $(am_libebl_pic_a_OBJECTS)
diff --git a/libebl/eblclosebackend.c b/libebl/eblclosebackend.c
index 67fbdfe9..501e5c7b 100644
--- a/libebl/eblclosebackend.c
+++ b/libebl/eblclosebackend.c
@@ -44,10 +44,6 @@ ebl_closebackend (Ebl *ebl)
       /* Run the destructor.  */
       ebl->destr (ebl);
 
-      /* Close the dynamically loaded object.  */
-      if (ebl->dlhandle != NULL)
-	(void) dlclose (ebl->dlhandle);
-
       /* Free the resources.  */
       free (ebl);
     }
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 36a24921..67db1c4e 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -41,6 +41,21 @@
 #include <system.h>
 #include <libeblP.h>
 
+const char *i386_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *sh_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *x86_64_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *ia64_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *alpha_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *arm_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *aarch64_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *sparc_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *ppc_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *ppc64_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *s390_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *tilegx_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *m68k_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *bpf_init (Elf *, GElf_Half, Ebl *, size_t);
+const char *riscv_init (Elf *, GElf_Half, Ebl *, size_t);
 
 /* This table should contain the complete list of architectures as far
    as the ELF specification is concerned.  */
@@ -48,7 +63,7 @@
    arrays to avoid relocations.  */
 static const struct
 {
-  const char *dsoname;
+  ebl_bhinit_t init;
   const char *emulation;
   const char *prefix;
   int prefix_len;
@@ -57,84 +72,84 @@ static const struct
   int data;
 } machines[] =
 {
-  { "i386", "elf_i386", "i386", 4, EM_386, ELFCLASS32, ELFDATA2LSB },
-  { "ia64", "elf_ia64", "ia64", 4, EM_IA_64, ELFCLASS64, ELFDATA2LSB },
-  { "alpha", "elf_alpha", "alpha", 5, EM_ALPHA, ELFCLASS64, ELFDATA2LSB },
-  { "x86_64", "elf_x86_64", "x86_64", 6, EM_X86_64, ELFCLASS64, ELFDATA2LSB },
-  { "ppc", "elf_ppc", "ppc", 3, EM_PPC, ELFCLASS32, ELFDATA2MSB },
-  { "ppc64", "elf_ppc64", "ppc64", 5, EM_PPC64, ELFCLASS64, ELFDATA2MSB },
-  { "tilegx", "elf_tilegx", "tilegx", 6, EM_TILEGX, ELFCLASS64, ELFDATA2LSB },
+  { i386_init, "elf_i386", "i386", 4, EM_386, ELFCLASS32, ELFDATA2LSB },
+  { ia64_init, "elf_ia64", "ia64", 4, EM_IA_64, ELFCLASS64, ELFDATA2LSB },
+  { alpha_init, "elf_alpha", "alpha", 5, EM_ALPHA, ELFCLASS64, ELFDATA2LSB },
+  { x86_64_init, "elf_x86_64", "x86_64", 6, EM_X86_64, ELFCLASS64, ELFDATA2LSB },
+  { ppc_init, "elf_ppc", "ppc", 3, EM_PPC, ELFCLASS32, ELFDATA2MSB },
+  { ppc64_init, "elf_ppc64", "ppc64", 5, EM_PPC64, ELFCLASS64, ELFDATA2MSB },
+  { tilegx_init, "elf_tilegx", "tilegx", 6, EM_TILEGX, ELFCLASS64, ELFDATA2LSB },
   // XXX class and machine fields need to be filled in for all archs.
-  { "sh", "elf_sh", "sh", 2, EM_SH, 0, 0 },
-  { "arm", "ebl_arm", "arm", 3, EM_ARM, 0, 0 },
-  { "sparc", "elf_sparcv9", "sparc", 5, EM_SPARCV9, 0, 0 },
-  { "sparc", "elf_sparc", "sparc", 5, EM_SPARC, 0, 0 },
-  { "sparc", "elf_sparcv8plus", "sparc", 5, EM_SPARC32PLUS, 0, 0 },
-  { "s390", "ebl_s390", "s390", 4, EM_S390, 0, 0 },
-
-  { "m32", "elf_m32", "m32", 3, EM_M32, 0, 0 },
-  { "m68k", "elf_m68k", "m68k", 4, EM_68K, ELFCLASS32, ELFDATA2MSB },
-  { "m88k", "elf_m88k", "m88k", 4, EM_88K, 0, 0 },
-  { "i860", "elf_i860", "i860", 4, EM_860, 0, 0 },
-  { "s370", "ebl_s370", "s370", 4, EM_S370, 0, 0 },
-  { "parisc", "elf_parisc", "parisc", 6, EM_PARISC, 0, 0 },
-  { "vpp500", "elf_vpp500", "vpp500", 5, EM_VPP500, 0, 0 },
-  { "sparc", "elf_v8plus", "v8plus", 6, EM_SPARC32PLUS, 0, 0 },
-  { "i960", "elf_i960", "i960", 4, EM_960, 0, 0 },
-  { "v800", "ebl_v800", "v800", 4, EM_V800, 0, 0 },
-  { "fr20", "ebl_fr20", "fr20", 4, EM_FR20, 0, 0 },
-  { "rh32", "ebl_rh32", "rh32", 4, EM_RH32, 0, 0 },
-  { "rce", "ebl_rce", "rce", 3, EM_RCE, 0, 0 },
-  { "tricore", "elf_tricore", "tricore", 7, EM_TRICORE, 0, 0 },
-  { "arc", "elf_arc", "arc", 3, EM_ARC, 0, 0 },
-  { "h8", "elf_h8_300", "h8_300", 6, EM_H8_300, 0, 0 },
-  { "h8", "elf_h8_300h", "h8_300h", 6, EM_H8_300H, 0, 0 },
-  { "h8", "elf_h8s", "h8s", 6, EM_H8S, 0, 0 },
-  { "h8", "elf_h8_500", "h8_500", 6, EM_H8_500, 0, 0 },
-  { "coldfire", "elf_coldfire", "coldfire", 8, EM_COLDFIRE, 0, 0 },
-  { "m68k", "elf_68hc12", "68hc12", 6, EM_68HC12, 0, 0 },
-  { "mma", "elf_mma", "mma", 3, EM_MMA, 0, 0 },
-  { "pcp", "elf_pcp", "pcp", 3, EM_PCP, 0, 0 },
-  { "ncpu", "elf_ncpu", "ncpu", 4, EM_NCPU, 0, 0 },
-  { "ndr1", "elf_ndr1", "ndr1", 4, EM_NDR1, 0, 0 },
-  { "starcore", "elf_starcore", "starcore", 8, EM_STARCORE, 0, 0 },
-  { "me16", "elf_me16", "em16", 4, EM_ME16, 0, 0 },
-  { "st100", "elf_st100", "st100", 5, EM_ST100, 0, 0 },
-  { "tinyj", "elf_tinyj", "tinyj", 5, EM_TINYJ, 0, 0 },
-  { "pdsp", "elf_pdsp", "pdsp", 4, EM_PDSP, 0, 0 },
-  { "fx66", "elf_fx66", "fx66", 4, EM_FX66, 0, 0 },
-  { "st9plus", "elf_st9plus", "st9plus", 7, EM_ST9PLUS, 0, 0 },
-  { "st7", "elf_st7", "st7", 3, EM_ST7, 0, 0 },
-  { "m68k", "elf_68hc16", "68hc16", 6, EM_68HC16, 0, 0 },
-  { "m68k", "elf_68hc11", "68hc11", 6, EM_68HC11, 0, 0 },
-  { "m68k", "elf_68hc08", "68hc08", 6, EM_68HC08, 0, 0 },
-  { "m68k", "elf_68hc05", "68hc05", 6, EM_68HC05, 0, 0 },
-  { "svx", "elf_svx", "svx", 3, EM_SVX, 0, 0 },
-  { "st19", "elf_st19", "st19", 4, EM_ST19, 0, 0 },
-  { "vax", "elf_vax", "vax", 3, EM_VAX, 0, 0 },
-  { "cris", "elf_cris", "cris", 4, EM_CRIS, 0, 0 },
-  { "javelin", "elf_javelin", "javelin", 7, EM_JAVELIN, 0, 0 },
-  { "firepath", "elf_firepath", "firepath", 8, EM_FIREPATH, 0, 0 },
-  { "zsp", "elf_zsp", "zsp", 3, EM_ZSP, 0, 0 },
-  { "mmix", "elf_mmix", "mmix", 4, EM_MMIX, 0, 0 },
-  { "hunay", "elf_huany", "huany", 5, EM_HUANY, 0, 0 },
-  { "prism", "elf_prism", "prism", 5, EM_PRISM, 0, 0 },
-  { "avr", "elf_avr", "avr", 3, EM_AVR, 0, 0 },
-  { "fr30", "elf_fr30", "fr30", 4, EM_FR30, 0, 0 },
-  { "dv10", "elf_dv10", "dv10", 4, EM_D10V, 0, 0 },
-  { "dv30", "elf_dv30", "dv30", 4, EM_D30V, 0, 0 },
-  { "v850", "elf_v850", "v850", 4, EM_V850, 0, 0 },
-  { "m32r", "elf_m32r", "m32r", 4, EM_M32R, 0, 0 },
-  { "mn10300", "elf_mn10300", "mn10300", 7, EM_MN10300, 0, 0 },
-  { "mn10200", "elf_mn10200", "mn10200", 7, EM_MN10200, 0, 0 },
-  { "pj", "elf_pj", "pj", 2, EM_PJ, 0, 0 },
-  { "openrisc", "elf_openrisc", "openrisc", 8, EM_OPENRISC, 0, 0 },
-  { "arc", "elf_arc_a5", "arc_a5", 6, EM_ARC_A5, 0, 0 },
-  { "xtensa", "elf_xtensa", "xtensa", 6, EM_XTENSA, 0, 0 },
-  { "aarch64", "elf_aarch64", "aarch64", 7, EM_AARCH64, ELFCLASS64, 0 },
-  { "bpf", "elf_bpf", "bpf", 3, EM_BPF, 0, 0 },
-  { "riscv", "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS64, ELFDATA2LSB },
-  { "riscv", "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS32, ELFDATA2LSB },
+  { sh_init, "elf_sh", "sh", 2, EM_SH, 0, 0 },
+  { arm_init, "ebl_arm", "arm", 3, EM_ARM, 0, 0 },
+  { sparc_init, "elf_sparcv9", "sparc", 5, EM_SPARCV9, 0, 0 },
+  { sparc_init, "elf_sparc", "sparc", 5, EM_SPARC, 0, 0 },
+  { sparc_init, "elf_sparcv8plus", "sparc", 5, EM_SPARC32PLUS, 0, 0 },
+  { s390_init, "ebl_s390", "s390", 4, EM_S390, 0, 0 },
+
+  { NULL, "elf_m32", "m32", 3, EM_M32, 0, 0 },
+  { m68k_init, "elf_m68k", "m68k", 4, EM_68K, ELFCLASS32, ELFDATA2MSB },
+  { NULL, "elf_m88k", "m88k", 4, EM_88K, 0, 0 },
+  { NULL, "elf_i860", "i860", 4, EM_860, 0, 0 },
+  { NULL, "ebl_s370", "s370", 4, EM_S370, 0, 0 },
+  { NULL, "elf_parisc", "parisc", 6, EM_PARISC, 0, 0 },
+  { NULL, "elf_vpp500", "vpp500", 5, EM_VPP500, 0, 0 },
+  { sparc_init, "elf_v8plus", "v8plus", 6, EM_SPARC32PLUS, 0, 0 },
+  { NULL, "elf_i960", "i960", 4, EM_960, 0, 0 },
+  { NULL, "ebl_v800", "v800", 4, EM_V800, 0, 0 },
+  { NULL, "ebl_fr20", "fr20", 4, EM_FR20, 0, 0 },
+  { NULL, "ebl_rh32", "rh32", 4, EM_RH32, 0, 0 },
+  { NULL, "ebl_rce", "rce", 3, EM_RCE, 0, 0 },
+  { NULL, "elf_tricore", "tricore", 7, EM_TRICORE, 0, 0 },
+  { NULL, "elf_arc", "arc", 3, EM_ARC, 0, 0 },
+  { NULL, "elf_h8_300", "h8_300", 6, EM_H8_300, 0, 0 },
+  { NULL, "elf_h8_300h", "h8_300h", 6, EM_H8_300H, 0, 0 },
+  { NULL, "elf_h8s", "h8s", 6, EM_H8S, 0, 0 },
+  { NULL, "elf_h8_500", "h8_500", 6, EM_H8_500, 0, 0 },
+  { NULL, "elf_coldfire", "coldfire", 8, EM_COLDFIRE, 0, 0 },
+  { m68k_init, "elf_68hc12", "68hc12", 6, EM_68HC12, 0, 0 },
+  { NULL, "elf_mma", "mma", 3, EM_MMA, 0, 0 },
+  { NULL, "elf_pcp", "pcp", 3, EM_PCP, 0, 0 },
+  { NULL, "elf_ncpu", "ncpu", 4, EM_NCPU, 0, 0 },
+  { NULL, "elf_ndr1", "ndr1", 4, EM_NDR1, 0, 0 },
+  { NULL, "elf_starcore", "starcore", 8, EM_STARCORE, 0, 0 },
+  { NULL, "elf_me16", "em16", 4, EM_ME16, 0, 0 },
+  { NULL, "elf_st100", "st100", 5, EM_ST100, 0, 0 },
+  { NULL, "elf_tinyj", "tinyj", 5, EM_TINYJ, 0, 0 },
+  { NULL, "elf_pdsp", "pdsp", 4, EM_PDSP, 0, 0 },
+  { NULL, "elf_fx66", "fx66", 4, EM_FX66, 0, 0 },
+  { NULL, "elf_st9plus", "st9plus", 7, EM_ST9PLUS, 0, 0 },
+  { NULL, "elf_st7", "st7", 3, EM_ST7, 0, 0 },
+  { m68k_init, "elf_68hc16", "68hc16", 6, EM_68HC16, 0, 0 },
+  { m68k_init, "elf_68hc11", "68hc11", 6, EM_68HC11, 0, 0 },
+  { m68k_init, "elf_68hc08", "68hc08", 6, EM_68HC08, 0, 0 },
+  { m68k_init, "elf_68hc05", "68hc05", 6, EM_68HC05, 0, 0 },
+  { NULL, "elf_svx", "svx", 3, EM_SVX, 0, 0 },
+  { NULL, "elf_st19", "st19", 4, EM_ST19, 0, 0 },
+  { NULL, "elf_vax", "vax", 3, EM_VAX, 0, 0 },
+  { NULL, "elf_cris", "cris", 4, EM_CRIS, 0, 0 },
+  { NULL, "elf_javelin", "javelin", 7, EM_JAVELIN, 0, 0 },
+  { NULL, "elf_firepath", "firepath", 8, EM_FIREPATH, 0, 0 },
+  { NULL, "elf_zsp", "zsp", 3, EM_ZSP, 0, 0 },
+  { NULL, "elf_mmix", "mmix", 4, EM_MMIX, 0, 0 },
+  { NULL, "elf_huany", "huany", 5, EM_HUANY, 0, 0 },
+  { NULL, "elf_prism", "prism", 5, EM_PRISM, 0, 0 },
+  { NULL, "elf_avr", "avr", 3, EM_AVR, 0, 0 },
+  { NULL, "elf_fr30", "fr30", 4, EM_FR30, 0, 0 },
+  { NULL, "elf_dv10", "dv10", 4, EM_D10V, 0, 0 },
+  { NULL, "elf_dv30", "dv30", 4, EM_D30V, 0, 0 },
+  { NULL, "elf_v850", "v850", 4, EM_V850, 0, 0 },
+  { NULL, "elf_m32r", "m32r", 4, EM_M32R, 0, 0 },
+  { NULL, "elf_mn10300", "mn10300", 7, EM_MN10300, 0, 0 },
+  { NULL, "elf_mn10200", "mn10200", 7, EM_MN10200, 0, 0 },
+  { NULL, "elf_pj", "pj", 2, EM_PJ, 0, 0 },
+  { NULL, "elf_openrisc", "openrisc", 8, EM_OPENRISC, 0, 0 },
+  { NULL, "elf_arc_a5", "arc_a5", 6, EM_ARC_A5, 0, 0 },
+  { NULL, "elf_xtensa", "xtensa", 6, EM_XTENSA, 0, 0 },
+  { aarch64_init, "elf_aarch64", "aarch64", 7, EM_AARCH64, ELFCLASS64, 0 },
+  { bpf_init, "elf_bpf", "bpf", 3, EM_BPF, 0, 0 },
+  { riscv_init, "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS64, ELFDATA2LSB },
+  { riscv_init, "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS32, ELFDATA2LSB },
 };
 #define nmachines (sizeof (machines) / sizeof (machines[0]))
 
@@ -251,51 +266,6 @@ fill_defaults (Ebl *result)
   result->sysvhash_entrysize = sizeof (Elf32_Word);
 }
 
-static Ebl *
-try_dlopen (const char *dsoname, Elf *elf, GElf_Half machine, size_t cnt,
-	    Ebl *result)
-{
-  void *h = dlopen (dsoname, RTLD_LAZY);
-
-  if (h != NULL)
-    {
-      /* We managed to load the object.  Now see whether the
-	 initialization function likes our file.  */
-      static const char version[] = MODVERSION;
-      const char *modversion;
-      ebl_bhinit_t initp;
-
-      // We use a static number to help the compiler see we don't
-      // overflow the stack with an arbitrary number.
-      assert (machines[cnt].prefix_len <= MAX_PREFIX_LEN);
-      char symname[MAX_PREFIX_LEN + sizeof "_init"];
-
-      strcpy (mempcpy (symname, machines[cnt].prefix,
-		       machines[cnt].prefix_len), "_init");
-
-      initp = (ebl_bhinit_t) dlsym (h, symname);
-      if (initp != NULL
-	  && (modversion = initp (elf, machine, result, sizeof (Ebl)))
-	  && strcmp (version, modversion) == 0)
-	{
-	  /* We found a module to handle our file.  */
-	  result->dlhandle = h;
-	  result->elf = elf;
-
-	  /* A few entries are mandatory.  */
-	  assert (result->name != NULL);
-	  assert (result->destr != NULL);
-
-	  return result;
-	}
-
-      /* Not the module we need.  */
-      (void) dlclose (h);
-    }
-
-  return NULL;
-}
-
 /* Find an appropriate backend for the file associated with ELF.  */
 static Ebl *
 openbackend (Elf *elf, const char *emulation, GElf_Half machine)
@@ -357,46 +327,18 @@ openbackend (Elf *elf, const char *emulation, GElf_Half machine)
 	    result->data = elf->state.elf32.ehdr->e_ident[EI_DATA];
 	  }
 
-#ifndef LIBEBL_SUBDIR
-# define LIBEBL_SUBDIR PACKAGE
-#endif
-
-/* This works if libebl has been staticly linked into a binary.
-   It might also work for shared libraries when installed in
-   ${prefix}/lib/ or ${prefix}/lib64/, but not for multiarch
-   library installs like ${prefix}/lib/i386-linux-gnu/  */
-#define BINORIGINDIR "$ORIGIN/../$LIB/" LIBEBL_SUBDIR "/"
-
-/* This works if libebl has been linked into a shared library,
-   just look in the subdir.  */
-#define LIBORIGINDIR "$ORIGIN/" LIBEBL_SUBDIR "/"
-
-	/* Give it a try.  At least the machine type matches.  First
-           try to load the module from the (bin) origin path.  */
-	char dsoname[100];
-	strcpy (stpcpy (stpcpy (dsoname, BINORIGINDIR "libebl_"),
-			machines[cnt].dsoname),
-		".so");
-	if (try_dlopen (dsoname, elf, machine, cnt, result) != NULL)
-	  return result;
-
-	/* Retry with the (lib) origin path.  */
-	strcpy (stpcpy (stpcpy (dsoname, LIBORIGINDIR "libebl_"),
-			machines[cnt].dsoname),
-		".so");
-	if (try_dlopen (dsoname, elf, machine, cnt, result) != NULL)
-	  return result;
-
-	/* Try without an explicit path (LD_LIBRARY_PATH or RPATH).  */
-	strcpy (stpcpy (stpcpy (dsoname, "libebl_"),
-			machines[cnt].dsoname),
-		".so");
-	if (try_dlopen (dsoname, elf, machine, cnt, result) != NULL)
-	  return result;
-
-	/* We cannot find a DSO but the emulation/machine ID matches.
+        if (machines[cnt].init &&
+            machines[cnt].init (elf, machine, result, sizeof(Ebl)))
+          {
+            result->elf = elf;
+            /* A few entries are mandatory.  */
+            assert (result->name != NULL);
+            assert (result->destr != NULL);
+            return result;
+          }
+
+	/* We don't have a backend but the emulation/machine ID matches.
 	   Return that information.  */
-	result->dlhandle = NULL;
 	result->elf = elf;
 	result->name = machines[cnt].prefix;
 	fill_defaults (result);
@@ -405,7 +347,6 @@ openbackend (Elf *elf, const char *emulation, GElf_Half machine)
       }
 
   /* Nothing matched.  We use only the default callbacks.   */
-  result->dlhandle = NULL;
   result->elf = elf;
   result->emulation = "<unknown>";
   result->name = "<unknown>";
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index 5b339b31..f1037300 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -80,9 +80,6 @@ struct ebl
      ebl_resolve_sym_value if available for this arch.  */
   GElf_Addr fd_addr;
   Elf_Data *fd_data;
-
-  /* Internal data.  */
-  void *dlhandle;
 };
 
 
diff --git a/src/ChangeLog b/src/ChangeLog
index c78e6fa1..461dc974 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Remove -ldl.
+	(elflint_LDADD): Add $(libdw).
+	(elfcmp_LDADD): Add $(libdw).
+	(objdump_LDADD): Add $(libdw).
+
 2019-06-25  Mark Wielaard  <mark@klomp.org>
 
 	* stack.c (parse_opt): Fix dwfl_core_file_attach error message.
diff --git a/src/Makefile.am b/src/Makefile.am
index 2b1c0dcb..c6e8a385 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,7 +40,7 @@ CLEANFILES += make-debug-archive
 
 if BUILD_STATIC
 libasm = ../libasm/libasm.a
-libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl
+libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl)
 libelf = ../libelf/libelf.a -lz
 else
 libasm = ../libasm/libasm.so
@@ -67,21 +67,21 @@ ranlib_no_Wstack_usage = yes
 ar_no_Wstack_usage = yes
 unstrip_no_Wstack_usage = yes
 
-readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
-nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl \
+readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD)
+nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) \
 	   $(demanglelib)
 size_LDADD = $(libelf) $(libeu) $(argp_LDADD)
-strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) -ldl
-elflint_LDADD  = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
+strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+elflint_LDADD  = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
 findtextrel_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD)
 addr2line_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) $(demanglelib)
-elfcmp_LDADD = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
-objdump_LDADD  = $(libasm) $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
+elfcmp_LDADD = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
+objdump_LDADD  = $(libasm) $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
 ranlib_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD)
 strings_LDADD = $(libelf) $(libeu) $(argp_LDADD)
 ar_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD)
-unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) -ldl
-stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) -ldl $(demanglelib)
+unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) $(demanglelib)
 elfcompress_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
 
 installcheck-binPROGRAMS: $(bin_PROGRAMS)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 400588f4..c69ddaf8 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,8 @@
+2019-07-02  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Remove -ldl.
+	* tests-subr.sh (self_test_files): Remove libebl_{i386,x86_64}.so.
+
 2019-07-01  Mark Wielaard  <mark@klomp.org>
 
 	* run-large-elf-file.sh: Add 2GB to mem_needed when running under
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3d95cf68..847dbdeb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -480,7 +480,7 @@ libasm = -lasm
 libebl = -lebl
 else !STANDALONE
 if BUILD_STATIC
-libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl
+libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl)
 libelf = ../libelf/libelf.a -lz
 libasm = ../libasm/libasm.a
 else
@@ -525,27 +525,27 @@ funcretval_LDADD = $(libdw) $(argp_LDADD)
 allregs_LDADD = $(libdw) $(argp_LDADD)
 find_prologues_LDADD = $(libdw) $(argp_LDADD)
 #show_ciefde_LDADD = ../libdwarf/libdwarf.so $(libelf)
-asm_tst1_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst2_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst3_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst4_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst5_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst6_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst7_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst8_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-asm_tst9_LDADD = $(libasm) $(libebl) $(libelf) $(libdw) -ldl
-dwflmodtest_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD) -ldl
+asm_tst1_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst2_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst3_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst4_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst5_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst6_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst7_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst8_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst9_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+dwflmodtest_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD)
 rdwrmmap_LDADD = $(libelf)
-dwfl_bug_addr_overflow_LDADD = $(libdw) $(libebl) $(libelf) -ldl
+dwfl_bug_addr_overflow_LDADD = $(libdw) $(libebl) $(libelf)
 arls_LDADD = $(libelf)
-dwfl_bug_fd_leak_LDADD = $(libdw) $(libebl) $(libelf) -ldl
-dwfl_bug_report_LDADD = $(libdw) $(libebl) $(libelf) -ldl
-dwfl_bug_getmodules_LDADD = $(libdw) $(libebl) $(libelf) -ldl
-dwfl_addr_sect_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD) -ldl
+dwfl_bug_fd_leak_LDADD = $(libdw) $(libebl) $(libelf)
+dwfl_bug_report_LDADD = $(libdw) $(libebl) $(libelf)
+dwfl_bug_getmodules_LDADD = $(libdw) $(libebl) $(libelf)
+dwfl_addr_sect_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD)
 dwarf_getmacros_LDADD = $(libdw)
 dwarf_ranges_LDADD = $(libdw)
 dwarf_getstring_LDADD = $(libdw)
-addrcfi_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD) -ldl
+addrcfi_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD)
 dwarfcfi_LDADD = $(libdw) $(libelf)
 test_flag_nobits_LDADD = $(libelf)
 rerequest_tag_LDADD = $(libdw)
diff --git a/tests/test-subr.sh b/tests/test-subr.sh
index 09f428d1..e23a0176 100644
--- a/tests/test-subr.sh
+++ b/tests/test-subr.sh
@@ -121,9 +121,7 @@ ${abs_top_builddir}/src/objdump \
 ${abs_top_builddir}/src/readelf`
 
 self_test_files_lib=`echo ${abs_top_builddir}/libelf/libelf.so \
-${abs_top_builddir}/libdw/libdw.so \
-${abs_top_builddir}/backends/libebl_i386.so \
-${abs_top_builddir}/backends/libebl_x86_64.so`
+${abs_top_builddir}/libdw/libdw.so`
 
 self_test_files_obj=`echo ${abs_top_builddir}/src/size.o \
 ${abs_top_builddir}/src/strip.o`
-- 
2.22.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
@ 2019-07-03 20:04 Omar Sandoval
  2019-07-03 20:04 ` [RFC PATCH 1/2] libcpu: merge libcpu_{i386,x86_64,bpf} into one library Omar Sandoval
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Omar Sandoval @ 2019-07-03 20:04 UTC (permalink / raw)
  To: elfutils-devel

From: Omar Sandoval <osandov@fb.com>

Hi,

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, 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.

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.

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

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

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).

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?

Thanks!

1: https://sourceware.org/ml/elfutils-devel/2018-q2/msg00171.html

Omar Sandoval (2):
  libcpu: merge libcpu_{i386,x86_64,bpf} into one library
  Don't use dlopen() for libebl modules

 ChangeLog                |   6 +
 Makefile.am              |   4 +-
 backends/ChangeLog       |   5 +
 backends/Makefile.am     |  99 ++-------------
 configure.ac             |  12 +-
 libcpu/ChangeLog         |   4 +
 libcpu/Makefile.am       |  12 +-
 libdw/ChangeLog          |   7 +
 libdw/Makefile.am        |  11 +-
 libebl/ChangeLog         |  11 ++
 libebl/Makefile.am       |   7 +-
 libebl/eblclosebackend.c |   4 -
 libebl/eblopenbackend.c  | 267 +++++++++++++++------------------------
 libebl/libeblP.h         |   3 -
 src/ChangeLog            |   7 +
 src/Makefile.am          |  18 +--
 tests/ChangeLog          |   5 +
 tests/Makefile.am        |  34 ++---
 tests/test-subr.sh       |   4 +-
 19 files changed, 208 insertions(+), 312 deletions(-)

-- 
2.22.0

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 20:04 [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules Omar Sandoval
  2019-07-03 20:04 ` [RFC PATCH 1/2] libcpu: merge libcpu_{i386,x86_64,bpf} into one library Omar Sandoval
  2019-07-03 20:04 ` [RFC PATCH 2/2] Don't use dlopen() for libebl modules Omar Sandoval
@ 2019-07-03 21:33 ` Frank Ch. Eigler
  2019-07-03 21:37   ` Omar Sandoval
  2019-07-08 20:33 ` Mark Wielaard
  3 siblings, 1 reply; 15+ messages in thread
From: Frank Ch. Eigler @ 2019-07-03 21:33 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: elfutils-devel

Hi -

> [...]
> 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
> 56K     ./src/objdump
> 
> Static backends (after this series):
> 44K     ./libasm/libasm.so
> 668K    ./libdw/libdw.so
> 120K    ./libelf/libelf.so
> 348K    ./src/objdump

Assuming a dynamically linked objdump would be the same size as
before, and that the libebl-* contents would only bloat libdw.so,
and only by 300K, IMHO we should just go for it.


- FChE

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 21:33 ` [RFC PATCH 0/2] elfutils: don't " Frank Ch. Eigler
@ 2019-07-03 21:37   ` Omar Sandoval
  2019-07-03 21:40     ` Frank Ch. Eigler
  0 siblings, 1 reply; 15+ messages in thread
From: Omar Sandoval @ 2019-07-03 21:37 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: elfutils-devel

On Wed, Jul 03, 2019 at 05:33:42PM -0400, Frank Ch. Eigler wrote:
> Hi -
> 
> > [...]
> > 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
> > 56K     ./src/objdump
> > 
> > Static backends (after this series):
> > 44K     ./libasm/libasm.so
> > 668K    ./libdw/libdw.so
> > 120K    ./libelf/libelf.so
> > 348K    ./src/objdump
> 
> Assuming a dynamically linked objdump would be the same size as
> before, and that the libebl-* contents would only bloat libdw.so,
> and only by 300K, IMHO we should just go for it.

This is actually with dynamically linked binaries -- the size increase
is because we link libebl.a directly into all of the binaries in
addition to libdw.so:

objdump_LDADD  = $(libasm) $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 21:37   ` Omar Sandoval
@ 2019-07-03 21:40     ` Frank Ch. Eigler
  2019-07-03 21:46       ` Omar Sandoval
  0 siblings, 1 reply; 15+ messages in thread
From: Frank Ch. Eigler @ 2019-07-03 21:40 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: elfutils-devel

Hi - 

> This is actually with dynamically linked binaries -- the size increase
> is because we link libebl.a directly into all of the binaries in
> addition to libdw.so:
> 
> objdump_LDADD  = $(libasm) $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD

Is there some reason to keep doing that?

- FChE

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 21:40     ` Frank Ch. Eigler
@ 2019-07-03 21:46       ` Omar Sandoval
  2019-07-04  0:56         ` Frank Ch. Eigler
  0 siblings, 1 reply; 15+ messages in thread
From: Omar Sandoval @ 2019-07-03 21:46 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: elfutils-devel

On Wed, Jul 03, 2019 at 05:39:53PM -0400, Frank Ch. Eigler wrote:
> Hi - 
> 
> > This is actually with dynamically linked binaries -- the size increase
> > is because we link libebl.a directly into all of the binaries in
> > addition to libdw.so:
> > 
> > objdump_LDADD  = $(libasm) $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD
> 
> Is there some reason to keep doing that?
> 
> - FChE

Yes:

$ make -C src
make: Entering directory '/home/osandov/dev/elfutils/src'
  CCLD     objdump
/bin/ld: objdump.o: in function `show_relocs_x':
/home/osandov/dev/elfutils/src/objdump.c:352: undefined reference to `ebl_reloc_type_name'
/bin/ld: objdump.o: in function `handle_elf':
/home/osandov/dev/elfutils/src/objdump.c:755: undefined reference to `ebl_openbackend'
/bin/ld: /home/osandov/dev/elfutils/src/objdump.c:757: undefined reference to `ebl_backend_name'
/bin/ld: /home/osandov/dev/elfutils/src/objdump.c:788: undefined reference to `ebl_closebackend'
collect2: error: ld returned 1 exit status
make: *** [Makefile:624: objdump] Error 1
make: Leaving directory '/home/osandov/dev/elfutils/src'

Some of the binaries use libebl, and although libebl is linked into libdw.so,
the libebl symbols are not exported by libdw. So, libebl is linked in
statically for the binaries.

This is why I suggested exporting those symbols from libdw.so. (I also
considered adding a libebl.so, but that would have a circular dependency with
libdw.so, so they might as well be combined).

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 21:46       ` Omar Sandoval
@ 2019-07-04  0:56         ` Frank Ch. Eigler
  2019-07-08 20:49           ` Mark Wielaard
  0 siblings, 1 reply; 15+ messages in thread
From: Frank Ch. Eigler @ 2019-07-04  0:56 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: elfutils-devel

Hi -

> Some of the binaries use libebl, and although libebl is linked into libdw.so,
> the libebl symbols are not exported by libdw. So, libebl is linked in
> statically for the binaries.
> 
> This is why I suggested exporting those symbols from libdw.so. (I also
> considered adding a libebl.so, but that would have a circular dependency with
> libdw.so, so they might as well be combined).

Ah, thanks for the (re-)explanation.  IMHO, if the API is useful
enough to be used by mainline elfutils binaries, it is useful enough
to be used by others.  So a +1 from me for solib-exporting them.

- FChE

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-03 20:04 [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules Omar Sandoval
                   ` (2 preceding siblings ...)
  2019-07-03 21:33 ` [RFC PATCH 0/2] elfutils: don't " Frank Ch. Eigler
@ 2019-07-08 20:33 ` Mark Wielaard
  3 siblings, 0 replies; 15+ messages in thread
From: Mark Wielaard @ 2019-07-08 20:33 UTC (permalink / raw)
  To: Omar Sandoval, elfutils-devel

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-04  0:56         ` Frank Ch. Eigler
@ 2019-07-08 20:49           ` Mark Wielaard
  2019-07-08 21:02             ` Omar Sandoval
  0 siblings, 1 reply; 15+ messages in thread
From: Mark Wielaard @ 2019-07-08 20:49 UTC (permalink / raw)
  To: Frank Ch. Eigler, Omar Sandoval; +Cc: elfutils-devel

On Wed, 2019-07-03 at 20:56 -0400, Frank Ch. Eigler wrote:
> > Some of the binaries use libebl, and although libebl is linked into libdw.so,
> > the libebl symbols are not exported by libdw. So, libebl is linked in
> > statically for the binaries.
> > 
> > This is why I suggested exporting those symbols from libdw.so. (I also
> > considered adding a libebl.so, but that would have a circular dependency with
> > libdw.so, so they might as well be combined).
> 
> Ah, thanks for the (re-)explanation.  IMHO, if the API is useful
> enough to be used by mainline elfutils binaries, it is useful enough
> to be used by others.  So a +1 from me for solib-exporting them.

The API is kind of useful enough to be used by the elfutils binaries
directly (or they would use it). But that doesn't make them good,
supportable API that we should expose through libdw.so. That would mean
we promise they are fixed and supported essentially forever. It means,
they are quick hacks that might work for now for internal use only.

It might still be a good idea to expose/move some into libdw.so. But we
should carefully review them one by one. This was done for example for
the ELF/DWARF string table functions (Dwelf_Strtab and Dwelf_Strent).
Or see my recent patch that replaces ebl->name with with a new libdw.so
function dwelf_elf_e_machine_string (which works for any ELF e_machine
value, not just for those which have a backend implementation):
https://sourceware.org/ml/elfutils-devel/2019-q2/msg00130.html

Cheers,

Mark

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-08 20:49           ` Mark Wielaard
@ 2019-07-08 21:02             ` Omar Sandoval
  2019-07-09  6:39               ` Florian Weimer
  2019-07-09 19:14               ` Mark Wielaard
  0 siblings, 2 replies; 15+ messages in thread
From: Omar Sandoval @ 2019-07-08 21:02 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: Frank Ch. Eigler, elfutils-devel

On Mon, Jul 08, 2019 at 10:48:52PM +0200, Mark Wielaard wrote:
> On Wed, 2019-07-03 at 20:56 -0400, Frank Ch. Eigler wrote:
> > > Some of the binaries use libebl, and although libebl is linked into libdw.so,
> > > the libebl symbols are not exported by libdw. So, libebl is linked in
> > > statically for the binaries.
> > > 
> > > This is why I suggested exporting those symbols from libdw.so. (I also
> > > considered adding a libebl.so, but that would have a circular dependency with
> > > libdw.so, so they might as well be combined).
> > 
> > Ah, thanks for the (re-)explanation.  IMHO, if the API is useful
> > enough to be used by mainline elfutils binaries, it is useful enough
> > to be used by others.  So a +1 from me for solib-exporting them.

Hi, Mark,

> The API is kind of useful enough to be used by the elfutils binaries
> directly (or they would use it). But that doesn't make them good,
> supportable API that we should expose through libdw.so. That would mean
> we promise they are fixed and supported essentially forever. It means,
> they are quick hacks that might work for now for internal use only.

This makes sense. One thing I noted in the patch to export the libebl
symbols [1] is that exporting them wouldn't necessarily mean supporting
them as an official API. However, I can see why you'd be concerned with
developers using them anyways.

My patch submission last Friday [2] still works without the patch to
export the libebl symbols, the only drawback being the size increase, of
course.

> It might still be a good idea to expose/move some into libdw.so. But we
> should carefully review them one by one. This was done for example for
> the ELF/DWARF string table functions (Dwelf_Strtab and Dwelf_Strent).
> Or see my recent patch that replaces ebl->name with with a new libdw.so
> function dwelf_elf_e_machine_string (which works for any ELF e_machine
> value, not just for those which have a backend implementation):
> https://sourceware.org/ml/elfutils-devel/2019-q2/msg00130.html

I imagine that little by little, most of the libebl functionality could
be converted in this way, and that's how we could chip away at the size
increase of the elfutils binaries.

Do you have any objections to patches 1-4 of my submission [2]?

Thanks for the timely response!

1: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00022.html
2: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00020.html

> Cheers,
> 
> Mark

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-08 21:02             ` Omar Sandoval
@ 2019-07-09  6:39               ` Florian Weimer
  2019-07-09 19:14               ` Mark Wielaard
  1 sibling, 0 replies; 15+ messages in thread
From: Florian Weimer @ 2019-07-09  6:39 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: Mark Wielaard, Frank Ch. Eigler, elfutils-devel

* Omar Sandoval:

> This makes sense. One thing I noted in the patch to export the libebl
> symbols [1] is that exporting them wouldn't necessarily mean supporting
> them as an official API. However, I can see why you'd be concerned with
> developers using them anyways.

You could ship a link-only libc as the .so which does not include those
symbols.  Anyone who uses the standard development setup would not be
able to link against them as a result.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-08 21:02             ` Omar Sandoval
  2019-07-09  6:39               ` Florian Weimer
@ 2019-07-09 19:14               ` Mark Wielaard
  2019-07-09 19:25                 ` Omar Sandoval
  1 sibling, 1 reply; 15+ messages in thread
From: Mark Wielaard @ 2019-07-09 19:14 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: Frank Ch. Eigler, elfutils-devel

Hi Omar,

On Mon, 2019-07-08 at 14:02 -0700, Omar Sandoval wrote:
> I imagine that little by little, most of the libebl functionality could
> be converted in this way, and that's how we could chip away at the size
> increase of the elfutils binaries.
> 
> Do you have any objections to patches 1-4 of my submission [2]?
> 
> Thanks for the timely response!
> 
> 1: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00022.html
> 2: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00020.html

I am still pondering this a little. But I do think (patches 1-4) is the
(first) step forward. But I think I would like to do a 0.177 release
with the last 4 months of fixes first. We normally do a release every
3-4 months, so it is about time, and it means your feature wouldn't
have to wait that long. Although it would be a couple of months before
it sees a release. But I think it would be good to have some time to
make sure the idea works out in practice.

So I would propose a release end of this week/start of next week. But
without the libebl build rewrite.

For the release there are then still 3 things pending:

- The eu-elfclassify tool
  https://sourceware.org/ml/elfutils-devel/2019-q2/msg00018.html
  I had hoped on some feedback from the rpm hackers, since they are
  one if the intended users. And there are some (small) missing
  features and tests. Lets see where we are end if the week to see
  whether we can include that, or also postpone it to the next release.
- The C-SKY backend:
  https://sourceware.org/ml/elfutils-devel/2019-q2/msg00007.html
  This is really just blocked on me not making enough time for a
  final review. It looks good, but I am confused about one aspect
  of the DWARF register numbering issue.
- The dwelf_elf_e_machine_string patch:
  https://sourceware.org/ml/elfutils-devel/2019-q2/msg00130.html
  I didn't see any objections, so I think this is good to go.

Then after the release, somewhere next week, we'll apply your patches
first and can then deal with any fallout and followups. I am thinking
of moving some of the functionality into libdw proper (as cleaned up,
exported api) to reduce the size increase a little. And add a mechanism
for only building some of the backends (or maybe just drop some old
ones that nobody uses anyway).

Cheers,

Mark

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-09 19:14               ` Mark Wielaard
@ 2019-07-09 19:25                 ` Omar Sandoval
  2019-08-26 13:57                   ` Mark Wielaard
  0 siblings, 1 reply; 15+ messages in thread
From: Omar Sandoval @ 2019-07-09 19:25 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: Frank Ch. Eigler, elfutils-devel

On Tue, Jul 09, 2019 at 09:14:03PM +0200, Mark Wielaard wrote:
> Hi Omar,
> 
> On Mon, 2019-07-08 at 14:02 -0700, Omar Sandoval wrote:
> > I imagine that little by little, most of the libebl functionality could
> > be converted in this way, and that's how we could chip away at the size
> > increase of the elfutils binaries.
> > 
> > Do you have any objections to patches 1-4 of my submission [2]?
> > 
> > Thanks for the timely response!
> > 
> > 1: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00022.html
> > 2: https://sourceware.org/ml/elfutils-devel/2019-q3/msg00020.html
> 
> I am still pondering this a little. But I do think (patches 1-4) is the
> (first) step forward. But I think I would like to do a 0.177 release
> with the last 4 months of fixes first. We normally do a release every
> 3-4 months, so it is about time, and it means your feature wouldn't
> have to wait that long. Although it would be a couple of months before
> it sees a release. But I think it would be good to have some time to
> make sure the idea works out in practice.
> 
> So I would propose a release end of this week/start of next week. But
> without the libebl build rewrite.
> 
> For the release there are then still 3 things pending:
> 
> - The eu-elfclassify tool
>   https://sourceware.org/ml/elfutils-devel/2019-q2/msg00018.html
>   I had hoped on some feedback from the rpm hackers, since they are
>   one if the intended users. And there are some (small) missing
>   features and tests. Lets see where we are end if the week to see
>   whether we can include that, or also postpone it to the next release.
> - The C-SKY backend:
>   https://sourceware.org/ml/elfutils-devel/2019-q2/msg00007.html
>   This is really just blocked on me not making enough time for a
>   final review. It looks good, but I am confused about one aspect
>   of the DWARF register numbering issue.
> - The dwelf_elf_e_machine_string patch:
>   https://sourceware.org/ml/elfutils-devel/2019-q2/msg00130.html
>   I didn't see any objections, so I think this is good to go.
> 
> Then after the release, somewhere next week, we'll apply your patches
> first and can then deal with any fallout and followups. I am thinking
> of moving some of the functionality into libdw proper (as cleaned up,
> exported api) to reduce the size increase a little. And add a mechanism
> for only building some of the backends (or maybe just drop some old
> ones that nobody uses anyway).

This works for me, thanks! I'll keep an eye out for any followups, and
I'm happy to help clean things up on the ebl side.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules
  2019-07-09 19:25                 ` Omar Sandoval
@ 2019-08-26 13:57                   ` Mark Wielaard
  0 siblings, 0 replies; 15+ messages in thread
From: Mark Wielaard @ 2019-08-26 13:57 UTC (permalink / raw)
  To: Omar Sandoval; +Cc: elfutils-devel

Hi Omar,

On Tue, 2019-07-09 at 12:25 -0700, Omar Sandoval wrote:
> On Tue, Jul 09, 2019 at 09:14:03PM +0200, Mark Wielaard wrote:
> > Then after the release, somewhere next week, we'll apply your patches
> > first and can then deal with any fallout and followups. I am thinking
> > of moving some of the functionality into libdw proper (as cleaned up,
> > exported api) to reduce the size increase a little. And add a mechanism
> > for only building some of the backends (or maybe just drop some old
> > ones that nobody uses anyway).
> 
> This works for me, thanks! I'll keep an eye out for any followups,
> and I'm happy to help clean things up on the ebl side.

Obviously next week, became next month, sorry about that.
But the release is out now and new patches are streaming in already.
Would you mind rebasing your ebl work on top of git master and
reposting it?

Thanks,

Mark

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2019-08-26 13:57 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-03 20:04 [RFC PATCH 0/2] elfutils: don't use dlopen() for libebl modules Omar Sandoval
2019-07-03 20:04 ` [RFC PATCH 1/2] libcpu: merge libcpu_{i386,x86_64,bpf} into one library Omar Sandoval
2019-07-03 20:04 ` [RFC PATCH 2/2] Don't use dlopen() for libebl modules Omar Sandoval
2019-07-03 21:33 ` [RFC PATCH 0/2] elfutils: don't " Frank Ch. Eigler
2019-07-03 21:37   ` Omar Sandoval
2019-07-03 21:40     ` Frank Ch. Eigler
2019-07-03 21:46       ` Omar Sandoval
2019-07-04  0:56         ` Frank Ch. Eigler
2019-07-08 20:49           ` Mark Wielaard
2019-07-08 21:02             ` Omar Sandoval
2019-07-09  6:39               ` Florian Weimer
2019-07-09 19:14               ` Mark Wielaard
2019-07-09 19:25                 ` Omar Sandoval
2019-08-26 13:57                   ` Mark Wielaard
2019-07-08 20:33 ` Mark Wielaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).