Пример #1
0
static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
/* Create the defines for a RUN segment */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name));
    CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start);
    SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name));
    CreateConstExport (GetStrBufId (&Buf), S->Seg->Size);
    S->Flags |= SF_RUN_DEF;
    SB_Done (&Buf);
}
Пример #2
0
static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr)
/* Create the defines for a LOAD segment */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name));
    CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start);
    S->Flags |= SF_LOAD_DEF;
    SB_Done (&Buf);
}
Пример #3
0
unsigned AddFile (const StrBuf* Name, FileType Type,
                  unsigned long Size, unsigned long MTime)
/* Add a new file to the list of input files. Return the index of the file in
 * the table.
 */
{
    /* Create a new file entry and insert it into the tables */
    FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime);

    /* Return the index */
    return F->Index;
}
Пример #4
0
unsigned GetFileIndex (const StrBuf* Name)
/* Return the file index for the given file name. */
{
    /* Get the string pool index from the name */
    unsigned NameIdx = GetStrBufId (Name);

    /* Search in the hash table for the name */
    const FileEntry* F = HT_Find (&HashTab, &NameIdx);

    /* If we don't have this index, print a diagnostic and use the main file */
    if (F == 0) {
        Error ("File name `%m%p' not found in file table", Name);
        return 0;
    } else {
        return F->Index;
    }
}
Пример #5
0
static int ValidateType (StrBuf* Type)
/* Check if the given type is valid and if so, return a string id for it. If
** the type isn't valid, return -1. Type is overwritten when checking.
*/
{
    unsigned        I;
    const char*     A;
    char*           B;


    /* The length must not be zero and divideable by two */
    unsigned Length = SB_GetLen (Type);
    if (Length < 2 || (Length & 0x01) != 0) {
        ErrorSkip ("Type value has invalid length");
        return -1;
    }

    /* The string must consist completely of hex digit chars */
    A = SB_GetConstBuf (Type);
    for (I = 0; I < Length; ++I) {
        if (!IsXDigit (A[I])) {
            ErrorSkip ("Type value contains invalid characters");
            return -1;
        }
    }

    /* Convert the type to binary */
    B = SB_GetBuf (Type);
    while (A < SB_GetConstBuf (Type) + Length) {
        /* Since we know, there are only hex digits, there can't be any errors */
        *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]);
        A += 2;
    }
    Type->Len = (Length /= 2);

    /* Allocate the type and return it */
    return GetStrBufId (Type);
}
Пример #6
0
SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
/* Allocate a symbol table entry, initialize and return it */
{
    unsigned I;

    /* Allocate memory */
    SymEntry* S = xmalloc (sizeof (SymEntry));

    /* Initialize the entry */
    S->Left       = 0;
    S->Right      = 0;
    S->Locals     = 0;
    S->Sym.Tab    = 0;
    S->DefLines   = EmptyCollection;
    S->RefLines   = EmptyCollection;
    for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
        S->GuessedUse[I] = 0;
    }
    S->HLLSym     = 0;
    S->Flags      = Flags;
    S->DebugSymId = ~0U;
    S->ImportId   = ~0U;
    S->ExportId   = ~0U;
    S->Expr       = 0;
    S->ExprRefs   = AUTO_COLLECTION_INITIALIZER;
    S->ExportSize = ADDR_SIZE_DEFAULT;
    S->AddrSize   = ADDR_SIZE_DEFAULT;
    memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio));
    S->Name       = GetStrBufId (Name);

    /* Insert it into the list of all entries */
    S->List = SymList;
    SymList = S;

    /* Return the initialized entry */
    return S;
}
Пример #7
0
void OptStr (unsigned char Type, const StrBuf* Text)
/* Add a string option */
{
    NewOption (Type, GetStrBufId (Text));
}
Пример #8
0
void OptOS (const StrBuf* OS)
/* Add an operating system option */
{
    NewOption (OPT_OS, GetStrBufId (OS));
}
Пример #9
0
void OptCompiler (const StrBuf* Compiler)
/* Add a compiler option */
{
    NewOption (OPT_COMPILER, GetStrBufId (Compiler));
}
Пример #10
0
void OptTranslator (const StrBuf* Translator)
/* Add a translator option */
{
    NewOption (OPT_TRANSLATOR, GetStrBufId (Translator));
}
Пример #11
0
void OptAuthor (const StrBuf* Author)
/* Add an author statement */
{
    NewOption (OPT_AUTHOR, GetStrBufId (Author));
}
Пример #12
0
void OptComment (const StrBuf* Comment)
/* Add a comment */
{
    NewOption (OPT_COMMENT, GetStrBufId (Comment));
}
Пример #13
0
static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name)
/* Allocate a symbol table on the heap and return it */
{
    /* Determine the lexical level and the number of table slots */
    unsigned Level = Parent? Parent->Level + 1 : 0;
    unsigned Slots = ScopeTableSize (Level);

    /* Allocate memory */
    SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*));

    /* Set variables and clear hash table entries */
    S->Next         = 0;
    S->Left         = 0;
    S->Right        = 0;
    S->Childs       = 0;
    S->Label        = 0;
    S->Spans        = AUTO_COLLECTION_INITIALIZER;
    S->Id           = ScopeCount++;
    S->Flags        = ST_NONE;
    S->AddrSize     = ADDR_SIZE_DEFAULT;
    S->Type         = SCOPE_UNDEF;
    S->Level        = Level;
    S->TableSlots   = Slots;
    S->TableEntries = 0;
    S->Parent       = Parent;
    S->Name         = GetStrBufId (Name);
    while (Slots--) {
        S->Table[Slots] = 0;
    }

    /* Insert the symbol table into the list of all symbol tables */
    if (RootScope == 0) {
        RootScope = S;
    } else {
        LastScope->Next = S;
    }
    LastScope = S;

    /* Insert the symbol table into the child tree of the parent */
    if (Parent) {
        SymTable* T = Parent->Childs;
        if (T == 0) {
            /* First entry */
            Parent->Childs = S;
        } else {
            while (1) {
                /* Choose next entry */
                int Cmp = SB_Compare (Name, GetStrBuf (T->Name));
                if (Cmp < 0) {
                    if (T->Left) {
                        T = T->Left;
                    } else {
                        T->Left = S;
                        break;
                    }
                } else if (Cmp > 0) {
                    if (T->Right) {
                        T = T->Right;
                    } else {
                        T->Right = S;
                        break;
                    }
                } else {
                    /* Duplicate scope name */
                    Internal ("Duplicate scope name: `%m%p'", Name);
                }
            }
        }
    }

    /* Return the prepared struct */
    return S;
}
Пример #14
0
void DbgInfoSym (void)
/* Parse and handle SYM subcommand of the .dbg pseudo instruction */
{
    static const char* const StorageKeys[] = {
        "AUTO",
        "EXTERN",
        "REGISTER",
        "STATIC",
    };

    unsigned    Name;
    int         Type;
    unsigned    AsmName = EMPTY_STRING_ID;
    unsigned    Flags;
    int         Offs = 0;
    HLLDbgSym*  S;


    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* Name */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Name = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Type */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Type = ValidateType (&CurTok.SVal);
    if (Type < 0) {
        return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* The storage class follows */
    if (CurTok.Tok != TOK_IDENT) {
        ErrorSkip ("Storage class specifier expected");
        return;
    }
    switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) {
        case 0:   Flags = HLL_SC_AUTO;                              break;
        case 1:   Flags = HLL_SC_EXTERN;                            break;
        case 2:   Flags = HLL_SC_REG;                               break;
        case 3:   Flags = HLL_SC_STATIC;                            break;
        default:  ErrorSkip ("Storage class specifier expected");   return;
    }

    /* Skip the storage class token and the following comma */
    NextTok ();
    ConsumeComma ();

    /* The next tokens depend on the storage class */
    if (Flags == HLL_SC_AUTO) {
        /* Auto: Stack offset follows */
        Offs = ConstExpression ();
    } else {
        /* Register, extern or static: Assembler name follows */
        if (CurTok.Tok != TOK_STRCON) {
            ErrorSkip ("String constant expected");
            return;
        }
        AsmName = GetStrBufId (&CurTok.SVal);
        NextTok ();

        /* For register, an offset follows */
        if (Flags == HLL_SC_REG) {
            ConsumeComma ();
            Offs = ConstExpression ();
        }
    }

    /* Add the function */
    S = NewHLLDbgSym (Flags | HLL_TYPE_SYM, Name, Type);
    S->AsmName = AsmName;
    S->Offs    = Offs;
    CollAppend (&HLLDbgSyms, S);
}
Пример #15
0
void DbgInfoFunc (void)
/* Parse and handle func subcommand of the .dbg pseudo instruction */
{
    static const char* const StorageKeys[] = {
        "EXTERN",
        "STATIC",
    };

    unsigned    Name;
    int         Type;
    unsigned    AsmName;
    unsigned    Flags;
    HLLDbgSym*  S;


    /* Parameters are separated by a comma */
    ConsumeComma ();

    /* Name */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Name = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Type */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    Type = ValidateType (&CurTok.SVal);
    if (Type < 0) {
        return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* The storage class follows */
    if (CurTok.Tok != TOK_IDENT) {
        ErrorSkip ("Storage class specifier expected");
        return;
    }
    switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) {
        case 0:   Flags = HLL_TYPE_FUNC | HLL_SC_EXTERN;            break;
        case 1:   Flags = HLL_TYPE_FUNC | HLL_SC_STATIC;            break;
        default:  ErrorSkip ("Storage class specifier expected");   return;
    }
    NextTok ();

    /* Comma expected */
    ConsumeComma ();

    /* Assembler name follows */
    if (CurTok.Tok != TOK_STRCON) {
        ErrorSkip ("String constant expected");
        return;
    }
    AsmName = GetStrBufId (&CurTok.SVal);
    NextTok ();

    /* There may only be one function per scope */
    if (CurrentScope == RootScope) {
        ErrorSkip ("Functions may not be used in the root scope");
        return;
    } else if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) {
        ErrorSkip ("Functions can only be tagged to .PROC scopes");
        return;
    } else if (CurrentScope->Label->HLLSym != 0) {
        ErrorSkip ("Only one HLL symbol per asm symbol is allowed");
        return;
    } else if (CurrentScope->Label->Name != AsmName) {
        ErrorSkip ("Scope label and asm name for function must match");
        return;
    }

    /* Add the function */
    S = NewHLLDbgSym (Flags, Name, Type);
    S->Sym = CurrentScope->Label;
    CurrentScope->Label->HLLSym = S;
    CollAppend (&HLLDbgSyms, S);
}
Пример #16
0
unsigned CfgAssignSegments (void)
/* Assign segments, define linker symbols where requested. The function will
 * return the number of memory area overflows (so zero means anything went ok).
 * In case of overflows, a short mapfile can be generated later, to ease the
 * task of rearranging segments for the user.
 */
{
    unsigned Overflows = 0;

    /* Walk through each of the memory sections. Add up the sizes and check
     * for an overflow of the section. Assign the start addresses of the
     * segments while doing this.
     */
    Memory* M = MemoryList;
    while (M) {

        MemListNode* N;

     	/* Get the start address of this memory area */
     	unsigned long Addr = M->Start;

        /* Remember if this is a relocatable memory area */
        M->Relocatable = RelocatableBinFmt (M->F->Format);

     	/* Walk through the segments in this memory area */
     	N = M->SegList;
     	while (N) {

     	    /* Get the segment from the node */
     	    SegDesc* S = N->Seg;

            /* Some actions depend on wether this is the load or run memory
             * area.
             */
            if (S->Run == M) {

                /* This is the run (and maybe load) memory area. Handle
                 * alignment and explict start address and offset.
                 */
                if (S->Flags & SF_ALIGN) {
                    /* Align the address */
                    unsigned long Val = (0x01UL << S->Align) - 1;
                    Addr = (Addr + Val) & ~Val;
                } else if (S->Flags & (SF_OFFSET | SF_START)) {
                    /* Give the segment a fixed starting address */
                    unsigned long NewAddr = S->Addr;
                    if (S->Flags & SF_OFFSET) {
                        /* An offset was given, no address, make an address */
                        NewAddr += M->Start;
                    }
                    if (Addr > NewAddr) {
                        /* Offset already too large */
                        if (S->Flags & SF_OFFSET) {
                            Error ("Offset too small in `%s', segment `%s'",
                                   GetString (M->Name), GetString (S->Name));
                        } else {
                            Error ("Start address too low in `%s', segment `%s'",
                                   GetString (M->Name), GetString (S->Name));
                        }
                    }
                    Addr = NewAddr;
                }

                /* Set the start address of this segment, set the readonly flag
                 * in the segment and and remember if the segment is in a
                 * relocatable file or not.
                 */
                S->Seg->PC = Addr;
                S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
                S->Seg->Relocatable = M->Relocatable;

            } else if (S->Load == M) {

                /* This is the load memory area, *and* run and load are
                 * different (because of the "else" above). Handle alignment.
                 */
                if (S->Flags & SF_ALIGN_LOAD) {
                    /* Align the address */
                    unsigned long Val = (0x01UL << S->AlignLoad) - 1;
                    Addr = (Addr + Val) & ~Val;
                }

            }

     	    /* Increment the fill level of the memory area and check for an
     	     * overflow.
     	     */
     	    M->FillLevel = Addr + S->Seg->Size - M->Start;
       	    if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
                ++Overflows;
                M->Flags |= MF_OVERFLOW;
                Warning ("Memory area overflow in `%s', segment `%s' (%lu bytes)",
                         GetString (M->Name), GetString (S->Name),
                         M->FillLevel - M->Size);
     	    }

     	    /* If requested, define symbols for the start and size of the
     	     * segment.
     	     */
     	    if (S->Flags & SF_DEFINE) {
                if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) {
                    CreateRunDefines (S, Addr);
                }
                if (S->Load == M && (S->Flags & SF_LOAD_DEF) == 0) {
                    CreateLoadDefines (S, Addr);
                }
     	    }

     	    /* Calculate the new address */
     	    Addr += S->Seg->Size;

	    /* Next segment */
	    N = N->Next;
	}

	/* If requested, define symbols for start and size of the memory area */
	if (M->Flags & MF_DEFINE) {
	    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
	    SB_Printf (&Buf, "__%s_START__", GetString (M->Name));
	    CreateMemoryExport (GetStrBufId (&Buf), M, 0);
	    SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name));
	    CreateConstExport (GetStrBufId (&Buf), M->Size);
	    SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
	    CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
            SB_Done (&Buf);
	}

	/* Next memory area */
	M = M->Next;
    }

    /* Return the number of memory area overflows */
    return Overflows;
}