X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=1474ebe5550f4cba2b108598d110c7b226737575;hb=35e1184901ca38bdb2e56d154ed3b71f6096eacc;hp=e203af508842a3e90adaa17c2e2943b559140f9b;hpb=ebbd68673b30f863c770c1ced80149ea76949fe8;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index e203af508..1474ebe55 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2001 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -37,9 +37,13 @@ #include /* common */ +#include "addrsize.h" +#include "alignment.h" #include "check.h" +#include "coll.h" #include "exprdefs.h" -#include "hashstr.h" +#include "fragdefs.h" +#include "hashfunc.h" #include "print.h" #include "segdefs.h" #include "symdefs.h" @@ -53,6 +57,7 @@ #include "global.h" #include "lineinfo.h" #include "segments.h" +#include "spool.h" @@ -63,11 +68,12 @@ /* Hash table */ -#define HASHTAB_SIZE 253 -static Segment* HashTab [HASHTAB_SIZE]; +#define HASHTAB_MASK 0x3FU +#define HASHTAB_SIZE (HASHTAB_MASK + 1) +static Segment* HashTab[HASHTAB_SIZE]; -static unsigned SegCount = 0; /* Segment count */ -static Segment* SegRoot = 0; /* List of all segments */ +/* List of all segments */ +static Collection SegmentList = STATIC_COLLECTION_INITIALIZER; @@ -77,56 +83,38 @@ static Segment* SegRoot = 0; /* List of all segments */ -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; -} - - - -static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type) +static Segment* NewSegment (unsigned Name, unsigned char AddrSize) /* Create a new segment and initialize it */ { - /* Get the length of the symbol name */ - unsigned Len = strlen (Name); + unsigned Hash; /* Allocate memory */ - Segment* S = xmalloc (sizeof (Segment) + Len); + Segment* S = xmalloc (sizeof (Segment)); /* Initialize the fields */ - S->Next = 0; - S->SecRoot = 0; - S->SecLast = 0; - S->PC = 0; - S->Size = 0; - S->AlignObj = 0; - S->Align = 0; - S->FillVal = 0; - S->Type = Type; - S->Dumped = 0; - memcpy (S->Name, Name, Len); - S->Name [Len] = '\0'; - - /* Insert the segment into the segment list */ - S->List = SegRoot; - SegRoot = S; - ++SegCount; + S->Name = Name; + S->Next = 0; + S->Flags = SEG_FLAG_NONE; + S->Sections = EmptyCollection; + S->MemArea = 0; + S->PC = 0; + S->Size = 0; + S->OutputName = 0; + S->OutputOffs = 0; + S->Alignment = 1; + S->FillVal = 0; + S->AddrSize = AddrSize; + S->ReadOnly = 0; + S->Dumped = 0; + + /* Insert the segment into the segment list and assign the segment id */ + S->Id = CollCount (&SegmentList); + CollAppend (&SegmentList, S); /* Insert the segment into the segment hash list */ - S->Next = HashTab [HashVal]; - HashTab [HashVal] = S; + Hash = (S->Name & HASHTAB_MASK); + S->Next = HashTab[Hash]; + HashTab[Hash] = S; /* Return the new entry */ return S; @@ -134,30 +122,30 @@ static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Ty -Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName) +Segment* GetSegment (unsigned Name, unsigned char AddrSize, 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); + /* Try to locate the segment in the table */ + Segment* S = SegFind (Name); /* 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); + S = NewSegment (Name, AddrSize); } else { - /* Check if the existing segment has the requested type */ - if (S->Type != Type) { + /* Check if the existing segment has the requested address size */ + if (S->AddrSize != AddrSize) { /* Allow an empty object name */ if (ObjName == 0) { ObjName = "[linker generated]"; } - Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name); + Error ("Module `%s': Type mismatch for segment `%s'", ObjName, + GetString (Name)); } } @@ -167,40 +155,31 @@ Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName) -Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) +Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize) /* Create a new section for the given segment */ { - unsigned long V; - - /* Allocate memory */ - Section* S = xmalloc (sizeof (Segment)); + Section* S = xmalloc (sizeof (Section)); /* Initialize the data */ S->Next = 0; S->Seg = Seg; + S->Obj = 0; S->FragRoot = 0; S->FragLast = 0; S->Size = 0; - S->Align = Align; - S->Type = Type; + S->Alignment= Alignment; + S->AddrSize = AddrSize; /* Calculate the alignment bytes needed for the section */ - V = (0x01UL << S->Align) - 1; - S->Fill = (unsigned char) (((Seg->Size + V) & ~V) - Seg->Size); + S->Fill = AlignCount (Seg->Size, S->Alignment); /* Adjust the segment size and set the section offset */ Seg->Size += S->Fill; S->Offs = Seg->Size; /* Current size is offset */ /* Insert the section into the segment */ - if (Seg->SecRoot == 0) { - /* First section in this segment */ - Seg->SecRoot = S; - } else { - Seg->SecLast->Next = S; - } - Seg->SecLast = S; + CollAppend (&Seg->Sections, S); /* Return the struct */ return S; @@ -211,126 +190,103 @@ Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { - char* Name; - unsigned long Size; - unsigned char Align; + unsigned Name; + unsigned Flags; + unsigned Size; + unsigned long Alignment; unsigned char Type; - Segment* S; - Section* Sec; - - /* Read the name */ - Name = ReadStr (F); + unsigned FragCount; + Segment* S; + Section* Sec; - /* Read the size */ - Size = Read32 (F); + /* Read the segment data */ + (void) Read32 (F); /* File size of data */ + Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */ + Flags = ReadVar (F); /* Segment flags */ + Size = ReadVar (F); /* Size of data */ + Alignment = ReadVar (F); /* Alignment */ + Type = Read8 (F); /* Segment type */ + FragCount = ReadVar (F); /* Number of fragments */ - /* Read the alignment */ - Align = Read8 (F); - - /* Read the segment type */ - Type = Read8 (F); /* Print some data */ - Print (stdout, 2, "Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", - GetObjFileName (O), Name, Size, Align, Type); + Print (stdout, 2, + "Module `%s': Found segment `%s', size = %u, alignment = %lu, type = %u\n", + GetObjFileName (O), GetString (Name), Size, Alignment, Type); /* Get the segment for this section */ S = GetSegment (Name, Type, GetObjFileName (O)); - - /* We have the segment and don't need the name any longer */ - xfree (Name); + + /* The only possible flag is currently SEG_FLAG_BANKREF, and it must be + * applied to the segment, not the section. + */ + S->Flags |= Flags; /* Allocate the section we will return later */ - Sec = NewSection (S, Align, Type); - - /* Set up the minimum segment alignment */ - if (Sec->Align > S->Align) { - /* Section needs larger alignment, use this one */ - S->Align = Sec->Align; - S->AlignObj = O; + Sec = NewSection (S, Alignment, Type); + + /* Remember the object file this section was from */ + Sec->Obj = O; + + /* Set up the combined segment alignment */ + if (Sec->Alignment > 1) { + Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment); + if (Alignment > MAX_ALIGNMENT) { + Error ("Combined alignment for segment `%s' is %lu which exceeds " + "%lu. Last module requiring alignment was `%s'.", + GetString (Name), Alignment, MAX_ALIGNMENT, + GetObjFileName (O)); + } else if (Alignment >= LARGE_ALIGNMENT) { + Warning ("Combined alignment for segment `%s' is suspiciously " + "large (%lu). Last module requiring alignment was `%s'.", + GetString (Name), Alignment, GetObjFileName (O)); + } + S->Alignment = Alignment; } /* Start reading fragments from the file and insert them into the section . */ - while (Size) { + while (FragCount--) { Fragment* Frag; - unsigned LineInfoIndex; /* Read the fragment type */ unsigned char Type = Read8 (F); + /* Extract the check mask from the type */ + unsigned char Bytes = Type & FRAG_BYTEMASK; + Type &= FRAG_TYPEMASK; + /* Handle the different fragment types */ switch (Type) { case FRAG_LITERAL: Frag = NewFragment (Type, ReadVar (F), Sec); + ReadData (F, Frag->LitBuf, Frag->Size); break; - case FRAG_EXPR8: - case FRAG_EXPR16: - case FRAG_EXPR24: - case FRAG_EXPR32: - case FRAG_SEXPR8: - case FRAG_SEXPR16: - case FRAG_SEXPR24: - case FRAG_SEXPR32: - Frag = NewFragment (Type & FRAG_TYPEMASK, Type & FRAG_BYTEMASK, Sec); + case FRAG_EXPR: + case FRAG_SEXPR: + Frag = NewFragment (Type, Bytes, Sec); + Frag->Expr = ReadExpr (F, O); break; case FRAG_FILL: /* Will allocate memory, but we don't care... */ - Frag = NewFragment (Type, ReadVar (F), Sec); + Frag = NewFragment (Type, ReadVar (F), Sec); break; default: Error ("Unknown fragment type in module `%s', segment `%s': %02X", - GetObjFileName (O), S->Name, Type); + GetObjFileName (O), GetString (S->Name), Type); /* NOTREACHED */ return 0; } - /* Now read the fragment data */ - switch (Frag->Type) { - - case FRAG_LITERAL: - /* Literal data */ - ReadData (F, Frag->LitBuf, Frag->Size); - break; - - case FRAG_EXPR: - case FRAG_SEXPR: - /* An expression */ - Frag->Expr = ReadExpr (F, O); - 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); - } + /* Read the line infos into the list of the fragment */ + ReadLineInfoList (F, O, &Frag->LineInfos); /* Remember the module we had this fragment from */ Frag->Obj = O; - - /* Next one */ - CHECK (Size >= Frag->Size); - Size -= Frag->Size; } /* Return the section */ @@ -339,10 +295,19 @@ Section* ReadSection (FILE* F, ObjData* O) -Segment* SegFind (const char* Name) +Segment* SegFind (unsigned Name) /* Return the given segment or NULL if not found. */ { - return SegFindInternal (Name, HashStr (Name) % HASHTAB_SIZE); + Segment* S = HashTab[Name & HASHTAB_MASK]; + while (S) { + if (Name == S->Name) { + /* Found */ + break; + } + S = S->Next; + } + /* Not found */ + return S; } @@ -353,8 +318,12 @@ int IsBSSType (Segment* S) */ { /* Loop over all sections */ - Section* Sec = S->SecRoot; - while (Sec) { + unsigned I; + for (I = 0; I < CollCount (&S->Sections); ++I) { + + /* Get the next section */ + Section* Sec = CollAtUnchecked (&S->Sections, I); + /* Loop over all fragments */ Fragment* F = Sec->FragRoot; while (F) { @@ -363,7 +332,7 @@ int IsBSSType (Segment* S) unsigned long Count = F->Size; while (Count--) { if (*Data++ != 0) { - return 0; + return 0; } } } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { @@ -373,7 +342,6 @@ int IsBSSType (Segment* S) } F = F->Next; } - Sec = Sec->Next; } return 1; } @@ -383,50 +351,51 @@ int IsBSSType (Segment* S) void SegDump (void) /* Dump the segments and it's contents */ { - unsigned I; + unsigned I, J; unsigned long Count; unsigned char* Data; - Segment* Seg = SegRoot; - while (Seg) { - Section* S = Seg->SecRoot; - printf ("Segment: %s (%lu)\n", Seg->Name, Seg->Size); - while (S) { + for (I = 0; I < CollCount (&SegmentList); ++I) { + Segment* Seg = CollAtUnchecked (&SegmentList, I); + printf ("Segment: %s (%lu)\n", GetString (Seg->Name), Seg->Size); + for (J = 0; J < CollCount (&Seg->Sections); ++J) { + Section* S = CollAtUnchecked (&Seg->Sections, J); + unsigned J; Fragment* F = S->FragRoot; printf (" Section:\n"); while (F) { switch (F->Type) { case FRAG_LITERAL: - printf (" Literal (%lu bytes):", F->Size); - Count = F->Size; - Data = F->LitBuf; - I = 100; - while (Count--) { - if (I > 75) { - printf ("\n "); - I = 3; + printf (" Literal (%u bytes):", F->Size); + Count = F->Size; + Data = F->LitBuf; + J = 100; + while (Count--) { + if (J > 75) { + printf ("\n "); + J = 3; } printf (" %02X", *Data++); - I += 3; + J += 3; } printf ("\n"); break; case FRAG_EXPR: - printf (" Expression (%lu bytes):\n", F->Size); + printf (" Expression (%u bytes):\n", F->Size); printf (" "); - DumpExpr (F->Expr); + DumpExpr (F->Expr, 0); break; case FRAG_SEXPR: - printf (" Signed expression (%lu bytes):\n", F->Size); + printf (" Signed expression (%u bytes):\n", F->Size); printf (" "); - DumpExpr (F->Expr); + DumpExpr (F->Expr, 0); break; case FRAG_FILL: - printf (" Empty space (%lu bytes)\n", F->Size); + printf (" Empty space (%u bytes)\n", F->Size); break; default: @@ -434,9 +403,7 @@ void SegDump (void) } F = F->Next; } - S = S->Next; } - Seg = Seg->List; } } @@ -447,14 +414,14 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) * check and return one of the SEG_EXPR_xxx codes. */ { - static const unsigned long U_HighRange [4] = { - 0x000000FF, 0x0000FFFF, 0x00FFFFFF, 0xFFFFFFFF + static const unsigned long U_Hi[4] = { + 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; - static const long S_HighRange [4] = { - 0x0000007F, 0x00007FFF, 0x007FFFFF, 0x7FFFFFFF + static const long S_Hi[4] = { + 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; - static const long S_LowRange [4] = { - 0xFFFFFF80, 0xFFFF8000, 0xFF800000, 0x80000000 + static const long S_Lo[4] = { + ~0x0000007FL, ~0x00007FFFL, ~0x007FFFFFL, ~0x7FFFFFFFL }; @@ -466,12 +433,12 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) /* Check for a range error */ if (Signed) { - if (Val > S_HighRange [Size-1] || Val < S_LowRange [Size-1]) { + if (Val > S_Hi[Size-1] || Val < S_Lo[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } else { - if (((unsigned long)Val) > U_HighRange [Size-1]) { + if (((unsigned long)Val) > U_Hi[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } @@ -486,58 +453,70 @@ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) -void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) +void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* Write the data from the given segment to a file. For expressions, F is * called (see description of SegWriteFunc above). */ { - int Sign; + unsigned I; + int Sign; unsigned long Offs = 0; + + /* Remember the output file and offset for the segment */ + S->OutputName = TgtName; + S->OutputOffs = (unsigned long) ftell (Tgt); + /* Loop over all sections in this segment */ - Section* Sec = S->SecRoot; - while (Sec) { - Fragment* Frag; + for (I = 0; I < CollCount (&S->Sections); ++I) { + Section* Sec = CollAtUnchecked (&S->Sections, I); + Fragment* Frag; - /* If we have fill bytes, write them now */ - WriteMult (Tgt, S->FillVal, Sec->Fill); - Offs += Sec->Fill; + /* Output were this section is from */ + Print (stdout, 2, " Section from \"%s\"\n", GetObjFileName (Sec->Obj)); - /* Loop over all fragments in this section */ - Frag = Sec->FragRoot; - while (Frag) { + /* If we have fill bytes, write them now */ + Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", + Sec->Fill, S->FillVal); + WriteMult (Tgt, S->FillVal, Sec->Fill); + Offs += Sec->Fill; - switch (Frag->Type) { + /* Loop over all fragments in this section */ + Frag = Sec->FragRoot; + while (Frag) { - case FRAG_LITERAL: - WriteData (Tgt, Frag->LitBuf, Frag->Size); - break; + /* Output fragment data */ + switch (Frag->Type) { - case FRAG_EXPR: - case FRAG_SEXPR: + case FRAG_LITERAL: + WriteData (Tgt, Frag->LitBuf, Frag->Size); + break; + + case FRAG_EXPR: + case FRAG_SEXPR: Sign = (Frag->Type == FRAG_SEXPR); /* Call the users function and evaluate the result */ switch (F (Frag->Expr, Sign, Frag->Size, Offs, Data)) { - case SEG_EXPR_OK: - break; + case SEG_EXPR_OK: + break; - case SEG_EXPR_RANGE_ERROR: - Error ("Range error in module `%s', line %lu", - GetSourceFileName (Frag->Obj, Frag->Pos.Name), - Frag->Pos.Line); - break; + case SEG_EXPR_RANGE_ERROR: + Error ("Range error in module `%s', line %u", + GetFragmentSourceName (Frag), + GetFragmentSourceLine (Frag)); + break; - case SEG_EXPR_TOO_COMPLEX: - Error ("Expression too complex in module `%s', line %lu", - GetSourceFileName (Frag->Obj, Frag->Pos.Name), - Frag->Pos.Line); + case SEG_EXPR_TOO_COMPLEX: + Error ("Expression too complex in module `%s', line %u", + GetFragmentSourceName (Frag), + GetFragmentSourceLine (Frag)); break; - case SEG_EXPR_INVALID: - Error ("Invalid expression in module `%s', line %lu", - GetSourceFileName (Frag->Obj, Frag->Pos.Name), - Frag->Pos.Line); + case SEG_EXPR_INVALID: + Error ("Invalid expression in module `%s', line %u", + GetFragmentSourceName (Frag), + GetFragmentSourceLine (Frag)); break; default: @@ -553,20 +532,27 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) Internal ("Invalid fragment type: %02X", Frag->Type); } - /* Update the offset */ + /* Update the offset */ + Print (stdout, 2, " Fragment with 0x%x bytes\n", + Frag->Size); Offs += Frag->Size; /* Next fragment */ Frag = Frag->Next; } - - /* Next section */ - Sec = Sec->Next; } } +unsigned SegmentCount (void) +/* Return the total number of segments */ +{ + return CollCount (&SegmentList); +} + + + static int CmpSegStart (const void* K1, const void* K2) /* Compare function for qsort */ { @@ -576,12 +562,12 @@ static int CmpSegStart (const void* K1, const void* K2) /* Compare the start addresses */ if (S1->PC > S2->PC) { - return 1; + return 1; } else if (S1->PC < S2->PC) { return -1; } else { /* Sort segments with equal starts by name */ - return strcmp (S1->Name, S2->Name); + return strcmp (GetString (S1->Name), GetString (S2->Name)); } } @@ -590,50 +576,39 @@ static int CmpSegStart (const void* K1, const void* K2) void PrintSegmentMap (FILE* F) /* Print a segment map to the given file */ { - unsigned I; - Segment* S; - Segment** SegPool; /* Allocate memory for the segment pool */ - SegPool = xmalloc (SegCount * sizeof (Segment*)); - - /* Collect pointers to the segments */ - I = 0; - S = SegRoot; - while (S) { - - /* Check the count for safety */ - CHECK (I < SegCount); + Segment** SegPool = xmalloc (CollCount (&SegmentList) * sizeof (Segment*)); - /* Remember the pointer */ - SegPool [I] = S; - - /* Follow the linked list */ - S = S->List; - - /* Next array index */ - ++I; + /* Copy the segment pointers */ + unsigned I; + for (I = 0; I < CollCount (&SegmentList); ++I) { + SegPool[I] = CollAtUnchecked (&SegmentList, I); } - CHECK (I == SegCount); /* Sort the array by increasing start addresses */ - qsort (SegPool, SegCount, sizeof (Segment*), CmpSegStart); + qsort (SegPool, CollCount (&SegmentList), sizeof (Segment*), CmpSegStart); /* Print a header */ - fprintf (F, "Name Start End Size\n" - "--------------------------------------------\n"); + fprintf (F, "Name Start End Size Align\n" + "----------------------------------------------------\n"); /* Print the segments */ - for (I = 0; I < SegCount; ++I) { + for (I = 0; I < CollCount (&SegmentList); ++I) { /* Get a pointer to the segment */ - S = SegPool [I]; - - /* Print empty segments only if explicitly requested */ - if (VerboseMap || S->Size > 0) { - /* Print the segment data */ - fprintf (F, "%-20s %06lX %06lX %06lX\n", - S->Name, S->PC, S->PC + S->Size, S->Size); + Segment* S = SegPool[I]; + + /* Print empty segments only if explicitly requested */ + if (VerboseMap || S->Size > 0) { + /* Print the segment data */ + long End = S->PC + S->Size; + if (S->Size > 0) { + /* Point to last element addressed */ + --End; + } + fprintf (F, "%-20s %06lX %06lX %06lX %05lX\n", + GetString (S->Name), S->PC, End, S->Size, S->Alignment); } } @@ -643,17 +618,48 @@ void PrintSegmentMap (FILE* F) +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); + } +} + + + void CheckSegments (void) /* Walk through the segment list and check if there are segments that were * not written to the output file. Output an error if this is the case. */ { - Segment* S = SegRoot; - while (S) { - if (S->Size > 0 && S->Dumped == 0) { - Error ("Missing memory area assignment for segment `%s'", S->Name); + unsigned I; + for (I = 0; I < CollCount (&SegmentList); ++I) { + + /* Get the next segment */ + const Segment* S = CollAtUnchecked (&SegmentList, I); + + /* Check it */ + if (S->Size > 0 && S->Dumped == 0) { + Error ("Missing memory area assignment for segment `%s'", + GetString (S->Name)); } - S = S->List; } }