summaryrefslogtreecommitdiff
path: root/misc/buildroot/toolchain/nxflat/readxflat.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-18 17:14:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-18 17:14:13 +0000
commit050865808bfb56aa3f3dee42157779cf47b16f0e (patch)
tree5d14751d56799e813097236560ee020447470007 /misc/buildroot/toolchain/nxflat/readxflat.c
parentd12b92e21445508bcb0b8acff9b03e2c71b9da71 (diff)
downloadnuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.tar.gz
nuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.tar.bz2
nuttx-050865808bfb56aa3f3dee42157779cf47b16f0e.zip
First rough port of XFLAT tools
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1903 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'misc/buildroot/toolchain/nxflat/readxflat.c')
-rw-r--r--misc/buildroot/toolchain/nxflat/readxflat.c669
1 files changed, 669 insertions, 0 deletions
diff --git a/misc/buildroot/toolchain/nxflat/readxflat.c b/misc/buildroot/toolchain/nxflat/readxflat.c
new file mode 100644
index 000000000..d4131bc75
--- /dev/null
+++ b/misc/buildroot/toolchain/nxflat/readxflat.c
@@ -0,0 +1,669 @@
+/***********************************************************************
+ * toolchain/nxflat/readnxflat.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Modified from readxflat (see http://xflat.org):
+ *
+ * Copyright (c) 2002, 2006, Cadenux, LLC. All rights reserved.
+ * Copyright (c) 2002, 2006, Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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.
+ *
+ ***********************************************************************/
+
+/***********************************************************************
+ * Compilation Flags
+ ***********************************************************************/
+
+#define SWAP_BYTES 1
+
+/***********************************************************************
+ * Included Files
+ ***********************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netinet/in.h> /* ntohl and friends */
+#include "nxflat.h"
+
+/***********************************************************************
+ * Compilation Switches
+ ***********************************************************************/
+
+/* #define RELOCS_IN_NETWORK_ORDER */
+
+/***********************************************************************
+ * Definitions
+ ***********************************************************************/
+#define NXFLAT_HDR_SIZE sizeof(struct nxflat_hdr_s)
+
+/***********************************************************************
+ * Private Data
+ ***********************************************************************/
+static const char *program_name;
+static const char *nxflat_filename;
+
+static int dump_header = 0;
+static int dump_relocs = 0;
+static int dump_imports = 0;
+static int dump_text = 0;
+static int dump_data = 0;
+static int verbose = 0;
+
+static int num_errors = 0;
+
+#ifdef ARCH_BIG_ENDIAN
+static int big_endian = 1; /* Assume big-endian */
+#else
+static int big_endian = 0; /* Assume little-endian */
+#endif
+
+/***********************************************************************
+ * Private Constant Data
+ ***********************************************************************/
+
+static const char unknown[] = "UNKNOWN";
+
+static const char header_reloc_none[] = "RELOC_NONE";
+static const char header_reloc_text[] = "RELOC_TEXT";
+static const char header_reloc_data[] = "RELOC_DATA";
+static const char header_reloc_bss[] = "RELOC_BSS";
+
+static const char *reloc_type_string[] = {
+ header_reloc_none,
+ header_reloc_text,
+ header_reloc_data,
+ header_reloc_bss,
+ unknown
+};
+
+/***********************************************************************
+ * Public Function Prototypes
+ ***********************************************************************/
+
+extern void __attribute__ ((weak)) print_insn_arm(u_int32_t pc,
+ FILE * stream,
+ u_int32_t given);
+
+/***********************************************************************
+ * Private Functions
+ ***********************************************************************/
+
+/***********************************************************************
+ * swap32
+ ***********************************************************************/
+
+static inline u_int32_t nxflat_swap32(u_int32_t little)
+{
+ u_int32_t big =
+ ((little >> 24) & 0xff) |
+ (((little >> 16) & 0xff) << 8) |
+ (((little >> 8) & 0xff) << 16) | ((little & 0xff) << 24);
+ return big;
+}
+
+/***********************************************************************
+ * get_nxflat32
+ ***********************************************************************/
+
+static inline u_int32_t get_nxflat32(u_int32_t * addr32)
+{
+ return ntohl(*addr32);
+}
+
+/***********************************************************************
+ * get_nxflat16
+ ***********************************************************************/
+
+static inline u_int16_t get_nxflat16(u_int16_t * addr16)
+{
+ return ntohs(*addr16);
+}
+
+/***********************************************************************
+ * dump_hex_data
+ ***********************************************************************/
+
+static void dump_hex_data(FILE * in_stream, struct nxflat_hdr_s *header)
+{
+ u_int32_t data_start = get_nxflat32(&header->h_datastart);
+ u_int32_t data_end = get_nxflat32(&header->h_dataend);
+ int32_t words_left = (data_end - data_start) / sizeof(u_int32_t);
+ u_int32_t addr;
+ u_int32_t buffer[64];
+
+ printf("\nXFLAT DATA SEGMENT:\n\n");
+
+ /* Seek to the beginning of data in the file */
+
+ if (fseek(in_stream, data_start, SEEK_SET) != 0)
+ {
+ fprintf(stderr,
+ "ERROR: Failed to seek to data in file: offset: %08x\n",
+ data_start);
+ return;
+ }
+
+ /* Now dump all of the data reading 64 words at a time */
+
+ addr = 0;
+ while (words_left > 0)
+ {
+ size_t nread = fread(buffer, sizeof(u_int32_t), 64, in_stream);
+ if (nread >= 0)
+ {
+ union
+ {
+ u_int32_t l[4];
+ unsigned char b[16];
+ } row;
+ int32_t i, j, k;
+
+ for (i = 0; i < nread; i += 4)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ row.l[j] = buffer[i + j];
+ }
+
+ printf("%08x: ", addr);
+
+ for (j = 0; j < 4; j++)
+ {
+ printf("%08x ", row.l[j]);
+ }
+
+ printf(" ");
+
+ for (j = 0; j < 4 * sizeof(u_int32_t); j += sizeof(u_int32_t))
+ {
+ for (k = 0; k < sizeof(u_int32_t); k++)
+ {
+ if (isprint(row.b[j + k]))
+ putchar(row.b[j + k]);
+ else
+ putchar('.');
+ }
+ }
+
+ putchar('\n');
+ addr += 4 * sizeof(u_int32_t);
+ }
+ words_left -= nread;
+ }
+ else
+ break;
+ }
+ putchar('\n');
+}
+
+/***********************************************************************
+ * disassemble_text
+ ***********************************************************************/
+
+static void disassemble_text(FILE * in_stream, struct nxflat_hdr_s *header)
+{
+ if (print_insn_arm)
+ {
+ u_int32_t text_start = NXFLAT_HDR_SIZE;
+ u_int32_t text_end = get_nxflat32(&header->h_datastart);
+ int32_t insns_left = (text_end - text_start) / sizeof(u_int32_t);
+ u_int32_t addr;
+ u_int32_t buffer[64];
+
+ printf("\nXFLAT TEXT:\n\n");
+
+ /* Seek to the beginning of text in the file */
+ if (fseek(in_stream, text_start, SEEK_SET) != 0)
+ {
+ fprintf(stderr,
+ "ERROR: Failed to seek to text in file: offset: %08x\n",
+ text_start);
+ return;
+ }
+
+ /* Now dump all of the data reading 64 insns at a time */
+
+ addr = text_start;
+ while (insns_left > 0)
+ {
+ size_t nread = fread(buffer, sizeof(u_int32_t), 64, in_stream);
+ if (nread > 0)
+ {
+ int i;
+ for (i = 0; i < nread; i++)
+ {
+ u_int32_t insn = buffer[i];
+ if (big_endian)
+ {
+ insn = nxflat_swap32(insn);
+ }
+
+ printf("%08x %08x\t", addr, insn);
+ print_insn_arm(addr, stdout, insn);
+ putchar('\n');
+ addr += sizeof(u_int32_t);
+ }
+ insns_left -= nread;
+ }
+ else
+ break;
+ putchar('\n');
+ }
+ }
+}
+
+/***********************************************************************
+ * dump_imported_symbols
+ ***********************************************************************/
+
+static void dump_imported_symbols(FILE * in_stream, struct nxflat_hdr_s *header)
+{
+ struct nxflat_import_s import;
+ u_int32_t import_offset;
+ u_int32_t file_offset;
+ char imported_symbol_name[NXFLAT_MAX_STRING_SIZE];
+ int status;
+ int i;
+
+ printf("\nIMPORTED SYMBOLS:\n");
+ printf(" ADDRESS DATA SEGM SYMBOL NAME\n\n");
+
+ import_offset = get_nxflat32(&header->h_importsymbols);
+
+ for (i = 0; i < get_nxflat16(&header->h_importcount); i++)
+ {
+ /* Seek to the next imported symbol */
+
+ file_offset = i * sizeof(struct nxflat_import_s) + import_offset;
+
+ if (fseek(in_stream, file_offset, SEEK_SET) != 0)
+ {
+ fprintf(stderr, "ERROR: fseek to imported symbol %d struct failed\n",
+ i);
+ fprintf(stderr, " file_offset: %d, errno: %d\n", file_offset,
+ errno);
+ exit(1);
+ }
+
+ /* Read the next import entry. */
+
+ status = fread((void *)&import,
+ sizeof(struct nxflat_import_s), 1, in_stream);
+
+ if (status != 1)
+ {
+ fprintf(stderr, "ERROR: Read imported symbol %d struct failed, "
+ "errno: %d\n", i + 1, errno);
+ exit(1);
+ }
+
+ if (big_endian)
+ {
+ import.i_funcname = nxflat_swap32(import.i_funcname);
+ import.i_funcaddress = nxflat_swap32(import.i_funcaddress);
+ }
+
+ if (verbose)
+ {
+ /* Print the raw info */
+
+ printf("[%4d %08x %08x]\n",
+ i + 1, import.i_funcaddress, import.i_funcname);
+ }
+
+ /* Seek to the function name in the file */
+
+ file_offset = import.i_funcname + NXFLAT_HDR_SIZE;
+ if (0 != fseek(in_stream, file_offset, SEEK_SET))
+ {
+ fprintf(stderr, "ERROR: fseek to imported symbol %d name failed\n",
+ i);
+ fprintf(stderr, " file_offset: %d, errno: %d\n",
+ file_offset, errno);
+ exit(1);
+ }
+
+ /* Then, read the imported symbol name (assuming it is less than
+ * NXFLAT_MAX_STRING_SIZE in length). */
+
+ status = fread((void *)imported_symbol_name, NXFLAT_MAX_STRING_SIZE,
+ 1, in_stream);
+ if (status != 1)
+ {
+ fprintf(stderr, "ERROR: Read imported symbol %d name failed, "
+ "errno: %d\n", i + 1, errno);
+ exit(1);
+ }
+ imported_symbol_name[NXFLAT_MAX_STRING_SIZE - 1] = '\0';
+
+ /* And print it */
+
+ printf("%5d ", i + 1);
+
+ if (import.i_funcaddress)
+ {
+ printf("%08x ", import.i_funcaddress);
+ }
+ else
+ {
+ printf("UNKNOWN ");
+ }
+
+ printf("%s\n", imported_symbol_name);
+ }
+}
+
+/***********************************************************************
+ * dump_relocation_entries
+ ***********************************************************************/
+
+static void dump_relocation_entries(FILE * in_stream, struct nxflat_hdr_s *header)
+{
+ struct nxflat_reloc_s reloc;
+ int status;
+ int i;
+
+ /* Seek to the beginning of the relocation records. */
+
+ if (0 != fseek(in_stream, get_nxflat32(&header->h_relocstart), SEEK_SET))
+ {
+ fprintf(stderr, "ERROR: fseek to reloc records failed, errno: %d\n",
+ errno);
+ exit(1);
+ }
+
+ printf("\nRELOCATION ENTRIES:\n");
+ printf(" DATA OFFS RELOC TYPE\n\n");
+
+ for (i = 0; i < get_nxflat32(&header->h_reloccount); i++)
+ {
+ /* Read the next reloction entry. */
+
+ status = fread((void *)&reloc, sizeof(struct nxflat_reloc_s), 1, in_stream);
+ if (status != 1)
+ {
+ fprintf(stderr, "Error reading reloc record %d, errno: %d\n",
+ i + 1, errno);
+ exit(1);
+ }
+
+#ifdef RELOCS_IN_NETWORK_ORDER
+ {
+ u_int32_t *ptmp;
+ ptmp = (u_int32_t *) & reloc;
+ *ptmp = get_nxflat32(ptmp);
+ }
+#endif
+
+ if (NXFLAT_RELOC_TYPE(reloc.r_info) >= NXFLAT_RELOC_TYPE_NUM)
+ {
+ printf("%5d %08x UNKNOWN(%d)\n", i + 1,
+ NXFLAT_RELOC_OFFSET(reloc.r_info), NXFLAT_RELOC_TYPE(reloc.r_info));
+ fprintf(stderr, "Error eloc type out of range(%d)\n",
+ NXFLAT_RELOC_TYPE(reloc.r_info));
+ num_errors++;
+ }
+ else
+ {
+ printf("%5d %08x %s\n",
+ i + 1, NXFLAT_RELOC_OFFSET(reloc.r_info),
+ reloc_type_string[NXFLAT_RELOC_TYPE(reloc.r_info)]);
+ }
+ }
+}
+
+/***********************************************************************
+ * dump_hdr
+ ***********************************************************************/
+
+static void dump_hdr(struct nxflat_hdr_s *header)
+{
+ /* Print the contents of the FLT header */
+
+ printf("\nXFLAT HEADER:\n");
+ printf("\nMagic %c%c%c%c\n",
+ header->h_magic[0], header->h_magic[1],
+ header->h_magic[2], header->h_magic[3]);
+
+ printf("\nMEMORY MAP:\n");
+ printf(" Text start %08lx\n", NXFLAT_HDR_SIZE);
+ printf(" Entry point %08x\n", get_nxflat32(&header->h_entry));
+ printf(" Data start %08x\n", get_nxflat32(&header->h_datastart));
+ printf(" Data end %08x\n", get_nxflat32(&header->h_dataend) - 1);
+ printf(" Bss start %08x\n", get_nxflat32(&header->h_dataend));
+ printf(" Bss end %08x\n", get_nxflat32(&header->h_bssend) - 1);
+ printf("TOTAL SIZE %08x\n\n", get_nxflat32(&header->h_bssend));
+ printf("Stack size %08x\n", get_nxflat32(&header->h_stacksize));
+ printf("\nRELOCATIONS:\n");
+ printf(" Reloc start %08x\n", get_nxflat32(&header->h_relocstart));
+ printf(" reloc count %d\n", get_nxflat32(&header->h_reloccount));
+ printf("\nIMPORTED SYMBOLS:\n");
+ printf(" Import start %08x\n", get_nxflat32(&header->h_importsymbols));
+ printf(" Import count %d\n\n", get_nxflat16(&header->h_importcount));
+}
+
+/***********************************************************************
+ * show_usage
+ ***********************************************************************/
+
+static void show_usage(void)
+{
+ fprintf(stderr, "Usage: %s [options] <flat-filename>\n\n", program_name);
+#if 1
+ fprintf(stderr, "Where options are one or more of the following:\n\n");
+#else
+ 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");
+#endif
+ fprintf(stderr, " -h Dump the XFLAT file header [not dumped]\n");
+ fprintf(stderr, " -r Dump relocation entries [not dumped]\n");
+ fprintf(stderr, " -i Dump the imported symbol table [not dumped]\n");
+ fprintf(stderr, " -x Dump xFLT loader pathname [not dumped]\n");
+ fprintf(stderr, " -c Disassemble the text section [not dumped]\n");
+ fprintf(stderr, " -d Dump data section (hex) [not dumped]\n");
+ fprintf(stderr, " -a Dump all of the above [not dumped]\n");
+#ifdef ARCH_BIG_ENDIAN
+ fprintf(stderr, " -b Assume little-endian byteorder [big endian]\n");
+#else
+ fprintf(stderr, " -b Assume big-endian byteorder [little endian]\n");
+#endif
+ fprintf(stderr, " -v Output verbose debug info [no output]\n");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+/***********************************************************************
+ * parse_args
+ ***********************************************************************/
+
+static void parse_args(int argc, char **argv)
+{
+ int opt;
+
+ /* Save our name (for show_usage) */
+
+ program_name = argv[0];
+
+ /* At least three things must appear on the program line: the program name,
+ * the BFD filname, and at least one option. */
+
+ if (argc < 3)
+ {
+ fprintf(stderr, "ERROR: Missing required arguments\n\n");
+ show_usage();
+ }
+
+ /* Get miscellaneous options from the command line. */
+
+ while ((opt = getopt(argc, argv, "hrieLlxcbdav")) != -1)
+ {
+ switch (opt)
+ {
+
+ case 'h': /* Dump the flat file header */
+ dump_header++;
+ break;
+
+ case 'r': /* Dump the flat file header */
+ dump_relocs++;
+ break;
+
+ case 'i': /* Dump the imported symbol table */
+ dump_imports++;
+ break;
+
+ case 'c': /* Disassembly text */
+ if (print_insn_arm)
+ {
+ dump_text++;
+ }
+ else
+ {
+ printf("-c ignored: No disassembler available\n");
+ }
+ break;
+
+ case 'b': /* other-endian */
+#ifdef ARCH_BIG_ENDIAN
+ big_endian = 0;
+#else
+ big_endian++;
+#endif
+ break;
+
+ case 'd': /* Dump data */
+ dump_data++;
+ break;
+
+ case 'a': /* Dump everying */
+ dump_header++;
+ dump_relocs++;
+ dump_imports++;
+ dump_text++;
+ dump_data++;
+ break;
+
+ case 'v': /* Output verbose debug information */
+ verbose++;
+ break;
+
+ default:
+ fprintf(stderr, "%s Unknown option\n\n", argv[0]);
+ show_usage();
+ break;
+ }
+ }
+
+ /* Get the name of the input BFD file. */
+
+ nxflat_filename = argv[argc - 1];
+}
+
+/***********************************************************************
+ * Public Functions
+ ***********************************************************************/
+
+/***********************************************************************
+ * main
+ ***********************************************************************/
+
+int main(int argc, char **argv, char **envp)
+{
+ FILE *in_stream;
+ struct nxflat_hdr_s header;
+
+ /* Get the input parameters */
+
+ parse_args(argc, argv);
+
+ /* Open the FLT file */
+
+ in_stream = fopen(nxflat_filename, "rb");
+ if (NULL == in_stream)
+ {
+ fprintf(stderr, "Cannot open file %s for reading\n", nxflat_filename);
+ exit(1);
+ }
+
+ /* Read the FLT header */
+
+ if (1 != fread((void *)&header, sizeof(struct nxflat_hdr_s), 1, in_stream))
+ {
+ fprintf(stderr, "Error reading flat header\n");
+ exit(1);
+ }
+
+ printf("Dumping Flat Binary File: %s\n", nxflat_filename);
+
+ /* Dump the contents of the FLT header */
+
+ if (dump_header)
+ {
+ dump_hdr(&header);
+ }
+
+ /* Dump the relocation entries */
+
+ if (dump_relocs)
+ {
+ dump_relocation_entries(in_stream, &header);
+ }
+
+ /* Dump all imported symbols */
+
+ if (dump_imports)
+ {
+ dump_imported_symbols(in_stream, &header);
+ }
+
+ if (dump_text)
+ {
+ disassemble_text(in_stream, &header);
+ }
+
+ if (dump_data)
+ {
+ dump_hex_data(in_stream, &header);
+ }
+
+ fclose(in_stream);
+
+ if (num_errors > 0)
+ {
+ fprintf(stderr, "Finished with %d errors\n", num_errors);
+ }
+
+ return 0;
+}