Added a new "--force-import" command line option to the linker.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4052 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2009-08-27 14:43:44 +00:00
parent 2b15f40424
commit ee6028993e
4 changed files with 170 additions and 73 deletions

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2008 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -106,6 +106,7 @@ static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
/* Initialize the fields */
I->Next = 0;
I->Obj = Obj;
InitFilePos (&I->Pos);
I->Exp = 0;
I->Name = INVALID_STRING_ID;
I->Flags = 0;
@@ -117,60 +118,6 @@ static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
void InsertImport (Import* I)
/* Insert an import into the table */
{
Export* E;
/* As long as the import is not inserted, V.Name is valid */
unsigned Name = I->Name;
/* Create a hash value for the given name */
unsigned Hash = (Name & HASHTAB_MASK);
/* Search through the list in that slot and print matching duplicates */
if (HashTab[Hash] == 0) {
/* The slot is empty, we need to insert a dummy export */
E = HashTab[Hash] = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
++ExpCount;
} else {
E = HashTab [Hash];
while (1) {
if (E->Name == Name) {
/* We have an entry, L points to it */
break;
}
if (E->Next == 0) {
/* End of list an entry not found, insert a dummy */
E->Next = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
E = E->Next; /* Point to dummy */
++ExpCount; /* One export more */
break;
} else {
E = E->Next;
}
}
}
/* Ok, E now points to a valid exports entry for the given import. Insert
* the import into the imports list and update the counters.
*/
I->Exp = E;
I->Next = E->ImpList;
E->ImpList = I;
E->ImpCount++;
++ImpCount; /* Total import count */
if (E->Expr == 0) {
/* This is a dummy export */
++ImpOpen;
}
/* Mark the import so we know it's in the list */
I->Flags |= IMP_INLIST;
}
void FreeImport (Import* I)
/* Free an import. NOTE: This won't remove the import from the exports table,
* so it may only be called for unused imports (imports from modules that
@@ -229,6 +176,95 @@ Import* ReadImport (FILE* F, ObjData* Obj)
Import* GenImport (const char* Name, unsigned char AddrSize)
/* Generate a new import with the given name and address size and return it */
{
/* Create a new import */
Import* I = NewImport (AddrSize, 0);
/* Read the name */
I->Name = GetStringId (Name);
/* Check the address size */
if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) {
/* Beware: This function may be called in cases where the object file
* is not read completely into memory. In this case, the file list is
* invalid. Be sure not to access it in this case.
*/
if (ObjHasFiles (I->Obj)) {
Error ("Invalid import size in for `%s', imported from %s(%lu): 0x%02X",
GetString (I->Name),
GetSourceFileName (I->Obj, I->Pos.Name),
I->Pos.Line,
I->AddrSize);
} else {
Error ("Invalid import size in for `%s', imported from %s: 0x%02X",
GetString (I->Name),
GetObjFileName (I->Obj),
I->AddrSize);
}
}
/* Return the new import */
return I;
}
void InsertImport (Import* I)
/* Insert an import into the table */
{
Export* E;
/* As long as the import is not inserted, V.Name is valid */
unsigned Name = I->Name;
/* Create a hash value for the given name */
unsigned Hash = (Name & HASHTAB_MASK);
/* Search through the list in that slot and print matching duplicates */
if (HashTab[Hash] == 0) {
/* The slot is empty, we need to insert a dummy export */
E = HashTab[Hash] = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
++ExpCount;
} else {
E = HashTab [Hash];
while (1) {
if (E->Name == Name) {
/* We have an entry, L points to it */
break;
}
if (E->Next == 0) {
/* End of list an entry not found, insert a dummy */
E->Next = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0);
E = E->Next; /* Point to dummy */
++ExpCount; /* One export more */
break;
} else {
E = E->Next;
}
}
}
/* Ok, E now points to a valid exports entry for the given import. Insert
* the import into the imports list and update the counters.
*/
I->Exp = E;
I->Next = E->ImpList;
E->ImpList = I;
E->ImpCount++;
++ImpCount; /* Total import count */
if (E->Expr == 0) {
/* This is a dummy export */
++ImpOpen;
}
/* Mark the import so we know it's in the list */
I->Flags |= IMP_INLIST;
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/

View File

@@ -6,10 +6,10 @@
/* */
/* */
/* */
/* (C) 1998-2003 Ullrich von Bassewitz */
/* R<EFBFBD>merstra<EFBFBD>e 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -114,6 +114,9 @@ void FreeImport (Import* I);
Import* ReadImport (FILE* F, ObjData* Obj);
/* Read an import from a file and insert it into the table */
Import* GenImport (const char* Name, unsigned char AddrSize);
/* Generate a new import with the given name and address size and return it */
void InsertImport (Import* I);
/* Insert an import into the table */

View File

@@ -1,15 +1,15 @@
/*****************************************************************************/
/* */
/* main.c */
/* */
/* */
/* main.c */
/* */
/* Main program for the ld65 linker */
/* */
/* */
/* */
/* (C) 1998-2005 Ullrich von Bassewitz */
/* R<EFBFBD>merstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* */
/* (C) 1998-2009, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
@@ -39,6 +39,7 @@
#include <errno.h>
/* common */
#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
#include "filetype.h"
@@ -114,6 +115,7 @@ static void Usage (void)
" --define sym=val\tDefine a symbol\n"
" --dump-config name\tDump a builtin configuration\n"
" --end-group\t\tEnd a library group\n"
" --force-import sym\tForce an import of symbol `sym'\n"
" --help\t\tHelp (this text)\n"
" --lib file\t\tLink this library\n"
" --lib-path path\tSpecify a library search path\n"
@@ -335,7 +337,7 @@ static void OptDumpConfig (const char* Opt attribute ((unused)), const char* Arg
static void OptEndGroup (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
const char* Arg attribute ((unused)))
/* End a library group */
{
LibEndGroup ();
@@ -343,6 +345,44 @@ static void OptEndGroup (const char* Opt attribute ((unused)),
static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg)
/* Force an import of a symbol */
{
/* An optional address size may be specified */
const char* ColPos = strchr (Arg, ':');
if (ColPos == 0) {
/* Use default address size (which for now is always absolute
* addressing)
*/
InsertImport (GenImport (Arg, ADDR_SIZE_ABS));
} else {
char* A;
/* Get the address size and check it */
unsigned char AddrSize = AddrSizeFromStr (ColPos+1);
if (AddrSize == ADDR_SIZE_INVALID) {
Error ("Invalid address size `%s'", ColPos+1);
}
/* Create a copy of the argument */
A = xstrdup (Arg);
/* We need just the symbol */
A[ColPos - Arg] = '\0';
/* Generate the import */
InsertImport (GenImport (A, AddrSize));
/* Delete the copy of the argument */
xfree (A);
}
}
static void OptHelp (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* Print usage information and exit */
@@ -466,6 +506,7 @@ int main (int argc, char* argv [])
{ "--define", 1, OptDefine },
{ "--dump-config", 1, OptDumpConfig },
{ "--end-group", 0, OptEndGroup },
{ "--force-import", 1, OptForceImport },
{ "--help", 0, OptHelp },
{ "--lib", 1, OptLib },
{ "--lib-path", 1, OptLibPath },