summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builder/Makefile.am.inc4
-rw-r--r--builder/builder-manifest.c113
-rw-r--r--builder/builder-utils.c91
-rw-r--r--builder/builder-utils.h7
-rw-r--r--configure.ac20
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)