--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
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>
Links a library to the output. Use this command line option instead of just
/* */
/* */
/* */
-/* (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 */
/* Initialize the fields */
I->Next = 0;
I->Obj = Obj;
+ InitFilePos (&I->Pos);
I->Exp = 0;
I->Name = INVALID_STRING_ID;
I->Flags = 0;
-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
+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 */
/*****************************************************************************/
/* */
/* */
/* */
-/* (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 */
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 */
/*****************************************************************************/
-/* */
-/* 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 */
#include <errno.h>
/* common */
+#include "addrsize.h"
#include "chartype.h"
#include "cmdline.h"
#include "filetype.h"
" --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"
static void OptEndGroup (const char* Opt attribute ((unused)),
- const char* Arg attribute ((unused)))
+ const char* Arg attribute ((unused)))
/* End a library group */
{
LibEndGroup ();
+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 */
{ "--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 },