diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-01-05 13:35:12 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-01-05 13:35:12 +0000 |
commit | f6d83168b86cb3f48151a462f3513f58c3762063 (patch) | |
tree | 179aa6e6cd3dcbddf9610108c622e94a1a34d222 /misc/pascal/plink/plreloc.c | |
parent | 46ce8c4bbb9bb2bda3b25fe97cc1008a607abce8 (diff) | |
download | nuttx-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.c | 254 |
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++; +} + +/***********************************************************************/ + |