casaroli commented on code in PR #19940: URL: https://github.com/apache/nuttx/pull/19940#discussion_r3882618130
########## Documentation/components/tools/fdpic.rst: ########## @@ -0,0 +1,111 @@ +===================================== +fdpic: FDPIC module build tooling +===================================== + +``tools/fdpic`` is everything needed to build an FDPIC module out of tree. A +module is an ELF shared object whose read-only segment the target maps straight +out of flash and executes in place, while its writable segment is copied to RAM +once per running instance. It links against nothing: libc and everything else +are imported from the firmware's exported symbol table at load time. + +These are host tools only. ``apps/examples/fdpicxip`` uses them to rebuild its +committed module blobs, which is what they are in the tree for. The loader that +runs such a module is proposed separately; until it is in, a module built here +has nothing in NuttX to load it. + +Contents +======== + +============================ ================================================== +File Purpose +============================ ================================================== +``nuttx-fdpic.mk`` The module build itself; include it from a + two-line makefile +``fdpic-verify.sh`` Checks a built module's imports resolve against + the firmware +``nuttx-exports.sh`` Turns ``libs/libc/exec_symtab.c`` into a symbol + list +``fdpic-embed.py`` Turns a built module into a C header, for carrying + one inside an image +``build-binutils.sh`` Builds the ``arm-uclinuxfdpiceabi`` binutils, the + one from-source dependency +``crt0.c`` The module start-up file, linked into every + module that is entered +``init-array.ld`` Names the bounds of ``.init_array`` for it +============================ ================================================== + +Building a module +================= + +A whole module is three lines of makefile beside the source. Taking +``apps/examples/fdpicxip/modules/qsorter.c``, which is a module in its own +right, as the source: + +.. code:: makefile + + MODULE = qsorter + SRCS = qsorter.c + + include /path/to/nuttx/tools/fdpic/nuttx-fdpic.mk + +Then: + +.. code:: console + + $ make NUTTX_DIR=/path/to/nuttx + CC crt0.c + CC qsorter.c + LD qsorter.fdpic + OK qsorter.fdpic: FDPIC, entry 0x2a1, 4 imports resolved + +``NUTTX_DIR`` has to be a configured, built tree: the compile needs its headers +and the verify step needs the export table generated into +``libs/libc/exec_symtab.c``. + +Toolchain +========= + +Two toolchains are involved. The stock ``arm-none-eabi`` compiler does the +compiling -- it emits perfectly good FDPIC objects for both C and C++ -- and +``arm-uclinuxfdpiceabi`` **binutils** does the linking, because Review Comment: Done ########## tools/fdpic/crt0.c: ########## @@ -0,0 +1,126 @@ +/**************************************************************************** + * tools/fdpic/crt0.c + * + * 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. + * + ****************************************************************************/ + +/* The start-up file of an FDPIC module, the counterpart of + * arch/<arch>/src/common/crt0.c for a module that the in-tree build + * produces. A module that exec() runs is entered here rather than at main, + * so that its constructors run on the task that runs the module, in that + * task's group and with that task's data base, rather than on whichever + * task happened to call the loader. + * + * Destructors are not registered here. -fno-use-cxa-atexit puts them in + * .fini_array, which the loader walks in libelf_uninit() when the module is + * unloaded, and registering them again would run each one twice. + * + * A shared library is not entered at all, so it does not link this file. + * Its constructors run from libelf_insert() when dlopen() maps it. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdint.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int main(int argc, char *argv[]); +void exit(int status); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* init-array.ld defines these around .init_array. The linker's built-in + * script does not, when it links a shared object. + * + * They are declared hidden so that the compiler reaches them through the + * GOT of this object rather than through a dynamic symbol, which is what + * lets the loader resolve them with an ordinary R_ARM_RELATIVE. + * + * Each entry is a code address rather than a function descriptor: the + * linker resolves .init_array with R_ARM_RELATIVE too, not with + * R_ARM_FUNCDESC_VALUE. + */ + +extern uintptr_t __init_array_start[] __attribute__((visibility("hidden"))); +extern uintptr_t __init_array_end[] __attribute__((visibility("hidden"))); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: call_initializer + * + * Description: + * Enter one .init_array entry. A plain call through a function pointer + * cannot be used: under -mfdpic the compiler would take the entry for a + * function descriptor and load a data base out of the code address. The + * data base is right already, because this runs inside the module. + * + ****************************************************************************/ + +static void call_initializer(uintptr_t entry) +{ + __asm__ __volatile__ + ( + "blx %[entry]\n" + : + : [entry] "r" (entry) + : "r0", "r1", "r2", "r3", "r12", "lr", "cc", "memory" + ); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _start + * + * Description: + * The entry point of a module. Runs the constructors, calls main and + * passes its return value to exit(). + * + * Input Parameters: + * argc - The number of parameters being passed. + * argv - The parameters being passed. + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + +void _start(int argc, char *argv[]) Review Comment: Done -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
