Skip to content
Snippets Groups Projects
Commit 2da6e0ce authored by Simon McVittie's avatar Simon McVittie
Browse files

Add a function to classify strings to be loaded by libdl

parent 7c0abc72
No related branches found
No related tags found
1 merge request!337pressure-vessel: Remap preloadable modules better
......@@ -35,3 +35,23 @@ G_GNUC_INTERNAL gchar *_srt_libdl_detect_lib (gchar **envp,
const char *helpers_path,
const char *multiarch_tuple,
GError **error);
typedef enum
{
SRT_LOADABLE_KIND_ERROR,
SRT_LOADABLE_KIND_BASENAME,
SRT_LOADABLE_KIND_PATH,
} SrtLoadableKind;
typedef enum
{
SRT_LOADABLE_FLAGS_DYNAMIC_TOKENS = (1 << 0),
SRT_LOADABLE_FLAGS_ABI_DEPENDENT = (1 << 1),
SRT_LOADABLE_FLAGS_ORIGIN = (1 << 2),
SRT_LOADABLE_FLAGS_UNKNOWN_TOKENS = (1 << 3),
SRT_LOADABLE_FLAGS_NONE = 0
} SrtLoadableFlags;
G_GNUC_INTERNAL
SrtLoadableKind _srt_loadable_classify (const char *loadable,
SrtLoadableFlags *flags_out);
......@@ -126,3 +126,97 @@ _srt_libdl_detect_lib (gchar **envp,
"detect-lib",
error);
}
SrtLoadableKind
_srt_loadable_classify (const char *loadable,
SrtLoadableFlags *flags_out)
{
SrtLoadableFlags flags = SRT_LOADABLE_FLAGS_NONE;
SrtLoadableKind kind;
gsize i;
g_return_val_if_fail (loadable != NULL, SRT_LOADABLE_KIND_ERROR);
if (loadable[0] == '\0')
{
kind = SRT_LOADABLE_KIND_ERROR;
goto out;
}
if (strchr (loadable, '/') != NULL)
{
kind = SRT_LOADABLE_KIND_PATH;
}
else
{
/* Dynamic string tokens are not interpreted in a bare SONAME
* so we don't need to do that part. */
kind = SRT_LOADABLE_KIND_BASENAME;
goto out;
}
for (i = 0; loadable[i] != '\0'; i++)
{
if (loadable[i] == '$')
{
const char *token = loadable + i + 1;
gsize len;
flags |= SRT_LOADABLE_FLAGS_DYNAMIC_TOKENS;
if (token[0] == '{')
{
token++;
len = strcspn (token, "}");
}
else
{
len = 0;
while (g_ascii_isalnum (token[len]) || token[len] == '_')
len++;
}
switch (len)
{
case 3:
if (strncmp ("LIB", token, len) == 0)
{
flags |= SRT_LOADABLE_FLAGS_ABI_DEPENDENT;
continue;
}
break;
case 6:
if (strncmp ("ORIGIN", token, len) == 0)
{
flags |= SRT_LOADABLE_FLAGS_ORIGIN;
continue;
}
break;
case 8:
if (strncmp ("PLATFORM", token, len) == 0)
{
flags |= SRT_LOADABLE_FLAGS_ABI_DEPENDENT;
continue;
}
break;
default:
break;
}
flags |= SRT_LOADABLE_FLAGS_UNKNOWN_TOKENS;
}
}
out:
if (flags_out != NULL)
*flags_out = flags;
return kind;
}
/*
* Copyright © 2019 Collabora Ltd.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <steam-runtime-tools/steam-runtime-tools.h>
#include <string.h>
#include <unistd.h>
#include <glib.h>
#include <glib/gstdio.h>
#include "steam-runtime-tools/libdl-internal.h"
#include "test-utils.h"
typedef struct
{
int unused;
} Fixture;
typedef struct
{
int unused;
} Config;
static void
setup (Fixture *f,
gconstpointer context)
{
G_GNUC_UNUSED const Config *config = context;
}
static void
teardown (Fixture *f,
gconstpointer context)
{
G_GNUC_UNUSED const Config *config = context;
}
#define ERROR SRT_LOADABLE_KIND_ERROR
#define PATH SRT_LOADABLE_KIND_PATH
#define BASE SRT_LOADABLE_KIND_BASENAME
#define DYN SRT_LOADABLE_FLAGS_DYNAMIC_TOKENS
#define ABI SRT_LOADABLE_FLAGS_ABI_DEPENDENT
#define ORIGIN SRT_LOADABLE_FLAGS_ORIGIN
#define UNKNOWN SRT_LOADABLE_FLAGS_UNKNOWN_TOKENS
#define NONE SRT_LOADABLE_FLAGS_NONE
static const struct
{
const char *loadable;
SrtLoadableKind kind;
SrtLoadableFlags flags;
}
libdl_classify_tests[] =
{
{ "", ERROR, NONE },
{ "/usr/lib/libc.so.6", PATH, NONE },
{ "/usr/$LIB/libMangoHud.so", PATH, DYN|ABI },
{ "${LIB}/libfoo.so", PATH, DYN|ABI },
{ "/usr/plat-$PLATFORM/libc.so.6", PATH, DYN|ABI },
{ "${PLATFORM}/libc.so.6", PATH, DYN|ABI },
{ "${ORIGIN}/../${LIB}/libc.so.6", PATH, DYN|ABI|ORIGIN },
{ "/$ORIGIN/libfoo", PATH, DYN|ORIGIN },
{ "$ORIGIN/$FUTURE/${PLATFORM}-libfoo.so", PATH, DYN|ORIGIN|ABI|UNKNOWN },
{ "${FUTURE}/libfoo.so", PATH, DYN|UNKNOWN },
{ "libc.so.6", BASE, NONE },
{ "libMangoHud.so", BASE, NONE },
{ "looks-like-${TOKENS}-interpreted-but-not-really", BASE, NONE },
};
#undef ERROR
#undef PATH
#undef BASE
#undef DYN
#undef ABI
#undef ORIGIN
#undef UNKNOWN
#undef NONE
static void
test_libdl_classify (Fixture *f,
gconstpointer context)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (libdl_classify_tests); i++)
{
SrtLoadableFlags flags = -1;
SrtLoadableKind kind;
kind = _srt_loadable_classify (libdl_classify_tests[i].loadable, &flags);
g_assert_cmpuint (kind, ==, libdl_classify_tests[i].kind);
g_assert_cmphex (flags, ==, libdl_classify_tests[i].flags);
kind = _srt_loadable_classify (libdl_classify_tests[i].loadable, NULL);
g_assert_cmpuint (kind, ==, libdl_classify_tests[i].kind);
}
}
int
main (int argc,
char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add ("/libdl/classify", Fixture, NULL, setup,
test_libdl_classify, teardown);
return g_test_run ();
}
......@@ -42,6 +42,7 @@ tests = [
],
},
{'name': 'json-utils', 'static': true},
{'name': 'libdl', 'static': true},
{'name': 'library'},
{'name': 'locale'},
{'name': 'system-info'},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment