[sysprof] kallsyms: add API to extract kallsyms with strtok_r()



commit 26343e3d2a59a890c52275eb1761d8fb07494f20
Author: Christian Hergert <chergert redhat com>
Date:   Sun Jan 28 21:26:17 2018 -0800

    kallsyms: add API to extract kallsyms with strtok_r()
    
    This will allow us to simplify some code, and provide an API in both
    the lib and daemon to get symbols while sharing code.

 lib/meson.build   |    2 +
 lib/sp-kallsyms.c |  148 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/sp-kallsyms.h |   41 +++++++++++++++
 3 files changed, 191 insertions(+), 0 deletions(-)
---
diff --git a/lib/meson.build b/lib/meson.build
index d02d9f3..5f9f2a5 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -28,12 +28,14 @@ libsysprof_base_headers = [
   'sp-address.h',
   'sp-clock.h',
   'sp-error.h',
+  'sp-kallsyms.h',
 ]
 
 libsysprof_base_sources = [
   'sp-address.c',
   'sp-clock.c',
   'sp-error.c',
+  'sp-kallsyms.c',
 ]
 
 libsysprof_headers = libsysprof_base_headers
diff --git a/lib/sp-kallsyms.c b/lib/sp-kallsyms.c
new file mode 100644
index 0000000..3e799cb
--- /dev/null
+++ b/lib/sp-kallsyms.c
@@ -0,0 +1,148 @@
+/* sp-kallsyms.c
+ *
+ * Copyright © 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "sp-kallsyms"
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "sp-kallsyms.h"
+
+struct _SpKallsyms
+{
+  gchar *buf;
+  gsize  buflen;
+  gchar *endptr;
+  gchar *iter;
+};
+
+void
+sp_kallsyms_free (SpKallsyms *self)
+{
+  if (self != NULL)
+    {
+      g_clear_pointer (&self->buf, g_free);
+      g_slice_free (SpKallsyms, self);
+    }
+}
+
+SpKallsyms *
+sp_kallsyms_new (void)
+{
+  g_autoptr(SpKallsyms) self = NULL;
+
+  self = g_slice_new0 (SpKallsyms);
+
+  if (!g_file_get_contents ("/proc/kallsyms", &self->buf, &self->buflen, NULL))
+    return NULL;
+
+  self->iter = self->buf;
+  self->endptr = self->buf + self->buflen;
+
+  return g_steal_pointer (&self);
+}
+
+gboolean
+sp_kallsyms_next (SpKallsyms   *self,
+                  const gchar **name,
+                  guint64      *address,
+                  guint8       *type)
+{
+  guint64 addr;
+  char *tok;
+
+  g_return_val_if_fail (self != NULL, FALSE);
+  g_return_val_if_fail (self->buf != NULL, FALSE);
+  g_return_val_if_fail (self->buflen > 0, FALSE);
+  g_return_val_if_fail (self->iter != NULL, FALSE);
+  g_return_val_if_fail (self->endptr != NULL, FALSE);
+
+try_next:
+
+  if (self->iter >= self->endptr)
+    return FALSE;
+
+  tok = strtok_r (self->iter, " \t\n", &self->iter);
+  if (!tok || *tok == 0)
+    return FALSE;
+
+  if (*tok == '[')
+    {
+      tok = strtok_r (self->iter, " \t\n", &self->iter);
+      if (!tok || *tok == 0)
+        return FALSE;
+    }
+
+  addr = g_ascii_strtoull (tok, NULL, 10);
+  if ((addr == G_MAXUINT64 && errno == ERANGE) ||
+      (addr == 0 && errno == EINVAL))
+    return FALSE;
+
+  *address = addr;
+
+  if (self->iter >= self->endptr)
+    return FALSE;
+
+  tok = strtok_r (self->iter, " \t\n", &self->iter);
+  if (!tok || *tok == 0)
+    return FALSE;
+
+  switch (*tok)
+    {
+    case 'A':
+    case 'B':
+    case 'D':
+    case 'R':
+    case 'T':
+    case 'V':
+    case 'W':
+    case 'a':
+    case 'b':
+    case 'd':
+    case 'r':
+    case 't':
+    case 'w':
+      *type = *tok;
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  if (self->iter >= self->endptr)
+    return FALSE;
+
+  tok = strtok_r (self->iter, " \t\n", &self->iter);
+  if (!tok || *tok == 0)
+    return FALSE;
+
+  if (self->iter >= self->endptr)
+    return FALSE;
+
+  if (g_strcmp0 (tok, "(null)") == 0)
+    goto try_next;
+
+  *name = tok;
+
+  return TRUE;
+}
diff --git a/lib/sp-kallsyms.h b/lib/sp-kallsyms.h
new file mode 100644
index 0000000..76b7a62
--- /dev/null
+++ b/lib/sp-kallsyms.h
@@ -0,0 +1,41 @@
+/* sp-kallsyms.h
+ *
+ * Copyright © 2018 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SP_KALLSYMS_H
+#define SP_KALLSYMS_H
+
+#include <gio/gio.h>
+
+#include "sp-kallsyms.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SpKallsyms SpKallsyms;
+
+SpKallsyms *sp_kallsyms_new  (void);
+gboolean    sp_kallsyms_next (SpKallsyms   *self,
+                              const gchar **name,
+                              guint64      *address,
+                              guint8       *type);
+void        sp_kallsyms_free (SpKallsyms   *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpKallsyms, sp_kallsyms_free)
+
+G_END_DECLS
+
+#endif /* SP_KALLSYMS_H */


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