builder: Use libelf to detect elf files

This additionally looks for already stripped files
This commit is contained in:
Alexander Larsson committed 2016-01-11 11:40:46 +01:00
1 parent 8be0031355
commit 62b4ffaa72
5 files changed
+142 -93

No files matched your search

+2 -2
View File
@@ -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)
+22 -91
View File
@@ -736,20 +736,6 @@ builder_manifest_build (BuilderManifest *self,
return TRUE;
}
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,
@@ -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;
}
}
}
+91
View File
@@ -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;
}
+7
View File
@@ -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__ */
+20
View File
@@ -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)