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 */
