diff options
author | Alexander Larsson <alexl@redhat.com> | 2016-01-08 16:47:01 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2016-01-11 11:40:46 +0100 |
commit | 62b4ffaa72891520d57ce32ba99b40ceeda6cd99 (patch) | |
tree | d78a57f078ecfdd499cebb210326f5d6064328b4 /builder/builder-utils.c | |
parent | 8be003135589486ce8e6570e45af022950af8665 (diff) | |
download | xdg-app-62b4ffaa72891520d57ce32ba99b40ceeda6cd99.tar.gz |
builder: Use libelf to detect elf files
This additionally looks for already stripped files
Diffstat (limited to 'builder/builder-utils.c')
-rw-r--r-- | builder/builder-utils.c | 91 |
1 files changed, 91 insertions, 0 deletions
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; +} |