[gnome-ostree/wip/libgelf] WIP libgelf/debuginfo processing



commit 53fde17f52004c0525f57437e8ebbcc903ec7aab
Author: Colin Walters <walters verbum org>
Date:   Thu Feb 21 15:27:09 2013 -0500

    WIP libgelf/debuginfo processing

 Makefile-gsystem-introspection.am |   16 ++
 Makefile-libgelf.am               |   25 +++
 Makefile.am                       |   35 ++---
 configure.ac                      |   10 +-
 src/libgelf/gelf-file.c           |  330 +++++++++++++++++++++++++++++++++++++
 src/libgelf/gelf-file.h           |   61 +++++++
 src/libgelf/libgelf.h             |   32 ++++
 7 files changed, 483 insertions(+), 26 deletions(-)
---
diff --git a/Makefile-gsystem-introspection.am b/Makefile-gsystem-introspection.am
new file mode 100644
index 0000000..3f7d763
--- /dev/null
+++ b/Makefile-gsystem-introspection.am
@@ -0,0 +1,16 @@
+INTROSPECTION_GIRS += GSystem-1.0.gir
+
+GSystem-1.0.gir: libgsystem.la Makefile
+GSystem_1_0_gir_NAMESPACE = GSystem
+GSystem_1_0_gir_VERSION = 1.0
+GSystem_1_0_gir_LIBS = libgsystem.la
+GSystem_1_0_gir_CFLAGS = $(libgsystem_cflags)
+GSystem_1_0_gir_SCANNERFLAGS =                 \
+       --warn-all                              \
+       --warn-error                            \
+       --symbol-prefix=gs_                     \
+       --identifier-prefix=GS                  \
+        --c-include="libgsystem.h"             \
+       $(NULL)
+GSystem_1_0_gir_INCLUDES = Gio-2.0
+GSystem_1_0_gir_FILES = $(libgsystem_la_SOURCES)
diff --git a/Makefile-libgelf.am b/Makefile-libgelf.am
new file mode 100644
index 0000000..e619a94
--- /dev/null
+++ b/Makefile-libgelf.am
@@ -0,0 +1,25 @@
+privlib_LTLIBRARIES += libgelf.la
+libgelf_la_SOURCES = src/libgelf/libgelf.h \
+       src/libgelf/gelf-file.c \
+       src/libgelf/gelf-file.h \
+       $(NULL)
+libgelf_la_CFLAGS = $(AM_CFLAGS) $(OSTBUILD_DEP_CFLAGS) -I$(top_srcdir)/src/libgelf
+libgelf_la_LDFLAGS = -avoid-version -Bsymbolic-functions -export-symbols-regex "^gelf_" -no-undefined 
-export-dynamic
+libgelf_la_LIBADD = $(OSTBUILD_DEP_LIBS) -lelf
+
+INTROSPECTION_GIRS += GElf-1.0.gir
+
+GElf-1.0.gir: libgelf.la Makefile
+GElf_1_0_gir_NAMESPACE = GElf
+GElf_1_0_gir_VERSION = 1.0
+GElf_1_0_gir_LIBS = libgelf.la
+GElf_1_0_gir_CFLAGS = $(OSTBUILD_DEP_CFLAGS) -I$(top_srcdir)/src/libgelf
+GElf_1_0_gir_SCANNERFLAGS =                    \
+       --warn-all                              \
+       --warn-error                            \
+       --symbol-prefix=gelf_                   \
+       --identifier-prefix=GElf                        \
+        --c-include="libgelf.h"                        \
+       $(NULL)
+GElf_1_0_gir_INCLUDES = Gio-2.0
+GElf_1_0_gir_FILES = $(libgelf_la_SOURCES)
diff --git a/Makefile.am b/Makefile.am
index f19a3f3..2c27782 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,6 +34,15 @@ privlibdir = $(pkglibdir)
 privlib_LTLIBRARIES =
 INSTALL_DATA_HOOKS =
 
+include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+
+girdir= $(pkgdatadir)/gir-1.0
+typelibdir= $(pkglibdir)/girepository-1.0
+
+gir_DATA = $(INTROSPECTION_GIRS)
+typelib_DATA = $(gir_DATA:.gir=.typelib)
+
 libgsystem_srcpath := src/libgsystem
 libgsystem_cflags = $(GIO_UNIX_CFLAGS) -I$(srcdir)/src/libgsystem
 libgsystem_libs = $(GIO_UNIX_LIBS)
@@ -42,30 +51,8 @@ privlib_LTLIBRARIES += libgsystem.la
 
 include Makefile-ostbuild.am
 include Makefile-tests.am
-
-include $(INTROSPECTION_MAKEFILE)
-INTROSPECTION_GIRS = GSystem-1.0.gir
-
-GSystem-1.0.gir: libgsystem.la Makefile
-GSystem_1_0_gir_NAMESPACE = GSystem
-GSystem_1_0_gir_VERSION = 1.0
-GSystem_1_0_gir_LIBS = libgsystem.la
-GSystem_1_0_gir_CFLAGS = $(libgsystem_cflags)
-GSystem_1_0_gir_SCANNERFLAGS =                 \
-       --warn-all                              \
-       --warn-error                            \
-       --symbol-prefix=gs_                     \
-       --identifier-prefix=GS                  \
-        --c-include="libgsystem.h"             \
-       $(NULL)
-GSystem_1_0_gir_INCLUDES = Gio-2.0
-GSystem_1_0_gir_FILES = $(libgsystem_la_SOURCES)
-
-girdir= $(pkgdatadir)/gir-1.0
-typelibdir= $(pkglibdir)/girepository-1.0
-
-gir_DATA = $(INTROSPECTION_GIRS)
-typelib_DATA = $(gir_DATA:.gir=.typelib)
+include Makefile-libgelf.am
+include Makefile-gsystem-introspection.am
 
 install-data-hook: $(INSTALL_DATA_HOOKS)
 
diff --git a/configure.ac b/configure.ac
index a29ac58..18b37af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,8 +44,14 @@ AC_ARG_ENABLE(buildsystem,
            enable_buildsystem=yes)
 AM_CONDITIONAL(BUILDSYSTEM, test x$enable_buildsystem != xno)
 
-PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0 >= 2.34.0])
-GIO_UNIX_CFLAGS="$GIO_UNIX_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_34 
-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_34"
+gio_unix_dep_version=2.34.0
+PKG_CHECK_MODULES(GIO_UNIX, [gio-unix-2.0 >= ${gio_unix_dep_version}])
+PKG_CHECK_MODULES(OSTBUILD_DEP, [gio-unix-2.0 >= ${gio_unix_dep_version}])
+
+AC_CHECK_HEADER([libelf.h],,[AC_MSG_ERROR(libelf.h is required)])
+
+AC_DEFINE(GLIB_VERSION_MIN_REQUIRED, [GLIB_VERSION_2_34], [Define to GLib min version])
+AC_DEFINE(GLIB_VERSION_MAX_ALLOWED, [GLIB_VERSION_2_34], [Define to GLib max version])
 
 AC_CONFIG_FILES([
 Makefile
diff --git a/src/libgelf/gelf-file.c b/src/libgelf/gelf-file.c
new file mode 100644
index 0000000..dc80c0d
--- /dev/null
+++ b/src/libgelf/gelf-file.c
@@ -0,0 +1,330 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright © 2013 Colin Walters <walters verbum org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the licence or (at
+ * your option) any later version.
+ *
+ * See the included COPYING file for more information.
+ */
+
+#include "config.h"
+
+#include "gelf-file.h"
+
+/**
+ * SECTION:gelffile
+ * @title: GElfFile
+ * @short_description: Read an ELF object
+ *
+ * This class provides a high-level API for inspecting ELF object
+ * files.
+ */
+
+#include "config.h"
+
+#include "gelf-file.h"
+
+#include "libelf.h"
+#include <gio/gfiledescriptorbased.h>
+
+#include <string.h>
+#include <glib-unix.h>
+
+static void initable_iface_init (GInitableIface         *initable_iface);
+
+typedef GObjectClass GElfFileClass;
+
+struct _GElfFile
+{
+  GObject parent;
+
+  GFile *path;
+  GFileInputStream *stream;
+  Elf *elf;
+  Ebl *ebl;
+  guint shnum;
+  guint phnum;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GElfFile, gelf_file, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init));
+
+enum
+{
+  PROP_0,
+  PROP_PATH,
+  N_PROPS
+};
+
+static GParamSpec *gelf_file_pspecs[N_PROPS];
+
+static void
+gelf_file_init (GElfFile  *self)
+{
+}
+
+static void
+gelf_file_finalize (GObject *object)
+{
+  GElfFile *self = GELF_FILE (object);
+
+  if (self->elf)
+    elf_end (self->elf);
+  if (self->ebl)
+    ebl_closebackend (self->ebl);
+
+  g_clear_object (&self->path);
+  g_clear_object (&self->stream);
+
+  if (G_OBJECT_CLASS (gelf_file_parent_class)->finalize != NULL)
+    G_OBJECT_CLASS (gelf_file_parent_class)->finalize (object);
+}
+
+static void
+gelf_file_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  GElfFile *self = GELF_FILE (object);
+
+  switch (prop_id)
+    {
+    case PROP_PATH:
+      self->path = g_value_dup_object (value);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gelf_file_get_property (GObject    *object,
+                        guint       prop_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+  GElfFile *self = GELF_FILE (object);
+
+  switch (prop_id)
+    {
+    case PROP_PATH:
+      g_value_set_object (value, self->path);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gelf_file_class_init (GElfFileClass *class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+  gobject_class->finalize = gelf_file_finalize;
+  gobject_class->get_property = gelf_file_get_property;
+  gobject_class->set_property = gelf_file_set_property;
+
+  gelf_file_pspecs[PROP_PATH] = g_param_spec_object ("path", "", "", G_TYPE_FILE,
+                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                                                     G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (gobject_class, N_PROPS, gelf_file_pspecs);
+}
+
+G_DEFINE_QUARK (gelf-error-quark, gelf_error)
+
+static void
+set_elf_error (Elf     *elf,
+               GError **error)
+{
+  g_set_error_literal (error, GELF_ERROR, GELF_ERROR_INVALID,
+                       elf_errmsg (elf_errno ()));
+}
+
+static gboolean
+initable_init (GInitable     *initable,
+               GCancellable  *cancellable,
+               GError       **error)
+{
+  GElfFile *self = GELF_FILE (initable);
+  gboolean ret = FALSE;
+  int fd;
+  Elf_Kind kind;
+
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return FALSE;
+
+  self->stream = g_file_read (self->path, cancellable, error);
+  if (!self->stream)
+    goto out;
+
+  (void) elf_version (EV_CURRENT);
+
+  g_assert (G_IS_FILE_DESCRIPTOR_BASED (self->stream));
+  fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*) self->stream);
+
+  self->elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (!self->elf)
+    {
+      set_elf_error (self->elf, error);
+      goto out;
+    }
+  
+  kind = elf_kind (self->elf);
+  if (kind != ELF_K_ELF)
+    {
+      g_set_error (error, GELF_ERROR, GELF_ERROR_NOT_ELF,
+                   "Not an ELF file");
+      goto out;
+    }
+
+  self->ebl = ebl_openbackend (self->elf);
+
+  if (elf_getshdrnum (self->ebl->elf, &self->shnum) < 0)
+    {
+      set_elf_error (self->ebl->elf, error);
+      goto out;
+    }
+
+  if (elf_getphdrnum (self->ebl->elf, &self->phnum) < 0)
+    {
+      set_elf_error (self->ebl->elf, error);
+      goto out;
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+static void
+initable_iface_init (GInitableIface *initable_iface)
+{
+  initable_iface->init = initable_init;
+}
+
+/**
+ * gelf_file_new:
+ * @path: Path to ELF file
+ * @cancellable:
+ * @error:
+ *
+ * Create a new #GElfFile; will throw an error if @path is not ELF.
+ *
+ * Returns: (transfer full): A newly created %GElfFile, or %NULL on error (and @error will be set)
+ */
+GElfFile *
+gelf_file_new (GFile                 *path,
+               GCancellable          *cancellable,
+               GError               **error)
+{
+  return g_initable_new (GELF_TYPE_FILE,
+                         cancellable, error,
+                         "path", path,
+                         NULL);
+}
+
+/**
+ * gelf_file_maybe_new:
+ * @path: Path to ELF file
+ * @cancellable:
+ * @error:
+ *
+ * Create a new #GElfFile; if @path is not ELF, then %NULL will be
+ * returned, and @error will not be set.
+ *
+ * Returns: (transfer full): A newly created %GElfFile, or %NULL on error (and @error will be set)
+ */
+GElfFile *
+gelf_file_maybe_new (GFile                 *path,
+                     GCancellable          *cancellable,
+                     GError               **error)
+{
+  GError *tmp_error = NULL;
+  GElfFile *ret;
+
+  ret = g_initable_new (GELF_TYPE_FILE,
+                        cancellable, &tmp_error,
+                        "path", path,
+                        NULL);
+  if (tmp_error != NULL)
+    {
+      if (g_error_matches (tmp_error, GELF_ERROR, GELF_ERROR_NOT_ELF))
+        g_clear_error (&tmp_error);
+      else
+        g_propagate_error (error, tmp_error);
+    }
+
+  return ret;
+}
+
+static 
+
+/**
+ * gelf_file_get_build_id:
+ * @self:
+ * @out_build_id: (out) (allow-none): Build-Id, or %NULL if none found
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ */
+gboolean
+gelf_file_get_build_id (GElfFile *self,
+                        char    **out_build_id,
+                        GError  **error)
+{
+  gboolean ret = FALSE;
+  char *ret_build_id = NULL;
+  Elf_Scn *scn = NULL;
+
+  if (self->shnum > 0)
+    {
+      size_t shstrndx;
+      if (elf_getshdrstrndx (self->ebl->elf, &shstrndx) < 0)
+        {
+          set_elf_error (self->ebl->elf, error);
+          goto out;
+        }
+      while ((scn = elf_nextscn (self->ebl->elf, scn)) != NULL)
+        {
+         GElf_Shdr shdr_mem;
+         GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+          GElf_Off start;
+          Elf_Data *data;
+
+         if (shdr == NULL || shdr->sh_type != SHT_NOTE)
+           continue;
+
+          start = shdr->sh_offset;
+          data = elf_getdata (scn, NULL);
+
+          if (data == NULL)
+            continue;
+          
+        }
+    }
+
+ out:
+  if (out_build_id)
+    *out_build_id = ret_build_id;
+  else
+    g_free (ret_build_id);
+  return ret;
+}
+
+/**
+ * gelf_file_get_dt_needed:
+ * @self:
+ *
+ * Returns: (transfer full) (element-type utf8): the list of DT_NEEDED entries
+ */
+GList *
+gelf_file_get_dt_needed (GElfFile *self)
+{
+  return NULL;
+}
diff --git a/src/libgelf/gelf-file.h b/src/libgelf/gelf-file.h
new file mode 100644
index 0000000..e73cbf5
--- /dev/null
+++ b/src/libgelf/gelf-file.h
@@ -0,0 +1,61 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2013 Colin Walters <walters verbum org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GELF_FILE_H__
+#define __GELF_FILE_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GELF_TYPE_FILE         (gelf_file_get_type ())
+#define GELF_FILE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GELF_TYPE_FILE, GElfFile))
+#define GELF_IS_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GELF_TYPE_FILE))
+
+typedef struct _GElfFile GElfFile;
+
+GQuark           gelf_error_quark (void);
+
+#define GELF_ERROR (gelf_error_quark ())
+
+typedef enum {
+  GELF_ERROR_NOT_ELF = 1,
+  GELF_ERROR_INVALID
+} GElfError;
+
+GType            gelf_file_get_type (void) G_GNUC_CONST;
+
+GElfFile *    gelf_file_new (GFile                 *path,
+                             GCancellable          *cancellable,
+                             GError               **error);
+
+GElfFile *    gelf_file_maybe_new (GFile                 *path,
+                                   GCancellable          *cancellable,
+                                   GError               **error);
+
+gboolean      gelf_file_get_build_id (GElfFile    *self,
+                                      char       **out_build_id,
+                                      GError     **error);
+
+GList *       gelf_file_get_dt_needed (GElfFile    *self);
+
+G_END_DECLS
+
+#endif
diff --git a/src/libgelf/libgelf.h b/src/libgelf/libgelf.h
new file mode 100644
index 0000000..5111dba
--- /dev/null
+++ b/src/libgelf/libgelf.h
@@ -0,0 +1,32 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Colin Walters <walters verbum org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LIBGSYSTEM__
+#define __LIBGSYSTEM__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#include <gelf-file.h>
+
+G_END_DECLS
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]