From 90ca5c1af97aaa4f3897ed643fa090450844a205 Mon Sep 17 00:00:00 2001 From: cuz Date: Sat, 1 Dec 2001 17:14:12 +0000 Subject: [PATCH] Added o65 symbol export capability git-svn-id: svn://svn.cc65.org/cc65/trunk@1127 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ld65/cfg/lunix.cfg | 4 +- src/ld65/config.c | 26 +++++--- src/ld65/exports.c | 12 +++- src/ld65/exports.h | 10 ++- src/ld65/o65.c | 139 ++++++++++++++++++++++++++++++++--------- 5 files changed, 147 insertions(+), 44 deletions(-) diff --git a/src/ld65/cfg/lunix.cfg b/src/ld65/cfg/lunix.cfg index b66e31988..610b16e49 100644 --- a/src/ld65/cfg/lunix.cfg +++ b/src/ld65/cfg/lunix.cfg @@ -22,7 +22,9 @@ FILES { %O: format = o65; } FORMATS { - o65: os = lunix, type = small, import = LUNIXKERNAL, import = LIB6502; + o65: os = lunix, type = small, + import = LUNIXKERNAL, import = LIB6502, + export = _main; } SYMBOLS { __STACKSIZE__ = $800; # 2K stack diff --git a/src/ld65/config.c b/src/ld65/config.c index c8aa03b45..fc4fc04e7 100644 --- a/src/ld65/config.c +++ b/src/ld65/config.c @@ -833,6 +833,10 @@ static void ParseO65 (void) case CFGTOK_EXPORT: /* We expect an identifier */ CfgAssureIdent (); + /* Check if the export symbol is also defined as an import. */ + if (O65GetImport (O65FmtDesc, CfgSVal) != 0) { + CfgError ("Exported symbol `%s' cannot be an import", CfgSVal); + } /* Check if we have this symbol defined already. The entry * routine will check this also, but we get a more verbose * error message when checking it here. @@ -847,15 +851,19 @@ static void ParseO65 (void) case CFGTOK_IMPORT: /* We expect an identifier */ CfgAssureIdent (); - /* Check if we have this symbol defined already. The entry - * routine will check this also, but we get a more verbose - * error message when checking it here. - */ - if (O65GetImport (O65FmtDesc, CfgSVal) != 0) { - CfgError ("Duplicate imported symbol: `%s'", CfgSVal); - } - /* Insert the symbol into the table */ - O65SetImport (O65FmtDesc, CfgSVal); + /* Check if the imported symbol is also defined as an export. */ + if (O65GetExport (O65FmtDesc, CfgSVal) != 0) { + CfgError ("Imported symbol `%s' cannot be an export", CfgSVal); + } + /* Check if we have this symbol defined already. The entry + * routine will check this also, but we get a more verbose + * error message when checking it here. + */ + if (O65GetImport (O65FmtDesc, CfgSVal) != 0) { + CfgError ("Duplicate imported symbol: `%s'", CfgSVal); + } + /* Insert the symbol into the table */ + O65SetImport (O65FmtDesc, CfgSVal); break; case CFGTOK_TYPE: diff --git a/src/ld65/exports.c b/src/ld65/exports.c index ad426d238..6518bcaf9 100644 --- a/src/ld65/exports.c +++ b/src/ld65/exports.c @@ -400,9 +400,9 @@ Export* CreateSegExport (const char* Name, Section* Sec, unsigned long Offs) -static Export* FindExport (const char* Name) +Export* FindExport (const char* Name) /* Check for an identifier in the list. Return 0 if not found, otherwise - * return a pointer to the export. + * return a pointer to the export. */ { /* Get a pointer to the list with the symbols hash value */ @@ -426,8 +426,14 @@ int IsUnresolved (const char* Name) /* Check if this symbol is an unresolved export */ { /* Find the export */ - Export* E = FindExport (Name); + return IsUnresolvedExport (FindExport (Name)); +} + + +int IsUnresolvedExport (const Export* E) +/* Return true if the given export is unresolved */ +{ /* Check if it's unresolved */ return E != 0 && E->Expr == 0; } diff --git a/src/ld65/exports.h b/src/ld65/exports.h index 7204f8c8e..1a0e1a008 100644 --- a/src/ld65/exports.h +++ b/src/ld65/exports.h @@ -126,10 +126,18 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs); Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs); /* Create a relative export to a segment (section) */ +Export* FindExport (const char* Name); +/* Check for an identifier in the list. Return 0 if not found, otherwise + * return a pointer to the export. + */ + int IsUnresolved (const char* Name); /* Check if this symbol is an unresolved export */ -int IsConstExport (const Export* E); +int IsUnresolvedExport (const Export* E); +/* Return true if the given export is unresolved */ + +int IsConstExport (const Export* E); /* Return true if the expression associated with this export is const */ long GetExportVal (const Export* E); diff --git a/src/ld65/o65.c b/src/ld65/o65.c index aadfe2fe3..123bad624 100644 --- a/src/ld65/o65.c +++ b/src/ld65/o65.c @@ -130,7 +130,7 @@ struct O65RelocTab { /* Structure describing the format */ struct O65Desc { - O65Header Header; /* File header */ + O65Header Header; /* File header */ O65Option* Options; /* List of file options */ ExtSymTab* Exports; /* Table with exported symbols */ ExtSymTab* Imports; /* Table with imported symbols */ @@ -168,18 +168,31 @@ struct ExprDesc { /*****************************************************************************/ -/* Helper functions */ +/* Helper functions */ /*****************************************************************************/ +static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D) +/* Initialize an ExprDesc structure for use with O65ParseExpr */ +{ + ED->D = D; + ED->Val = 0; + ED->TooComplex = 0; + ED->SegRef = 0; + ED->ExtRef = 0; + return ED; +} + + + static void WriteSize (const O65Desc* D, unsigned long Val) /* Write a "size" word to the file */ { - if (D->Header.Mode & MF_SIZE_32BIT) { - Write32 (D->F, Val); - } else { - Write16 (D->F, (unsigned) Val); + switch (D->Header.Mode & MF_SIZE_MASK) { + case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break; + case MF_SIZE_32BIT: Write32 (D->F, Val); break; + default: Internal ("Invalid size in header: %04X", D->Header.Mode); } } @@ -297,7 +310,7 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) } } else { MarkExport (E); - O65ParseExpr (E->Expr, D, Sign); + O65ParseExpr (E->Expr, D, Sign); UnmarkExport (E); } break; @@ -437,7 +450,7 @@ static void FreeO65Option (O65Option* O) /*****************************************************************************/ -/* Subroutines to write o65 sections */ +/* Subroutines to write o65 sections */ /*****************************************************************************/ @@ -529,15 +542,8 @@ static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, Expr = E->Left; } - /* Initialize the descriptor for expression parsing */ - ED.D = D; - ED.Val = 0; - ED.TooComplex = 0; - ED.SegRef = 0; - ED.ExtRef = 0; - /* Recursively collect information about this expression */ - O65ParseExpr (Expr, &ED, 1); + O65ParseExpr (Expr, InitExprDesc (&ED, D), 1); /* We cannot handle both, an imported symbol and a segment ref */ if (ED.SegRef != 0 && ED.ExtRef != 0) { @@ -749,20 +755,20 @@ static void O65WriteZPSeg (O65Desc* D, Memory* M attribute ((unused))) static void O65WriteImports (O65Desc* D) /* Write the list of imported symbols to the O65 file */ { - const ExtSym* E; + const ExtSym* S; - /* Write the number of external symbols */ + /* Write the number of imports */ WriteSize (D, ExtSymCount (D->Imports)); /* Write out the symbol names, zero terminated */ - E = ExtSymList (D->Imports); - while (E) { - /* Get the name */ - const char* Name = ExtSymName (E); - /* And write it to the output file */ - WriteData (D->F, Name, strlen (Name) + 1); - /* Next symbol */ - E = ExtSymNext (E); + S = ExtSymList (D->Imports); + while (S) { + /* Get the name */ + const char* Name = ExtSymName (S); + /* And write it to the output file */ + WriteData (D->F, Name, strlen (Name) + 1); + /* Next symbol */ + S = ExtSymNext (S); } } @@ -787,10 +793,75 @@ static void O65WriteDataReloc (O65Desc* D) static void O65WriteExports (O65Desc* D) /* Write the list of exports */ { - /* Since ld65 creates exectutables, not object files, we do not have - * exports. This may change if we support writing shared libraries... - */ - WriteSize (D, 0); + const ExtSym* S; + + /* Write the number of exports */ + WriteSize (D, ExtSymCount (D->Exports)); + + /* Write out the symbol information */ + S = ExtSymList (D->Exports); + while (S) { + + ExprNode* Expr; + unsigned char SegmentID; + ExprDesc ED; + + /* Get the name */ + const char* Name = ExtSymName (S); + + /* Get the export for this symbol. We've checked before that this + * export does really exist, so if it is unresolved, or if we don't + * find it, there is an error in the linker code. + */ + Export* E = FindExport (Name); + if (E == 0 || IsUnresolvedExport (E)) { + Internal ("Unresolved export `%s' found in O65WriteExports", Name); + } + + /* Get the expression for the symbol */ + Expr = E->Expr; + + /* Recursively collect information about this expression */ + O65ParseExpr (Expr, InitExprDesc (&ED, D), 1); + + /* We cannot handle expressions with imported symbols here */ + if (ED.ExtRef != 0) { + ED.TooComplex = 1; + } + + /* Bail out if we cannot handle the expression */ + if (ED.TooComplex) { + Error ("Expression for symbol `%s' is too complex", Name); + } + + /* Determine the segment id for the expression */ + if (ED.SegRef == 0) { + /* Absolute value */ + SegmentID = O65SEG_ABS; + } else { + /* Segment reference. Search for the segment and map it to it's + * o65 segmentID + */ + const SegDesc* Seg = O65FindSeg (D, ED.SegRef->Seg); + if (Seg == 0) { + /* For some reason, we didn't find this segment in the list of + * segments written to the o65 file. + */ + Error ("Segment for symbol `%s' is undefined", Name); + } + SegmentID = O65SegType (Seg); + } + + /* Write the name to the output file */ + WriteData (D->F, Name, strlen (Name) + 1); + + /* Output the segment id followed by the literal value */ + Write8 (D->F, SegmentID); + WriteSize (D, ED.Val); + + /* Next symbol */ + S = ExtSymNext (S); + } } @@ -992,6 +1063,14 @@ ExtSym* O65GetExport (O65Desc* D, const char* Ident) void O65SetExport (O65Desc* D, const char* Ident) /* Set an exported identifier */ { + /* Get the export for this symbol and check if it does exist and is + * a resolved symbol. + */ + Export* E = FindExport (Ident); + if (E == 0 || IsUnresolvedExport (E)) { + Error ("Unresolved export: `%s'", Ident); + } + /* Insert the entry into the table */ NewExtSym (D->Exports, Ident); } -- 2.39.5