mirror of
https://github.com/flatpak/flatpak.git
synced 2026-10-20 14:45:30 -04:00
builder: Use libelf to detect elf files
This additionally looks for already stripped files
This commit is contained in:
1 parent
8be0031355
commit
62b4ffaa72
5 files changed
+142
-93
No files matched your search
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user