Resync new repository with old repo r5166

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-09-17 18:18:44 +00:00
commit 57623d42eb
5691 changed files with 1361853 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
############################################################################
# plink/Makefile
#
# Copyright (C) 2008 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# 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.
#
############################################################################
#
# Directories
#
PLINKDIR = ${shell pwd}
PASCAL = $(PLINKDIR)/..
include $(PASCAL)/Make.config
include $(PASCAL)/Make.defs
INCDIR = $(PASCAL)/include
LIBDIR = $(PASCAL)/lib
BINDIR-$(CONFIG_INSN16) = $(PASCAL)/bin16
BINDIR-$(CONFIG_INSN32) = $(PASCAL)/bin32
#
# Objects and targets
#
PLINKSRCS = plink.c plsym.c plreloc.c
PLINKOBJS = $(PLINKSRCS:.c=.o)
OBJS = $(PLINKOBJS)
all: plink
.PHONY: all plink clean
$(OBJS): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
check_libs:
@if [ ! -f $(LIBDIR)/libpoff.a ] ; then \
echo "$(LIBDIR)/libpoff.a does not exist" ; \
exit 1 ; \
fi
@if [ ! -f $(LIBDIR)/libpas.a ] ; then \
echo "$(LIBDIR)/libpas.a does not exist" ; \
exit 1 ; \
fi
@if [ ! -f $(LIBDIR)/libinsn.a ] ; then \
echo "$(LIBDIR)/libinsn.a does not exist" ; \
exit 1 ; \
fi
$(BINDIR-y)/plink: check_libs $(PLINKOBJS)
$(CC) -o $@ $(LDFLAGS) $(PLINKOBJS) -linsn -lpoff -lpas
plink: $(BINDIR-y)/plink
clean:
$(RM) plink *.o core *~
+551
View File
@@ -0,0 +1,551 @@
/**********************************************************************
* plink.c
* P-Code Linker
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <stdint.h>
#include <stdbool.h>
#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 "paslib.h"
#include "perr.h"
#include "plsym.h"
#include "plreloc.h"
#include "pinsn.h"
#include "plink.h"
/**********************************************************************
* Definitions
**********************************************************************/
#define MAX_POFF_FILES 8
/**********************************************************************
* Private Type Definitions
**********************************************************************/
/**********************************************************************
* Private Constant Data
**********************************************************************/
/**********************************************************************
* Private Data
**********************************************************************/
static const char *outFileName;
static const char *inFileName[MAX_POFF_FILES];
static int nPoffFiles = 0;
/**********************************************************************
* Private Function Prototypes
**********************************************************************/
static void showUsage (const char *progname);
static void parseArgs (int argc, char **argv);
static void loadInputFiles (poffHandle_t outHandle);
static void checkFileHeader (poffHandle_t inHandle, poffHandle_t outHandle,
uint32_t pcOffset, bool *progFound);
static uint32_t mergeRoData (poffHandle_t inHandle, poffHandle_t outHandle);
static uint32_t mergeProgramData (poffHandle_t inHandle, poffHandle_t outHandle,
uint32_t pcOffset, uint32_t roOffset);
static uint32_t mergeFileNames (poffHandle_t inHandle, poffHandle_t outHandle);
static uint32_t mergeLineNumbers (poffHandle_t inHandle, poffHandle_t outHandle,
uint32_t pcOffset, uint32_t fnOffset);
static void writeOutputFile (poffHandle_t outHandle);
/**********************************************************************
* Global Variables
**********************************************************************/
/**********************************************************************
* Private Variables
**********************************************************************/
/**********************************************************************
* Public Functions
**********************************************************************/
int main(int argc, char *argv[], char *envp[])
{
poffHandle_t outHandle;
/* Parse the command line arguments */
parseArgs(argc, argv);
/* Create a handle to hold the output file data */
outHandle = poffCreateHandle();
if (outHandle == NULL) fatal(eNOMEMORY);
/* Load the POFF files specified on the command line */
loadInputFiles(outHandle);
/* Verify that all symbols were processed correctly */
verifySymbols();
/* Apply the relocation data to the program data */
applyRelocations(outHandle);
/* Write the symbol table information to the output file */
writeSymbols(outHandle);
/* Write the output file */
writeOutputFile(outHandle);
/* Release bufferred symbol/relocation informtion */
releaseSymbols();
releaseRelocations();
/* Release the input file data */
poffDestroyHandle(outHandle);
return 0;
} /* end main */
/**********************************************************************
* Private Functions
**********************************************************************/
static void showUsage(const char *progname)
{
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s <in-file-name> {<in-file-name>} <out-file-name>\n",
progname);
}
/***********************************************************************/
static void parseArgs(int argc, char **argv)
{
int i;
/* Check for existence of filename argument */
if (argc < 3)
{
fprintf(stderr,
"ERROR: <in-file-name> and one <out-file-name> required\n");
showUsage(argv[0]);
} /* end if */
/* Get the name of the p-code file(s) from the last argument(s) */
for (i = 1; i < argc-1; i++)
{
inFileName[nPoffFiles] = argv[i];
nPoffFiles++;
}
/* The last thing on the command line is the output file name */
outFileName = argv[argc-1];
}
/***********************************************************************/
/* This function loads each POFF file specified on the command line,
* merges the input POFF data, and generates intermediate structures
* to be used in the final link.
*/
static void loadInputFiles(poffHandle_t outHandle)
{
poffHandle_t inHandle;
FILE *instream;
char fileName[FNAME_SIZE+1]; /* Object file name */
uint32_t pcOffset = 0;
uint32_t fnOffset = 0;
uint32_t symOffset = 0;
uint32_t roOffset = 0;
uint32_t pcEnd = 0;
uint32_t fnEnd = 0;
uint32_t symEnd = 0;
uint16_t errCode;
bool progFound = false;
int i;
/* Load the POFF files specified on the command line */
for (i = 0; i < nPoffFiles; i++)
{
/* Create a handle to hold the input file data */
inHandle = poffCreateHandle();
if (inHandle == NULL) fatal(eNOMEMORY);
/* Use .o or command line extension, if supplied, to get the
* input file name.
*/
(void)extension(inFileName[i], "o", fileName, 0);
/* Open the input file */
instream = fopen(fileName, "rb");
if (instream == NULL)
{
fprintf(stderr, "ERROR: Could not open %s: %s\n",
fileName, strerror(errno));
exit(1);
}
/* Load the POFF file */
errCode = poffReadFile(inHandle, instream);
if (errCode != eNOERROR)
{
fprintf(stderr, "ERROR: Could not read %s (%d)\n",
fileName, errCode);
exit(1);
}
/* Check file header for critical settings */
checkFileHeader(inHandle, outHandle, pcOffset, &progFound);
/* Merge the read-only data sections */
roOffset = mergeRoData(inHandle, outHandle);
/* Merge program section data from the new input file into the
* output file container.
*/
pcEnd = mergeProgramData(inHandle, outHandle, pcOffset, roOffset);
/* Merge the file name data from the new input file into the
* output file container.
*/
fnEnd = mergeFileNames(inHandle, outHandle);
/* Merge the line number data from the new input file into the
* output file container.
*/
(void)mergeLineNumbers(inHandle, outHandle, pcOffset, fnOffset);
/* On this pass, we just want to collect all symbol table in a
* local list where we can resolve all undefined symbols (later)
*/
symEnd = mergeSymbols(inHandle, pcOffset, symOffset);
/* On this pass, we will also want to buffer all relocation data,
* adjusting only the program section offset and sym table
* offsets.
*/
mergeRelocations(inHandle, pcOffset, symOffset);
/* Release the input file data */
insn_ResetOpCodeRead(inHandle);
poffDestroyHandle(inHandle);
/* Close the input file */
fclose(instream);
/* Set the offsest to be used for the next file equal
* to the end values found from processing this file
*/
pcOffset = pcEnd;
fnOffset = fnEnd;
symOffset = symEnd;
}
/* Did we find exactly one program file? */
if (!progFound)
{
/* No! We have to have a program file to generate an executable */
fprintf(stderr, "ERROR: No program file found in input files\n");
exit(1);
}
} /* end loadInputFiles */
/***********************************************************************/
static void checkFileHeader(poffHandle_t inHandle, poffHandle_t outHandle,
uint32_t pcOffset, bool *progFound)
{
uint8_t fileType;
/* What kind of file are we processing? */
fileType = poffGetFileType(inHandle);
if (fileType == FHT_PROGRAM)
{
/* We can handle only one pascal program file */
if (*progFound)
{
fprintf(stderr,
"ERROR: Only one compiled pascal program file "
"may appear in input file list\n");
exit(1);
}
else
{
/* Get the entry point from the pascal file, apply any
* necessary offsets, and store the entry point in the
* linked output file's file header.
*/
poffSetEntryPoint(outHandle,
poffGetEntryPoint(inHandle) + pcOffset);
/* Copy the program name from the pascal file to the linked
* output file's file header and mark the output file as
* a pascal executable.
*/
poffSetFileType(outHandle, FHT_EXEC, 0,
poffGetFileHdrName(inHandle));
/* Indicate that we have found the program file */
*progFound = true;
}
}
else if (fileType != FHT_UNIT)
{
/* It is something other than a compiled pascal program or unit
* file.
*/
fprintf(stderr,
"ERROR: Only compiled pascal program and unit files "
"may appear in input file list\n");
exit(1);
}
}
/***********************************************************************/
static uint32_t mergeRoData(poffHandle_t inHandle, poffHandle_t outHandle)
{
uint8_t *newRoData;
uint32_t oldRoDataSize;
uint32_t newRoDataSize;
/* Get the size of the read-only data section before we add the
* new data. This is the offset that must be applied to any
* references to the new data.
*/
oldRoDataSize = poffGetRoDataSize(outHandle);
/* Remove the read-only data from new input file */
newRoDataSize = poffExtractRoData(inHandle, &newRoData);
/* And append the new read-only data to output file */
poffAppendRoData(outHandle, newRoData, newRoDataSize);
return oldRoDataSize;
}
/***********************************************************************/
/* This function merges the program data section of a new file into the
* program data section of the output file, relocating simple program
* section references as they are encountered.
*/
static uint32_t mergeProgramData(poffHandle_t inHandle,
poffHandle_t outHandle,
uint32_t pcOffset, uint32_t roOffset)
{
OPTYPE op;
uint32_t pc;
uint32_t opSize;
int endOp;
/* Read each opcode from the input file, add pcOffset to each program
* section address, and add each opcode to the output file.
*/
pc = pcOffset;
do
{
/* Read the next opcode (with its size) */
opSize = insn_GetOpCode(inHandle, &op);
/* Perform any necessary relocations */
endOp = insn_Relocate(&op, pcOffset, roOffset);
/* Save the potentially modified opcode in the temporary
* program data container.
*/
insn_AddOpCode(outHandle, &op);
pc += opSize;
}
while (endOp == 0);
return pc;
}
/***********************************************************************/
/* This function merges the file name section of a new file into the
* file name section of the output file, relocating simple program
* section references as they are encountered.
*/
static uint32_t mergeFileNames(poffHandle_t inHandle,
poffHandle_t outHandle)
{
int32_t inOffset;
uint32_t outOffset;
const char *fname;
do
{
/* Read each file name from the input File */
inOffset = poffGetFileName(inHandle, &fname);
if (inOffset >= 0)
{
/* And write it to the output file */
outOffset = poffAddFileName(outHandle, fname);
}
}
while (inOffset >= 0);
/* Return the offset to the last file name written to the
* output file
*/
return outOffset;
}
/***********************************************************************/
/* This function merges the line number section of a new file into the
* line number section of the output file, relocating simple program
* section references as they are encountered.
*/
static uint32_t mergeLineNumbers(poffHandle_t inHandle,
poffHandle_t outHandle,
uint32_t pcOffset,
uint32_t fnOffset)
{
poffLineNumber_t lineno;
int32_t inOffset;
uint32_t outOffset;
do
{
/* Read each line number from the input File */
inOffset = poffGetRawLineNumber(inHandle, &lineno);
if (inOffset >= 0)
{
/* And write it to the output file */
outOffset = poffAddLineNumber(outHandle, lineno.ln_lineno,
lineno.ln_fileno + fnOffset,
lineno.ln_poffset + pcOffset);
}
}
while (inOffset >= 0);
/* Return the offset to the last line number written to the
* output file
*/
return outOffset;
}
/***********************************************************************/
static void writeOutputFile(poffHandle_t outHandle)
{
FILE *outstream;
char fileName[FNAME_SIZE+1]; /* Output file name */
/* Use .pex or command line extension, if supplied, to get the
* input file name.
*/
(void)extension(outFileName, "pex", fileName, 0);
/* Open the output file */
outstream = fopen(fileName, "wb");
if (outstream == NULL)
{
fprintf(stderr, "ERROR: Could not open %s: %s\n",
fileName, strerror(errno));
exit(1);
}
/* Write the POFF file */
(void)poffWriteFile(outHandle, outstream);
/* Close the output file */
fclose(outstream);
}
/***********************************************************************/
+52
View File
@@ -0,0 +1,52 @@
/***************************************************************************
* plink.h
* External Declarations associated with plink.c
*
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
*
***************************************************************************/
#ifndef __PLINK_H
#define __PLINK_H
/***************************************************************************
* Included Files
***************************************************************************/
/***************************************************************************
* Global Variables
***************************************************************************/
/***************************************************************************
* Global Function Prototypes
***************************************************************************/
#endif /* __PLINK_H */
+255
View File
@@ -0,0 +1,255 @@
/**********************************************************************
* plreloc.c
* Relocation management for the P-Code Linker
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <stdint.h>
#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"
/**********************************************************************
* Pre-processor 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_t relocListAlloc = 0;
static uint32_t nRelocs = 0;
/**********************************************************************
* Private Function Prototypes
**********************************************************************/
static void offsetRelocation(poffRelocation_t *reloc,
uint32_t pcOffset, uint32_t symOffset);
static void addRelocToList(poffRelocation_t *reloc);
/**********************************************************************
* Public Functions
**********************************************************************/
void mergeRelocations(poffHandle_t inHandle,
uint32_t pcOffset, uint32_t symOffset)
{
poffRelocation_t reloc;
int32_t 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)
{
uint8_t *progData;
uint32_t 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_t symIndex = RLI_SYM(reloc->rl_info);
uint32_t relType = RLI_TYPE(reloc->rl_info);
poffLibSymbol_t *sym;
uint32_t 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_t pcOffset, uint32_t symOffset)
{
uint32_t symIndex = RLI_SYM(reloc->rl_info);
uint32_t 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_t 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++;
}
/***********************************************************************/
+60
View File
@@ -0,0 +1,60 @@
/***************************************************************************
* plreloc.h
* External Declarations associated with plreloc.c
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
*
***************************************************************************/
#ifndef __PLRELOC_H
#define __PLRELOC_H
/***************************************************************************
* Included Files
***************************************************************************/
#include <stdint.h>
#include "pofflib.h"
/***************************************************************************
* Global Variables
***************************************************************************/
/***************************************************************************
* Global Function Prototypes
***************************************************************************/
extern void mergeRelocations(poffHandle_t inHandle,
uint32_t pcOffset, uint32_t symOffset);
extern void applyRelocations(poffHandle_t outHandle);
extern void releaseRelocations(void);
#endif /* __PLRELOC_H */
+469
View File
@@ -0,0 +1,469 @@
/**********************************************************************
* plsym.c
* Symbol management for the P-Code Linker
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <stdint.h>
#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"
/**********************************************************************
* Pre-processor 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_t symListAlloc = 0;
static int nUndefined = 0;
static int nMultiplyDefined = 0;
/**********************************************************************
* Private Function Prototypes
**********************************************************************/
static void offsetSymbolValue(poffLibSymbol_t *sym,
uint32_t pcOffset);
static symContainer_t *insertSymbol(poffLibSymbol_t *sym);
static void addSymbolToList(symContainer_t *symbol,
uint32_t index);
/**********************************************************************
* Public Functions
**********************************************************************/
uint32_t mergeSymbols(poffHandle_t inHandle, uint32_t pcOffset, uint32_t symOffset)
{
poffLibSymbol_t symbol;
symContainer_t *container;
int32_t inIndex;
uint32_t 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_t 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_t 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_t 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_t 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;
}
/***********************************************************************/
+62
View File
@@ -0,0 +1,62 @@
/***************************************************************************
* plsym.h
* External Declarations associated with plsym.c
*
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
*
***************************************************************************/
#ifndef __PLSYM_H
#define __PLSYM_H
/***************************************************************************
* Included Files
***************************************************************************/
#include <stdint.h>
#include "pofflib.h"
/***************************************************************************
* Global Variables
***************************************************************************/
/***************************************************************************
* Global Function Prototypes
***************************************************************************/
extern uint32_t mergeSymbols(poffHandle_t inHandle,
uint32_t pcOffset, uint32_t symOffset);
extern void verifySymbols(void);
extern void writeSymbols(poffHandle_t outHandle);
extern poffLibSymbol_t *getSymbolByIndex(uint32_t symIndex);
extern void releaseSymbols(void);
#endif /* __PLSYM_H */