Ejemplo n.º 1
0
void DumpObjSegments (FILE* F, unsigned long Offset)
/* Dump the segments in the object file */
{
    ObjHeader  H;
    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
    unsigned   Count;
    unsigned   I;

    /* Seek to the header position and read the header */
    FileSetPos (F, Offset);
    ReadObjHeader (F, &H);

    /* Seek to the start of the string pool and read it */
    FileSetPos (F, Offset + H.StrPoolOffs);
    ReadStrPool (F, &StrPool);

    /* Seek to the start of the segments */
    FileSetPos (F, Offset + H.SegOffs);

    /* Output a header */
    printf ("  Segments:\n");

    /* Read the number of segments and print it */
    Count = ReadVar (F);
    printf ("    Count:%27u\n", Count);

    /* Read and print all segments */
    for (I = 0; I < Count; ++I) {

	/* Read the data for one segments */
        unsigned long DataSize  = Read32 (F);
        unsigned long NextSeg   = ftell (F) + DataSize;
       	const char*   Name      = GetString (&StrPool, ReadVar (F));
	unsigned      Len       = strlen (Name);
        unsigned      Flags     = ReadVar (F);
	unsigned long Size      = ReadVar (F);
       	unsigned long Align     = ReadVar (F);
       	unsigned char AddrSize  = Read8 (F);
        unsigned long FragCount = ReadVar (F);

	/* Print the header */
	printf ("    Index:%27u\n", I);

	/* Print the data */
	printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
        printf ("      Flags:%25u\n", Flags);
       	printf ("      Size:%26lu\n", Size);
	printf ("      Alignment:%21lu\n", Align);
	printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
                AddrSizeToStr (AddrSize));
       	printf ("      Fragment count:%16lu\n", FragCount);

        /* Seek to the end of the segment data (start of next) */
        FileSetPos (F, NextSeg);
    }

    /* Destroy the string pool */
    DestroyStrPool (&StrPool);
}
Ejemplo n.º 2
0
static void CheckSymType (const Export* E)
/* Check the types for one export */
{
    /* External with matching imports */
    Import* Imp = E->ImpList;
    while (Imp) {
       	if (E->AddrSize != Imp->AddrSize) {
	    /* Export is ZP, import is abs or the other way round */
            const char* ExpAddrSize = AddrSizeToStr (E->AddrSize);
            const char* ImpAddrSize = AddrSizeToStr (Imp->AddrSize);
            const char* ExpObjName  = GetObjFileName (E->Obj);
            const char* ImpObjName  = GetObjFileName (Imp->Obj);
	    if (E->Obj) {
	      	/* User defined export */
       	       	Warning ("Address size mismatch for `%s': Exported from %s, "
			 "%s(%lu) as `%s', import in %s, %s(%lu) as `%s'",
			 GetString (E->Name),
                         ExpObjName,
                         GetSourceFileName (E->Obj, E->Pos.Name),
    			 E->Pos.Line,
                         ExpAddrSize,
                         ImpObjName,
                         GetSourceFileName (Imp->Obj, Imp->Pos.Name),
		   	 Imp->Pos.Line,
                         ImpAddrSize);
	    } else {
		/* Export created by the linker */
		Warning ("Address size mismatch for `%s': Symbol is `%s'"
                         ", but imported from %s, %s(%lu) as `%s'",
			 GetString (E->Name),
                         ExpAddrSize,
                         ImpObjName,
                         GetSourceFileName (Imp->Obj, Imp->Pos.Name),
			 Imp->Pos.Line,
                         ImpAddrSize);
	    }
	}
	Imp = Imp->Next;
    }
}
Ejemplo n.º 3
0
void DumpObjImports (FILE* F, unsigned long Offset)
/* Dump the imports in the object file */
{
    ObjHeader  H;
    Collection StrPool = AUTO_COLLECTION_INITIALIZER;
    unsigned   Count;
    unsigned   I;

    /* Seek to the header position and read the header */
    FileSetPos (F, Offset);
    ReadObjHeader (F, &H);

    /* Seek to the start of the string pool and read it */
    FileSetPos (F, Offset + H.StrPoolOffs);
    ReadStrPool (F, &StrPool);

    /* Seek to the start of the imports */
    FileSetPos (F, Offset + H.ImportOffs);

    /* Output a header */
    printf ("  Imports:\n");

    /* Read the number of imports and print it */
    Count = ReadVar (F);
    printf ("    Count:%27u\n", Count);

    /* Read and print all imports */
    for (I = 0; I < Count; ++I) {

       	/* Read the data for one import */
       	unsigned char AddrSize = Read8 (F);
       	const char*   Name     = GetString (&StrPool, ReadVar (F));
	unsigned      Len      = strlen (Name);

        /* Skip both line info lists */
        SkipLineInfoList (F);
        SkipLineInfoList (F);

	/* Print the header */
	printf ("    Index:%27u\n", I);

	/* Print the data */
	printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
                AddrSizeToStr (AddrSize));
	printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
    }

    /* Destroy the string pool */
    DestroyStrPool (&StrPool);
}
Ejemplo n.º 4
0
void StartSegment (const char* Name, unsigned AddrSize)
/* Start a segment */
{
    if (Pass == PassCount) {
        Output (".segment");
        Indent (ACol);
        if (AddrSize == ADDR_SIZE_DEFAULT) {
            Output ("\"%s\"", Name);
        } else {
            Output ("\"%s\": %s", Name, AddrSizeToStr (AddrSize));
        }
        LineFeed ();
    }
}
Ejemplo n.º 5
0
void SymDump (FILE* F)
/* Dump the symbol table */
{
    SymEntry* S = SymList;

    while (S) {
        /* Ignore unused symbols */
        if ((S->Flags & SF_UNUSED) == 0) {
            fprintf (F,
                     "%-24s %s %s %s %s %s\n",
                     SB_GetConstBuf (GetSymName (S)),
                     (S->Flags & SF_DEFINED)? "DEF" : "---",
                     (S->Flags & SF_REFERENCED)? "REF" : "---",
                     (S->Flags & SF_IMPORT)? "IMP" : "---",
                     (S->Flags & SF_EXPORT)? "EXP" : "---",
                     AddrSizeToStr (S->AddrSize));
        }
        /* Next symbol */
        S = S->List;
    }
}
Ejemplo n.º 6
0
Archivo: segments.c Proyecto: cc65/cc65
void PrintDbgSegments (FILE* F)
/* Output the segments to the debug file */
{
    /* Walk over all segments */
    unsigned I;
    for (I = 0; I < CollCount (&SegmentList); ++I) {

        /* Get the next segment */
        const Segment* S = CollAtUnchecked (&SegmentList, I);

        /* Print the segment data */
        fprintf (F,
                 "seg\tid=%u,name=\"%s\",start=0x%06lX,size=0x%04lX,addrsize=%s,type=%s",
                 S->Id, GetString (S->Name), S->PC, S->Size,
                 AddrSizeToStr (S->AddrSize),
                 S->ReadOnly? "ro" : "rw");
        if (S->OutputName) {
            fprintf (F, ",oname=\"%s\",ooffs=%lu",
                     S->OutputName, S->OutputOffs);
        }
        fputc ('\n', F);
    }
}
Ejemplo n.º 7
0
void DumpObjDbgSyms (FILE* F, unsigned long Offset)
/* Dump the debug symbols from an object file */
{
    ObjHeader   H;
    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
    unsigned    Count;
    unsigned    I;

    /* Seek to the header position and read the header */
    FileSetPos (F, Offset);
    ReadObjHeader (F, &H);

    /* Seek to the start of the string pool and read it */
    FileSetPos (F, Offset + H.StrPoolOffs);
    ReadStrPool (F, &StrPool);

    /* Seek to the start of the debug syms */
    FileSetPos (F, Offset + H.DbgSymOffs);

    /* Output a header */
    printf ("  Debug symbols:\n");

    /* Check if the object file was compiled with debug info */
    if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) {
	/* Print that there no debug symbols and bail out */
	printf ("    Count:%27u\n", 0);
	return;
    }

    /* Read the number of exports and print it */
    Count = ReadVar (F);
    printf ("    Count:%27u\n", Count);

    /* Read and print all debug symbols */
    for (I = 0; I < Count; ++I) {

    	unsigned long 	Value = 0;
        unsigned long   Size = 0;
        unsigned        ImportId = 0;
        unsigned        ExportId = 0;

       	/* Read the data for one symbol */
       	unsigned Type          = ReadVar (F);
        unsigned char AddrSize = Read8 (F);
        unsigned long Owner    = ReadVar (F);
       	const char*   Name     = GetString (&StrPool, ReadVar (F));
	unsigned      Len      = strlen (Name);
	if (SYM_IS_CONST (Type)) {
	    Value = Read32 (F);
	} else {
	    SkipExpr (F);
	}
        if (SYM_HAS_SIZE (Type)) {
            Size = ReadVar (F);
        }
        if (SYM_IS_IMPORT (Type)) {
            ImportId = ReadVar (F);
        }
        if (SYM_IS_EXPORT (Type)) {
            ExportId = ReadVar (F);
        }

        /* Skip both line info lists */
        SkipLineInfoList (F);
        SkipLineInfoList (F);

	/* Print the header */
	printf ("    Index:%27u\n", I);

	/* Print the data */
       	printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, 0));
	printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
                AddrSizeToStr (AddrSize));
       	printf ("      Owner:%25lu\n", Owner);
	printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
	if (SYM_IS_CONST (Type)) {
	    printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
	}
       	if (SYM_HAS_SIZE (Type)) {
	    printf ("      Size:%20s0x%04lX  (%lu)\n", "", Size, Size);
	}
       	if (SYM_IS_IMPORT (Type)) {
	    printf ("      Import:%24u\n", ImportId);
	}
       	if (SYM_IS_EXPORT (Type)) {
	    printf ("      Export:%24u\n", ExportId);
	}
    }

    /* Destroy the string pool */
    DestroyStrPool (&StrPool);
}
Ejemplo n.º 8
0
void DumpObjExports (FILE* F, unsigned long Offset)
/* Dump the exports in the object file */
{
    ObjHeader 	H;
    Collection  StrPool = AUTO_COLLECTION_INITIALIZER;
    unsigned   	Count;
    unsigned   	I;

    /* Seek to the header position and read the header */
    FileSetPos (F, Offset);
    ReadObjHeader (F, &H);

    /* Seek to the start of the string pool and read it */
    FileSetPos (F, Offset + H.StrPoolOffs);
    ReadStrPool (F, &StrPool);

    /* Seek to the start of the exports */
    FileSetPos (F, Offset + H.ExportOffs);

    /* Output a header */
    printf ("  Exports:\n");

    /* Read the number of exports and print it */
    Count = ReadVar (F);
    printf ("    Count:%27u\n", Count);

    /* Read and print all exports */
    for (I = 0; I < Count; ++I) {

	unsigned long 	Value = 0;
        unsigned long   Size = 0;
       	unsigned char  	ConDes[CD_TYPE_COUNT];
       	const char*    	Name;
	unsigned	Len;


       	/* Read the data for one export */
       	unsigned Type          = ReadVar (F);
        unsigned char AddrSize = Read8 (F);
	ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));
       	Name  = GetString (&StrPool, ReadVar (F));
	Len   = strlen (Name);
       	if (SYM_IS_CONST (Type)) {
	    Value = Read32 (F);
	} else {
       	    SkipExpr (F);
	}
        if (SYM_HAS_SIZE (Type)) {
            Size = ReadVar (F);
        }

        /* Skip both line infos lists */
        SkipLineInfoList (F);
        SkipLineInfoList (F);

	/* Print the header */
	printf ("    Index:%27u\n", I);

	/* Print the data */
       	printf ("      Type:%22s0x%02X  (%s)\n", "", Type, GetExportFlags (Type, ConDes));
	printf ("      Address size:%14s0x%02X  (%s)\n", "", AddrSize,
                AddrSizeToStr (AddrSize));
	printf ("      Name:%*s\"%s\"\n", (int)(24-Len), "", Name);
	if (SYM_IS_CONST (Type)) {
    	    printf ("      Value:%15s0x%08lX  (%lu)\n", "", Value, Value);
    	}
       	if (SYM_HAS_SIZE (Type)) {
	    printf ("      Size:%16s0x%04lX  (%lu)\n", "", Size, Size);
	}
    }

    /* Destroy the string pool */
    DestroyStrPool (&StrPool);
}
Ejemplo n.º 9
0
static void CheckSymType (const Export* E)
/* Check the types for one export */
{
    /* External with matching imports */
    Import* I = E->ImpList;
    while (I) {
        if (E->AddrSize != I->AddrSize) {
            /* Export and import address sizes do not match */
            StrBuf ExportLoc = STATIC_STRBUF_INITIALIZER;
            StrBuf ImportLoc = STATIC_STRBUF_INITIALIZER;
            const char* ExpAddrSize = AddrSizeToStr ((unsigned char) E->AddrSize);
            const char* ImpAddrSize = AddrSizeToStr ((unsigned char) I->AddrSize);
            const LineInfo* ExportLI = GetExportPos (E);
            const LineInfo* ImportLI = GetImportPos (I);

            /* Generate strings that describe the location of the im- and
            ** exports. This depends on the place from where they come:
            ** Object file or linker config.
            */
            if (E->Obj) {
                /* The export comes from an object file */
                SB_Printf (&ExportLoc, "%s, %s(%u)",
                           GetString (E->Obj->Name),
                           GetSourceName (ExportLI),
                           GetSourceLine (ExportLI));
            } else {
                SB_Printf (&ExportLoc, "%s(%u)",
                           GetSourceName (ExportLI),
                           GetSourceLine (ExportLI));
            }
            if (I->Obj) {
                /* The import comes from an object file */
                SB_Printf (&ImportLoc, "%s, %s(%u)",
                           GetString (I->Obj->Name),
                           GetSourceName (ImportLI),
                           GetSourceLine (ImportLI));
            } else if (ImportLI) {
                /* The import is linker generated and we have line
                ** information
                */
                SB_Printf (&ImportLoc, "%s(%u)",
                           GetSourceName (ImportLI),
                           GetSourceLine (ImportLI));
            } else {
                /* The import is linker generated and we don't have line
                ** information
                */
                SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj));
            }

            /* Output the diagnostic */
            Warning ("Address size mismatch for `%s': "
                     "Exported from %s as `%s', "
                     "import in %s as `%s'",
                     GetString (E->Name),
                     SB_GetConstBuf (&ExportLoc),
                     ExpAddrSize,
                     SB_GetConstBuf (&ImportLoc),
                     ImpAddrSize);

            /* Free the temporary strings */
            SB_Done (&ExportLoc);
            SB_Done (&ImportLoc);
        }
        I = I->Next;
    }
}
Ejemplo n.º 10
0
void SymCheck (void)
/* Run through all symbols and check for anomalies and errors */
{
    SymEntry* S;

    /* Check for open scopes */
    if (CurrentScope->Parent != 0) {
        Error ("Local scope was not closed");
    }

    /* First pass: Walk through all symbols, checking for undefined's and
    ** changing them to trampoline symbols or make them imports.
    */
    S = SymList;
    while (S) {
        /* If the symbol is marked as global, mark it as export, if it is
        ** already defined, otherwise mark it as import.
        */
        if (S->Flags & SF_GLOBAL) {
            if (S->Flags & SF_DEFINED) {
                SymExportFromGlobal (S);
            } else {
                SymImportFromGlobal (S);
            }
        }

        /* Handle undefined symbols */
        if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) {
            /* This is an undefined symbol. Handle it. */
            SymCheckUndefined (S);
        }

        /* Next symbol */
        S = S->List;
    }

    /* Second pass: Walk again through the symbols. Count exports and imports
    ** and set address sizes where this has not happened before. Ignore
    ** undefined's, since we handled them in the last pass, and ignore unused
    ** symbols, since we handled them in the last pass, too.
    */
    S = SymList;
    while (S) {
        if ((S->Flags & SF_UNUSED) == 0 &&
            (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) {

            /* Check for defined symbols that were never referenced */
            if (IsSizeOfSymbol (S)) {
                /* Remove line infos, we don't need them any longer */
                ReleaseFullLineInfo (&S->DefLines);
                ReleaseFullLineInfo (&S->RefLines);
            } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) {
                LIWarning (&S->DefLines, 2,
                           "Symbol `%m%p' is defined but never used",
                           GetSymName (S));
            }

            /* Assign an index to all imports */
            if (S->Flags & SF_IMPORT) {
                if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) {
                    /* Imported symbol is not referenced */
                    LIWarning (&S->DefLines, 2,
                               "Symbol `%m%p' is imported but never used",
                               GetSymName (S));
                } else {
                    /* Give the import an id, count imports */
                    S->ImportId = ImportCount++;
                }
            }

            /* Count exports, assign the export ID */
            if (S->Flags & SF_EXPORT) {
                S->ExportId = ExportCount++;
            }

            /* If the symbol is defined but has an unknown address size,
            ** recalculate it.
            */
            if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) {
                ExprDesc ED;
                ED_Init (&ED);
                StudyExpr (S->Expr, &ED);
                S->AddrSize = ED.AddrSize;
                if (SymIsExport (S)) {
                    if (S->ExportSize == ADDR_SIZE_DEFAULT) {
                        /* Use the real export size */
                        S->ExportSize = S->AddrSize;
                    } else if (S->AddrSize > S->ExportSize) {
                        /* We're exporting a symbol smaller than it actually is */
                        LIWarning (&S->DefLines, 1,
                                   "Symbol `%m%p' is %s but exported %s",
                                   GetSymName (S),
                                   AddrSizeToStr (S->AddrSize),
                                   AddrSizeToStr (S->ExportSize));
                    }
                }
                ED_Done (&ED);
            }

            /* If the address size of the symbol was guessed, check the guess
            ** against the actual address size and print a warning if the two
            ** differ.
            */
            if (S->AddrSize != ADDR_SIZE_DEFAULT) {
                /* Do we have data for this address size? */
                if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) {
                    /* Get the file position where the symbol was used */
                    const FilePos* P = S->GuessedUse[S->AddrSize - 1];
                    if (P) {
                        PWarning (P, 0,
                                  "Didn't use %s addressing for `%m%p'",
                                  AddrSizeToStr (S->AddrSize),
                                  GetSymName (S));
                    }
                }
            }

        }

        /* Next symbol */
        S = S->List;
    }
}
Ejemplo n.º 11
0
static void SymCheckUndefined (SymEntry* S)
/* Handle an undefined symbol */
{
    /* Undefined symbol. It may be...
    **
    **   - An undefined symbol in a nested lexical level. If the symbol is not
    **     fixed to this level, search for the symbol in the higher levels and
    **     make the entry a trampoline entry if we find one.
    **
    **   - If the symbol is not found, it is a real undefined symbol. If the
    **     AutoImport flag is set, make it an import. If the AutoImport flag is
    **     not set, it's an error.
    */
    SymEntry* Sym = 0;
    if ((S->Flags & SF_FIXED) == 0) {
        SymTable* Tab = GetSymParentScope (S);
        while (Tab) {
            Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY);
            if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) {
                /* We've found a symbol in a higher level that is
                ** either defined in the source, or an import.
                */
                 break;
            }
            /* No matching symbol found in this level. Look further */
            Tab = Tab->Parent;
        }
    }

    if (Sym) {

        /* We found the symbol in a higher level. Transfer the flags and
        ** address size from the local symbol to that in the higher level
        ** and check for problems.
        */
        if (S->Flags & SF_EXPORT) {
            if (Sym->Flags & SF_IMPORT) {
                /* The symbol is already marked as import */
                LIError (&S->RefLines,
                         "Symbol `%s' is already an import",
                         GetString (Sym->Name));
            }
            if ((Sym->Flags & SF_EXPORT) == 0) {
                /* Mark the symbol as an export */
                Sym->Flags |= SF_EXPORT;
                Sym->ExportSize = S->ExportSize;
                if (Sym->ExportSize == ADDR_SIZE_DEFAULT) {
                    /* Use the actual size of the symbol */
                    Sym->ExportSize = Sym->AddrSize;
                }
                if (Sym->AddrSize > Sym->ExportSize) {
                    /* We're exporting a symbol smaller than it actually is */
                    LIWarning (&Sym->DefLines, 1,
                               "Symbol `%m%p' is %s but exported %s",
                               GetSymName (Sym),
                               AddrSizeToStr (Sym->AddrSize),
                               AddrSizeToStr (Sym->ExportSize));
                }
            }
        }
        if (S->Flags & SF_REFERENCED) {
            /* Mark as referenced and move the line info */
            Sym->Flags |= SF_REFERENCED;
            CollTransfer (&Sym->RefLines, &S->RefLines);
            CollDeleteAll (&S->RefLines);
        }

        /* Transfer all expression references */
        SymTransferExprRefs (S, Sym);

        /* Mark the symbol as unused removing all other flags */
        S->Flags = SF_UNUSED;

    } else {
        /* The symbol is definitely undefined */
        if (S->Flags & SF_EXPORT) {
            /* We will not auto-import an export */
            LIError (&S->RefLines,
                     "Exported symbol `%m%p' was never defined",
                     GetSymName (S));
        } else {
            if (AutoImport) {
                /* Mark as import, will be indexed later */
                S->Flags |= SF_IMPORT;
                /* Use the address size for code */
                S->AddrSize = CodeAddrSize;
                /* Mark point of import */
                GetFullLineInfo (&S->DefLines);
            } else {
                /* Error */
                LIError (&S->RefLines,
                         "Symbol `%m%p' is undefined",
                         GetSymName (S));
            }
        }
    }
}
Ejemplo n.º 12
0
void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as a global symbol, that is, as a symbol that is
** either imported or exported.
*/
{
    if (S->Flags & SF_VAR) {
        /* Variable symbols cannot be exported or imported */
        Error ("Var symbol `%m%p' cannot be made global", GetSymName (S));
        return;
    }

    /* If the symbol is already marked as import, the address size must match.
    ** Apart from that, ignore the global declaration.
    */
    if (S->Flags & SF_IMPORT) {
        if (AddrSize == ADDR_SIZE_DEFAULT) {
            /* Use the size of the current segment */
            AddrSize = GetCurrentSegAddrSize ();
        }
        if (AddrSize != S->AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        return;
    }

    /* If the symbol is already an export: If it is not defined, the address
    ** sizes must match.
    */
    if (S->Flags & SF_EXPORT) {
        if ((S->Flags & SF_DEFINED) == 0) {
            /* Symbol is undefined */
            if (AddrSize != S->ExportSize) {
                Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
            }
        } else if (AddrSize != ADDR_SIZE_DEFAULT) {
            /* Symbol is defined and address size given */
            if (AddrSize != S->ExportSize) {
                Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
            }
        }
        return;
    }

    /* If the symbol is already marked as global, the address size must match.
    ** Use the ExportSize here, since it contains the actual address size
    ** passed to this function.
    */
    if (S->Flags & SF_GLOBAL) {
        if (AddrSize != S->ExportSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        return;
    }

    /* If we come here, the symbol was neither declared as export, import or
    ** global before. Check if it is already defined, in which case it will
    ** become an export. If it is not defined, mark it as global and remember
    ** the given address sizes.
    */
    if (S->Flags & SF_DEFINED) {
        /* The symbol is defined, export it */
        S->ExportSize = AddrSize;
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* No export size given, use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize > S->ExportSize) {
            /* We're exporting a symbol smaller than it actually is */
            Warning (1, "Symbol `%m%p' is %s but exported %s",
                     GetSymName (S), AddrSizeToStr (S->AddrSize),
                     AddrSizeToStr (S->ExportSize));
        }
        S->Flags |= (SF_EXPORT | Flags);
    } else {
        /* Since we don't know if the symbol will get exported or imported,
        ** remember two different address sizes: One for an import in AddrSize,
        ** and the other one for an export in ExportSize.
        */
        S->AddrSize = AddrSize;
        if (S->AddrSize == ADDR_SIZE_DEFAULT) {
            /* Use the size of the current segment */
            S->AddrSize = GetCurrentSegAddrSize ();
        }
        S->ExportSize = AddrSize;
        S->Flags |= (SF_GLOBAL | Flags);

        /* Remember the current location as location of definition in case
        ** an .IMPORT follows later.
        */
        GetFullLineInfo (&S->DefLines);
    }
}
Ejemplo n.º 13
0
void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
/* Mark the given symbol as an exported symbol */
{
    /* Check if it's ok to export the symbol */
    if (S->Flags & SF_IMPORT) {
        /* The symbol is already marked as imported external symbol */
        Error ("Symbol `%m%p' is already an import", GetSymName (S));
        return;
    }
    if (S->Flags & SF_VAR) {
        /* Variable symbols cannot be exported */
        Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
        return;
    }

    /* If the symbol was marked as global before, remove the global flag and
    ** proceed, but check the address size.
    */
    if (S->Flags & SF_GLOBAL) {
        if (AddrSize != S->ExportSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        S->Flags &= ~SF_GLOBAL;

        /* .GLOBAL remembers line infos in case an .IMPORT follows. We have
        ** to remove these here.
        */
        ReleaseFullLineInfo (&S->DefLines);
    }

    /* If the symbol was already marked as an export, but wasn't defined
    ** before, the address sizes in both definitions must match.
    */
    if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) {
        if (S->ExportSize != AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
    }
    S->ExportSize = AddrSize;

    /* If the symbol is already defined, check symbol size against the
    ** exported size.
    */
    if (S->Flags & SF_DEFINED) {
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* No export size given, use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize > S->ExportSize) {
            /* We're exporting a symbol smaller than it actually is */
            Warning (1, "Symbol `%m%p' is %s but exported %s",
                     GetSymName (S), AddrSizeToStr (S->AddrSize),
                     AddrSizeToStr (S->ExportSize));
        }
    }

    /* Set the symbol data */
    S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags);

    /* Remember line info for this reference */
    CollAppend (&S->RefLines, GetAsmLineInfo ());
}
Ejemplo n.º 14
0
void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags)
/* Define a new symbol */
{
    if (S->Flags & SF_IMPORT) {
        /* Defined symbol is marked as imported external symbol */
        Error ("Symbol `%m%p' is already an import", GetSymName (S));
        return;
    }
    if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) {
        /* Variable symbols cannot be exports or globals */
        Error ("Var symbol `%m%p' cannot be an export or global symbol", GetSymName (S));
        return;
    }
    if (S->Flags & SF_DEFINED) {
        /* Multiple definition. In case of a variable, this is legal. */
        if ((S->Flags & SF_VAR) == 0) {
            Error ("Symbol `%m%p' is already defined", GetSymName (S));
            S->Flags |= SF_MULTDEF;
            return;
        } else {
            /* Redefinition must also be a variable symbol */
            if ((Flags & SF_VAR) == 0) {
                Error ("Symbol `%m%p' is already different kind", GetSymName (S));
                return;
            }
            /* Delete the current symbol expression, since it will get
            ** replaced
            */
            FreeExpr (S->Expr);
            S->Expr = 0;
        }
    }

    /* Map a default address size to a real value */
    if (AddrSize == ADDR_SIZE_DEFAULT) {
        /* ### Must go! Delay address size calculation until end of assembly! */
        ExprDesc ED;
        ED_Init (&ED);
        StudyExpr (Expr, &ED);
        AddrSize = ED.AddrSize;
        ED_Done (&ED);
    }

    /* Set the symbol value */
    S->Expr = Expr;

    /* In case of a variable symbol, walk over all expressions containing
    ** this symbol and replace the (sub-)expression by the literal value of
    ** the tree. Be sure to replace the expression node in place, since there
    ** may be pointers to it.
    */
    if (Flags & SF_VAR) {
        SymReplaceExprRefs (S);
    }

    /* If the symbol is marked as global, export it. Address size is checked
    ** below.
    */
    if (S->Flags & SF_GLOBAL) {
        S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
        ReleaseFullLineInfo (&S->DefLines);
    }

    /* Mark the symbol as defined and use the given address size */
    S->Flags |= (SF_DEFINED | Flags);
    S->AddrSize = AddrSize;

    /* Remember the line info of the symbol definition */
    GetFullLineInfo (&S->DefLines);

    /* If the symbol is exported, check the address sizes */
    if (S->Flags & SF_EXPORT) {
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* Use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize > S->ExportSize) {
            /* We're exporting a symbol smaller than it actually is */
            Warning (1, "Symbol `%m%p' is %s but exported %s",
                     GetSymName (S), AddrSizeToStr (S->AddrSize),
                     AddrSizeToStr (S->ExportSize));
        }
    }

    /* If this is not a local symbol, remember it as the last global one */
    if ((S->Flags & SF_LOCAL) == 0) {
        SymLast = S;
    }
}