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:
@@ -77,6 +77,7 @@ Long options:
|
|||||||
--define sym=val Define a symbol
|
--define sym=val Define a symbol
|
||||||
--dump-config name Dump a builtin configuration
|
--dump-config name Dump a builtin configuration
|
||||||
--end-group End a library group
|
--end-group End a library group
|
||||||
|
--force-import sym Force an import of symbol `sym'
|
||||||
--help Help (this text)
|
--help Help (this text)
|
||||||
--lib file Link this library
|
--lib file Link this library
|
||||||
--lib-path path Specify a library search path
|
--lib-path path Specify a library search path
|
||||||
@@ -263,6 +264,22 @@ Here is a description of all the command line options:
|
|||||||
file and it's contents are subject to change without further notice.
|
file and it's contents are subject to change without further notice.
|
||||||
|
|
||||||
|
|
||||||
|
<tag><tt>--force-import sym[:addrsize]</tt></tag>
|
||||||
|
|
||||||
|
Force an import of a symbol. While object files are always linked to the
|
||||||
|
output file, regardless if there are any references, object modules from
|
||||||
|
libraries get only linked in if an import can be satisfied by this module.
|
||||||
|
The <tt/--fore-import/ option may be used to add a reference to a symbol and
|
||||||
|
as a result force linkage of the module that exports the identifier.
|
||||||
|
|
||||||
|
The name of the symbol may be followed by a colon and an address size
|
||||||
|
specifier. If no address size is specified, the default address size
|
||||||
|
for the target machine is used.
|
||||||
|
|
||||||
|
Please note that the symbol name needs to have the internal representation,
|
||||||
|
meaning you have to prepend an underline for C identifiers.
|
||||||
|
|
||||||
|
|
||||||
<tag><tt>--lib file</tt></tag>
|
<tag><tt>--lib file</tt></tag>
|
||||||
|
|
||||||
Links a library to the output. Use this command line option instead of just
|
Links a library to the output. Use this command line option instead of just
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2008 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
@@ -106,6 +106,7 @@ static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
|
|||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
I->Next = 0;
|
I->Next = 0;
|
||||||
I->Obj = Obj;
|
I->Obj = Obj;
|
||||||
|
InitFilePos (&I->Pos);
|
||||||
I->Exp = 0;
|
I->Exp = 0;
|
||||||
I->Name = INVALID_STRING_ID;
|
I->Name = INVALID_STRING_ID;
|
||||||
I->Flags = 0;
|
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)
|
void FreeImport (Import* I)
|
||||||
/* Free an import. NOTE: This won't remove the import from the exports table,
|
/* 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
|
* 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 */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* R<EFBFBD>merstra<EFBFBD>e 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@@ -114,6 +114,9 @@ void FreeImport (Import* I);
|
|||||||
Import* ReadImport (FILE* F, ObjData* Obj);
|
Import* ReadImport (FILE* F, ObjData* Obj);
|
||||||
/* Read an import from a file and insert it into the table */
|
/* 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);
|
void InsertImport (Import* I);
|
||||||
/* Insert an import into the table */
|
/* Insert an import into the table */
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2005 Ullrich von Bassewitz */
|
/* (C) 1998-2009, Ullrich von Bassewitz */
|
||||||
/* R<EFBFBD>merstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "addrsize.h"
|
||||||
#include "chartype.h"
|
#include "chartype.h"
|
||||||
#include "cmdline.h"
|
#include "cmdline.h"
|
||||||
#include "filetype.h"
|
#include "filetype.h"
|
||||||
@@ -114,6 +115,7 @@ static void Usage (void)
|
|||||||
" --define sym=val\tDefine a symbol\n"
|
" --define sym=val\tDefine a symbol\n"
|
||||||
" --dump-config name\tDump a builtin configuration\n"
|
" --dump-config name\tDump a builtin configuration\n"
|
||||||
" --end-group\t\tEnd a library group\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"
|
" --help\t\tHelp (this text)\n"
|
||||||
" --lib file\t\tLink this library\n"
|
" --lib file\t\tLink this library\n"
|
||||||
" --lib-path path\tSpecify a library search path\n"
|
" --lib-path path\tSpecify a library search path\n"
|
||||||
@@ -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)),
|
static void OptHelp (const char* Opt attribute ((unused)),
|
||||||
const char* Arg attribute ((unused)))
|
const char* Arg attribute ((unused)))
|
||||||
/* Print usage information and exit */
|
/* Print usage information and exit */
|
||||||
@@ -466,6 +506,7 @@ int main (int argc, char* argv [])
|
|||||||
{ "--define", 1, OptDefine },
|
{ "--define", 1, OptDefine },
|
||||||
{ "--dump-config", 1, OptDumpConfig },
|
{ "--dump-config", 1, OptDumpConfig },
|
||||||
{ "--end-group", 0, OptEndGroup },
|
{ "--end-group", 0, OptEndGroup },
|
||||||
|
{ "--force-import", 1, OptForceImport },
|
||||||
{ "--help", 0, OptHelp },
|
{ "--help", 0, OptHelp },
|
||||||
{ "--lib", 1, OptLib },
|
{ "--lib", 1, OptLib },
|
||||||
{ "--lib-path", 1, OptLibPath },
|
{ "--lib-path", 1, OptLibPath },
|
||||||
|
|||||||
Reference in New Issue
Block a user