summaryrefslogtreecommitdiff
path: root/misc/pascal/plink/plsym.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-01-05 13:35:12 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-01-05 13:35:12 +0000
commitf6d83168b86cb3f48151a462f3513f58c3762063 (patch)
tree179aa6e6cd3dcbddf9610108c622e94a1a34d222 /misc/pascal/plink/plsym.c
parent46ce8c4bbb9bb2bda3b25fe97cc1008a607abce8 (diff)
downloadnuttx-f6d83168b86cb3f48151a462f3513f58c3762063.tar.gz
nuttx-f6d83168b86cb3f48151a462f3513f58c3762063.tar.bz2
nuttx-f6d83168b86cb3f48151a462f3513f58c3762063.zip
P-Code linker
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@488 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'misc/pascal/plink/plsym.c')
-rw-r--r--misc/pascal/plink/plsym.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/misc/pascal/plink/plsym.c b/misc/pascal/plink/plsym.c
new file mode 100644
index 000000000..1ef40461a
--- /dev/null
+++ b/misc/pascal/plink/plsym.c
@@ -0,0 +1,468 @@
+/**********************************************************************
+ * plsym.c
+ * Symbol management for the P-Code Linker
+ *
+ * Copyright (C) 2008 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.
+ *
+ **********************************************************************/
+
+/**********************************************************************
+ * Included Files
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "keywords.h"
+#include "pdefs.h"
+#include "podefs.h"
+#include "pedefs.h"
+
+#include "pofflib.h"
+#include "paslib.h"
+#include "perr.h"
+#include "plsym.h"
+
+/**********************************************************************
+ * Definitions
+ **********************************************************************/
+
+#define INITIAL_SYMBOL_LIST_SIZE (1024*sizeof(symContainer_t*))
+#define SYMBOL_LIST_INCREMENT (256*sizeof(symContainer_t*))
+
+/**********************************************************************
+ * Private Types
+ **********************************************************************/
+
+/* This structure just contains a POFF library symbol */
+
+struct symContainer_s
+{
+ struct symContainer_s *next;
+ struct symContainer_s *prev;
+ poffLibSymbol_t s;
+};
+typedef struct symContainer_s symContainer_t;
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+static symContainer_t *symHead = NULL;
+static symContainer_t *symTail = NULL;
+static symContainer_t **symList = NULL;
+static uint32 symListAlloc = 0;
+
+static int nUndefined = 0;
+static int nMultiplyDefined = 0;
+
+/**********************************************************************
+ * Private Function Prototypes
+
+ **********************************************************************/
+
+static void offsetSymbolValue(poffLibSymbol_t *sym,
+ uint32 pcOffset);
+static symContainer_t *insertSymbol(poffLibSymbol_t *sym);
+static void addSymbolToList(symContainer_t *symbol,
+ uint32 index);
+
+/**********************************************************************
+ * Public Functions
+ **********************************************************************/
+
+uint32 mergeSymbols(poffHandle_t inHandle, uint32 pcOffset, uint32 symOffset)
+{
+ poffLibSymbol_t symbol;
+ symContainer_t *container;
+ sint32 inIndex;
+ uint32 outIndex;
+
+ do
+ {
+ /* Read each symbol from the input File */
+
+ inIndex = poffGetSymbol(inHandle, &symbol);
+ if (inIndex >= 0)
+ {
+ /* If the symbol carries a "payload" that is a program
+ * section offset, then apply the pcOffset value to
+ * that "payload"
+ */
+
+ offsetSymbolValue(&symbol, pcOffset);
+
+ /* Create a container for the symbol information */
+
+ container = insertSymbol(&symbol);
+
+ /* Add the symbol to the linearly indexed list */
+
+ outIndex = inIndex + symOffset;
+ addSymbolToList(container, outIndex);
+ }
+ }
+ while (inIndex >= 0);
+
+ /* Return the offset to the last symbol inserted */
+
+ return outIndex;
+}
+
+/***********************************************************************/
+
+void verifySymbols(void)
+{
+ symContainer_t *sym;
+
+ /* At the conclusion the link, there should be no undefined symbols.
+ * This function simply asserts that condition. It traverses the
+ * symbol container list and if any undefined symbol is found, it
+ * errors out.
+ */
+
+ for (sym = symHead; (sym); sym = sym->next)
+ {
+ if ((sym->s.flags & STF_UNDEFINED) != 0)
+ {
+ fprintf(stderr, "ERROR: Undefined symbol '%s'\n",
+ sym->s.name);
+ nUndefined++;
+ }
+ }
+
+ if (nUndefined) fatal(eUNDEFINEDSYMBOL);
+ if (nMultiplyDefined) fatal(eMULTIDEFSYMBOL);
+}
+
+/***********************************************************************/
+
+void writeSymbols(poffHandle_t outHandle)
+{
+ symContainer_t *sym;
+
+ /* Transfer all buffered symbol information to the output file */
+
+ for (sym = symHead; (sym); sym = sym->next)
+ {
+ (void)poffAddSymbol(outHandle, &sym->s);
+ }
+}
+
+/***********************************************************************/
+
+poffLibSymbol_t *getSymbolByIndex(uint32 symIndex)
+{
+ if (symIndex * sizeof(symContainer_t*) >= symListAlloc)
+ fatal(ePOFFCONFUSION);
+ return &symList[symIndex]->s;
+}
+
+/***********************************************************************/
+
+void releaseSymbols(void)
+{
+ static symContainer_t *curr;
+ static symContainer_t *next;
+
+ for (curr = symHead; (curr); curr = next)
+ {
+ /* Get the next pointer from the container -- we are going
+ * to deallocate the container!
+ */
+
+ next = curr->next;
+
+ /* Deallocate the name string copy */
+
+ if (curr->s.name) free((void*)curr->s.name);
+
+ /* Free the container */
+
+ free(curr);
+ }
+
+ /* Free the index-able symbol list */
+
+ if (symList) free((void*)symList);
+
+ symHead = NULL;
+ symTail = NULL;
+ symList = NULL;
+}
+
+/**********************************************************************/
+
+static void offsetSymbolValue(poffLibSymbol_t *sym, uint32 pcOffset)
+{
+ /* Don't do anything with undefined symbols. By definition, these
+ * cannot cannot any meaning values.
+ */
+
+ if ((sym->flags & STF_UNDEFINED) == 0)
+ {
+ switch (sym->type)
+ {
+ case STT_PROC:
+ case STT_FUNC:
+ sym->value += pcOffset;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**********************************************************************/
+
+static inline symContainer_t *makeSymContainer(poffLibSymbol_t *psym)
+{
+ symContainer_t *sym;
+ sym = (symContainer_t*)malloc(sizeof(symContainer_t));
+ if (sym == NULL)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ /* The next container is not linked to anything yet */
+
+ sym->next = NULL;
+ sym->prev = NULL;
+
+ /* Copy the whole symbol record */
+
+ sym->s = *psym;
+
+ /* Duplicate the symbol name -- the reference in the symbol entry
+ * belongs to the input file and will be lost if/when the input file
+ * is released.
+ */
+
+ if (psym->name)
+ {
+ sym->s.name = strdup(psym->name);
+ }
+ return sym;
+}
+
+static symContainer_t *insertSymbol(poffLibSymbol_t *sym)
+{
+ symContainer_t *prev;
+ symContainer_t *curr;
+ symContainer_t *newsym;
+ int compare;
+
+ /* Find where to insert the symbol */
+
+ for (prev = NULL, curr = symHead; (curr); prev = curr, curr = curr->next)
+ {
+ /* Compare the names of the symbols */
+
+ compare = strcmp(curr->s.name, sym->name);
+
+ /* Break out of the loop if curr->name > sym_name or
+ * if curr->name == sym_name AND the types of the
+ * symbols are the same.
+ */
+
+ if (compare > 0)
+ {
+ /* Break out... curr refers to a symbol AFTER the position
+ * where we want to put the new symbol.
+ */
+
+ break;
+ }
+ else if (compare == 0)
+ {
+ /* The symbols are the same. break out only if the types
+ * are the same or this is where we need to insert the new
+ * symbol (same name different type)
+ */
+
+ if (curr->s.type > sym->type)
+ {
+ compare = 1;
+ break;
+ }
+ else if (curr->s.type == sym->type)
+ {
+ break;
+ }
+ }
+ }
+
+ /* We get here if:
+ * a. curr == NULL meaning that the symbol goes at the end of the
+ * list. (special case, prev == NULL as well. This happens when
+ * the list is empty).
+ * b. curr != NULL mean that the symbol goes between prev and curr
+ * (special cases: (i) compare == 0 meaning that the symbol is
+ * already in the list, or (ii) compare > 0 with prev == NULL
+ * meaning that the new entry goes at the beginning of the list).
+ */
+
+ if (curr == NULL)
+ {
+ /* The symbol goes at the end of the list */
+
+ newsym = makeSymContainer(sym);
+ newsym->next = NULL;
+ newsym->prev = prev;
+ symTail = newsym;
+
+ if (prev)
+ prev->next = newsym;
+ else
+ symHead = newsym;
+ }
+ else if (compare == 0)
+ {
+ /* curr is non-NULL and refers to the same symbol (of the same
+ * type). If both are undefined, then just discard the new
+ * symbol.
+ */
+
+ if ((curr->s.flags & STF_UNDEFINED) != 0)
+ {
+ /* The symbol in the table is undefined */
+
+ if ((sym->flags & STF_UNDEFINED) != 0)
+ {
+ /* Both symbols are undefined. Just ignore the new one */
+ }
+ else
+ {
+ /* The symbol in the table is undefined, but the new
+ * one is defined. Replace the one in the table (retaining
+ * the allocated symbol name).
+ */
+ const char *save = curr->s.name;
+ curr->s = *sym;
+ curr->s.name = save;
+ }
+ }
+ else
+ {
+ /* The symbol in the table is defined */
+
+ if ((sym->flags & STF_UNDEFINED) != 0)
+ {
+ /* But the new symbol is undefined. Just ignore the
+ * new symbol
+ */
+ }
+ else
+ {
+ /* OOPS! both symbols are defined */
+
+ fprintf(stderr,
+ "ERROR: Multiply defined symbol: '%s'\n",
+ sym->name);
+ nMultiplyDefined++;
+ }
+
+ /* In any case, return the pointer to the old container */
+
+ newsym = curr;
+ }
+ }
+ else
+ {
+ /* curr is non-NULL and the symbol goes between prev and curr */
+
+ newsym = makeSymContainer(sym);
+ newsym->next = curr;
+ newsym->prev = prev;
+
+ if (prev)
+ prev->next = newsym;
+ else
+ symHead = newsym;
+ }
+
+ return newsym;
+}
+
+/***********************************************************************/
+/* Add a symbol to the linear symbol table list. This list is necessary
+ * to quickly mapped a symbol index value (as might be found in the
+ * relocation data) to the unique representation of the symbol as
+ * deterimed by insertSymbol().
+ */
+
+static void addSymbolToList(symContainer_t *symbol, uint32 index)
+{
+ /* Check if we have allocated a symbol table buffer yet */
+
+ if (!symList)
+ {
+ /* No, allocate it now */
+
+ symList = (symContainer_t**)malloc(INITIAL_SYMBOL_LIST_SIZE);
+ if (!symList)
+ {
+ fatal(eNOMEMORY);
+ }
+ symListAlloc = INITIAL_SYMBOL_LIST_SIZE;
+ }
+
+ /* Check if there is room for a new symbol */
+
+ if ((index + 1) * sizeof(symContainer_t*) > symListAlloc)
+ {
+ uint32 newAlloc = symListAlloc + SYMBOL_LIST_INCREMENT;
+ symContainer_t **tmp;
+
+ /* Reallocate the file name buffer */
+
+ tmp = (symContainer_t**)realloc(symList, newAlloc);
+ if (!tmp)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ /* And set the new size */
+
+ symListAlloc = newAlloc;
+ symList = tmp;
+ }
+
+ /* Save the new symbol information in the symbol table data */
+
+ symList[index] = symbol;
+}
+
+/***********************************************************************/
+