mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
1. The .kasan.unused and .kasan.global sections contain compiler-generated data with the WRITE flag (.data..LASAN*), but the linker script placed them before .text without specifying a memory region. The linker could not put writable sections into the read-only ROM (rx) region, so it silently placed them at 0x40000000 in RAM, creating an extra LOAD segment that conflicts with QEMU virt's RAM layout and causes boot failure. 2. The .kasan.global should be placed before .data because .data patten (*(.data*)) includes .kasan.global pattern (*(.data..LASAN0)), and it cause kasan_global.py cannot find .kasan.global section to generate the g_global_region array. 3. Move .kasan.shadows from before .text to after .rodata. Placing it before .text causes .text to shift when .kasan.shadows transitions from empty (pass 1) to populated (pass 2+), preventing the multi-pass link addresses from converging. After .rodata it does not affect any upstream section addresses. 4. Add CMake post-build step to strip .kasan.unused and .kasan.global sections from the final binary, matching the Makefile build behavior. Signed-off-by: leisiji <2265215145@qq.com>
180 lines
6.9 KiB
CMake
180 lines
6.9 KiB
CMake
# ##############################################################################
|
|
# cmake/nuttx_multiple_link.cmake
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
|
# license agreements. See the NOTICE file distributed with this work for
|
|
# additional information regarding copyright ownership. The ASF licenses this
|
|
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
|
# use this file except in compliance with the License. You may obtain a copy of
|
|
# the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations under
|
|
# the License.
|
|
#
|
|
# ##############################################################################
|
|
|
|
# create an empty allsyms source file for `nuttx`
|
|
if(CONFIG_ALLSYMS)
|
|
set(ALLSYMS_SOURCE ${CMAKE_BINARY_DIR}/allsyms_empty.c)
|
|
add_custom_command(
|
|
OUTPUT ${ALLSYMS_SOURCE}
|
|
COMMAND ${NUTTX_DIR}/tools/mkallsyms.py nuttx.empty ${ALLSYMS_SOURCE}
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMENT "Generating allsyms_empty.c")
|
|
add_custom_target(generate_empty_allsyms DEPENDS ${ALLSYMS_SOURCE})
|
|
add_dependencies(nuttx generate_empty_allsyms)
|
|
|
|
target_sources(nuttx PRIVATE ${ALLSYMS_SOURCE})
|
|
set(ALLSYMS_INCDIR ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include)
|
|
set_source_files_properties(${ALLSYMS_SOURCE} PROPERTIES INCLUDE_DIRECTORIES
|
|
"${ALLSYMS_INCDIR}")
|
|
endif()
|
|
|
|
if(CONFIG_MM_KASAN_GLOBAL)
|
|
set(KASAN_GLOBAL_SOURCE ${CMAKE_BINARY_DIR}/kasan_global.c)
|
|
add_custom_command(
|
|
OUTPUT ${KASAN_GLOBAL_SOURCE}
|
|
COMMAND ${NUTTX_DIR}/tools/kasan_global.py -e nuttx.empty -o
|
|
${KASAN_GLOBAL_SOURCE} -a ${CONFIG_MM_KASAN_GLOBAL_ALIGN}
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMENT "Generating kasan_global.c")
|
|
add_custom_target(generate_empty_kasan_global DEPENDS ${KASAN_GLOBAL_SOURCE})
|
|
add_dependencies(nuttx generate_empty_kasan_global)
|
|
|
|
target_sources(nuttx PRIVATE ${KASAN_GLOBAL_SOURCE})
|
|
set(KASAN_GLOBAL_INCDIR ${CMAKE_SOURCE_DIR}/include
|
|
${CMAKE_BINARY_DIR}/include)
|
|
set_source_files_properties(
|
|
${KASAN_GLOBAL_SOURCE} PROPERTIES INCLUDE_DIRECTORIES
|
|
"${KASAN_GLOBAL_INCDIR}")
|
|
endif()
|
|
|
|
# ~~~
|
|
# define_multiple_link_target
|
|
#
|
|
# Description:
|
|
# Wrapper of cmake declaration of nuttx executable
|
|
# in order to implement ALLSYMS.
|
|
#
|
|
# When declaring the target to be `nuttx`,
|
|
# create an empty allsyms source file for it;
|
|
# When the target is declared as something else,
|
|
# the link behavior of the `nuttx` target is cloned
|
|
# and added to actually generate the allsyms file.
|
|
#
|
|
# Parameters:
|
|
# inter_target : declaration of target
|
|
# dep_target : targets which depends on
|
|
# linktimes : link times of the target
|
|
# ~~~
|
|
|
|
macro(define_multiple_link_target inter_target dep_target linktimes)
|
|
set(MULTIPLE_LINK_SOURCES_${linktimes})
|
|
if(CONFIG_ALLSYMS)
|
|
set(LINK_ALLSYMS_SOURCE allsyms_${linktimes}.c)
|
|
list(APPEND MULTIPLE_LINK_SOURCES_${linktimes} ${LINK_ALLSYMS_SOURCE})
|
|
add_custom_command(
|
|
OUTPUT ${LINK_ALLSYMS_SOURCE} POST_BUILD
|
|
COMMAND ${NUTTX_DIR}/tools/mkallsyms.py ${CMAKE_BINARY_DIR}/${dep_target}
|
|
${LINK_ALLSYMS_SOURCE}
|
|
DEPENDS ${dep_target}
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMAND_EXPAND_LISTS)
|
|
endif()
|
|
|
|
if(CONFIG_MM_KASAN_GLOBAL)
|
|
set(LINK_KASAN_GLOBAL_SOURCE kasan_global_${linktimes}.c)
|
|
list(APPEND MULTIPLE_LINK_SOURCES_${linktimes} ${LINK_KASAN_GLOBAL_SOURCE})
|
|
add_custom_command(
|
|
OUTPUT ${LINK_KASAN_GLOBAL_SOURCE} POST_BUILD
|
|
COMMAND
|
|
${NUTTX_DIR}/tools/kasan_global.py -e ${CMAKE_BINARY_DIR}/${dep_target}
|
|
-o ${LINK_KASAN_GLOBAL_SOURCE} -a ${CONFIG_MM_KASAN_GLOBAL_ALIGN}
|
|
DEPENDS ${dep_target}
|
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
|
COMMAND_EXPAND_LISTS)
|
|
endif()
|
|
|
|
# relink target with allsysm.c which generated by the elf of the previous
|
|
# phase
|
|
add_executable(
|
|
${inter_target}
|
|
${MULTIPLE_LINK_SOURCES_${linktimes}}
|
|
$<FILTER:$<TARGET_OBJECTS:nuttx>,EXCLUDE,allsyms_empty|kasan_global>)
|
|
|
|
# relink target and nuttx have exactly the same configuration
|
|
target_include_directories(
|
|
${inter_target} SYSTEM PUBLIC ${CMAKE_SOURCE_DIR}/include
|
|
${CMAKE_BINARY_DIR}/include)
|
|
target_compile_definitions(
|
|
${inter_target} PRIVATE $<TARGET_PROPERTY:nuttx,NUTTX_KERNEL_DEFINITIONS>)
|
|
target_compile_options(
|
|
${inter_target}
|
|
PRIVATE $<TARGET_PROPERTY:nuttx,NUTTX_KERNEL_COMPILE_OPTIONS>)
|
|
target_link_options(${inter_target} PRIVATE
|
|
$<TARGET_PROPERTY:nuttx,LINK_OPTIONS>)
|
|
target_link_libraries(
|
|
${inter_target}
|
|
PRIVATE $<TARGET_GENEX_EVAL:nuttx,$<TARGET_PROPERTY:nuttx,LINK_LIBRARIES>>)
|
|
endmacro()
|
|
|
|
# allsyms link phase 1 with generated allsyms source file
|
|
define_multiple_link_target(first_link nuttx first)
|
|
# allsyms link phase 2 since the table offset may changed
|
|
define_multiple_link_target(second_link first_link second)
|
|
# allsyms link phase 3 since the table offset may changed
|
|
define_multiple_link_target(final_nuttx second_link final)
|
|
|
|
# fixing timing dependencies
|
|
add_dependencies(nuttx_post final_nuttx)
|
|
|
|
# Strip .kasan.unused and .kasan.global sections from the final binary. These
|
|
# sections are only needed during the intermediate link passes for
|
|
# kasan_global.py to extract global variable descriptors. At runtime they sit at
|
|
# the start of RAM (0x40000000) and conflict with QEMU's DTB placement.
|
|
if(CONFIG_MM_KASAN_GLOBAL)
|
|
add_custom_command(
|
|
TARGET final_nuttx
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_OBJCOPY} -R .kasan.unused -R .kasan.global final_nuttx
|
|
COMMENT "Stripping .kasan.unused and .kasan.global sections")
|
|
endif()
|
|
|
|
# finally use final_nuttx to overwrite the already generated nuttx
|
|
add_custom_command(
|
|
TARGET final_nuttx
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different final_nuttx nuttx DEPENDS
|
|
final_nuttx
|
|
COMMENT "Overwrite nuttx with final_nuttx")
|
|
|
|
# regenerate binary outputs in different formats (.bin, .hex, etc)
|
|
if(CONFIG_INTELHEX_BINARY)
|
|
add_custom_command(
|
|
TARGET final_nuttx
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_OBJCOPY} -O ihex final_nuttx nuttx.hex DEPENDS nuttx-hex
|
|
COMMENT "Regenerate nuttx.hex")
|
|
|
|
endif()
|
|
if(CONFIG_MOTOROLA_SREC)
|
|
add_custom_command(
|
|
TARGET final_nuttx
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_OBJCOPY} -O srec final_nuttx nuttx.srec DEPENDS nuttx-srec
|
|
COMMENT "Regenerate nuttx.srec")
|
|
endif()
|
|
if(CONFIG_RAW_BINARY)
|
|
add_custom_command(
|
|
TARGET final_nuttx
|
|
POST_BUILD
|
|
COMMAND ${CMAKE_OBJCOPY} -O binary final_nuttx nuttx.bin DEPENDS nuttx-bin
|
|
COMMENT "Regenerate nuttx.bin")
|
|
endif()
|