llext: fix link order for weak syscall symbols
The weak syscall symbols generated by gen_syscalls.py are currently compiled in the LLEXT subsystem library, which is then linked among all other Zephyr libraries in an unspecified order. This can cause the weak symbols to override the actual syscall implementations, leading to undefined behaviour. To fix this, the currently generated file is split in two elements: - syscall_exports_llext.c contains the EXPORT_SYMBOL directives for all syscalls. This part can be compiled with the LLEXT library and linked among all other Zephyr libraries, and ensures all syscalls symbols are preserved by the linker. - syscall_weakdefs_llext.c contains the weak definitions for all syscalls. This file is compiled in a separate library that is linked last, so that the weak symbols are only used if no other implementation is available. Signed-off-by: Luca Burelli <l.burelli@arduino.cc>
This commit is contained in:
parent
bb417dad1c
commit
78ae035f89
3 changed files with 54 additions and 10 deletions
|
@ -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}
|
||||
$<$<BOOL:${CONFIG_USERSPACE}>:--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)
|
||||
|
|
|
@ -158,10 +158,14 @@ syscall_tracer_void_template = """
|
|||
"""
|
||||
|
||||
|
||||
exported_template = """
|
||||
llext_weakdefs_template = """/* auto-generated by gen_syscalls.py, don't edit */
|
||||
|
||||
#include <zephyr/toolchain.h>
|
||||
#include <zephyr/llext/symbol.h>
|
||||
|
||||
/*
|
||||
* 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()
|
||||
|
|
|
@ -16,4 +16,4 @@ EXPORT_SYMBOL(memcmp);
|
|||
EXPORT_SYMBOL(memcpy);
|
||||
EXPORT_SYMBOL(memset);
|
||||
|
||||
#include <zephyr/syscall_export_llext.c>
|
||||
#include <zephyr/syscall_exports_llext.c>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue