This commit is contained in:
Jarhmander 2024-05-03 16:00:18 +02:00 committed by GitHub
commit 22b73a7e3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 202 additions and 100 deletions

View File

@ -4156,6 +4156,28 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<tt><ref id=".OUT" name=".OUT"></tt>
<sect1><tt>.WEAK</tt><label id=".WEAK"><p>
Declare or make an existing symbol weak. Weak symbols can be overriden by a
"strong" (regular) symbol or other weak symbols at the link stage. Note that
redefinition of a symbol is still not allowed within the same source file,
even for weak ones.
You don't need to use an additional <tt><ref id=".GLOBAL" name=".GLOBAL"></tt>
statement, this is implied by <tt/.WEAK/.
Example:
<tscreen><verb>
.weak NumDisks
NumDisks = 1 ; NumDisks has a default value of 1, but another source
; file may override it.
</verb></tscreen>
See also: <tt><ref id=".GLOBAL" name=".GLOBAL"></tt>
<sect1><tt>.WORD</tt><label id=".WORD"><p>
Define word sized data. Must be followed by a sequence of (word ranged,

View File

@ -2000,6 +2000,14 @@ static void DoWarning (void)
static void DoWeak (void)
/* Declare a weak symbol */
{
ExportImport (SymGlobal, ADDR_SIZE_DEFAULT, SF_WEAK);
}
static void DoWord (void)
/* Define words */
{
@ -2203,6 +2211,7 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoUnion },
{ ccNone, DoUnexpected }, /* .VERSION */
{ ccNone, DoWarning },
{ ccNone, DoWeak },
{ ccNone, DoWord },
{ ccNone, DoUnexpected }, /* .XMATCH */
{ ccNone, DoZeropage },

View File

@ -300,6 +300,7 @@ struct DotKeyword {
{ ".UNION", TOK_UNION },
{ ".VERSION", TOK_VERSION },
{ ".WARNING", TOK_WARNING },
{ ".WEAK", TOK_WEAK },
{ ".WORD", TOK_WORD },
{ ".XMATCH", TOK_XMATCH },
{ ".XOR", TOK_BOOLXOR },

View File

@ -452,6 +452,11 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
return;
}
/* In any case, mark the symbol as "weak", if it is not an import. This will
** allow declaring a global or an export, then "weaken" it afterwards.
*/
S->Flags |= (Flags & SF_WEAK);
/* If the symbol is already an export: If it is not defined, the address
** sizes must match.
*/
@ -738,6 +743,9 @@ unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
if (S->Flags & SF_IMPORT) {
Flags |= SYM_IMPORT;
}
if (S->Flags & SF_WEAK) {
Flags |= SYM_WEAK;
}
/* Return the result */
return Flags;

View File

@ -71,6 +71,7 @@ struct HLLDbgSym;
#define SF_VAR 0x0080 /* Variable symbol */
#define SF_FORCED 0x0100 /* Forced import, SF_IMPORT also set */
#define SF_FIXED 0x0200 /* May not be trampoline */
#define SF_WEAK 0x0400 /* Weak symbol */
#define SF_MULTDEF 0x1000 /* Multiply defined symbol */
#define SF_DEFINED 0x2000 /* Defined */
#define SF_REFERENCED 0x4000 /* Referenced */

View File

@ -265,6 +265,7 @@ typedef enum token_t {
TOK_UNION,
TOK_VERSION,
TOK_WARNING,
TOK_WEAK,
TOK_WORD,
TOK_XMATCH,
TOK_ZEROPAGE,

View File

@ -98,6 +98,12 @@
#define SYM_IS_IMPORT(x) (((x) & SYM_MASK_IMPORT) == SYM_IMPORT)
/* Weak symbols */
#define SYM_WEAK 0x0200U /* Weak */
#define SYM_MASK_WEAK 0x0200U /* Value mask */
#define SYM_IS_WEAK(x) (((x) & SYM_MASK_WEAK) == SYM_WEAK)
/* End of symdefs.h */

View File

@ -88,7 +88,7 @@ static Export** ExpPool = 0; /* Exports array */
/*****************************************************************************/
/* Import handling */
/* Symbol table handling */
/*****************************************************************************/
@ -99,6 +99,114 @@ static Export* NewExport (unsigned Type, unsigned char AddrSize,
static void UpdateExportsInImportList (Export *E)
/* Update all exports in the given export's import list */
{
Import* I = E->ImpList;
while (I) {
I->Exp = E;
I = I->Next;
}
}
static Export** GetExportRefRaw (unsigned Name)
/* Check for an identifier in the symbol table and return the pointer to its
** preceding chain pointer. If the element is not found, the last pointer in
** the chain is returned.
**/
{
/* Pointer to the first chain in the bucket. */
Export** Ref = &HashTab[Name & HASHTAB_MASK];
Export* E;
while (1)
{
E = *Ref;
/* Either its the end of chain, or the element is found. */
if (E == 0 || E->Name == Name)
return Ref;
/* Go to the next element in the chain. */
Ref = &E->Next;
}
}
static Export* InsertExportAt (Export** Ref, Export* Value)
/* Insert an export at a given position */
{
/* Value must not be NULL */
PRECONDITION (Value != 0);
/* Not at end of chain? */
if (*Ref != 0) {
/* Point to the rest of the chain. */
Value->Next = (*Ref)->Next;
}
*Ref = Value;
++ExpCount; /* One more export */
return Value;
}
static Export* ReplaceExportAt (Export** Ref, Export* Value)
/* Replace the given export by another one */
{
/* Value must not be NULL */
PRECONDITION (Value != 0);
Export* E = *Ref;
/* At end of chain? */
if (E == 0) {
/* Treat it as an insertion and quit */
return InsertExportAt (Ref, Value);
}
Value->Next = E->Next;
Value->ImpCount = E->ImpCount;
Value->ImpList = E->ImpList;
*Ref = Value;
xfree (E);
/* We must run through the import list and change the
** export pointer now.
*/
UpdateExportsInImportList (Value);
return Value;
}
static Export* GetOrCreateExport (unsigned Name)
/* Try to find an export, create one if it doesn't exist */
{
Export** Ref = GetExportRefRaw (Name);
/* Not found? */
if (*Ref == 0) {
/* Insert a dummy export */
InsertExportAt (Ref, NewExport (0, ADDR_SIZE_DEFAULT, Name, 0));
}
return *Ref;
}
/*****************************************************************************/
/* Import handling */
/*****************************************************************************/
static Import* NewImport (unsigned char AddrSize, ObjData* Obj)
/* Create a new import and initialize it */
{
@ -213,41 +321,10 @@ Import* GenImport (unsigned Name, unsigned char AddrSize)
Import* InsertImport (Import* I)
/* Insert an import into the table, return I */
{
Export* E;
/* As long as the import is not inserted, V.Name is valid */
unsigned Name = I->Name;
Export* E = GetOrCreateExport (I->Name);
/* Create a hash value for the given name */
unsigned Hash = (Name & HASHTAB_MASK);
/* Search through the list in that slot for a symbol with that name */
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.
*/
/* Insert the import into the imports list and update the counters. */
I->Exp = E;
I->Next = E->ImpList;
E->ImpList = I;
@ -281,7 +358,7 @@ const LineInfo* GetImportPos (const Import* Imp)
/*****************************************************************************/
/* Code */
/* Export handling */
/*****************************************************************************/
@ -430,10 +507,8 @@ Export* ReadExport (FILE* F, ObjData* O)
void InsertExport (Export* E)
/* Insert an exported identifier and check if it's already in the list */
{
Export** ExportRef;
Export* L;
Export* Last;
Import* Imp;
unsigned Hash;
/* Mark the export as inserted */
E->Flags |= EXP_INLIST;
@ -443,59 +518,45 @@ void InsertExport (Export* E)
ConDesAddExport (E);
}
/* Create a hash value for the given name */
Hash = (E->Name & HASHTAB_MASK);
/* Search through the list in that slot */
if (HashTab[Hash] == 0) {
/* The slot is empty */
HashTab[Hash] = E;
++ExpCount;
ExportRef = GetExportRefRaw (E->Name);
L = *ExportRef;
if (L == 0) {
/* The symbol was not found, so store the export in the symbol table. */
InsertExportAt (ExportRef, E);
} else {
Last = 0;
L = HashTab[Hash];
do {
if (L->Name == E->Name) {
/* This may be an unresolved external */
if (L->Expr == 0) {
/* This *is* an unresolved external. Use the actual export
** in E instead of the dummy one in L.
*/
E->Next = L->Next;
E->ImpCount = L->ImpCount;
E->ImpList = L->ImpList;
if (Last) {
Last->Next = E;
} else {
HashTab[Hash] = E;
}
ImpOpen -= E->ImpCount; /* Decrease open imports now */
xfree (L);
/* We must run through the import list and change the
** export pointer now.
*/
Imp = E->ImpList;
while (Imp) {
Imp->Exp = E;
Imp = Imp->Next;
}
} else if (AllowMultDef == 0) {
/* Duplicate entry, this is fatal unless allowed by the user */
Error ("Duplicate external identifier: '%s'",
GetString (L->Name));
}
return;
/* Unresolved external, weak symbol or ODR (One Definition Rule)
** violation?
*/
if (L->Expr == 0) {
/* This *is* an unresolved external. Use the actual export
** in E instead of the dummy one in L.
*/
ReplaceExportAt (ExportRef, E);
ImpOpen -= E->ImpCount; /* Decrease open imports now */
} else if (SYM_IS_WEAK (L->Type)) {
/* The existing export is a weak symbol. Override it with the new
** symbol (strong or weak) without any fuss.
*/
ReplaceExportAt (ExportRef, E);
} else {
/* Here the existing export is "strong" (not weak). If the new
** symbol is weak, *or* we explicitely specified at the command-line
** that we allow multiple definitions (which effectively make all
** symbols weak) then that's OK and we can ignore the new weak
** symbol.
*/
if (!SYM_IS_WEAK (E->Type) && AllowMultDef == 0) {
/* Both the existing export and the new symbol are strong, so
** this is an ODR violation.
*/
Error ("Duplicate external identifier: '%s'",
GetString (L->Name));
}
Last = L;
L = L->Next;
} while (L);
/* Insert export at end of queue */
Last->Next = E;
++ExpCount;
xfree (E);
}
}
}
@ -609,19 +670,8 @@ Export* FindExport (unsigned Name)
** return a pointer to the export.
*/
{
/* Get a pointer to the list with the symbols hash value */
Export* L = HashTab[Name & HASHTAB_MASK];
while (L) {
/* Search through the list in that slot */
if (L->Name == Name) {
/* Entry found */
return L;
}
L = L->Next;
}
/* Not found */
return 0;
/* This gives a end of chain (NULL) or the pointer to the export */
return *GetExportRefRaw (Name);
}

View File

@ -221,6 +221,10 @@ static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes)
case SYM_EXPR: strcat (TypeDesc, ",SYM_EXPR"); break;
}
/* Is the symbol weak? */
if (Flags & SYM_MASK_WEAK) {
strcat (TypeDesc, ",SYM_WEAK");
}
/* Size available? */
if (SYM_HAS_SIZE (Flags)) {
strcat (TypeDesc, ",SYM_SIZE");