[systemd-devel] [RFC 04/12] build: add target to link binary sources

David Herrmann dh.herrmann at gmail.com
Wed Nov 27 10:48:39 PST 2013


In several situations we want to link a binary file into our executable
and access it from our C code. The easiest way is to transform it into a
C-array and compile it as usual. However, for large files (>1MB) such
compilations can take a considerable amount of time or even fail on
low-memory systems.

This adds a new automake-target to link binary sources directly. Instead
of transforming it into a C-array, we simply use "ld -r" to create an
object file via:
  ld -r -o my-source.bin.o --format=binary my-source.bin
We also use "-z noexecstack" to mark "my-source.bin.o" to not require an
executable stack.

As we only want to support read-only data sources here, we do some
post-processing to mark the object as read-only via:
  objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents my-source.bin.o

As libtool requires "*.lo" files, we cannot link this object-file
directly. Thus, we also create a fake "*.lo" file for such objects which
libtool can use. Note that libtool actually *requires* the comment-section
in "*.lo" files (ugh?!) so we need to fake that, too.

How to use this helper?
 - put your binary source file into the tree as:
     src/somewhere/something.bin
 - for the library you want to link that to, add this to mylib_LIBADD:
     src/somewhere/something.bin.lo
This causes the helper to create src/somewhere/something.bin.[o,lo] and
it will be linked as a normal object file.

GNU-ld automatically creates 3 symbols for such objects, but the important
symbols are:
  extern const char _binary_src_somewhere_something_bin_start[];
  extern const char _binary_src_somewhere_something_bin_end[];
Use these to access start/end of the binary section.

I tested this with in-tree and out-of-tree builds, with GNU-ld and
GNU-gold and cross-compilation. All worked fine..
---
 Makefile.am  | 19 +++++++++++++++++++
 configure.ac |  5 +++++
 2 files changed, 24 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 4aa2bdf..ce27e82 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -632,6 +632,25 @@ EXTRA_DIST += \
 	xml_helper.py
 
 # ------------------------------------------------------------------------------
+CLEANFILES += *.bin.lo *.bin.o
+
+%.bin.lo: %.bin
+	$(AM_V_GEN)$(LD) -r -o "$*.bin.o" -z noexecstack --format=binary "$<"
+	$(AM_V_at)$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "$*.bin.o"
+	$(AM_V_at)echo "# $@ - a libtool object file" >"$@"
+	$(AM_V_at)echo "# Generated by $(shell $(LIBTOOL) --version | head -n 1)" >>"$@"
+	$(AM_V_at)echo "#" >>"$@"
+	$(AM_V_at)echo "# Please DO NOT delete this file!" >>"$@"
+	$(AM_V_at)echo "# It is necessary for linking the library." >>"$@"
+	$(AM_V_at)echo >>"$@"
+	$(AM_V_at)echo "# Name of the PIC object." >>"$@"
+	$(AM_V_at)echo "pic_object='$(notdir $*).bin.o'" >>"$@"
+	$(AM_V_at)echo >>"$@"
+	$(AM_V_at)echo "# Name of the non-PIC object" >>"$@"
+	$(AM_V_at)echo "non_pic_object='$(notdir $*).bin.o'" >>"$@"
+	$(AM_V_at)echo >>"$@"
+
+# ------------------------------------------------------------------------------
 noinst_LTLIBRARIES += \
 	libsystemd-rtnl.la
 
diff --git a/configure.ac b/configure.ac
index c0656f4..3fd05da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -101,6 +101,11 @@ if test -z "$GPERF" ; then
         AC_MSG_ERROR([*** gperf not found])
 fi
 
+AC_CHECK_TOOL([OBJCOPY], objcopy)
+if test -z "$OBJCOPY" ; then
+        AC_MSG_ERROR([*** objcopy not found])
+fi
+
 # ------------------------------------------------------------------------------
 address_sanitizer_cflags=
 address_sanitizer_cppflags=
-- 
1.8.4.2



More information about the systemd-devel mailing list