This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 31acf10057f5244fe2dfa9c712176a02284b7190
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Sep 27 11:56:10 2026 +0200

    tools/nxflat: Split the ELF reader out of mknxflat.
    
    The converter that follows reads the same objects as mknxflat, so the reader
    goes into a file of its own before it gains a second user.  nxflat_elf.c
    normalises the tables that describe the object -- the headers, the symbols,
    the relocation entries -- into the host's order, and leaves the section
    contents alone, because those are the target's bytes and the tools write 
them
    out again.  A tool reads a field without knowing whose order it arrived in.
    
    The -d option goes with it.  It chose a dynamic symbol table, which the ld 
-r
    object these tools convert does not have, and which the NXFLAT loader cannot
    use anyway: imports reach a module through the array mknxflat generates.
    
    The output is unchanged.  The thunk mknxflat generates for each of the 
eleven
    modules of apps/examples/nxflat/tests is byte identical to the one the
    previous version generated.
    
    Assisted-by: Claude Opus 5 (1M context) <[email protected]>
    Signed-off-by: Marco Casaroli <[email protected]>
---
 tools/Makefile.host       |   3 +-
 tools/nxflat/mknxflat.c   | 327 +++++++---------------------------------------
 tools/nxflat/nxflat_elf.c | 263 +++++++++++++++++++++++++++++++++++++
 tools/nxflat/nxflat_elf.h | 171 ++++++++++++++++++++++++
 4 files changed, 481 insertions(+), 283 deletions(-)

diff --git a/tools/Makefile.host b/tools/Makefile.host
index c378a8d7dae..70cff7ce602 100644
--- a/tools/Makefile.host
+++ b/tools/Makefile.host
@@ -137,7 +137,8 @@ endif
 
 # mknxflat - Generate the thunk file for an NXFLAT module
 
-MKNXFLAT_SRCS = nxflat/mknxflat.c nxflat/thunk_arm.c nxflat/thunk_thumb2.c
+MKNXFLAT_SRCS = nxflat/mknxflat.c nxflat/thunk_arm.c nxflat/thunk_thumb2.c \
+  nxflat/nxflat_elf.c
 
 mknxflat$(HOSTEXEEXT): $(MKNXFLAT_SRCS)
        $(Q) $(HOSTCC) $(HOSTCFLAGS) -Inxflat -o mknxflat$(HOSTEXEEXT) \
diff --git a/tools/nxflat/mknxflat.c b/tools/nxflat/mknxflat.c
index 467e2daa290..718f2f4b7dc 100644
--- a/tools/nxflat/mknxflat.c
+++ b/tools/nxflat/mknxflat.c
@@ -32,6 +32,8 @@
  * dependency was never deep: the upstream tool used it only to open the
  * file and enumerate symbols, never to relocate or rewrite anything.
  *
+ * The reading itself is in nxflat_elf.c, which ldnxflat uses as well.
+ *
  * The emitted text is unchanged.  The format strings live in the .def
  * files, which are carried here byte-for-byte from upstream.
  ****************************************************************************/
@@ -50,8 +52,29 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include "nxflat_elf.h"
 #include "nxflat_thunk.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define STB_WEAK                2
+#define MAX_EXPORT_NAMES        1024
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* One imported symbol, in symbol table order */
+
+struct import_s
+{
+  const char *name;
+  int   is_object;
+  int   is_weak;
+};
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -71,78 +94,6 @@
  */
 
 #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
-{
-  const char *name;
-  int   is_object;
-  int   is_weak;
-};
-
 typedef int (*namefunc_type)(const char *name, void *arg);
 
 /****************************************************************************
@@ -153,7 +104,6 @@ typedef int (*namefunc_type)(const char *name, void *arg);
 
 static int verbose = 0;
 static int weak_imports = 0;
-static int dsyms = 0;
 
 /* Characteristics of things */
 
@@ -176,12 +126,6 @@ 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
  ****************************************************************************/
@@ -208,70 +152,6 @@ static const char *const nonreturners[] =
  * 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
  *
@@ -290,136 +170,29 @@ static void xread(int fd, void *buffer, size_t nbytes, 
off_t offset)
 
 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;
+  struct nxflat_elf_s elf;
+  size_t strsize = 0;
   size_t i;
-  uint16_t probe;
-  int host_le;
-  int obj_le;
-  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 */
-
-  probe   = 1;
-  host_le = *(const unsigned char *)&probe;
-  obj_le  = (ehdr.e_ident[5] == ELFDATA2LSB);
-
-  need_swap = (host_le != obj_le);
+  nxflat_elf_read(&elf, elf_filename, program_name);
 
-  /* 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);
+  /* The size of the string table the symbols point into, which bounds
+   * st_name.  nxflat_elf_read() has located the table itself.
+   */
 
-  for (i = 0; i < ehdr.e_shnum; i++)
+  for (i = 0; i < elf.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)
+      if (elf.shdr[i].sh_type == SHT_SYMTAB)
         {
-          symidx = (int)i;
+          strsize = elf.shdr[elf.shdr[i].sh_link].sh_size;
+          break;
         }
     }
 
-  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 + 1, sizeof(struct import_s));
+  imports = malloc((elf.nsyms + 1) * sizeof(struct import_s));
   if (imports == NULL)
     {
-      fprintf(stderr, "Failed to allocate import table\n");
+      fprintf(stderr, "Failed to allocate imports\n");
       exit(3);
     }
 
@@ -434,20 +207,18 @@ static void load_imports(void)
   imports[0].is_weak   = 0;
   number_undefined     = 1;
 
-  for (i = 0; i < nsyms; i++)
+  for (i = 0; i < elf.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;
+      const struct elf32_sym_s *sym = &elf.syms[i];
+      unsigned char info = sym->st_info;
 
-      if (st_shndx != SHN_UNDEF || st_value != 0 || st_name == 0 ||
-          st_name >= strsize)
+      if (sym->st_shndx != SHN_UNDEF || sym->st_value != 0 ||
+          sym->st_name == 0 || sym->st_name >= strsize)
         {
           continue;
         }
 
-      if (ELF_ST_TYPE(info) == STT_OBJECT)
+      if (ELF32_ST_TYPE(info) == STT_OBJECT)
         {
           /* An undefined object is not something a thunk can stand in
            * for; leave it to the link to complain.
@@ -456,16 +227,13 @@ static void load_imports(void)
           continue;
         }
 
-      imports[number_undefined].name = &strtab[st_name];
+      imports[number_undefined].name      = elf.strtab + sym->st_name;
       imports[number_undefined].is_object = 0;
-      imports[number_undefined].is_weak =
-        (ELF_ST_BIND(info) == STB_WEAK);
+      imports[number_undefined].is_weak   =
+        (ELF32_ST_BIND(info) == STB_WEAK);
       number_undefined++;
     }
 
-  free(shdrs);
-  free(syms);
-
   dbg("Found %ld undefined symbols\n", number_undefined);
 }
 
@@ -631,7 +399,6 @@ static void show_usage(void)
   fprintf(stderr, "  -a <arch>\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 <out-filename>\n");
   fprintf(stderr, "     Output to <out-filename> [stdout]\n");
   fprintf(stderr, "  -v Verbose output [no output]\n");
@@ -653,7 +420,7 @@ static void parse_args(int argc, char **argv)
 
   program_name = argv[0];
 
-  while ((opt = getopt(argc, argv, "a:do:vw")) != -1)
+  while ((opt = getopt(argc, argv, "a:o:vw")) != -1)
     {
       switch (opt)
         {
@@ -661,10 +428,6 @@ static void parse_args(int argc, char **argv)
             arch = optarg;
             break;
 
-          case 'd':
-            dsyms++;
-            break;
-
           case 'o':
             out_filename = optarg;
             break;
diff --git a/tools/nxflat/nxflat_elf.c b/tools/nxflat/nxflat_elf.c
new file mode 100644
index 00000000000..18731d10b5b
--- /dev/null
+++ b/tools/nxflat/nxflat_elf.c
@@ -0,0 +1,263 @@
+/****************************************************************************
+ * tools/nxflat/nxflat_elf.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Reading the object is the one thing mknxflat and ldnxflat both do, so they
+ * do it here.  The two also used to disagree about byte order: one swapped
+ * the fields it read, the other refused anything but little endian.
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "nxflat_elf.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static bool g_swap;            /* The object disagrees with this host */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static uint16_t swap16(uint16_t v)
+{
+  return g_swap ? (uint16_t)((v >> 8) | (v << 8)) : v;
+}
+
+static uint32_t swap32(uint32_t v)
+{
+  if (!g_swap)
+    {
+      return v;
+    }
+
+  return ((v >> 24) & 0x000000ff) | ((v >> 8) & 0x0000ff00) |
+         ((v << 8) & 0x00ff0000) | ((v << 24) & 0xff000000);
+}
+
+static void elf_fail(const char *program, const char *path, const char *why)
+{
+  fprintf(stderr, "%s: %s: %s\n", program, path, why);
+  exit(2);
+}
+
+/****************************************************************************
+ * Name: normalise
+ *
+ * Description:
+ *   Put every table that describes the object into the host's byte order.
+ *   The section contents are not touched: they belong to the target.
+ *
+ ****************************************************************************/
+
+static void normalise(struct nxflat_elf_s *elf)
+{
+  size_t i;
+  size_t j;
+
+  elf->ehdr->e_type      = swap16(elf->ehdr->e_type);
+  elf->ehdr->e_machine   = swap16(elf->ehdr->e_machine);
+  elf->ehdr->e_entry     = swap32(elf->ehdr->e_entry);
+  elf->ehdr->e_shoff     = swap32(elf->ehdr->e_shoff);
+  elf->ehdr->e_shentsize = swap16(elf->ehdr->e_shentsize);
+  elf->ehdr->e_shnum     = swap16(elf->ehdr->e_shnum);
+  elf->ehdr->e_shstrndx  = swap16(elf->ehdr->e_shstrndx);
+
+  elf->shdr = (struct elf32_shdr_s *)(elf->img + elf->ehdr->e_shoff);
+
+  for (i = 0; i < elf->ehdr->e_shnum; i++)
+    {
+      struct elf32_shdr_s *s = &elf->shdr[i];
+
+      s->sh_name      = swap32(s->sh_name);
+      s->sh_type      = swap32(s->sh_type);
+      s->sh_flags     = swap32(s->sh_flags);
+      s->sh_addr      = swap32(s->sh_addr);
+      s->sh_offset    = swap32(s->sh_offset);
+      s->sh_size      = swap32(s->sh_size);
+      s->sh_link      = swap32(s->sh_link);
+      s->sh_info      = swap32(s->sh_info);
+      s->sh_addralign = swap32(s->sh_addralign);
+      s->sh_entsize   = swap32(s->sh_entsize);
+    }
+
+  /* The symbol and relocation tables describe the object too.  Everything
+   * else is left alone.
+   */
+
+  for (i = 0; i < elf->ehdr->e_shnum; i++)
+    {
+      struct elf32_shdr_s *s = &elf->shdr[i];
+
+      if (s->sh_type == SHT_SYMTAB && s->sh_entsize == sizeof(*elf->syms))
+        {
+          struct elf32_sym_s *syms =
+            (struct elf32_sym_s *)(elf->img + s->sh_offset);
+
+          for (j = 0; j < s->sh_size / sizeof(*syms); j++)
+            {
+              syms[j].st_name  = swap32(syms[j].st_name);
+              syms[j].st_value = swap32(syms[j].st_value);
+              syms[j].st_size  = swap32(syms[j].st_size);
+              syms[j].st_shndx = swap16(syms[j].st_shndx);
+            }
+        }
+      else if (s->sh_type == SHT_REL &&
+               s->sh_entsize == sizeof(struct elf32_rel_s))
+        {
+          struct elf32_rel_s *rel =
+            (struct elf32_rel_s *)(elf->img + s->sh_offset);
+
+          for (j = 0; j < s->sh_size / sizeof(*rel); j++)
+            {
+              rel[j].r_offset = swap32(rel[j].r_offset);
+              rel[j].r_info   = swap32(rel[j].r_info);
+            }
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void nxflat_elf_read(struct nxflat_elf_s *elf, const char *path,
+                     const char *program)
+{
+  struct stat st;
+  uint16_t probe = 1;
+  bool host_le;
+  int symidx = -1;
+  size_t i;
+  int fd;
+
+  memset(elf, 0, sizeof(*elf));
+
+  fd = open(path, O_RDONLY);
+  if (fd < 0 || fstat(fd, &st) < 0)
+    {
+      elf_fail(program, path, strerror(errno));
+    }
+
+  elf->size = (size_t)st.st_size;
+  elf->img  = malloc(elf->size);
+  if (elf->img == NULL)
+    {
+      elf_fail(program, path, "out of memory");
+    }
+
+  if (read(fd, elf->img, elf->size) != (ssize_t)elf->size)
+    {
+      elf_fail(program, path, strerror(errno));
+    }
+
+  close(fd);
+
+  if (elf->size < sizeof(struct elf32_ehdr_s) ||
+      memcmp(elf->img, "\177ELF", 4) != 0)
+    {
+      elf_fail(program, path, "not an ELF file");
+    }
+
+  elf->ehdr = (struct elf32_ehdr_s *)elf->img;
+
+  if (elf->ehdr->e_ident[4] != ELFCLASS32)
+    {
+      elf_fail(program, path, "not a 32-bit ELF file");
+    }
+
+  if (elf->ehdr->e_ident[5] != ELFDATA2LSB &&
+      elf->ehdr->e_ident[5] != ELFDATA2MSB)
+    {
+      elf_fail(program, path, "has no byte order");
+    }
+
+  elf->littleendian = elf->ehdr->e_ident[5] == ELFDATA2LSB;
+
+  host_le = *(const unsigned char *)&probe != 0;
+  g_swap  = host_le != elf->littleendian;
+
+  normalise(elf);
+
+  if (elf->ehdr->e_shnum == 0 ||
+      elf->ehdr->e_shentsize != sizeof(struct elf32_shdr_s))
+    {
+      elf_fail(program, path, "has no usable section header table");
+    }
+
+  elf->shstrtab = (const char *)
+                  (elf->img + elf->shdr[elf->ehdr->e_shstrndx].sh_offset);
+
+  /* The static symbol table.  There is no dynamic one: ld -r does not make
+   * .dynsym, and NXFLAT has no use for it -- imports reach a module through
+   * the array mknxflat generates.
+   */
+
+  for (i = 0; i < elf->ehdr->e_shnum; i++)
+    {
+      if (elf->shdr[i].sh_type == SHT_SYMTAB)
+        {
+          symidx = (int)i;
+          break;
+        }
+    }
+
+  if (symidx < 0)
+    {
+      elf_fail(program, path, "has no symbol table");
+    }
+
+  if (elf->shdr[symidx].sh_entsize != sizeof(struct elf32_sym_s))
+    {
+      elf_fail(program, path, "has symbols of an unexpected size");
+    }
+
+  if (elf->shdr[symidx].sh_link >= elf->ehdr->e_shnum)
+    {
+      elf_fail(program, path, "has a symbol table with no names");
+    }
+
+  elf->syms   = (struct elf32_sym_s *)
+                (elf->img + elf->shdr[symidx].sh_offset);
+  elf->nsyms  = elf->shdr[symidx].sh_size / sizeof(struct elf32_sym_s);
+  elf->strtab = (const char *)
+                (elf->img + elf->shdr[elf->shdr[symidx].sh_link].sh_offset);
+}
+
+const char *nxflat_elf_symname(const struct nxflat_elf_s *elf,
+                               const struct elf32_sym_s *sym)
+{
+  return sym->st_name != 0 ? elf->strtab + sym->st_name : "";
+}
diff --git a/tools/nxflat/nxflat_elf.h b/tools/nxflat/nxflat_elf.h
new file mode 100644
index 00000000000..114ed128728
--- /dev/null
+++ b/tools/nxflat/nxflat_elf.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+ * tools/nxflat/nxflat_elf.h
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __TOOLS_NXFLAT_NXFLAT_ELF_H
+#define __TOOLS_NXFLAT_NXFLAT_ELF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* ELF32, declared here and not taken from a host elf.h: macOS has none, and
+ * a tool that writes a target's binary should not use the host's idea of the
+ * format.
+ */
+
+#define ELFCLASS32              1
+#define ELFDATA2LSB             1
+#define ELFDATA2MSB             2
+
+#define ET_REL                  1
+#define EM_ARM                  40
+
+#define SHT_SYMTAB              2
+#define SHT_NOBITS              8
+#define SHT_REL                 9
+
+#define SHF_WRITE               0x1
+#define SHF_ALLOC               0x2
+#define SHF_EXECINSTR           0x4
+
+#define SHN_UNDEF               0
+#define SHN_COMMON              0xfff2
+
+#define STT_NOTYPE              0
+#define STT_OBJECT              1
+#define STT_FUNC                2
+
+#define ELF32_R_SYM(i)          ((i) >> 8)
+#define ELF32_R_TYPE(i)         ((i) & 0xff)
+#define ELF32_ST_TYPE(i)        ((i) & 0x0f)
+#define ELF32_ST_BIND(i)        ((i) >> 4)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct elf32_ehdr_s
+{
+  unsigned char e_ident[16];
+  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;
+};
+
+struct elf32_rel_s
+{
+  uint32_t r_offset;
+  uint32_t r_info;
+};
+
+/* One object, read and put into the host's byte order.
+ *
+ * The tables that describe it -- headers, symbols, relocation entries --
+ * are normalised, so a tool reads a field without asking whose byte order
+ * it is in.  Section contents are not: they are the target's bytes, and are
+ * written out again as they were read.
+ */
+
+struct nxflat_elf_s
+{
+  uint8_t *img;                /* The file */
+  size_t   size;
+  bool     littleendian;       /* The byte order the object's contents are in 
*/
+  struct elf32_ehdr_s *ehdr;
+  struct elf32_shdr_s *shdr;   /* e_shnum of them */
+  const char *shstrtab;
+  struct elf32_sym_s  *syms;   /* The static symbol table */
+  size_t      nsyms;
+  const char *strtab;          /* The names those symbols point into */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxflat_elf_read
+ *
+ * Description:
+ *   Read one ELF32 object and locate its section headers, symbol table and
+ *   string tables.  A bad file is reported against program and the tool
+ *   exits; neither tool has anything else to try.
+ *
+ ****************************************************************************/
+
+void nxflat_elf_read(struct nxflat_elf_s *elf, const char *path,
+                     const char *program);
+
+/****************************************************************************
+ * Name: nxflat_elf_symname
+ *
+ * Description:
+ *   The name of a symbol, or "" for one that has none.
+ *
+ ****************************************************************************/
+
+const char *nxflat_elf_symname(const struct nxflat_elf_s *elf,
+                               const struct elf32_sym_s *sym);
+
+#endif /* __TOOLS_NXFLAT_NXFLAT_ELF_H */

Reply via email to