diff options
-rw-r--r-- | builder/Makefile.am.inc | 4 | ||||
-rw-r--r-- | builder/builder-manifest.c | 113 | ||||
-rw-r--r-- | builder/builder-utils.c | 91 | ||||
-rw-r--r-- | builder/builder-utils.h | 7 | ||||
-rw-r--r-- | configure.ac | 20 |
5 files changed, 142 insertions, 93 deletions
diff --git a/builder/Makefile.am.inc b/builder/Makefile.am.inc index 72e40be..014907c 100644 --- a/builder/Makefile.am.inc +++ b/builder/Makefile.am.inc @@ -32,6 +32,6 @@ xdg_app_builder_SOURCES = \ builder/builder-utils.h \ $(NULL) -xdg_app_builder_LDADD = $(BASE_LIBS) $(OSTREE_LIBS) $(JSON_LIBS) $(SOUP_LIBS) $(LIBARCHIVE_LIBS) libglnx.la libxdgapp-common.la +xdg_app_builder_LDADD = $(BASE_LIBS) $(OSTREE_LIBS) $(JSON_LIBS) $(SOUP_LIBS) $(LIBARCHIVE_LIBS) $(LIBELF_LIBS) \ + libglnx.la libxdgapp-common.la xdg_app_builder_CFLAGS = $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(JSON_CFLAGS) $(SOUP_CFLAGS) $(LIBARCHIVE_CFLAGS) - diff --git a/builder/builder-manifest.c b/builder/builder-manifest.c index 1c31278..e00c373 100644 --- a/builder/builder-manifest.c +++ b/builder/builder-manifest.c @@ -737,20 +737,6 @@ builder_manifest_build (BuilderManifest *self, } static gboolean -strip (GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = xdg_app_spawn (NULL, NULL, error, "strip", ap); - va_end (ap); - - return res; -} - -static gboolean command (GFile *app_dir, char **env_vars, const char *commandline, @@ -794,54 +780,6 @@ command (GFile *app_dir, return TRUE; } -guint16 -read_elf_16(guchar *ptr, guint16 endianness) -{ - guint16 lo, hi; - if (endianness == 1) - { - lo = ptr[0]; - hi = ptr[1]; - } - else - { - lo = ptr[1]; - hi = ptr[0]; - } - return lo | (hi << 8); -} - -static gboolean -is_elf (int fd, gboolean *is_shared) -{ - guchar elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; - guchar header[64]; - gssize r; - guint8 endianness; - guint16 e_type; - - r = read (fd, header, sizeof (header)); - if (r != sizeof (header)) - return FALSE; - - if (memcmp (header, elf_magic, 4) != 0) - return FALSE; - - endianness = header[0x5]; - if (endianness != 1 && endianness != 2) /* 1 == little, 2 == big endian */ - return FALSE; - - e_type = read_elf_16 (&header[0x10], endianness); - - /* Only handle executable (2) or shared (3) */ - if (e_type != 2 && e_type != 3) - return FALSE; - - *is_shared = (e_type == 3); - - return TRUE; -} - typedef gboolean (*ForeachFileFunc) (BuilderManifest *self, int source_parent_fd, const char *source_name, @@ -929,40 +867,33 @@ foreach_file (BuilderManifest *self, static gboolean strip_file_cb (BuilderManifest *self, - int source_parent_fd, - const char *source_name, - const char *full_dir, - const char *rel_dir, - struct stat *stbuf, - gboolean *found, - int depth, - GError **error) + int source_parent_fd, + const char *source_name, + const char *full_dir, + const char *rel_dir, + struct stat *stbuf, + gboolean *found, + int depth, + GError **error) { - if (S_ISREG (stbuf->st_mode) && - ((strstr (source_name, ".so.") != NULL || g_str_has_suffix (source_name, ".so")) || - (stbuf->st_mode & 0111) != 0)) + if (S_ISREG (stbuf->st_mode)) { - glnx_fd_close int fd = -1; + g_autofree char *path = g_strconcat (full_dir, "/", source_name, NULL); + gboolean is_shared, is_stripped; - fd = openat (source_parent_fd, source_name, O_RDONLY|O_NOFOLLOW|O_CLOEXEC); - if (fd >= 0) + if (is_elf_file (path, &is_shared, &is_stripped) && !is_stripped) { - gboolean is_shared; - if (is_elf (fd, &is_shared)) + g_autofree char *rel_path = g_strconcat (rel_dir, "/", source_name, NULL); + g_print ("stripping: %s\n", rel_path); + if (is_shared) { - g_autofree char *path = g_strconcat (full_dir, "/", source_name, NULL); - g_autofree char *rel_path = g_strconcat (rel_dir, "/", source_name, NULL); - g_print ("stripping: %s\n", rel_path); - if (is_shared) - { - if (!strip (error, "--remove-section=.comment", "--remove-section=.note", "--strip-unneeded", path, NULL)) - return FALSE; - } - else - { - if (!strip (error, "--remove-section=.comment", "--remove-section=.note", path, NULL)) - return FALSE; - } + if (!strip (error, "--remove-section=.comment", "--remove-section=.note", "--strip-unneeded", path, NULL)) + return FALSE; + } + else + { + if (!strip (error, "--remove-section=.comment", "--remove-section=.note", path, NULL)) + return FALSE; } } } diff --git a/builder/builder-utils.c b/builder/builder-utils.c index a5aba96..9b94423 100644 --- a/builder/builder-utils.c +++ b/builder/builder-utils.c @@ -21,8 +21,13 @@ #include "config.h" +#include <libelf.h> +#include <gelf.h> +#include <sys/mman.h> + #include <string.h> +#include "xdg-app-utils.h" #include "builder-utils.h" char * @@ -113,3 +118,89 @@ path_prefix_match (const char *pattern, } return NULL; /* Should not be reached */ } + +gboolean +strip (GError **error, + ...) +{ + gboolean res; + va_list ap; + + va_start (ap, error); + res = xdg_app_spawn (NULL, NULL, error, "strip", ap); + va_end (ap); + + return res; +} + +static gboolean elf_has_symtab (Elf *elf) +{ + Elf_Scn *scn; + GElf_Shdr shdr; + + scn = NULL; + while ((scn = elf_nextscn(elf, scn)) != NULL) + { + if (gelf_getshdr (scn, &shdr) == NULL) + continue; + + if (shdr.sh_type != SHT_SYMTAB) + continue; + + return TRUE; + } + + return FALSE; +} + +gboolean is_elf_file (const char *path, + gboolean *is_shared, + gboolean *is_stripped) +{ + g_autofree char *filename = g_path_get_basename (path); + struct stat stbuf; + + if (lstat (path, &stbuf) == -1) + return FALSE; + + if (!S_ISREG (stbuf.st_mode)) + return FALSE; + + if ((strstr (filename, ".so.") != NULL || + g_str_has_suffix (filename, ".so")) || + (stbuf.st_mode & 0111) != 0) + { + glnx_fd_close int fd = -1; + + fd = open (path, O_RDONLY|O_NOFOLLOW|O_CLOEXEC); + if (fd >= 0) + { + Elf *elf; + GElf_Ehdr ehdr; + gboolean res = FALSE; + + if (elf_version (EV_CURRENT) == EV_NONE ) + return FALSE; + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + return FALSE; + + if (elf_kind (elf) == ELF_K_ELF && + gelf_getehdr (elf, &ehdr)) + { + if (is_shared) + *is_shared = ehdr.e_type == ET_DYN; + if (is_stripped) + *is_stripped = !elf_has_symtab (elf); + + res = TRUE; + } + + elf_end (elf); + return res; + } + } + + return FALSE; +} diff --git a/builder/builder-utils.h b/builder/builder-utils.h index 58614bb..d0b59ac 100644 --- a/builder/builder-utils.h +++ b/builder/builder-utils.h @@ -33,6 +33,13 @@ char *builder_uri_to_filename (const char *uri); const char *path_prefix_match (const char *pattern, const char *string); +gboolean strip (GError **error, + ...); + +gboolean is_elf_file (const char *path, + gboolean *is_shared, + gboolean *is_stripped); + G_END_DECLS #endif /* __BUILDER_UTILS_H__ */ diff --git a/configure.ac b/configure.ac index 1cdeab6..b055c20 100644 --- a/configure.ac +++ b/configure.ac @@ -177,7 +177,27 @@ AS_IF([ test x$with_libarchive != xno ], [ ], [ with_libarchive=no ]) AM_CONDITIONAL(USE_LIBARCHIVE, test $with_libarchive != no) +dnl ************************ +dnl *** check for libelf *** +dnl ************************ +PKG_CHECK_MODULES([LIBELF], [libelf >= 0.8.12], [have_libelf=yes], [have_libelf=maybe]) +AS_IF([ test $have_libelf = maybe ], [ + save_LIBS=$LIBS + AC_CHECK_LIB([elf], [elf_begin], [:], [have_libelf=no]) + AC_CHECK_LIB([elf], [elf_getshdrstrndx], [:], [have_libelf=no]) + AC_CHECK_LIB([elf], [elf_getshdrnum], [:], [have_libelf=no]) + AC_CHECK_HEADER([libelf.h], [:], [have_libelf=no]) + LIBS=$save_LIBS + + if test $have_libelf != no; then + LIBELF_LIBS=-lelf + have_libelf=yes + fi +]) +if test x$have_libelf != xyes; then + AC_MSG_ERROR([libelf not found]) +fi AC_ARG_ENABLE(documentation, AC_HELP_STRING([--enable-documentation], [Build documentation]),, enable_documentation=yes) |