From ee6028993e3c7b3d535d7ea17e2ecc14bc179e6b Mon Sep 17 00:00:00 2001 From: uz Date: Thu, 27 Aug 2009 14:43:44 +0000 Subject: [PATCH] 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 --- doc/ld65.sgml | 17 +++++ src/ld65/exports.c | 152 ++++++++++++++++++++++++++++----------------- src/ld65/exports.h | 11 ++-- src/ld65/main.c | 63 +++++++++++++++---- 4 files changed, 170 insertions(+), 73 deletions(-) diff --git a/doc/ld65.sgml b/doc/ld65.sgml index ca431ff6e..27723cd59 100644 --- a/doc/ld65.sgml +++ b/doc/ld65.sgml @@ -77,6 +77,7 @@ Long options: --define sym=val Define a symbol --dump-config name Dump a builtin configuration --end-group End a library group + --force-import sym Force an import of symbol `sym' --help Help (this text) --lib file Link this library --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. + --force-import sym[:addrsize] + + 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 --lib file Links a library to the output. Use this command line option instead of just diff --git a/src/ld65/exports.c b/src/ld65/exports.c index 7a3c120e9..a5415bf82 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -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 */ /*****************************************************************************/ diff --git a/src/ld65/exports.h b/src/ld65/exports.h index 6247691d0..e3c3d89a1 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstraß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 */ diff --git a/src/ld65/main.c b/src/ld65/main.c index b51acefca..7821cdd7b 100644 --- a/src/ld65/main.c +++ b/src/ld65/main.c @@ -1,15 +1,15 @@ /*****************************************************************************/ -/* */ -/* main.c */ -/* */ +/* */ +/* main.c */ +/* */ /* Main program for the ld65 linker */ -/* */ -/* */ -/* */ -/* (C) 1998-2005 Ullrich von Bassewitz */ -/* Rö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 /* 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 }, -- 2.39.5