Skip to content
Snippets Groups Projects

Add inspect-library helper

Merged Ludovico de Nittis requested to merge wip/denittis/inspect-library into master
Compare and Show latest version
4 files
+ 165
48
Compare changes
  • Side-by-side
  • Inline
Files
4
+ 143
28
@@ -28,76 +28,191 @@
* JSON with the path and the dependencies of the requested library.
*/
#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <link.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
void clean_exit (void *handle);
#define BASE "Base"
static void print_json_string_content (const char *s);
static void clean_exit (void *handle);
int
main (int argc,
char **argv)
{
const char *soname;
const char *version;
const char *symbol;
void *handle = NULL;
/* 4096 should be the standard PATH_MAX */
char library_path[4096];
struct link_map *dep_map = NULL;
struct link_map *the_library = NULL;
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t chars;
bool first;
if (argc != 2)
if (argc < 2 || argc > 3)
{
g_warning ("Expected exactly one SONAME as argument.\n");
fprintf (stderr, "Expected, as argument, one SONAME and optionally a filename for symbols.\n");
return 1;
}
soname = argv[1];
g_print ("{\n");
g_print (" \"%s\": {\n", soname);
handle = dlopen (soname, RTLD_LAZY);
printf ("{\n");
printf (" \"");
print_json_string_content (soname);
printf ("\": {");
handle = dlopen (soname, RTLD_NOW);
if (handle == NULL)
{
g_warning ("Unable to find the library: %s\n", dlerror ());
fprintf (stderr, "Unable to find the library: %s\n", dlerror ());
clean_exit (handle);
return 1;
}
if (dlinfo (handle, RTLD_DI_ORIGIN, library_path) != 0)
/* Using RTLD_DI_LINKMAP insted of RTLD_DI_ORIGIN we don't need to worry
* about allocating a big enough array for the path. */
if (dlinfo (handle, RTLD_DI_LINKMAP, &the_library) != 0 || the_library == NULL)
{
g_warning ("Unable to obtain the path: %s\n", dlerror ());
fprintf (stderr, "Unable to obtain the path: %s\n", dlerror ());
clean_exit (handle);
return 1;
}
g_print (" \"path\": \"%s\",\n", library_path);
printf ("\n \"path\": \"");
print_json_string_content (the_library->l_name);
printf ("\",\n");
if (dlinfo (handle, RTLD_DI_LINKMAP, &dep_map) != 0)
{
g_warning ("Unable to obtain the dependencies list: %s\n", dlerror ());
clean_exit (handle);
return 1;
}
printf (" \"missing_symbols\": [");
if (argc == 3)
{
fp = fopen(argv[2], "r");
if (fp == NULL)
{
int saved_errno = errno;
g_print (" \"dependencies\": [");
if (dep_map != NULL)
{
g_print ("\n \"%s\"", dep_map->l_name);
dep_map = dep_map->l_next;
}
fprintf (stderr, "Error reading \"%s\": %s\n", argv[2], strerror (saved_errno));
printf ("\n ]");
clean_exit (handle);
return 1;
}
first = true;
while ((chars = getline(&line, &len, fp)) != -1)
{
if (line[chars - 1] == '\n')
line[chars - 1] = '\0';
/* Skip any empty line */
if (chars > 1)
{
version = strsep(&line, "@");
symbol = strsep(&line, "@");
if (symbol == NULL)
{
fprintf (stderr, "Probably the version@symbol pair is mispelled.");
printf ("\n ]");
free(line);
clean_exit (handle);
return 1;
}
if (strcmp (version, BASE) == 0)
{
if (dlsym (handle, symbol) == NULL)
{
if (first)
{
printf ("\n \"");
first = false;
}
else
printf (",\n \"");
print_json_string_content (symbol);
printf ("\"");
}
}
else
{
if (dlvsym (handle, symbol, version) == NULL)
{
if (first)
{
printf ("\n \"");
first = false;
}
else
printf (",\n \"");
print_json_string_content (version);
printf ("@");
print_json_string_content (symbol);
printf ("\"");
}
}
}
}
free(line);
fclose(fp);
}
printf ("\n ]");
dep_map = the_library;
/* Some loaded libraries may be before our handle.
* To list them all we move the pointer at the beginning. */
while (dep_map != NULL && dep_map->l_prev != NULL)
dep_map = dep_map->l_prev;
printf (",\n \"dependencies\": [");
first = true;
for (; dep_map != NULL; dep_map = dep_map->l_next)
{
g_print (",\n \"%s\"", dep_map->l_name);
if (dep_map == the_library || strcmp (dep_map->l_name, "") == 0)
continue;
if (first)
{
printf ("\n \"");
first = false;
}
else
printf (",\n \"");
print_json_string_content (dep_map->l_name);
printf ("\"");
}
g_print ("\n ]\n }\n");
printf ("\n ]\n }");
clean_exit (handle);
return 0;
}
void
print_json_string_content (const char *s)
{
const char *p;
for (p = s; *p != '\0'; p++)
{
if (*p == '"' || *p == '\\' || *p <= 0x1F)
printf ("\\u%04x", *p);
else
printf ("%c", *p);
}
}
void
clean_exit (void *handle)
{
if (handle != NULL)
dlclose (handle);
g_print ("}\n");
printf ("\n}\n");
}
Loading