X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=1474ebe5550f4cba2b108598d110c7b226737575;hb=35e1184901ca38bdb2e56d154ed3b71f6096eacc;hp=17976e52d804514084187442744e32bd99fc623b;hpb=5ee8618510eacaca1f779612103bf709f59e9450;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 17976e52d..1474ebe55 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (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,14 @@ #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" #include "xmalloc.h" @@ -48,8 +53,11 @@ #include "error.h" #include "expr.h" #include "fileio.h" +#include "fragment.h" #include "global.h" +#include "lineinfo.h" #include "segments.h" +#include "spool.h" @@ -59,26 +67,13 @@ -/* 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]; +#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; @@ -88,103 +83,103 @@ 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* NewSegment (unsigned Name, unsigned char AddrSize) +/* Create a new segment and initialize it */ { + unsigned Hash; + /* Allocate memory */ - Fragment* F = xmalloc (sizeof (Fragment) - 1 + Size); /* Portable? */ + Segment* S = xmalloc (sizeof (Segment)); - /* 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; - } - S->FragLast = F; - S->Size += Size; + /* Initialize the fields */ + 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 */ + Hash = (S->Name & HASHTAB_MASK); + S->Next = HashTab[Hash]; + HashTab[Hash] = S; - /* Return the new fragment */ - return F; + /* Return the new entry */ + return S; } -static Segment* NewSegment (const char* Name, unsigned char Type) -/* Create a new segment and initialize it */ +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. + */ { - /* Get the length of the symbol name */ - unsigned Len = strlen (Name); - - /* Allocate memory */ - Segment* S = xmalloc (sizeof (Segment) + Len); + /* Try to locate the segment in the table */ + Segment* S = SegFind (Name); - /* 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; + /* 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, AddrSize); + } else { + /* 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, + GetString (Name)); + } + } - /* Return the new entry */ + /* Return the segment */ return S; } -static 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->Size = 0; + 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; @@ -192,174 +187,127 @@ 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]; - 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 */ - ReadStr (F, Name); + 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 */ - if (Verbose > 1) { - printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", - O->Name, 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); - - /* If we don't have that segment already, allocate it using the type of - * the first section. + 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)); + + /* The only possible flag is currently SEG_FLAG_BANKREF, and it must be + * applied to the segment, not the section. */ - if (S == 0) { - /* Create a new segment and insert it */ - S = NewSegment (Name, Type); - S->Next = HashTab [HashVal]; - HashTab [HashVal] = S; - } + S->Flags |= Flags; /* 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 */ - 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; /* 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_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); + 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 (FRAG_FILL, Read16 (F), Sec); + Frag = NewFragment (Type, ReadVar (F), Sec); break; default: Error ("Unknown fragment type in module `%s', segment `%s': %02X", - O->Name, 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 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; } - /* Increment the segment size by the section size */ - S->Size += Sec->Size; - /* Return the section */ return Sec; } -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; } @@ -370,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) { @@ -380,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) { @@ -390,7 +342,6 @@ int IsBSSType (Segment* S) } F = F->Next; } - Sec = Sec->Next; } return 1; } @@ -400,60 +351,59 @@ 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); - break; + printf (" Empty space (%u bytes)\n", F->Size); + break; default: Internal ("Invalid fragment type: %02X", F->Type); } F = F->Next; } - S = S->Next; } - Seg = Seg->List; } } @@ -464,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 }; @@ -483,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; } @@ -503,49 +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); + /* 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", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + 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 %u", + GetFragmentSourceName (Frag), + GetFragmentSourceLine (Frag)); break; - case SEG_EXPR_TOO_COMPLEX: - Error ("Expression too complex in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + case SEG_EXPR_INVALID: + Error ("Invalid expression in module `%s', line %u", + GetFragmentSourceName (Frag), + GetFragmentSourceLine (Frag)); break; default: @@ -561,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 */ { @@ -584,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)); } } @@ -598,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); } } @@ -651,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; } }