mirror of
https://github.com/cc65/cc65.git
synced 2025-02-09 17:33:00 +00:00
Added o65 symbol export capability
git-svn-id: svn://svn.cc65.org/cc65/trunk@1127 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
ebbd68673b
commit
90ca5c1af9
@ -22,7 +22,9 @@ FILES {
|
|||||||
%O: format = o65;
|
%O: format = o65;
|
||||||
}
|
}
|
||||||
FORMATS {
|
FORMATS {
|
||||||
o65: os = lunix, type = small, import = LUNIXKERNAL, import = LIB6502;
|
o65: os = lunix, type = small,
|
||||||
|
import = LUNIXKERNAL, import = LIB6502,
|
||||||
|
export = _main;
|
||||||
}
|
}
|
||||||
SYMBOLS {
|
SYMBOLS {
|
||||||
__STACKSIZE__ = $800; # 2K stack
|
__STACKSIZE__ = $800; # 2K stack
|
||||||
|
@ -833,6 +833,10 @@ static void ParseO65 (void)
|
|||||||
case CFGTOK_EXPORT:
|
case CFGTOK_EXPORT:
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
CfgAssureIdent ();
|
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
|
/* Check if we have this symbol defined already. The entry
|
||||||
* routine will check this also, but we get a more verbose
|
* routine will check this also, but we get a more verbose
|
||||||
* error message when checking it here.
|
* error message when checking it here.
|
||||||
@ -847,15 +851,19 @@ static void ParseO65 (void)
|
|||||||
case CFGTOK_IMPORT:
|
case CFGTOK_IMPORT:
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
CfgAssureIdent ();
|
CfgAssureIdent ();
|
||||||
/* Check if we have this symbol defined already. The entry
|
/* Check if the imported symbol is also defined as an export. */
|
||||||
* routine will check this also, but we get a more verbose
|
if (O65GetExport (O65FmtDesc, CfgSVal) != 0) {
|
||||||
* error message when checking it here.
|
CfgError ("Imported symbol `%s' cannot be an export", CfgSVal);
|
||||||
*/
|
}
|
||||||
if (O65GetImport (O65FmtDesc, CfgSVal) != 0) {
|
/* Check if we have this symbol defined already. The entry
|
||||||
CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
|
* routine will check this also, but we get a more verbose
|
||||||
}
|
* error message when checking it here.
|
||||||
/* Insert the symbol into the table */
|
*/
|
||||||
O65SetImport (O65FmtDesc, CfgSVal);
|
if (O65GetImport (O65FmtDesc, CfgSVal) != 0) {
|
||||||
|
CfgError ("Duplicate imported symbol: `%s'", CfgSVal);
|
||||||
|
}
|
||||||
|
/* Insert the symbol into the table */
|
||||||
|
O65SetImport (O65FmtDesc, CfgSVal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CFGTOK_TYPE:
|
case CFGTOK_TYPE:
|
||||||
|
@ -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
|
/* 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 */
|
/* 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 */
|
/* Check if this symbol is an unresolved export */
|
||||||
{
|
{
|
||||||
/* Find the 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 */
|
/* Check if it's unresolved */
|
||||||
return E != 0 && E->Expr == 0;
|
return E != 0 && E->Expr == 0;
|
||||||
}
|
}
|
||||||
|
@ -126,10 +126,18 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
|
|||||||
Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
|
Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
|
||||||
/* Create a relative export to a segment (section) */
|
/* 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);
|
int IsUnresolved (const char* Name);
|
||||||
/* Check if this symbol is an unresolved export */
|
/* 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 */
|
/* Return true if the expression associated with this export is const */
|
||||||
|
|
||||||
long GetExportVal (const Export* E);
|
long GetExportVal (const Export* E);
|
||||||
|
139
src/ld65/o65.c
139
src/ld65/o65.c
@ -130,7 +130,7 @@ struct O65RelocTab {
|
|||||||
|
|
||||||
/* Structure describing the format */
|
/* Structure describing the format */
|
||||||
struct O65Desc {
|
struct O65Desc {
|
||||||
O65Header Header; /* File header */
|
O65Header Header; /* File header */
|
||||||
O65Option* Options; /* List of file options */
|
O65Option* Options; /* List of file options */
|
||||||
ExtSymTab* Exports; /* Table with exported symbols */
|
ExtSymTab* Exports; /* Table with exported symbols */
|
||||||
ExtSymTab* Imports; /* Table with imported 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)
|
static void WriteSize (const O65Desc* D, unsigned long Val)
|
||||||
/* Write a "size" word to the file */
|
/* Write a "size" word to the file */
|
||||||
{
|
{
|
||||||
if (D->Header.Mode & MF_SIZE_32BIT) {
|
switch (D->Header.Mode & MF_SIZE_MASK) {
|
||||||
Write32 (D->F, Val);
|
case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break;
|
||||||
} else {
|
case MF_SIZE_32BIT: Write32 (D->F, Val); break;
|
||||||
Write16 (D->F, (unsigned) Val);
|
default: Internal ("Invalid size in header: %04X", D->Header.Mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +310,7 @@ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MarkExport (E);
|
MarkExport (E);
|
||||||
O65ParseExpr (E->Expr, D, Sign);
|
O65ParseExpr (E->Expr, D, Sign);
|
||||||
UnmarkExport (E);
|
UnmarkExport (E);
|
||||||
}
|
}
|
||||||
break;
|
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;
|
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 */
|
/* 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 */
|
/* We cannot handle both, an imported symbol and a segment ref */
|
||||||
if (ED.SegRef != 0 && ED.ExtRef != 0) {
|
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)
|
static void O65WriteImports (O65Desc* D)
|
||||||
/* Write the list of imported symbols to the O65 file */
|
/* 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));
|
WriteSize (D, ExtSymCount (D->Imports));
|
||||||
|
|
||||||
/* Write out the symbol names, zero terminated */
|
/* Write out the symbol names, zero terminated */
|
||||||
E = ExtSymList (D->Imports);
|
S = ExtSymList (D->Imports);
|
||||||
while (E) {
|
while (S) {
|
||||||
/* Get the name */
|
/* Get the name */
|
||||||
const char* Name = ExtSymName (E);
|
const char* Name = ExtSymName (S);
|
||||||
/* And write it to the output file */
|
/* And write it to the output file */
|
||||||
WriteData (D->F, Name, strlen (Name) + 1);
|
WriteData (D->F, Name, strlen (Name) + 1);
|
||||||
/* Next symbol */
|
/* Next symbol */
|
||||||
E = ExtSymNext (E);
|
S = ExtSymNext (S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,10 +793,75 @@ static void O65WriteDataReloc (O65Desc* D)
|
|||||||
static void O65WriteExports (O65Desc* D)
|
static void O65WriteExports (O65Desc* D)
|
||||||
/* Write the list of exports */
|
/* Write the list of exports */
|
||||||
{
|
{
|
||||||
/* Since ld65 creates exectutables, not object files, we do not have
|
const ExtSym* S;
|
||||||
* exports. This may change if we support writing shared libraries...
|
|
||||||
*/
|
/* Write the number of exports */
|
||||||
WriteSize (D, 0);
|
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)
|
void O65SetExport (O65Desc* D, const char* Ident)
|
||||||
/* Set an exported identifier */
|
/* 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 */
|
/* Insert the entry into the table */
|
||||||
NewExtSym (D->Exports, Ident);
|
NewExtSym (D->Exports, Ident);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user