X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=0ae19b6d6398e8db36dd3ca5bf96f884cbf96656;hb=3e887bd9dd06b89177bff864b50fc58c8dadc8bf;hp=57b288f0960b77d790eb626e8a06514b38235d85;hpb=386c3d412d265b0e86c938eb137b4ae7e907f132;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 57b288f09..0ae19b6d6 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ +/* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -36,16 +36,22 @@ #include #include -#include "../common/exprdefs.h" -#include "../common/symdefs.h" -#include "../common/segdefs.h" -#include "../common/hashstr.h" +/* common */ +#include "check.h" +#include "exprdefs.h" +#include "hashstr.h" +#include "print.h" +#include "segdefs.h" +#include "symdefs.h" +#include "xmalloc.h" -#include "mem.h" -#include "global.h" +/* ld65 */ #include "error.h" -#include "fileio.h" #include "expr.h" +#include "fileio.h" +#include "fragment.h" +#include "global.h" +#include "lineinfo.h" #include "segments.h" @@ -56,20 +62,6 @@ -/* Fragment structure */ -typedef struct Fragment_ Fragment; -struct Fragment_ { - Fragment* Next; /* Next fragment in list */ - ObjData* Obj; /* Source of fragment */ - unsigned long Size; /* Size of data/expression */ - ExprNode* Expr; /* Expression if FRAG_EXPR */ - FilePos Pos; /* File position in source */ - unsigned char Type; /* Type of fragment */ - unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */ -}; - - - /* Hash table */ #define HASHTAB_SIZE 253 static Segment* HashTab [HASHTAB_SIZE]; @@ -85,43 +77,33 @@ static Segment* SegRoot = 0; /* List of all segments */ -static Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S) -/* Create a new fragment and insert it into the segment S */ +static Segment* SegFindInternal (const char* Name, unsigned HashVal) +/* Try to find the segment with the given name, return a pointer to the + * segment structure, or 0 if not found. + */ { - /* Allocate memory */ - Fragment* F = Xmalloc (sizeof (Fragment) - 1 + Size); /* Portable? */ - - /* Initialize the data */ - F->Next = 0; - F->Obj = 0; - F->Size = Size; - F->Expr = 0; - F->Type = Type; - - /* Insert the code fragment into the segment */ - if (S->FragRoot == 0) { - /* First fragment */ - S->FragRoot = F; - } else { - S->FragLast->Next = F; + Segment* S = HashTab [HashVal]; + while (S) { + if (strcmp (Name, S->Name) == 0) { + /* Found */ + break; + } + S = S->Next; } - S->FragLast = F; - S->Size += Size; - - /* Return the new fragment */ - return F; + /* Not found */ + return S; } -static Segment* NewSegment (const char* Name, unsigned char Type) +static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type) /* Create a new segment and initialize it */ { /* Get the length of the symbol name */ unsigned Len = strlen (Name); /* Allocate memory */ - Segment* S = Xmalloc (sizeof (Segment) + Len); + Segment* S = xmalloc (sizeof (Segment) + Len); /* Initialize the fields */ S->Next = 0; @@ -142,27 +124,64 @@ static Segment* NewSegment (const char* Name, unsigned char Type) SegRoot = S; ++SegCount; + /* Insert the segment into the segment hash list */ + S->Next = HashTab [HashVal]; + HashTab [HashVal] = S; + /* Return the new entry */ return S; } -static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) +Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName) +/* Search for a segment and return an existing one. If the segment does not + * exist, create a new one and return that. ObjName is only used for the error + * message and may be NULL if the segment is linker generated. + */ +{ + /* Create a hash over the name and try to locate the segment in the table */ + unsigned HashVal = HashStr (Name) % HASHTAB_SIZE; + Segment* S = SegFindInternal (Name, HashVal); + + /* If we don't have that segment already, allocate it using the type of + * the first section. + */ + if (S == 0) { + /* Create a new segment */ + S = NewSegment (Name, HashVal, Type); + } else { + /* Check if the existing segment has the requested type */ + if (S->Type != Type) { + /* Allow an empty object name */ + if (ObjName == 0) { + ObjName = "[linker generated]"; + } + Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name); + } + } + + /* Return the segment */ + return S; +} + + + +Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) /* Create a new section for the given segment */ { unsigned long V; /* Allocate memory */ - Section* S = Xmalloc (sizeof (Segment)); + Section* S = xmalloc (sizeof (Segment)); /* Initialize the data */ S->Next = 0; S->Seg = Seg; S->FragRoot = 0; S->FragLast = 0; - S->Size = 0; + S->Size = 0; S->Align = Align; S->Type = Type; @@ -189,30 +208,10 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ -static Segment* SegFindInternal (const char* Name, unsigned HashVal) -/* Try to find the segment with the given name, return a pointer to the - * segment structure, or 0 if not found. - */ -{ - Segment* S = HashTab [HashVal]; - while (S) { - if (strcmp (Name, S->Name) == 0) { - /* Found */ - break; - } - S = S->Next; - } - /* Not found */ - return S; -} - - - Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { - unsigned HashVal; - char Name [256]; + char* Name; unsigned long Size; unsigned char Align; unsigned char Type; @@ -220,7 +219,7 @@ Section* ReadSection (FILE* F, ObjData* O) Section* Sec; /* Read the name */ - ReadStr (F, Name); + Name = ReadStr (F); /* Read the size */ Size = Read32 (F); @@ -232,34 +231,18 @@ Section* ReadSection (FILE* F, ObjData* O) Type = Read8 (F); /* Print some data */ - if (Verbose > 1) { - printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", - O->Name, Name, Size, Align, Type); - } + Print (stdout, 2, "Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", + GetObjFileName (O), Name, Size, Align, Type); - /* Create a hash over the name and try to locate the segment in the table */ - HashVal = HashStr (Name) % HASHTAB_SIZE; - S = SegFindInternal (Name, HashVal); + /* Get the segment for this section */ + S = GetSegment (Name, Type, GetObjFileName (O)); - /* If we don't have that segment already, allocate it using the type of - * the first section. - */ - if (S == 0) { - /* Create a new segment and insert it */ - S = NewSegment (Name, Type); - S->Next = HashTab [HashVal]; - HashTab [HashVal] = S; - } + /* We have the segment and don't need the name any longer */ + xfree (Name); /* Allocate the section we will return later */ Sec = NewSection (S, Align, Type); - /* Check if the section has the same type as the segment */ - if (Sec->Type != S->Type) { - /* OOPS */ - Error ("Module `%s': Type mismatch for segment `%s'", O->Name, S->Name); - } - /* Set up the minimum segment alignment */ if (Sec->Align > S->Align) { /* Section needs larger alignment, use this one */ @@ -271,6 +254,7 @@ Section* ReadSection (FILE* F, ObjData* O) while (Size) { Fragment* Frag; + unsigned LineInfoIndex; /* Read the fragment type */ unsigned char Type = Read8 (F); @@ -278,20 +262,8 @@ Section* ReadSection (FILE* F, ObjData* O) /* Handle the different fragment types */ switch (Type) { - case FRAG_LITERAL8: - Frag = NewFragment (FRAG_LITERAL, Read8 (F), Sec); - break; - - case FRAG_LITERAL16: - Frag = NewFragment (FRAG_LITERAL, Read16 (F), Sec); - break; - - case FRAG_LITERAL24: - Frag = NewFragment (FRAG_LITERAL, Read24 (F), Sec); - break; - - case FRAG_LITERAL32: - Frag = NewFragment (FRAG_LITERAL, Read32 (F), Sec); + case FRAG_LITERAL: + Frag = NewFragment (Type, ReadVar (F), Sec); break; case FRAG_EXPR8: @@ -303,17 +275,17 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_SEXPR24: case FRAG_SEXPR32: Frag = NewFragment (Type & FRAG_TYPEMASK, Type & FRAG_BYTEMASK, Sec); - break; + break; case FRAG_FILL: - /* Will allocate memory, but we don't care... */ - Frag = NewFragment (FRAG_FILL, Read16 (F), Sec); - break; + /* Will allocate memory, but we don't care... */ + Frag = NewFragment (Type, ReadVar (F), Sec); + break; default: - Error ("Unknown fragment type in module `%s', segment `%s': %02X", - O->Name, S->Name, Type); - /* NOTREACHED */ + Error ("Unknown fragment type in module `%s', segment `%s': %02X", + GetObjFileName (O), S->Name, Type); + /* NOTREACHED */ return 0; } @@ -329,13 +301,30 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_SEXPR: /* An expression */ Frag->Expr = ReadExpr (F, O); - break; + break; } /* Read the file position of the fragment */ ReadFilePos (F, &Frag->Pos); + /* Read the additional line info and resolve it */ + LineInfoIndex = ReadVar (F); + if (LineInfoIndex) { + --LineInfoIndex; + if (LineInfoIndex >= O->LineInfoCount) { + Internal ("In module `%s', file `%s', line %lu: Invalid line " + "info with index %u (max count %u)", + GetObjFileName (O), + GetSourceFileName (O, Frag->Pos.Name), + Frag->Pos.Line, LineInfoIndex, O->LineInfoCount); + } + /* Point from the fragment to the line info... */ + Frag->LI = O->LineInfos[LineInfoIndex]; + /* ...and back from the line info to the fragment */ + CollAppend (&Frag->LI->Fragments, Frag); + } + /* Remember the module we had this fragment from */ Frag->Obj = O; @@ -344,9 +333,6 @@ Section* ReadSection (FILE* F, ObjData* O) Size -= Frag->Size; } - /* Increment the segment size by the section size */ - S->Size += Sec->Size; - /* Return the section */ return Sec; } @@ -419,7 +405,7 @@ void SegDump (void) while (Count--) { if (I > 75) { printf ("\n "); - I = 3; + I = 3; } printf (" %02X", *Data++); I += 3; @@ -441,7 +427,7 @@ void SegDump (void) case FRAG_FILL: printf (" Empty space (%lu bytes)\n", F->Size); - break; + break; default: Internal ("Invalid fragment type: %02X", F->Type); @@ -515,6 +501,7 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* If we have fill bytes, write them now */ WriteMult (Tgt, S->FillVal, Sec->Fill); + Offs += Sec->Fill; /* Loop over all fragments in this section */ Frag = Sec->FragRoot; @@ -537,12 +524,14 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) case SEG_EXPR_RANGE_ERROR: Error ("Range error in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; case SEG_EXPR_TOO_COMPLEX: Error ("Expression too complex in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; default: @@ -600,7 +589,7 @@ void PrintSegmentMap (FILE* F) Segment** SegPool; /* Allocate memory for the segment pool */ - SegPool = Xmalloc (SegCount * sizeof (Segment*)); + SegPool = xmalloc (SegCount * sizeof (Segment*)); /* Collect pointers to the segments */ I = 0; @@ -643,7 +632,7 @@ void PrintSegmentMap (FILE* F) } /* Free the segment pool */ - Xfree (SegPool); + xfree (SegPool); }