Skip to content

Commit 62b19ef

Browse files
edersondisouzanashif
authored andcommitted
syscalls: llext: Export z_impl symbols so they are available to kernel
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>
1 parent 321e395 commit 62b19ef

File tree

3 files changed

+31
-7
lines changed

3 files changed

+31
-7
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,7 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h}
759759
--json-file ${syscalls_json} # Read this file
760760
--base-output include/generated/syscalls # Write to this dir
761761
--syscall-dispatch include/generated/syscall_dispatch.c # Write this file
762+
--syscall-export-llext include/generated/syscall_export_llext.c
762763
--syscall-list ${syscall_list_h}
763764
$<$<BOOL:${CONFIG_USERSPACE}>:--gen-mrsh-files>
764765
${SYSCALL_LONG_REGISTERS_ARG}

scripts/build/gen_syscalls.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@
6262
const _k_syscall_handler_t _k_syscall_table[K_SYSCALL_LIMIT] = {
6363
\t%s
6464
};
65-
/* Export syscalls for extensions */
66-
%s
6765
"""
6866

6967
list_template = """/* auto-generated by gen_syscalls.py, don't edit */
@@ -159,6 +157,20 @@
159157
#endif
160158
"""
161159

160+
161+
exported_template = """
162+
/* Export syscalls for extensions */
163+
static void * const no_handler = NULL;
164+
165+
/* Weak references, if something is not found by the linker, it will be NULL
166+
* and simply fail during extension load
167+
*/
168+
%s
169+
170+
/* Exported symbols */
171+
%s
172+
"""
173+
162174
typename_regex = re.compile(r'(.*?)([A-Za-z0-9_]+)$')
163175

164176

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

415429

@@ -431,6 +445,7 @@ def main():
431445
table_entries = []
432446
handlers = []
433447
emit_list = []
448+
exported = []
434449

435450
for match_group, fn, to_emit in syscalls:
436451
handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn)
@@ -445,6 +460,7 @@ def main():
445460
ids_emit.append(sys_id)
446461
table_entries.append(entry)
447462
emit_list.append(handler)
463+
exported.append(handler.replace("z_mrsh_", "z_impl_"))
448464
else:
449465
ids_not_emit.append(sys_id)
450466

@@ -464,12 +480,17 @@ def main():
464480
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);"
465481
% s for s in noweak])
466482

467-
# Export symbols for emitted syscalls
468-
exported_symbols = "\n".join("EXPORT_SYMBOL(%s);" % e for e in emit_list)
469-
470483
fp.write(table_template % (weak_defines,
471-
",\n\t".join(table_entries),
472-
exported_symbols))
484+
",\n\t".join(table_entries)))
485+
486+
if args.syscall_export_llext:
487+
with open(args.syscall_export_llext, "w") as fp:
488+
# Export symbols for emitted syscalls
489+
weak_refs = "\n".join("extern __weak ALIAS_OF(no_handler) void * const %s;"
490+
% e for e in exported)
491+
exported_symbols = "\n".join("EXPORT_SYMBOL(%s);"
492+
% e for e in exported)
493+
fp.write(exported_template % (weak_refs, exported_symbols))
473494

474495
# Listing header emitted to stdout
475496
ids_emit.sort()

subsys/llext/llext_export.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ EXPORT_SYMBOL(strncmp);
1515
EXPORT_SYMBOL(memcmp);
1616
EXPORT_SYMBOL(memcpy);
1717
EXPORT_SYMBOL(memset);
18+
19+
#include <syscall_export_llext.c>

0 commit comments

Comments
 (0)