diff --git a/CMakeLists.txt b/CMakeLists.txt index 65cf26ff75e..505eeafff46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -842,7 +842,12 @@ if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) endif() -add_custom_command(OUTPUT include/generated/zephyr/syscall_dispatch.c ${syscall_list_h} +add_custom_command( + OUTPUT + include/generated/zephyr/syscall_dispatch.c + include/generated/zephyr/syscall_exports_llext.c + syscall_weakdefs_llext.c + ${syscall_list_h} # Also, some files are written to include/generated/zephyr/syscalls/ COMMAND ${PYTHON_EXECUTABLE} @@ -850,7 +855,8 @@ add_custom_command(OUTPUT include/generated/zephyr/syscall_dispatch.c ${syscall_ --json-file ${syscalls_json} # Read this file --base-output include/generated/zephyr/syscalls # Write to this dir --syscall-dispatch include/generated/zephyr/syscall_dispatch.c # Write this file - --syscall-export-llext include/generated/zephyr/syscall_export_llext.c + --syscall-exports-llext include/generated/zephyr/syscall_exports_llext.c + --syscall-weakdefs-llext syscall_weakdefs_llext.c # compiled in CMake library 'syscall_weakdefs' --syscall-list ${syscall_list_h} $<$:--gen-mrsh-files> ${SYSCALL_LONG_REGISTERS_ARG} @@ -1009,6 +1015,16 @@ else() set(NO_WHOLE_ARCHIVE_LIBS kernel) endif() +if(CONFIG_LLEXT) + # LLEXT exports symbols for all syscalls, including unimplemented ones. + # Weak definitions for these must be added at the end of the link order + # to avoid shadowing actual implementations. + add_library(syscall_weakdefs syscall_weakdefs_llext.c) + add_dependencies(syscall_weakdefs zephyr_generated_headers) + target_link_libraries(syscall_weakdefs zephyr_interface) + list(APPEND NO_WHOLE_ARCHIVE_LIBS syscall_weakdefs) +endif() + get_property(OUTPUT_FORMAT GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT) if (CONFIG_CODE_DATA_RELOCATION) diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index 607445ce129..d2bb3249a81 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -158,10 +158,14 @@ syscall_tracer_void_template = """ """ -exported_template = """ +llext_weakdefs_template = """/* auto-generated by gen_syscalls.py, don't edit */ + +#include +#include + /* * This symbol is placed at address 0 by llext-sections.ld. Its value and - * type is not important, we are only interested in its location + * type is not important, we are only interested in its location. */ static void * const no_syscall_impl Z_GENERIC_SECTION(llext_no_syscall_impl); @@ -171,6 +175,19 @@ static void * const no_syscall_impl Z_GENERIC_SECTION(llext_no_syscall_impl); * an extension requiring them is loaded. */ %s +""" + + +llext_exports_template = """/* auto-generated by gen_syscalls.py, don't edit */ + +/* + * Export the implementation functions of all emitted syscalls. + * Only the symbol names are relevant in this file, they will be + * resolved to the actual implementation functions by the linker. + */ + +/* Symbol declarations */ +%s /* Exported symbols */ %s @@ -435,8 +452,10 @@ 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", + parser.add_argument("-e", "--syscall-exports-llext", help="output C system call export for extensions") + parser.add_argument("-w", "--syscall-weakdefs-llext", + help="output C system call weak definitions") parser.add_argument("-u", "--userspace-only", action="store_true", help="Only generate the userpace path of wrappers") args = parser.parse_args() @@ -498,14 +517,23 @@ def main(): fp.write(table_template % (weak_defines, ",\n\t".join(table_entries))) - if args.syscall_export_llext: - with open(args.syscall_export_llext, "w") as fp: - # Export symbols for emitted syscalls + exported.sort() + + if args.syscall_weakdefs_llext: + with open(args.syscall_weakdefs_llext, "w") as fp: + # Provide weak definitions for all emitted syscalls weak_refs = "\n".join("extern __weak ALIAS_OF(no_syscall_impl) void * const %s;" % e for e in exported) + fp.write(llext_weakdefs_template % weak_refs) + + if args.syscall_exports_llext: + with open(args.syscall_exports_llext, "w") as fp: + # Export symbols for emitted syscalls + extern_refs = "\n".join("extern 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)) + fp.write(llext_exports_template % (extern_refs, exported_symbols)) # Listing header emitted to stdout ids_emit.sort() diff --git a/subsys/llext/llext_export.c b/subsys/llext/llext_export.c index d2d117ec6ff..42fa3410947 100644 --- a/subsys/llext/llext_export.c +++ b/subsys/llext/llext_export.c @@ -16,4 +16,4 @@ EXPORT_SYMBOL(memcmp); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); -#include +#include