diff --git a/tools/.gitignore b/tools/.gitignore index 957b27157d5..a30ce43ca8d 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -7,6 +7,7 @@ /gencromfs /initialconfig /mkconfig +/mknxflat /mkdeps /cnvwindeps /logparser diff --git a/tools/Makefile.host b/tools/Makefile.host index 3a2926cd659..c378a8d7dae 100644 --- a/tools/Makefile.host +++ b/tools/Makefile.host @@ -39,14 +39,15 @@ all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \ initialconfig$(HOSTEXEEXT) gencromfs$(HOSTEXEEXT) \ convert-comments$(HOSTEXEEXT) lowhex$(HOSTEXEEXT) \ detab$(HOSTEXEEXT) rmcr$(HOSTEXEEXT) incdir$(HOSTEXEEXT) \ - jlink-nuttx$(HOSTDYNEXT) + mknxflat$(HOSTEXEEXT) jlink-nuttx$(HOSTDYNEXT) default: mkconfig$(HOSTEXEEXT) mksyscall$(HOSTEXEEXT) mkdeps$(HOSTEXEEXT) \ cnvwindeps$(HOSTEXEEXT) incdir$(HOSTEXEEXT) ifdef HOSTEXEEXT .PHONY: b16 bdf-converter cmpconfig clean configure kconfig2html mkconfig \ mkdeps mksymtab mksyscall mkversion mkpasswd cnvwindeps nxstyle \ - initialconfig gencromfs convert-comments lowhex detab rmcr incdir + initialconfig gencromfs convert-comments lowhex detab rmcr incdir \ + mknxflat endif ifdef HOSTDYNEXT .PHONY: jlink-nuttx @@ -134,6 +135,18 @@ ifdef HOSTEXEEXT mksymtab: mksymtab$(HOSTEXEEXT) endif +# mknxflat - Generate the thunk file for an NXFLAT module + +MKNXFLAT_SRCS = nxflat/mknxflat.c nxflat/thunk_arm.c nxflat/thunk_thumb2.c + +mknxflat$(HOSTEXEEXT): $(MKNXFLAT_SRCS) + $(Q) $(HOSTCC) $(HOSTCFLAGS) -Inxflat -o mknxflat$(HOSTEXEEXT) \ + $(MKNXFLAT_SRCS) + +ifdef HOSTEXEEXT +mknxflat: mknxflat$(HOSTEXEEXT) +endif + # bdf-converter - Converts a BDF font to the NuttX font format bdf-converter$(HOSTEXEEXT): bdf-converter.c @@ -270,6 +283,8 @@ clean: $(call DELFILE, Make.dep) $(call DELFILE, mkconfig) $(call DELFILE, mkconfig.exe) + $(call DELFILE, mknxflat) + $(call DELFILE, mknxflat.exe) $(call DELFILE, mkdeps) $(call DELFILE, mkdeps.exe) $(call DELFILE, mksymtab) diff --git a/tools/nxflat/dyncall_skeleton_arm.def b/tools/nxflat/dyncall_skeleton_arm.def new file mode 100644 index 00000000000..0dd0951101f --- /dev/null +++ b/tools/nxflat/dyncall_skeleton_arm.def @@ -0,0 +1,251 @@ +/*********************************************************************** + * toolchain/nxflat/arm/dyncall_skeleton.def + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/******************************************************************* + * File Prologue + *******************************************************************/ + +static const char file_prologue[] = + "/*******************************************************************\n" + " *\n" + " * This file contains the dynamic call logic that performs the thunk\n" + " * for outound calls from one module to another.\n" + " *\n" + " * ARM register quick reference:\n" + " *\n" + " * Name Number ARM Procedure Calling Standard Role\n" + " *\n" + " * a1 r0 argument 1/integer result/scratch register/argc\n" + " * a2 r1 argument 2/scratch register/argv\n" + " * a3 r2 argument 3/scratch register/envp\n" + " * a4 r3 argument 4/scratch register\n" + " * v1 r4 register variable\n" + " * v2 r5 register variable\n" + " * v3 r6 register variable\n" + " * v4 r7 register variable\n" + " * v5 r8 register variable\n" + " * sb/v6 r9 static base/register variable\n" + " * sl/v7 r10 stack limit/stack chunk handle/reg. variable\n" + " * fp r11 frame pointer\n" + " * ip r12 scratch register/new-sb in inter-link-unit calls\n" + " * sp r13 lower end of current stack frame\n" + " * lr r14 link address/scratch register\n" + " * pc r15 program counter\n" + " *******************************************************************/\n\n" + "/*******************************************************************\n" + " * Included Files\n" + " *******************************************************************/\n\n" + "/*******************************************************************\n" + " * Definitions\n" + " *******************************************************************/\n\n" + "/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */\n" + "#ifndef __ARM_ARCH\n" + "# ifdef __ARM_ARCH_2__\n" + "# define __ARM_ARCH 2\n" + "# elif defined (__ARM_ARCH_3__) || defined (__ARM_ARCH_3M__)\n" + "# define __ARM_ARCH 3\n" + "# elif defined (__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__)\n" + "# define __ARM_ARCH 4\n" + "# elif defined (__ARM_ARCH_5__) || defined (__ARM_ARCH_5E__) \\\n" + " || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \\\n" + " || defined(__ARM_ARCH_5TEJ__)\n" + "# define __ARM_ARCH 5\n" + "# elif defined (__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \\\n" + " || defined (__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \\\n" + " || defined (__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__)\n" + "# define __ARM_ARCH 6\n" + "# elif defined (__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \\\n" + " || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \\\n" + " || defined(__ARM_ARCH_7EM__)\n" + "# define __ARM_ARCH 7\n" + "# else\n" + "# error unknown arm architecture\n" + "# endif\n" + "#endif\n\n" + "#if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__)\n" + "# define ARCH_HAS_BX\n" + "#endif\n" + "#if __ARM_ARCH > 4\n" + "# define ARCH_HAS_BLX\n" + "#endif\n" + "#if defined(ARCH_HAS_BX)\n" + "#define BX(x) bx\t##x\n" + "#else\n" + "#define BX(x) mov\tpc, ##x\n" + "#endif\n\n"; + +static const char import_prologue[] = ""; + +/******************************************************************* + * Import Function Name String Table + *******************************************************************/ + +static const char import_name_strtab_prologue[] = + "\n/*******************************************************************\n" + " * Import Function Names\n" + " *******************************************************************/\n\n" + "/* These are the names of all of the functions that are imported.\n" + " * Notice that all data associated with the library names is retained\n" + " * in the .text section." + " */\n\n" + "\t.text\n" + "\t.align\t0\n"; + +#define MKIMPSTRTABARG(fn,i) (i), (i), (i), (fn), (i), (i) + +static const char import_name_strtab_format[] = + "\n\t.local\t__dynimport%04d\n" + "\t.type\t__dynimport%04d, object\n\n" + "__dynimport%04d:\n" + "\t.asciz\t\"%s\"\n" + "\t.size\t__dynimport%04d, .-__dynimport%04d\n"; + +/******************************************************************* + * Dyanamic Call Information + *******************************************************************/ + +static const char dynimport_decl_prologue[] = + "\n/*******************************************************************\n" + " * Imported Symbol Table (an array of type struct flat_import)\n" + " *******************************************************************/\n\n" + "/* Notice that, unlike most other arrays in this file, this array\n" + " * is declared to reside in .data. Because of this, there will be\n" + " * per-process instances of this table.\n" + " */\n\n" + "\t.data\n" + "\t.align\t2\n\n" + "\t.global\t__dynimport_begin\n" + "\t.type\t__dynimport_begin, object\n" + "\t.global\t__dynimport_end\n" + "\t.type\t__dynimport_end, object\n\n"; + +#define MKINFODECLARGS(fn, i) (i), (fn), (i) + +static const char dynimport_decl_format[] = + "\t.local\t__dyninfo%04d\t/* Dynamic info for imported symbol %s */\n" + "\t.type\t__dyninfo%04d, object\n"; + +static const char dynimport_array_prologue[] = + "\n__dynimport_begin:\n"; + +#define MKINFOARGS(fn, i) (i), (fn), (i), (i), (i) + +static const char dynimport_array_format[] = + "__dyninfo%04d:\t\t\t/* Dynamic info for imported symbol %s */\n" + "\t.word\t__dynimport%04d\t/* Offset to name of imported function */\n" + "\t.word\t0\t\t/* Resolved address of imported function */\n" + "\t.size\t__dyninfo%04d, .-__dyninfo%04d\n"; + +static const char dynimport_array_epilogue[] = + "__dynimport_end:\n" + "\t.size\t__dynimport_begin, __dynimport_end-__dynimport_begin\n"; + +static const char dyncall_decl_prologue[] = + "\n/*******************************************************************\n" + " * Dynamic Call Logic\n" + " *******************************************************************/\n\n" + "\t.text\n" + "\t.align\t2\n"; + +#define MKCALLARGS(fn, i) (fn), (fn), (fn), (fn), (i), (i), (i), (fn), (fn) + +#ifndef __NO_GOT__ + +static const char dyncall_format[] = + "\n/* Dynamic call logic for imported symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tBX(ip)\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d(GOTOFF)\n" + "\t.size\t%s, .-%s\n"; + +static const char nonreturning_dyncall_format[] = + "\n/* Dynamic call logic for imported, non-returning symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tBX(ip)\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d(GOTOFF)\n" + "\t.size\t%s, .-%s\n"; + +#else + +static const char dyncall_format[] = + "\n/* Dynamic call logic for imported symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tBX(ip)\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d\n" + "\t.size\t%s, .-%s\n"; + +static const char nonreturning_dyncall_format[] = + "\n/* Dynamic call logic for imported, non-returning symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tBX(ip)\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d\n" + "\t.size\t%s, .-%s\n"; + +#endif + +/******************************************************************* + * File Epilogue + *******************************************************************/ + +static const char file_epilogue[] = + "\t.end\n"; + + + + diff --git a/tools/nxflat/dyncall_skeleton_thumb2.def b/tools/nxflat/dyncall_skeleton_thumb2.def new file mode 100644 index 00000000000..5d4b81c126d --- /dev/null +++ b/tools/nxflat/dyncall_skeleton_thumb2.def @@ -0,0 +1,222 @@ +/*********************************************************************** + * toolchain/nxflat/thumb2/dyncall_skeleton.def + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ***********************************************************************/ + +/******************************************************************* + * File Prologue + *******************************************************************/ + +static const char file_prologue[] = + "/*******************************************************************\n" + " *\n" + " * This file contains the dynamic call logic that performs the thunk\n" + " * for outound calls from one module to another.\n" + " *\n" + " * ARM register quick reference:\n" + " *\n" + " * Name Number ARM Procedure Calling Standard Role\n" + " *\n" + " * a1 r0 argument 1/integer result/scratch register/argc\n" + " * a2 r1 argument 2/scratch register/argv\n" + " * a3 r2 argument 3/scratch register/envp\n" + " * a4 r3 argument 4/scratch register\n" + " * v1 r4 register variable\n" + " * v2 r5 register variable\n" + " * v3 r6 register variable\n" + " * v4 r7 register variable\n" + " * v5 r8 register variable\n" + " * sb/v6 r9 static base/register variable\n" + " * sl/v7 r10 stack limit/stack chunk handle/reg. variable\n" + " * fp r11 frame pointer\n" + " * ip r12 scratch register/new-sb in inter-link-unit calls\n" + " * sp r13 lower end of current stack frame\n" + " * lr r14 link address/scratch register\n" + " * pc r15 program counter\n" + " *******************************************************************/\n\n" + "\t.syntax\tunified\n" + "\t.thumb\n\n" + "/*******************************************************************\n" + " * Included Files\n" + " *******************************************************************/\n\n" + "/*******************************************************************\n" + " * Definitions\n" + " *******************************************************************/\n"; + +static const char import_prologue[] = ""; + +/******************************************************************* + * Import Function Name String Table + *******************************************************************/ + +static const char import_name_strtab_prologue[] = + "\n/*******************************************************************\n" + " * Import Function Names\n" + " *******************************************************************/\n\n" + "/* These are the names of all of the functions that are imported.\n" + " * Notice that all data associated with the library names is retained\n" + " * in the .text section." + " */\n\n" + "\t.text\n" + "\t.align\t0\n"; + +#define MKIMPSTRTABARG(fn,i) (i), (i), (i), (fn), (i), (i) + +static const char import_name_strtab_format[] = + "\n\t.local\t__dynimport%04d\n" + "\t.type\t__dynimport%04d, object\n\n" + "__dynimport%04d:\n" + "\t.asciz\t\"%s\"\n" + "\t.size\t__dynimport%04d, .-__dynimport%04d\n"; + +/******************************************************************* + * Dyanamic Call Information + *******************************************************************/ + +static const char dynimport_decl_prologue[] = + "\n/*******************************************************************\n" + " * Imported Symbol Table (an array of type struct flat_import)\n" + " *******************************************************************/\n\n" + "/* Notice that, unlike most other arrays in this file, this array\n" + " * is declared to reside in .data. Because of this, there will be\n" + " * per-process instances of this table.\n" + " */\n\n" + "\t.data\n" + "\t.align\t2\n\n" + "\t.global\t__dynimport_begin\n" + "\t.type\t__dynimport_begin, object\n" + "\t.global\t__dynimport_end\n" + "\t.type\t__dynimport_end, object\n\n"; + +#define MKINFODECLARGS(fn, i) (i), (fn), (i) + +static const char dynimport_decl_format[] = + "\t.local\t__dyninfo%04d\t/* Dynamic info for imported symbol %s */\n" + "\t.type\t__dyninfo%04d, object\n"; + +static const char dynimport_array_prologue[] = + "\n__dynimport_begin:\n"; + +#define MKINFOARGS(fn, i) (i), (fn), (i), (i), (i) + +static const char dynimport_array_format[] = + "__dyninfo%04d:\t\t\t/* Dynamic info for imported symbol %s */\n" + "\t.word\t__dynimport%04d\t/* Offset to name of imported function */\n" + "\t.word\t0\t\t/* Resolved address of imported function */\n" + "\t.size\t__dyninfo%04d, .-__dyninfo%04d\n"; + +static const char dynimport_array_epilogue[] = + "__dynimport_end:\n" + "\t.size\t__dynimport_begin, __dynimport_end-__dynimport_begin\n"; + +static const char dyncall_decl_prologue[] = + "\n/*******************************************************************\n" + " * Dynamic Call Logic\n" + " *******************************************************************/\n\n" + "\t.text\n" + "\t.align\t2\n"; + +#define MKCALLARGS(fn, i) (fn), (fn), (fn), (fn), (i), (i), (i), (fn), (fn) + +#ifndef __NO_GOT__ + +static const char dyncall_format[] = + "\n/* Dynamic call logic for imported symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n" + "\t.thumb_func\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tbx\tip\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d(GOTOFF)\n" + "\t.size\t%s, .-%s\n"; + +static const char nonreturning_dyncall_format[] = + "\n/* Dynamic call logic for imported, non-returning symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n" + "\t.thumb_func\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tbx\tip\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d(GOTOFF)\n" + "\t.size\t%s, .-%s\n"; + +#else + +static const char dyncall_format[] = + "\n/* Dynamic call logic for imported symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n" + "\t.thumb_func\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tbx\tip\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d\n" + "\t.size\t%s, .-%s\n"; + +static const char nonreturning_dyncall_format[] = + "\n/* Dynamic call logic for imported, non-returning symbol %s */\n\n" + "\t.global\t%s\n" + "\t.type\t%s, function\n" + "\t.thumb_func\n\n" + "%s:\n" + "\tldr\tip,.Ldyn%04d\n" + "\tadd\tip,ip,sl\n" + "\tldr\tip,[ip,#4]\n" + "\tbx\tip\n" + ".Ldyn%04d:\n" + "\t.word\t__dyninfo%04d\n" + "\t.size\t%s, .-%s\n"; + +#endif + +/******************************************************************* + * File Epilogue + *******************************************************************/ + +static const char file_epilogue[] = + "\t.end\n"; + + + + diff --git a/tools/nxflat/mknxflat.c b/tools/nxflat/mknxflat.c new file mode 100644 index 00000000000..8208fe1e8fc --- /dev/null +++ b/tools/nxflat/mknxflat.c @@ -0,0 +1,770 @@ +/**************************************************************************** + * tools/nxflat/mknxflat.c + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2009, 2018 Gregory Nutt. All rights reserved. + * SPDX-FileCopyrightText: 2002, 2006 Cadenux, LLC. All rights reserved. + * SPDX-FileContributor: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * mknxflat generates the "thunk" assembly file for an NXFLAT module: one + * stub per imported function, plus the import name string table and the + * per-process __dyninfo array the loader fills in at load time. + * + * This is a port of the tool from the NuttX buildroot NXFLAT toolchain. + * The one substantive change is that the symbol table is read from the ELF + * file directly rather than through libbfd. libbfd is GPL, which an Apache + * project cannot depend on, and it is awkward to obtain besides -- but the + * dependency was never deep: the upstream tool used it only to open the + * file and enumerate symbols, never to relocate or rewrite anything. + * + * The emitted text is unchanged. The format strings live in the .def + * files, which are carried here byte-for-byte from upstream. + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nxflat_thunk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define dbg(format, ...) \ + do \ + { \ + if (verbose) \ + { \ + printf(format, ##__VA_ARGS__); \ + } \ + } \ + while (0) + +/* Just enough of the ELF32 ABI to walk a symbol table. Spelled out here + * rather than pulled from so the tool builds on any host. + */ + +#define EI_NIDENT 16 +#define ELFCLASS32 1 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define SHT_SYMTAB 2 +#define SHT_DYNSYM 11 + +#define SHN_UNDEF 0 + +#define STB_WEAK 2 +#define STT_OBJECT 1 + +#define ELF_ST_BIND(i) ((i) >> 4) +#define ELF_ST_TYPE(i) ((i) & 0x0f) + +#define MAX_EXPORT_NAMES 1024 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct elf32_ehdr_s +{ + unsigned char e_ident[EI_NIDENT]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +}; + +struct elf32_shdr_s +{ + uint32_t sh_name; + uint32_t sh_type; + uint32_t sh_flags; + uint32_t sh_addr; + uint32_t sh_offset; + uint32_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint32_t sh_addralign; + uint32_t sh_entsize; +}; + +struct elf32_sym_s +{ + uint32_t st_name; + uint32_t st_value; + uint32_t st_size; + unsigned char st_info; + unsigned char st_other; + uint16_t st_shndx; +}; + +/* One imported symbol, in symbol table order */ + +struct import_s +{ + char *name; + int is_object; + int is_weak; +}; + +typedef int (*namefunc_type)(const char *name, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Command line settings (counters but treated like booleans) */ + +static int verbose = 0; +static int weak_imports = 0; +static int dsyms = 0; + +/* Characteristics of things */ + +static int calls_nonreturning_functions = 0; + +/* Names of things */ + +static const char *program_name = NULL; +static const char *elf_filename = NULL; +static const char *out_filename = NULL; + +/* The selected architecture's thunk format strings */ + +static const struct nxflat_thunk_s *thunk = NULL; + +/* The imported symbols, in symbol table order */ + +static struct import_s *imports = NULL; +static long number_undefined = 0; + +static int counter; + +/* Big-endian input? ARM is normally little-endian but big-endian ARM + * exists, so honour EI_DATA rather than assuming. + */ + +static int need_swap = 0; + +/**************************************************************************** + * Private constant data + ****************************************************************************/ + +/* This is the list of names of libc and libpthread functions that + * do not return. These may require some special handling -- at a + * minimum, they must tie up resources that can only be released + * when the function returns. + */ + +static const char *const nonreturners[] = +{ + "abort", /* Never returns */ + "exit", /* Never returns */ + "_exit", /* Never returns */ + "longjmp", /* Never returns */ + "_longjmp", /* Never returns */ + "pthread_exit", /* Never returns */ + "siglongjmp", /* Never returns */ + NULL +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: swap16 / swap32 + ****************************************************************************/ + +static uint16_t swap16(uint16_t v) +{ + return need_swap ? (uint16_t)((v >> 8) | (v << 8)) : v; +} + +static uint32_t swap32(uint32_t v) +{ + if (!need_swap) + { + return v; + } + + return ((v & 0x000000fful) << 24) | ((v & 0x0000ff00ul) << 8) | + ((v & 0x00ff0000ul) >> 8) | ((v & 0xff000000ul) >> 24); +} + +/**************************************************************************** + * Name: xread + * + * Description: + * Read exactly nbytes at an absolute offset, or die. + * + ****************************************************************************/ + +static void xread(int fd, void *buffer, size_t nbytes, off_t offset) +{ + ssize_t nread; + + if (lseek(fd, offset, SEEK_SET) == (off_t)-1) + { + fprintf(stderr, "%s: seek to %ld failed: %s\n", + elf_filename, (long)offset, strerror(errno)); + exit(2); + } + + while (nbytes > 0) + { + nread = read(fd, buffer, nbytes); + if (nread < 0) + { + if (errno == EINTR) + { + continue; + } + + fprintf(stderr, "%s: read failed: %s\n", + elf_filename, strerror(errno)); + exit(2); + } + else if (nread == 0) + { + fprintf(stderr, "%s: unexpected end of file\n", elf_filename); + exit(2); + } + + buffer = (char *)buffer + nread; + nbytes -= nread; + } +} + +/**************************************************************************** + * Name: load_imports + * + * Description: + * Collect every undefined, non-object symbol from the ELF file, in symbol + * table order. + * + * The selection rule is the upstream one. Symbol typing is not + * trustworthy here: imported functions are frequently emitted as + * STT_NOTYPE rather than STT_FUNC, while a weakly defined *object* does + * show up as an undefined object. So rather than looking for functions, + * this takes everything undefined that is not explicitly an object. A + * genuinely undefined object would be an error, and is left to the link. + * + ****************************************************************************/ + +static void load_imports(void) +{ + struct elf32_ehdr_s ehdr; + struct elf32_shdr_s *shdrs; + struct elf32_sym_s *syms; + char *strtab; + int wanted = dsyms ? SHT_DYNSYM : SHT_SYMTAB; + int symidx = -1; + size_t nsyms; + size_t strsize; + size_t i; + int fd; + + fd = open(elf_filename, O_RDONLY); + if (fd < 0) + { + fprintf(stderr, "%s: cannot open: %s\n", + elf_filename, strerror(errno)); + exit(2); + } + + xread(fd, &ehdr, sizeof(ehdr), 0); + + if (memcmp(ehdr.e_ident, "\177ELF", 4) != 0) + { + fprintf(stderr, "%s: not an ELF file\n", elf_filename); + exit(2); + } + + if (ehdr.e_ident[4] != ELFCLASS32) + { + fprintf(stderr, "%s: not a 32-bit ELF file\n", elf_filename); + exit(2); + } + + /* Decide whether the host and the object disagree about byte order */ + + { + const uint16_t probe = 1; + int host_le = *(const unsigned char *)&probe; + int obj_le = (ehdr.e_ident[5] == ELFDATA2LSB); + + need_swap = (host_le != obj_le); + } + + /* Re-read the fields that mattered now that byte order is known */ + + ehdr.e_shoff = swap32(ehdr.e_shoff); + ehdr.e_shnum = swap16(ehdr.e_shnum); + ehdr.e_shentsize = swap16(ehdr.e_shentsize); + + if (ehdr.e_shnum == 0 || ehdr.e_shentsize != sizeof(struct elf32_shdr_s)) + { + fprintf(stderr, "%s: no usable section header table\n", elf_filename); + exit(2); + } + + shdrs = malloc((size_t)ehdr.e_shnum * sizeof(struct elf32_shdr_s)); + if (shdrs == NULL) + { + fprintf(stderr, "Failed to allocate section headers\n"); + exit(3); + } + + xread(fd, shdrs, (size_t)ehdr.e_shnum * sizeof(struct elf32_shdr_s), + ehdr.e_shoff); + + for (i = 0; i < ehdr.e_shnum; i++) + { + shdrs[i].sh_type = swap32(shdrs[i].sh_type); + shdrs[i].sh_offset = swap32(shdrs[i].sh_offset); + shdrs[i].sh_size = swap32(shdrs[i].sh_size); + shdrs[i].sh_link = swap32(shdrs[i].sh_link); + shdrs[i].sh_entsize = swap32(shdrs[i].sh_entsize); + + if ((int)shdrs[i].sh_type == wanted && symidx < 0) + { + symidx = (int)i; + } + } + + if (symidx < 0) + { + fprintf(stderr, "%s: no %s section\n", elf_filename, + dsyms ? "dynamic symbol table" : "symbol table"); + exit(2); + } + + if (shdrs[symidx].sh_entsize != sizeof(struct elf32_sym_s)) + { + fprintf(stderr, "%s: unexpected symbol entry size\n", elf_filename); + exit(2); + } + + nsyms = shdrs[symidx].sh_size / sizeof(struct elf32_sym_s); + + syms = malloc(shdrs[symidx].sh_size); + if (syms == NULL) + { + fprintf(stderr, "Failed to allocate symbol table\n"); + exit(3); + } + + xread(fd, syms, shdrs[symidx].sh_size, shdrs[symidx].sh_offset); + + /* The linked string table holds the names */ + + if (shdrs[symidx].sh_link >= ehdr.e_shnum) + { + fprintf(stderr, "%s: symbol table has no string table\n", + elf_filename); + exit(2); + } + + strsize = shdrs[shdrs[symidx].sh_link].sh_size; + strtab = malloc(strsize + 1); + if (strtab == NULL) + { + fprintf(stderr, "Failed to allocate string table\n"); + exit(3); + } + + xread(fd, strtab, strsize, shdrs[shdrs[symidx].sh_link].sh_offset); + strtab[strsize] = '\0'; + + close(fd); + + imports = calloc(nsyms, sizeof(struct import_s)); + if (imports == NULL) + { + fprintf(stderr, "Failed to allocate import table\n"); + exit(3); + } + + for (i = 0; i < nsyms; i++) + { + uint32_t st_name = swap32(syms[i].st_name); + uint32_t st_value = swap32(syms[i].st_value); + uint16_t st_shndx = swap16(syms[i].st_shndx); + unsigned char info = syms[i].st_info; + + if (st_shndx != SHN_UNDEF || st_value != 0 || st_name == 0 || + st_name >= strsize) + { + continue; + } + + if (ELF_ST_TYPE(info) == STT_OBJECT) + { + /* An undefined object is not something a thunk can stand in + * for; leave it to the link to complain. + */ + + continue; + } + + imports[number_undefined].name = &strtab[st_name]; + imports[number_undefined].is_object = 0; + imports[number_undefined].is_weak = + (ELF_ST_BIND(info) == STB_WEAK); + number_undefined++; + } + + free(shdrs); + free(syms); + + dbg("Found %ld undefined symbols\n", number_undefined); +} + +/**************************************************************************** + * Name: traverse_undefined_functions + ****************************************************************************/ + +static int traverse_undefined_functions(void *arg, namefunc_type fn) +{ + long i; + + for (i = 0; i < number_undefined; i++) + { + /* Is it imported as a "weak" symbol? If so, we will process the + * symbol only if we were requested to do so from the command line. + */ + + if (imports[i].is_weak && weak_imports == 0) + { + continue; + } + + if (fn(imports[i].name, arg) != 0) + { + return 1; + } + } + + return 0; +} + +/**************************************************************************** + * Name: put_string + ****************************************************************************/ + +static void put_string(int fd, const char *string) +{ + ssize_t bytes_available = strlen(string); + ssize_t bytes_written = write(fd, string, bytes_available); + + if (bytes_written < 0) + { + fprintf(stderr, + "Failed to write %ld bytes of string to output, errno=%d\n", + (long)bytes_available, errno); + exit(5); + } + else if (bytes_written != bytes_available) + { + fprintf(stderr, "Only wrote %ld of %ld bytes of string to output\n", + (long)bytes_written, (long)bytes_available); + exit(6); + } +} + +/**************************************************************************** + * Name: does_not_return_name + ****************************************************************************/ + +static int does_not_return_name(const char *func_name) +{ + int i; + + for (i = 0; nonreturners[i] != NULL; i++) + { + if (strcmp(func_name, nonreturners[i]) == 0) + { + return 1; + } + } + + return 0; +} + +static int check_nonreturning(const char *func_name, void *arg) +{ + if (does_not_return_name(func_name)) + { + calls_nonreturning_functions = 1; + } + + return 0; +} + +/**************************************************************************** + * Name: put_import_name_strtab / put_dynimport_decl / ... + * + * Description: + * The four emission passes. Each walks the import list in the same + * order, so the %04d counters line up across passes. + * + ****************************************************************************/ + +static int put_import_name(const char *func_name, void *arg) +{ + char buffer[4096]; + int fd = *(int *)arg; + + snprintf(buffer, sizeof(buffer), thunk->import_name_strtab_format, + counter, counter, counter, func_name, counter, counter); + put_string(fd, buffer); + counter++; + return 0; +} + +static int put_dynimport_decl(const char *func_name, void *arg) +{ + char buffer[4096]; + int fd = *(int *)arg; + + snprintf(buffer, sizeof(buffer), thunk->dynimport_decl_format, + counter, func_name, counter); + put_string(fd, buffer); + counter++; + return 0; +} + +static int put_dynimport_array(const char *func_name, void *arg) +{ + char buffer[4096]; + int fd = *(int *)arg; + + snprintf(buffer, sizeof(buffer), thunk->dynimport_array_format, + counter, func_name, counter, counter, counter); + put_string(fd, buffer); + counter++; + return 0; +} + +static int put_dyncall(const char *func_name, void *arg) +{ + char buffer[4096]; + int fd = *(int *)arg; + const char *format; + + if (does_not_return_name(func_name)) + { + format = thunk->nonreturning_dyncall_format; + } + else + { + format = thunk->dyncall_format; + } + + snprintf(buffer, sizeof(buffer), format, + func_name, func_name, func_name, func_name, + counter, counter, counter, func_name, func_name); + put_string(fd, buffer); + counter++; + return 0; +} + +/**************************************************************************** + * Name: show_usage + ****************************************************************************/ + +static void show_usage(void) +{ + fprintf(stderr, "Usage: %s [options] \n\n", program_name); + fprintf(stderr, "Where options are one or more of the following. Note\n"); + fprintf(stderr, "that a space is always required between the option and\n"); + fprintf(stderr, "any following arguments.\n\n"); + fprintf(stderr, " -a \n"); + fprintf(stderr, " Instruction set of the module: arm or thumb2\n"); + fprintf(stderr, " [thumb2]\n"); + fprintf(stderr, " -d Use dynamic symbol table. [symtab]\n"); + fprintf(stderr, " -o \n"); + fprintf(stderr, " Output to [stdout]\n"); + fprintf(stderr, " -v Verbose output [no output]\n"); + fprintf(stderr, " -w Import weakly declared functions, i.e., weakly\n"); + fprintf(stderr, " declared functions are expected to be provided at\n"); + fprintf(stderr, " load-time [not imported]\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/**************************************************************************** + * Name: parse_args + ****************************************************************************/ + +static void parse_args(int argc, char **argv) +{ + const char *arch = "thumb2"; + int opt; + + program_name = argv[0]; + + while ((opt = getopt(argc, argv, "a:do:vw")) != -1) + { + switch (opt) + { + case 'a': + arch = optarg; + break; + + case 'd': + dsyms++; + break; + + case 'o': + out_filename = optarg; + break; + + case 'v': + verbose++; + break; + + case 'w': + weak_imports++; + break; + + default: + show_usage(); + break; + } + } + + if (strcmp(arch, "thumb2") == 0) + { + thunk = &g_thunk_thumb2; + } + else if (strcmp(arch, "arm") == 0) + { + thunk = &g_thunk_arm; + } + else + { + fprintf(stderr, "Unrecognized architecture '%s'\n\n", arch); + show_usage(); + } + + if (optind >= argc) + { + fprintf(stderr, "No ELF file provided\n\n"); + show_usage(); + } + + elf_filename = argv[optind]; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + int fd = 1; + + parse_args(argc, argv); + + if (out_filename != NULL) + { + fd = open(out_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + { + fprintf(stderr, "Failed to open %s: %s\n", out_filename, + strerror(errno)); + exit(4); + } + } + + load_imports(); + + traverse_undefined_functions(NULL, check_nonreturning); + + /* Output the thunk file in the same order the upstream tool used: + * prologue, import name string table, the __dyninfo declarations, the + * __dyninfo array, then the call thunks. + */ + + put_string(fd, thunk->file_prologue); + put_string(fd, thunk->import_prologue); + + put_string(fd, thunk->import_name_strtab_prologue); + counter = 0; + traverse_undefined_functions(&fd, put_import_name); + + put_string(fd, thunk->dynimport_decl_prologue); + counter = 0; + traverse_undefined_functions(&fd, put_dynimport_decl); + + put_string(fd, thunk->dynimport_array_prologue); + counter = 0; + traverse_undefined_functions(&fd, put_dynimport_array); + put_string(fd, thunk->dynimport_array_epilogue); + + put_string(fd, thunk->dyncall_decl_prologue); + counter = 0; + traverse_undefined_functions(&fd, put_dyncall); + + put_string(fd, thunk->file_epilogue); + + if (fd != 1) + { + close(fd); + } + + return 0; +} diff --git a/tools/nxflat/nxflat_thunk.h b/tools/nxflat/nxflat_thunk.h new file mode 100644 index 00000000000..b2870c70cd1 --- /dev/null +++ b/tools/nxflat/nxflat_thunk.h @@ -0,0 +1,79 @@ +/**************************************************************************** + * tools/nxflat/nxflat_thunk.h + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2009, 2018 Gregory Nutt. All rights reserved. + * SPDX-FileCopyrightText: 2002, 2006 Cadenux, LLC. All rights reserved. + * SPDX-FileContributor: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __TOOLS_NXFLAT_NXFLAT_THUNK_H +#define __TOOLS_NXFLAT_NXFLAT_THUNK_H + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The set of format strings that make up one architecture's thunk file. + * + * The upstream tool selected these at compile time through an "arch" + * symlink pointing at either arm/ or thumb2/. A symlink cannot be carried + * in the repository, and one host binary has to serve boards of both + * flavours -- lpc31xx is ARM while lpc17xx, tiva, stm32f1 and rp23xx are + * Thumb-2 -- so the choice moves to a runtime "-a" option instead. The + * .def files themselves are unmodified, so the emitted text is unchanged. + */ + +struct nxflat_thunk_s +{ + const char *file_prologue; + const char *import_prologue; + const char *import_name_strtab_prologue; + const char *import_name_strtab_format; + const char *dynimport_decl_prologue; + const char *dynimport_decl_format; + const char *dynimport_array_prologue; + const char *dynimport_array_format; + const char *dynimport_array_epilogue; + const char *dyncall_decl_prologue; + const char *dyncall_format; + const char *nonreturning_dyncall_format; + const char *file_epilogue; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern const struct nxflat_thunk_s g_thunk_arm; +extern const struct nxflat_thunk_s g_thunk_thumb2; + +#endif /* __TOOLS_NXFLAT_NXFLAT_THUNK_H */ diff --git a/tools/nxflat/thunk_arm.c b/tools/nxflat/thunk_arm.c new file mode 100644 index 00000000000..5c0ba813b4a --- /dev/null +++ b/tools/nxflat/thunk_arm.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * tools/nxflat/thunk_arm.c + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2009, 2018 Gregory Nutt. All rights reserved. + * SPDX-FileCopyrightText: 2002, 2006 Cadenux, LLC. All rights reserved. + * SPDX-FileContributor: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES. See the .def file + * included below, which is carried unmodified from the upstream NuttX + * buildroot NXFLAT toolchain. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nxflat_thunk.h" + +/* The format strings are file-scope statics inside the .def, so each + * architecture gets its own translation unit and the two sets cannot + * collide. The .def is byte-for-byte the upstream file. + */ + +#include "dyncall_skeleton_arm.def" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct nxflat_thunk_s g_thunk_arm = +{ + file_prologue, + import_prologue, + import_name_strtab_prologue, + import_name_strtab_format, + dynimport_decl_prologue, + dynimport_decl_format, + dynimport_array_prologue, + dynimport_array_format, + dynimport_array_epilogue, + dyncall_decl_prologue, + dyncall_format, + nonreturning_dyncall_format, + file_epilogue +}; diff --git a/tools/nxflat/thunk_thumb2.c b/tools/nxflat/thunk_thumb2.c new file mode 100644 index 00000000000..f7d05fc1ccc --- /dev/null +++ b/tools/nxflat/thunk_thumb2.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * tools/nxflat/thunk_thumb2.c + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2009, 2018 Gregory Nutt. All rights reserved. + * SPDX-FileCopyrightText: 2002, 2006 Cadenux, LLC. All rights reserved. + * SPDX-FileContributor: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES. See the .def file + * included below, which is carried unmodified from the upstream NuttX + * buildroot NXFLAT toolchain. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "nxflat_thunk.h" + +/* The format strings are file-scope statics inside the .def, so each + * architecture gets its own translation unit and the two sets cannot + * collide. The .def is byte-for-byte the upstream file. + */ + +#include "dyncall_skeleton_thumb2.def" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +const struct nxflat_thunk_s g_thunk_thumb2 = +{ + file_prologue, + import_prologue, + import_name_strtab_prologue, + import_name_strtab_format, + dynimport_decl_prologue, + dynimport_decl_format, + dynimport_array_prologue, + dynimport_array_format, + dynimport_array_epilogue, + dyncall_decl_prologue, + dyncall_format, + nonreturning_dyncall_format, + file_epilogue +};