Exemplo n.º 1
0
void SegDone (void)
/* Check the segments for range and other errors. Do cleanup. */
{
    static const unsigned long U_Hi[4] = {
       	0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL
    };
    static const long S_Hi[4] = {
       	0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL
    };

    unsigned I;
    for (I = 0; I < CollCount (&SegmentList); ++I) {
        Segment* S = CollAtUnchecked (&SegmentList, I);
     	Fragment* F = S->Root;
     	while (F) {
       	    if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {

                /* We have an expression, study it */
                ExprDesc ED;
                ED_Init (&ED);
                StudyExpr (F->V.Expr, &ED);

                /* Check if the expression is constant */
                if (ED_IsConst (&ED)) {

     	       	    unsigned J;

       	       	    /* The expression is constant. Check for range errors. */
                    CHECK (F->Len <= 4);
                    if (F->Type == FRAG_SEXPR) {
                        long Hi = S_Hi[F->Len-1];
                        long Lo = ~Hi;
                        if (ED.Val > Hi || ED.Val < Lo) {
                            LIError (&F->LI,
                                     "Range error (%ld not in [%ld..%ld])",
                                     ED.Val, Lo, Hi);
                        }
                    } else {
                        if (((unsigned long)ED.Val) > U_Hi[F->Len-1]) {
                            LIError (&F->LI,
                                     "Range error (%lu not in [0..%lu])",
                                     (unsigned long)ED.Val, U_Hi[F->Len-1]);
                        }
                    }

                    /* We don't need the expression tree any longer */
                    FreeExpr (F->V.Expr);

     	     	    /* Convert the fragment into a literal fragment */
     	     	    for (J = 0; J < F->Len; ++J) {
     	     	       	F->V.Data[J] = ED.Val & 0xFF;
     	     	       	ED.Val >>= 8;
     	     	    }
     	     	    F->Type = FRAG_LITERAL;

      	     	} else if (RelaxChecks == 0) {

      	     	    /* We cannot evaluate the expression now, leave the job for
      	     	     * the linker. However, we can check if the address size
                     * matches the fragment size. Mismatches are errors in 
                     * most situations.
      	    	     */
                    if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP)  ||
                        (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
                        (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
      	       	        LIError (&F->LI, "Range error");
      	     	    }
     	    	}

                /* Release memory allocated for the expression decriptor */
                ED_Done (&ED);
     	    }
Exemplo n.º 2
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;
    }
}
Exemplo n.º 3
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;
    }
}
Exemplo n.º 4
0
void SegCheck (void)
/* Check the segments for range and other errors */
{
    Segment* S = SegmentList;
    while (S) {
     	Fragment* F = S->Root;
     	while (F) {
       	    if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) {

                /* We have an expression, study it */
                ExprDesc ED;
                ED_Init (&ED);
                StudyExpr (F->V.Expr, &ED);

                /* Try to simplify it before looking further */
                F->V.Expr = SimplifyExpr (F->V.Expr, &ED);

                /* Check if the expression is constant */
                if (ED_IsConst (&ED)) {

       	       	    /* The expression is constant. Check for range errors. */
     	       	    int Abs = (F->Type != FRAG_SEXPR);
                    long Val = ED.Val;
     	       	    unsigned I;

     	       	    if (F->Len == 1) {
     	       	   	if (Abs) {
     	       	   	    /* Absolute value */
     	       	   	    if (Val > 255) {
     	       	       	     	PError (&F->Pos, "Range error (%ld not in [0..255])", Val);
     	       	   	    }
     	       	   	} else {
     	     	   	    /* PC relative value */
     	     	   	    if (Val < -128 || Val > 127) {
     	       	       	     	PError (&F->Pos, "Range error (%ld not in [-128..127])", Val);
     	     	   	    }
     	     	   	}
     	       	    } else if (F->Len == 2) {
     	     	    	if (Abs) {
     	     	   	    /* Absolute value */
     	     	   	    if (Val > 65535) {
     	       	       	     	PError (&F->Pos, "Range error (%ld not in [0..65535])", Val);
     	     	   	    }
     	     	   	} else {
     	     	   	    /* PC relative value */
     	     	   	    if (Val < -32768 || Val > 32767) {
     	       	       	     	PError (&F->Pos, "Range error (%ld not in [-32768..32767])", Val);
     	       		    }
     	     		}
     	     	    }

                    /* We don't need the expression tree any longer */
                    FreeExpr (F->V.Expr);

     	     	    /* Convert the fragment into a literal fragment */
     	     	    for (I = 0; I < F->Len; ++I) {
     	     	       	F->V.Data [I] = Val & 0xFF;
     	     	       	Val >>= 8;
     	     	    }
     	     	    F->Type = FRAG_LITERAL;

     	     	} else if (ED.AddrSize != ADDR_SIZE_DEFAULT) {

     	     	    /* We cannot evaluate the expression now, leave the job for
     	     	     * the linker. However, we can check if the address size
                     * matches the fragment size, and we will do so.
     		     */
                    if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP)  ||
                        (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) ||
                        (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) {
     	       	        PError (&F->Pos, "Range error");
     	     	    }
     		}

                /* Release memory allocated for the expression decriptor */
                ED_Done (&ED);
     	    }