summaryrefslogtreecommitdiff
path: root/misc/pascal/plink/plreloc.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/plreloc.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/plreloc.c')
-rw-r--r--misc/pascal/plink/plreloc.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/misc/pascal/plink/plreloc.c b/misc/pascal/plink/plreloc.c
new file mode 100644
index 000000000..32911570c
--- /dev/null
+++ b/misc/pascal/plink/plreloc.c
@@ -0,0 +1,254 @@
+/**********************************************************************
+ * plreloc.c
+ * Relocation 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 "pinsn.h"
+#include "perr.h"
+#include "plsym.h"
+#include "plreloc.h"
+
+/**********************************************************************
+ * Definitions
+ **********************************************************************/
+
+#define INITIAL_RELOC_LIST_SIZE (1024*sizeof(poffRelocation_t*))
+#define RELOC_LIST_INCREMENT (256*sizeof(poffRelocation_t*))
+
+/**********************************************************************
+ * Private Types
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+static poffRelocation_t *relocList = NULL;
+static uint32 relocListAlloc = 0;
+static uint32 nRelocs = 0;
+
+/**********************************************************************
+ * Private Function Prototypes
+
+ **********************************************************************/
+
+static void offsetRelocation(poffRelocation_t *reloc,
+ uint32 pcOffset, uint32 symOffset);
+static void addRelocToList(poffRelocation_t *reloc);
+
+/**********************************************************************
+ * Public Functions
+ **********************************************************************/
+
+void mergeRelocations(poffHandle_t inHandle,
+ uint32 pcOffset, uint32 symOffset)
+{
+ poffRelocation_t reloc;
+ sint32 index;
+
+ do
+ {
+ /* Read each relocation record from the input File */
+
+ index = poffGetRawRelocation(inHandle, &reloc);
+ if (index >= 0)
+ {
+ /* If the rellocation carries a "payload" that is a program
+ * section offset, then apply the pcOffset value to
+ * that "payload"
+ */
+
+ offsetRelocation(&reloc, pcOffset, symOffset);
+
+ /* Add the relocation to the in-memory relocation list */
+
+ addRelocToList(&reloc);
+ }
+ }
+ while (index >= 0);
+}
+
+/***********************************************************************/
+
+void applyRelocations(poffHandle_t outHandle)
+{
+ ubyte *progData;
+ uint32 progSize;
+ int i;
+
+ /* Take ownership of the program data image for a little while */
+
+ progSize = poffExtractProgramData(outHandle, &progData);
+
+ /* Process each text data section reloation */
+
+ for (i = 0; i < nRelocs; i++)
+ {
+ poffRelocation_t *reloc = &relocList[i];
+ uint32 symIndex = RLI_SYM(reloc->rl_info);
+ uint32 relType = RLI_TYPE(reloc->rl_info);
+ poffLibSymbol_t *sym;
+ uint32 progIndex;
+
+ switch (relType)
+ {
+ case RLT_PCAL:
+ /* Get the symbol referenced by the relocation. At this
+ * point, we assume that the system has already verified
+ * that there are no undefined symbols.
+ */
+
+ sym = getSymbolByIndex(symIndex);
+
+ /* Get the index to the oPCAL instruction */
+
+ progIndex = reloc->rl_offset;
+
+ /* Sanity checking */
+
+ if (((sym->flags & STF_UNDEFINED) != 0) ||
+ (progIndex > progSize-4))
+ fatal(ePOFFCONFUSION);
+
+ /* Perform the relocation */
+
+ insn_FixupProcedureCall(&progData[progIndex], sym->value);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ /* Return ownership of the program data to the container */
+
+ poffInsertProgramData(outHandle, progData, progSize);
+}
+
+/***********************************************************************/
+
+void releaseRelocations(void)
+{
+ if (relocList) free(relocList);
+ relocList = NULL;
+}
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+static void offsetRelocation(poffRelocation_t *reloc,
+ uint32 pcOffset, uint32 symOffset)
+{
+ uint32 symIndex = RLI_SYM(reloc->rl_info);
+ uint32 relType = RLI_TYPE(reloc->rl_info);
+
+ switch (relType)
+ {
+ case RLT_PCAL:
+ symIndex += symOffset;
+ reloc->rl_info = RLI_MAKE(symIndex, relType);
+ reloc->rl_offset += pcOffset;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/***********************************************************************/
+/* Add to the linear relocation list. */
+
+static void addRelocToList(poffRelocation_t *reloc)
+{
+ /* Check if we have allocated a relocation buffer yet */
+
+ if (!relocList)
+ {
+ /* No, allocate it now */
+
+ relocList = (poffRelocation_t*)malloc(INITIAL_RELOC_LIST_SIZE);
+ if (!relocList)
+ {
+ fatal(eNOMEMORY);
+ }
+ relocListAlloc = INITIAL_RELOC_LIST_SIZE;
+ }
+
+ /* Check if there is room for a new symbol */
+
+ if ((nRelocs + 1) * sizeof(poffRelocation_t) > relocListAlloc)
+ {
+ uint32 newAlloc = relocListAlloc + RELOC_LIST_INCREMENT;
+ poffRelocation_t *tmp;
+
+ /* Reallocate the file name buffer */
+
+ tmp = (poffRelocation_t*)realloc(relocList, newAlloc);
+ if (!tmp)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ /* And set the new size */
+
+ relocListAlloc = newAlloc;
+ relocList = tmp;
+ }
+
+ /* Save the new symbol information in the relocation data */
+
+ relocList[nRelocs] = *reloc;
+ nRelocs++;
+}
+
+/***********************************************************************/
+