Skip to content

Commit

Permalink
syscalls: llext: Export z_impl symbols so they are available to kernel
Browse files Browse the repository at this point in the history
commit 67bb6db ("syscall: Export all emitted syscalls, enabling
them for extensions") exports all emitted syscalls, however, it does
that only for the `z_mrsh` symbols, effectively only available for
userspace. If an extension running at kernel level tries to use a
syscall, it will fail to load.

This patch fixes that by exposing the `z_impl` symbols instead. However,
this is not as straightforward as the `z_mrsh` ones. As, in their
signatures, they can basically contain any type, it's not just a matter
of emitting `EXPORT_SYMBOL(z_impl_<syscall>)`, as the compiler will
complain about the undefined types. Here, there are a few approaches.

One of them is to have the `EXPORT_SYMBOL` being generated on the same
files where the syscall is implemented - injecting it there would allow
it to access all known symbols. But changing a lot of files is
undesirable, and it was one of the nice points of first patch.

Another one would be to reconstruct - or simply use the absolute path -
for the includes where the syscalls are defined. Reconstruct the paths
seems fragile and I'm not sure using absolute paths is portable.

Finally, the approach used in this patch is to declare, on a different
generated file, all `z_impl_` symbols as `void *` - after all, only the
address (and the name) to the function is relevant to EXPORT_SYMBOL. By
living in an compilation unit that doesn't include any header which
would expose any of the syscalls, there shouldn't be any conflicts. And
to account for the possibility that a syscall is not compiled - due
being configured out via Kconfig - all those symbols are also weak
aliases to a pointer to NULL. This file is then included in
`llext_export.c` (which should naturally not include any conflicting
header).

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
  • Loading branch information
edersondisouza authored and nashif committed Mar 26, 2024
1 parent 321e395 commit 62b19ef
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h}
--json-file ${syscalls_json} # Read this file
--base-output include/generated/syscalls # Write to this dir
--syscall-dispatch include/generated/syscall_dispatch.c # Write this file
--syscall-export-llext include/generated/syscall_export_llext.c
--syscall-list ${syscall_list_h}
$<$<BOOL:${CONFIG_USERSPACE}>:--gen-mrsh-files>
${SYSCALL_LONG_REGISTERS_ARG}
Expand Down
35 changes: 28 additions & 7 deletions scripts/build/gen_syscalls.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@
const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
\t%s
};
/* Export syscalls for extensions */
%s
"""

list_template = """/* auto-generated by gen_syscalls.py, don't edit */
Expand Down Expand Up @@ -159,6 +157,20 @@
#endif
"""


exported_template = """
/* Export syscalls for extensions */
static void * const no_handler = NULL;
/* Weak references, if something is not found by the linker, it will be NULL
* and simply fail during extension load
*/
%s
/* Exported symbols */
%s
"""

typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$')


Expand Down Expand Up @@ -410,6 +422,8 @@ def parse_args():
help="Indicates we are on system with 64-bit registers")
parser.add_argument("--gen-mrsh-files", action="store_true",
help="Generate marshalling files (*_mrsh.c)")
parser.add_argument("-e", "--syscall-export-llext",
help="output C system call export for extensions")
args = parser.parse_args()


Expand All @@ -431,6 +445,7 @@ def main():
table_entries = []
handlers = []
emit_list = []
exported = []

for match_group, fn, to_emit in syscalls:
handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn)
Expand All @@ -445,6 +460,7 @@ def main():
ids_emit.append(sys_id)
table_entries.append(entry)
emit_list.append(handler)
exported.append(handler.replace("z_mrsh_", "z_impl_"))
else:
ids_not_emit.append(sys_id)

Expand All @@ -464,12 +480,17 @@ def main():
weak_defines += "\n".join(["extern uintptr_t %s(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf);"
% s for s in noweak])

# Export symbols for emitted syscalls
exported_symbols = "\n".join("EXPORT_SYMBOL(%s);" % e for e in emit_list)

fp.write(table_template % (weak_defines,
",\n\t".join(table_entries),
exported_symbols))
",\n\t".join(table_entries)))

if args.syscall_export_llext:
with open(args.syscall_export_llext, "w") as fp:
# Export symbols for emitted syscalls
weak_refs = "\n".join("extern __weak ALIAS_OF(no_handler) void * const %s;"
% e for e in exported)
exported_symbols = "\n".join("EXPORT_SYMBOL(%s);"
% e for e in exported)
fp.write(exported_template % (weak_refs, exported_symbols))

# Listing header emitted to stdout
ids_emit.sort()
Expand Down
2 changes: 2 additions & 0 deletions subsys/llext/llext_export.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memset);

#include <syscall_export_llext.c>

0 comments on commit 62b19ef

Please sign in to comment.