mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 07:33:33 +08:00
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:
@@ -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 *~
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -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 */
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user