mirror of
https://github.com/cc65/cc65.git
synced 2024-10-01 15:54:59 +00:00
First finished implementation of the condes feature
git-svn-id: svn://svn.cc65.org/cc65/trunk@456 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
7646787a6e
commit
518220f9cf
@ -140,7 +140,7 @@ static void BinWriteMem (BinDesc* D, Memory* M)
|
|||||||
* in the linker.
|
* in the linker.
|
||||||
*/
|
*/
|
||||||
Warning ("Segment `%s' in module `%s' requires larger alignment",
|
Warning ("Segment `%s' in module `%s' requires larger alignment",
|
||||||
S->Name, S->Seg->AlignObj->Name);
|
S->Name, GetObjFileName (S->Seg->AlignObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle ALIGN and OFFSET/START */
|
/* Handle ALIGN and OFFSET/START */
|
||||||
|
@ -33,13 +33,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
#include "segdefs.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
#include "exports.h"
|
#include "exports.h"
|
||||||
|
#include "fragment.h"
|
||||||
#include "segments.h"
|
#include "segments.h"
|
||||||
#include "condes.h"
|
#include "condes.h"
|
||||||
|
|
||||||
@ -55,24 +59,134 @@
|
|||||||
typedef struct ConDesDesc ConDesDesc;
|
typedef struct ConDesDesc ConDesDesc;
|
||||||
struct ConDesDesc {
|
struct ConDesDesc {
|
||||||
Collection ExpList; /* List of exported symbols */
|
Collection ExpList; /* List of exported symbols */
|
||||||
char* Label; /* Name of table label */
|
|
||||||
char* SegName; /* Name of segment the table is in */
|
char* SegName; /* Name of segment the table is in */
|
||||||
unsigned char Enable; /* Table enabled */
|
char* Label; /* Name of table label */
|
||||||
|
char* CountSym; /* Name of symbol for entry count */
|
||||||
|
unsigned char Order; /* Table order (increasing/decreasing) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Array for all types */
|
/* Array for all types */
|
||||||
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
|
static ConDesDesc ConDes[CD_TYPE_COUNT] = {
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0 },
|
{ STATIC_COLLECTION_INITIALIZER, 0, 0, 0, cdIncreasing },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Internally used function to create the condes tables */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int ConDesCompare (void* Data, const void* E1, const void* E2)
|
||||||
|
/* Compare function to sort the exports */
|
||||||
|
{
|
||||||
|
int Cmp;
|
||||||
|
|
||||||
|
/* Data is actually a pointer to a ConDesDesc from the table, E1 and
|
||||||
|
* E2 are exports from the collection. Get the condes type and cast
|
||||||
|
* the void pointers to object pointers.
|
||||||
|
*/
|
||||||
|
ConDesDesc* CD = ((ConDesDesc*) Data);
|
||||||
|
int Type = CD - ConDes;
|
||||||
|
const Export* Exp1 = (const Export*) E1;
|
||||||
|
const Export* Exp2 = (const Export*) E2;
|
||||||
|
|
||||||
|
/* Get the priorities of the two exports */
|
||||||
|
unsigned Prio1 = Exp1->ConDes[Type];
|
||||||
|
unsigned Prio2 = Exp2->ConDes[Type];
|
||||||
|
|
||||||
|
/* Compare the priorities for this condes type */
|
||||||
|
if (Prio1 < Prio2) {
|
||||||
|
Cmp = -1;
|
||||||
|
} else if (Prio1 > Prio2) {
|
||||||
|
Cmp = 1;
|
||||||
|
} else {
|
||||||
|
/* Use the name in this case */
|
||||||
|
Cmp = strcmp (Exp1->Name, Exp2->Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reverse the result for decreasing order */
|
||||||
|
if (CD->Order == cdIncreasing) {
|
||||||
|
return Cmp;
|
||||||
|
} else {
|
||||||
|
return -Cmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ConDesCreateOne (ConDesDesc* CD)
|
||||||
|
/* Create one table if requested */
|
||||||
|
{
|
||||||
|
Segment* Seg; /* Segment for table */
|
||||||
|
Section* Sec; /* Section for table */
|
||||||
|
unsigned Count; /* Number of exports */
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Check if this table has a segment and table label defined. If not,
|
||||||
|
* creation was not requested in the config file - ignore it.
|
||||||
|
*/
|
||||||
|
if (CD->SegName == 0 || CD->Label == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there is an import for the table label. If not, there is no
|
||||||
|
* reference to the table and we would just waste memory creating the
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
if (!IsUnresolved (CD->Label)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort the collection of exports according to priority */
|
||||||
|
CollSort (&CD->ExpList, ConDesCompare, CD);
|
||||||
|
|
||||||
|
/* Get the segment for the table, create it if needed */
|
||||||
|
Seg = GetSegment (CD->SegName, SEGTYPE_ABS, 0);
|
||||||
|
|
||||||
|
/* Create a new section for the table */
|
||||||
|
Sec = NewSection (Seg, 1, SEGTYPE_ABS);
|
||||||
|
|
||||||
|
/* Walk over the exports and create a fragment for each one. We will use
|
||||||
|
* the exported expression without copying it, since it's cheap and there
|
||||||
|
* is currently no place where it gets changed (hope this will not hunt
|
||||||
|
* me later...).
|
||||||
|
*/
|
||||||
|
Count = CollCount (&CD->ExpList);
|
||||||
|
for (I = 0; I < Count; ++I) {
|
||||||
|
|
||||||
|
/* Get the export */
|
||||||
|
Export* E = CollAt (&CD->ExpList, I);
|
||||||
|
|
||||||
|
/* Create the fragment */
|
||||||
|
Fragment* F = NewFragment (FRAG_EXPR, 2, Sec);
|
||||||
|
|
||||||
|
/* Set the expression pointer */
|
||||||
|
F->Expr = E->Expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define the table start as an export, offset into section is zero
|
||||||
|
* (the section only contains the table).
|
||||||
|
*/
|
||||||
|
CreateSegExport (CD->Label, Sec, 0);
|
||||||
|
|
||||||
|
/* If we have a CountSym name given AND if it is referenced, define it
|
||||||
|
* with the number of elements in the table.
|
||||||
|
*/
|
||||||
|
if (CD->CountSym) {
|
||||||
|
CreateConstExport (CD->CountSym, Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -125,26 +239,29 @@ void ConDesSetLabel (unsigned Type, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* ConDesGetSegName (unsigned Type)
|
void ConDesSetCountSym (unsigned Type, const char* Name)
|
||||||
/* Return the segment name for the given ConDes type */
|
/* Set the name for the given ConDes count symbol */
|
||||||
{
|
{
|
||||||
/* Check the parameters */
|
/* Check the parameters */
|
||||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX && Name != 0);
|
||||||
|
|
||||||
/* Return the name */
|
/* Setting the symbol twice is bad */
|
||||||
return ConDes[Type].SegName;
|
CHECK (ConDes[Type].CountSym == 0);
|
||||||
|
|
||||||
|
/* Set the name */
|
||||||
|
ConDes[Type].CountSym = xstrdup (Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* ConDesGetLabel (unsigned Type)
|
void ConDesSetOrder (unsigned Type, ConDesOrder Order)
|
||||||
/* Return the label for the given ConDes type */
|
/* Set the sorting oder for the given ConDes table */
|
||||||
{
|
{
|
||||||
/* Check the parameters */
|
/* Check the parameters */
|
||||||
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||||
|
|
||||||
/* Return the name */
|
/* Set the order */
|
||||||
return ConDes[Type].Label;
|
ConDes[Type].Order = Order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -152,7 +269,10 @@ const char* ConDesGetLabel (unsigned Type)
|
|||||||
int ConDesHasSegName (unsigned Type)
|
int ConDesHasSegName (unsigned Type)
|
||||||
/* Return true if a segment name is already defined for this ConDes type */
|
/* Return true if a segment name is already defined for this ConDes type */
|
||||||
{
|
{
|
||||||
return (ConDesGetSegName(Type) != 0);
|
/* Check the parameters */
|
||||||
|
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||||
|
|
||||||
|
return (ConDes[Type].SegName != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,7 +280,10 @@ int ConDesHasSegName (unsigned Type)
|
|||||||
int ConDesHasLabel (unsigned Type)
|
int ConDesHasLabel (unsigned Type)
|
||||||
/* Return true if a label is already defined for this ConDes type */
|
/* Return true if a label is already defined for this ConDes type */
|
||||||
{
|
{
|
||||||
return (ConDesGetLabel(Type) != 0);
|
/* Check the parameters */
|
||||||
|
PRECONDITION (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
|
||||||
|
|
||||||
|
return (ConDes[Type].Label != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -168,6 +291,12 @@ int ConDesHasLabel (unsigned Type)
|
|||||||
void ConDesCreate (void)
|
void ConDesCreate (void)
|
||||||
/* Create the condes tables if requested */
|
/* Create the condes tables if requested */
|
||||||
{
|
{
|
||||||
|
unsigned Type;
|
||||||
|
|
||||||
|
/* Walk over the descriptor array and create a table for each entry */
|
||||||
|
for (Type = 0; Type < CD_TYPE_COUNT; ++Type) {
|
||||||
|
ConDesCreateOne (ConDes + Type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,20 @@ struct Export;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Order of the tables */
|
||||||
|
typedef enum {
|
||||||
|
cdIncreasing, /* Increasing priority - default */
|
||||||
|
cdDecreasing /* Decreasing priority */
|
||||||
|
} ConDesOrder;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -63,11 +77,11 @@ void ConDesSetSegName (unsigned Type, const char* SegName);
|
|||||||
void ConDesSetLabel (unsigned Type, const char* Name);
|
void ConDesSetLabel (unsigned Type, const char* Name);
|
||||||
/* Set the label for the given ConDes type */
|
/* Set the label for the given ConDes type */
|
||||||
|
|
||||||
const char* ConDesGetSegName (unsigned Type);
|
void ConDesSetCountSym (unsigned Type, const char* Name);
|
||||||
/* Return the segment name for the given ConDes type */
|
/* Set the name for the given ConDes count symbol */
|
||||||
|
|
||||||
const char* ConDesGetLabel (unsigned Type);
|
void ConDesSetOrder (unsigned Type, ConDesOrder Order);
|
||||||
/* Return the label for the given ConDes type */
|
/* Set the sorting oder for the given ConDes table */
|
||||||
|
|
||||||
int ConDesHasSegName (unsigned Type);
|
int ConDesHasSegName (unsigned Type);
|
||||||
/* Return true if a segment name is already defined for this ConDes type */
|
/* Return true if a segment name is already defined for this ConDes type */
|
||||||
|
@ -958,7 +958,9 @@ static void ParseConDes (void)
|
|||||||
static const IdentTok Attributes [] = {
|
static const IdentTok Attributes [] = {
|
||||||
{ "SEGMENT", CFGTOK_SEGMENT },
|
{ "SEGMENT", CFGTOK_SEGMENT },
|
||||||
{ "LABEL", CFGTOK_LABEL },
|
{ "LABEL", CFGTOK_LABEL },
|
||||||
|
{ "COUNT", CFGTOK_COUNT },
|
||||||
{ "TYPE", CFGTOK_TYPE },
|
{ "TYPE", CFGTOK_TYPE },
|
||||||
|
{ "ORDER", CFGTOK_ORDER },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const IdentTok Types [] = {
|
static const IdentTok Types [] = {
|
||||||
@ -966,17 +968,27 @@ static void ParseConDes (void)
|
|||||||
{ "DESTRUCTOR", CFGTOK_DESTRUCTOR },
|
{ "DESTRUCTOR", CFGTOK_DESTRUCTOR },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const IdentTok Orders [] = {
|
||||||
|
{ "DECREASING", CFGTOK_DECREASING },
|
||||||
|
{ "INCREASING", CFGTOK_INCREASING },
|
||||||
|
};
|
||||||
|
|
||||||
/* Attribute values. */
|
/* Attribute values. */
|
||||||
char SegName[sizeof (CfgSVal)];
|
char SegName[sizeof (CfgSVal)];
|
||||||
char Label[sizeof (CfgSVal)];
|
char Label[sizeof (CfgSVal)];
|
||||||
int Type = -1; /* Initialize to avoid gcc warnings */
|
char Count[sizeof (CfgSVal)];
|
||||||
|
/* Initialize to avoid gcc warnings: */
|
||||||
|
int Type = -1;
|
||||||
|
ConDesOrder Order = cdIncreasing;
|
||||||
|
|
||||||
/* Bitmask to remember the attributes we got already */
|
/* Bitmask to remember the attributes we got already */
|
||||||
enum {
|
enum {
|
||||||
atNone = 0x0000,
|
atNone = 0x0000,
|
||||||
atSegName = 0x0001,
|
atSegName = 0x0001,
|
||||||
atLabel = 0x0002,
|
atLabel = 0x0002,
|
||||||
atType = 0x0004
|
atCount = 0x0004,
|
||||||
|
atType = 0x0008,
|
||||||
|
atOrder = 0x0010
|
||||||
};
|
};
|
||||||
unsigned AttrFlags = atNone;
|
unsigned AttrFlags = atNone;
|
||||||
|
|
||||||
@ -1013,6 +1025,14 @@ static void ParseConDes (void)
|
|||||||
strcpy (Label, CfgSVal);
|
strcpy (Label, CfgSVal);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CFGTOK_COUNT:
|
||||||
|
/* Don't allow this twice */
|
||||||
|
FlagAttr (&AttrFlags, atCount, "COUNT");
|
||||||
|
/* We expect an identifier */
|
||||||
|
CfgAssureIdent ();
|
||||||
|
/* Remember the value for later */
|
||||||
|
strcpy (Count, CfgSVal);
|
||||||
|
break;
|
||||||
|
|
||||||
case CFGTOK_TYPE:
|
case CFGTOK_TYPE:
|
||||||
/* Don't allow this twice */
|
/* Don't allow this twice */
|
||||||
@ -1031,6 +1051,17 @@ static void ParseConDes (void)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CFGTOK_ORDER:
|
||||||
|
/* Don't allow this twice */
|
||||||
|
FlagAttr (&AttrFlags, atOrder, "ORDER");
|
||||||
|
CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order");
|
||||||
|
switch (CfgTok) {
|
||||||
|
case CFGTOK_DECREASING: Order = cdDecreasing; break;
|
||||||
|
case CFGTOK_INCREASING: Order = cdIncreasing; break;
|
||||||
|
default: FAIL ("Unexpected order token");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FAIL ("Unexpected attribute token");
|
FAIL ("Unexpected attribute token");
|
||||||
|
|
||||||
@ -1060,6 +1091,12 @@ static void ParseConDes (void)
|
|||||||
/* Define the attributes */
|
/* Define the attributes */
|
||||||
ConDesSetSegName (Type, SegName);
|
ConDesSetSegName (Type, SegName);
|
||||||
ConDesSetLabel (Type, Label);
|
ConDesSetLabel (Type, Label);
|
||||||
|
if (AttrFlags & atCount) {
|
||||||
|
ConDesSetCountSym (Type, Count);
|
||||||
|
}
|
||||||
|
if (AttrFlags & atOrder) {
|
||||||
|
ConDesSetOrder (Type, Order);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -170,7 +170,8 @@ Import* ReadImport (FILE* F, ObjData* Obj)
|
|||||||
/* Read the import type and check it */
|
/* Read the import type and check it */
|
||||||
unsigned char Type = Read8 (F);
|
unsigned char Type = Read8 (F);
|
||||||
if (Type != IMP_ZP && Type != IMP_ABS) {
|
if (Type != IMP_ZP && Type != IMP_ABS) {
|
||||||
Error ("Unknown import type in module `%s': %02X", Obj->Name, Type);
|
Error ("Unknown import type in module `%s': %02X",
|
||||||
|
GetObjFileName (Obj), Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a new import */
|
/* Create a new import */
|
||||||
@ -349,7 +350,7 @@ Export* CreateConstExport (const char* Name, long Value)
|
|||||||
/* Create an export for a literal date */
|
/* Create an export for a literal date */
|
||||||
{
|
{
|
||||||
/* Create a new export */
|
/* Create a new export */
|
||||||
Export* E = NewExport (EXP_ABS, Name, 0);
|
Export* E = NewExport (EXP_ABS | EXP_CONST, Name, 0);
|
||||||
|
|
||||||
/* Assign the value */
|
/* Assign the value */
|
||||||
E->Expr = LiteralExpr (Value, 0);
|
E->Expr = LiteralExpr (Value, 0);
|
||||||
@ -367,7 +368,7 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs)
|
|||||||
/* Create an relative export for a memory area offset */
|
/* Create an relative export for a memory area offset */
|
||||||
{
|
{
|
||||||
/* Create a new export */
|
/* Create a new export */
|
||||||
Export* E = NewExport (EXP_ABS, Name, 0);
|
Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
|
||||||
|
|
||||||
/* Assign the value */
|
/* Assign the value */
|
||||||
E->Expr = MemExpr (Mem, Offs, 0);
|
E->Expr = MemExpr (Mem, Offs, 0);
|
||||||
@ -381,6 +382,24 @@ Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Export* CreateSegExport (const char* Name, Section* Sec, unsigned long Offs)
|
||||||
|
/* Create a relative export to a segment (section) */
|
||||||
|
{
|
||||||
|
/* Create a new export */
|
||||||
|
Export* E = NewExport (EXP_ABS | EXP_EXPR, Name, 0);
|
||||||
|
|
||||||
|
/* Assign the value */
|
||||||
|
E->Expr = SegExpr (Sec, Offs, 0);
|
||||||
|
|
||||||
|
/* Insert the export */
|
||||||
|
InsertExport (E);
|
||||||
|
|
||||||
|
/* Return the new export */
|
||||||
|
return E;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Export* FindExport (const char* Name)
|
static Export* FindExport (const char* Name)
|
||||||
/* Check for an identifier in the list. Return 0 if not found, otherwise
|
/* Check for an identifier in the list. Return 0 if not found, otherwise
|
||||||
* return a pointer to the export.
|
* return a pointer to the export.
|
||||||
@ -453,13 +472,13 @@ static void CheckSymType (const Export* E)
|
|||||||
/* User defined export */
|
/* User defined export */
|
||||||
Warning ("Type mismatch for `%s', export in "
|
Warning ("Type mismatch for `%s', export in "
|
||||||
"%s(%lu), import in %s(%lu)",
|
"%s(%lu), import in %s(%lu)",
|
||||||
E->Name, E->Obj->Files [Imp->Pos.Name],
|
E->Name, GetSourceFileName (E->Obj, Imp->Pos.Name),
|
||||||
E->Pos.Line, Imp->Obj->Files [Imp->Pos.Name],
|
E->Pos.Line, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
|
||||||
Imp->Pos.Line);
|
Imp->Pos.Line);
|
||||||
} else {
|
} else {
|
||||||
/* Export created by the linker */
|
/* Export created by the linker */
|
||||||
Warning ("Type mismatch for `%s', imported from %s(%lu)",
|
Warning ("Type mismatch for `%s', imported from %s(%lu)",
|
||||||
E->Name, Imp->Obj->Files [Imp->Pos.Name],
|
E->Name, GetSourceFileName (Imp->Obj, Imp->Pos.Name),
|
||||||
Imp->Pos.Line);
|
Imp->Pos.Line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,7 +522,7 @@ static void PrintUnresolved (ExpCheckFunc F, void* Data)
|
|||||||
"Unresolved external `%s' referenced in:\n",
|
"Unresolved external `%s' referenced in:\n",
|
||||||
E->Name);
|
E->Name);
|
||||||
while (Imp) {
|
while (Imp) {
|
||||||
const char* Name = Imp->Obj->Files [Imp->Pos.Name];
|
const char* Name = GetSourceFileName (Imp->Obj, Imp->Pos.Name);
|
||||||
fprintf (stderr, " %s(%lu)\n", Name, Imp->Pos.Line);
|
fprintf (stderr, " %s(%lu)\n", Name, Imp->Pos.Line);
|
||||||
Imp = Imp->Next;
|
Imp = Imp->Next;
|
||||||
}
|
}
|
||||||
@ -580,7 +599,7 @@ void PrintExportMap (FILE* F)
|
|||||||
const Export* E = ExpPool [I];
|
const Export* E = ExpPool [I];
|
||||||
|
|
||||||
/* Print unreferenced symbols only if explictly requested */
|
/* Print unreferenced symbols only if explictly requested */
|
||||||
if (VerboseMap || E->ImpCount > 0) {
|
if (VerboseMap || E->ImpCount > 0 || IS_EXP_CONDES (E->Type)) {
|
||||||
fprintf (F,
|
fprintf (F,
|
||||||
"%-25s %06lX %c%c%c ",
|
"%-25s %06lX %c%c%c ",
|
||||||
E->Name,
|
E->Name,
|
||||||
@ -616,17 +635,11 @@ void PrintImportMap (FILE* F)
|
|||||||
*/
|
*/
|
||||||
if (VerboseMap || Exp->ImpCount > 0) {
|
if (VerboseMap || Exp->ImpCount > 0) {
|
||||||
|
|
||||||
/* Get the name of the object file that exports the symbol.
|
|
||||||
* Beware: There may be no object file if the symbol is a linker
|
|
||||||
* generated symbol.
|
|
||||||
*/
|
|
||||||
const char* ObjName = (Exp->Obj != 0)? Exp->Obj->Name : "linker generated";
|
|
||||||
|
|
||||||
/* Print the export */
|
/* Print the export */
|
||||||
fprintf (F,
|
fprintf (F,
|
||||||
"%s (%s):\n",
|
"%s (%s):\n",
|
||||||
Exp->Name,
|
Exp->Name,
|
||||||
ObjName);
|
GetObjFileName (Exp->Obj));
|
||||||
|
|
||||||
/* Print all imports for this symbol */
|
/* Print all imports for this symbol */
|
||||||
Imp = Exp->ImpList;
|
Imp = Exp->ImpList;
|
||||||
@ -635,8 +648,8 @@ void PrintImportMap (FILE* F)
|
|||||||
/* Print the import */
|
/* Print the import */
|
||||||
fprintf (F,
|
fprintf (F,
|
||||||
" %-25s %s(%lu)\n",
|
" %-25s %s(%lu)\n",
|
||||||
Imp->Obj->Name,
|
GetObjFileName (Imp->Obj),
|
||||||
Imp->Obj->Files [Imp->Pos.Name],
|
GetSourceFileName (Imp->Obj, Imp->Pos.Name),
|
||||||
Imp->Pos.Line);
|
Imp->Pos.Line);
|
||||||
|
|
||||||
/* Next import */
|
/* Next import */
|
||||||
@ -691,7 +704,7 @@ void CircularRefError (const Export* E)
|
|||||||
/* Print an error about a circular reference using to define the given export */
|
/* Print an error about a circular reference using to define the given export */
|
||||||
{
|
{
|
||||||
Error ("Circular reference for symbol `%s', %s(%lu)",
|
Error ("Circular reference for symbol `%s', %s(%lu)",
|
||||||
E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
|
E->Name, GetSourceFileName (E->Obj, E->Pos.Name), E->Pos.Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,6 +123,9 @@ Export* CreateConstExport (const char* Name, long Value);
|
|||||||
Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
|
Export* CreateMemExport (const char* Name, Memory* Mem, unsigned long Offs);
|
||||||
/* Create an relative export for a memory area offset */
|
/* Create an relative export for a memory area offset */
|
||||||
|
|
||||||
|
Export* CreateSegExport (const char* Name, Section* S, unsigned long Offs);
|
||||||
|
/* Create a relative export to a segment (section) */
|
||||||
|
|
||||||
int IsUnresolved (const char* Name);
|
int IsUnresolved (const char* Name);
|
||||||
/* Check if this symbol is an unresolved export */
|
/* Check if this symbol is an unresolved export */
|
||||||
|
|
||||||
|
@ -119,7 +119,8 @@ int IsConstExpr (ExprNode* Root)
|
|||||||
*/
|
*/
|
||||||
if (ExportHasMark (E)) {
|
if (ExportHasMark (E)) {
|
||||||
Error ("Circular reference for symbol `%s', %s(%lu)",
|
Error ("Circular reference for symbol `%s', %s(%lu)",
|
||||||
E->Name, E->Obj->Files [E->Pos.Name], E->Pos.Line);
|
E->Name, GetSourceFileName (E->Obj, E->Pos.Name),
|
||||||
|
E->Pos.Line);
|
||||||
Const = 0;
|
Const = 0;
|
||||||
} else {
|
} else {
|
||||||
MarkExport (E);
|
MarkExport (E);
|
||||||
@ -208,8 +209,16 @@ Section* GetExprSection (ExprNode* Expr)
|
|||||||
/* Check that this is really a segment node */
|
/* Check that this is really a segment node */
|
||||||
PRECONDITION (Expr->Op == EXPR_SEGMENT);
|
PRECONDITION (Expr->Op == EXPR_SEGMENT);
|
||||||
|
|
||||||
|
/* If we have an object file, get the section from it, otherwise
|
||||||
|
* (internally generated expressions), get the section from the
|
||||||
|
* section pointer.
|
||||||
|
*/
|
||||||
|
if (Expr->Obj) {
|
||||||
/* Return the export */
|
/* Return the export */
|
||||||
return Expr->Obj->Sections [Expr->V.SegNum];
|
return Expr->Obj->Sections [Expr->V.SegNum];
|
||||||
|
} else {
|
||||||
|
return Expr->V.Sec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -381,6 +390,25 @@ ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O)
|
||||||
|
/* Return an expression tree that encodes an offset into a segment */
|
||||||
|
{
|
||||||
|
ExprNode* Root;
|
||||||
|
|
||||||
|
ExprNode* Expr = NewExprNode (O);
|
||||||
|
Expr->Op = EXPR_SEGMENT;
|
||||||
|
Expr->V.Sec = Sec;
|
||||||
|
|
||||||
|
Root = NewExprNode (O);
|
||||||
|
Root->Op = EXPR_PLUS;
|
||||||
|
Root->Left = Expr;
|
||||||
|
Root->Right = LiteralExpr (Offs, O);
|
||||||
|
|
||||||
|
return Root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ExprNode* ReadExpr (FILE* F, ObjData* O)
|
ExprNode* ReadExpr (FILE* F, ObjData* O)
|
||||||
/* Read an expression from the given file */
|
/* Read an expression from the given file */
|
||||||
{
|
{
|
||||||
@ -461,8 +489,8 @@ int EqualExpr (ExprNode* E1, ExprNode* E2)
|
|||||||
return (E1->V.ImpNum == E2->V.ImpNum);
|
return (E1->V.ImpNum == E2->V.ImpNum);
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SEGMENT:
|
||||||
/* Segment number must be identical */
|
/* Section must be identical */
|
||||||
return (E1->V.SegNum == E2->V.SegNum);
|
return (GetExprSection (E1) == GetExprSection (E2));
|
||||||
|
|
||||||
case EXPR_MEMAREA:
|
case EXPR_MEMAREA:
|
||||||
/* Memory area must be identical */
|
/* Memory area must be identical */
|
||||||
|
@ -80,6 +80,9 @@ ExprNode* LiteralExpr (long Val, ObjData* O);
|
|||||||
ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O);
|
ExprNode* MemExpr (Memory* Mem, long Offs, ObjData* O);
|
||||||
/* Return an expression tree that encodes an offset into the memory area */
|
/* Return an expression tree that encodes an offset into the memory area */
|
||||||
|
|
||||||
|
ExprNode* SegExpr (Section* Sec, long Offs, ObjData* O);
|
||||||
|
/* Return an expression tree that encodes an offset into a segment */
|
||||||
|
|
||||||
void DumpExpr (const ExprNode* Expr);
|
void DumpExpr (const ExprNode* Expr);
|
||||||
/* Dump an expression tree to stdout */
|
/* Dump an expression tree to stdout */
|
||||||
|
|
||||||
|
@ -59,9 +59,10 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S)
|
|||||||
F->Obj = 0;
|
F->Obj = 0;
|
||||||
F->Size = Size;
|
F->Size = Size;
|
||||||
F->Expr = 0;
|
F->Expr = 0;
|
||||||
|
InitFilePos (&F->Pos);
|
||||||
F->Type = Type;
|
F->Type = Type;
|
||||||
|
|
||||||
/* Insert the code fragment into the segment */
|
/* Insert the code fragment into the section */
|
||||||
if (S->FragRoot == 0) {
|
if (S->FragRoot == 0) {
|
||||||
/* First fragment */
|
/* First fragment */
|
||||||
S->FragRoot = F;
|
S->FragRoot = F;
|
||||||
@ -69,8 +70,13 @@ Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S)
|
|||||||
S->FragLast->Next = F;
|
S->FragLast->Next = F;
|
||||||
}
|
}
|
||||||
S->FragLast = F;
|
S->FragLast = F;
|
||||||
|
|
||||||
|
/* Increment the size of the section by the size of the fragment */
|
||||||
S->Size += Size;
|
S->Size += Size;
|
||||||
|
|
||||||
|
/* Increment the size of the segment that contains the section */
|
||||||
|
S->Seg->Size += Size;
|
||||||
|
|
||||||
/* Return the new fragment */
|
/* Return the new fragment */
|
||||||
return F;
|
return F;
|
||||||
}
|
}
|
||||||
|
@ -80,12 +80,13 @@ static void LibReadObjHeader (ObjData* O)
|
|||||||
{
|
{
|
||||||
O->Header.Magic = Read32 (Lib);
|
O->Header.Magic = Read32 (Lib);
|
||||||
if (O->Header.Magic != OBJ_MAGIC) {
|
if (O->Header.Magic != OBJ_MAGIC) {
|
||||||
Error ("Object file `%s' in library `%s' is invalid", O->Name, LibName);
|
Error ("Object file `%s' in library `%s' is invalid",
|
||||||
|
GetObjFileName (O), LibName);
|
||||||
}
|
}
|
||||||
O->Header.Version = Read16 (Lib);
|
O->Header.Version = Read16 (Lib);
|
||||||
if (O->Header.Version != OBJ_VERSION) {
|
if (O->Header.Version != OBJ_VERSION) {
|
||||||
Error ("Object file `%s' in library `%s' has wrong version",
|
Error ("Object file `%s' in library `%s' has wrong version",
|
||||||
O->Name, LibName);
|
GetObjFileName (O), LibName);
|
||||||
}
|
}
|
||||||
O->Header.Flags = Read16 (Lib);
|
O->Header.Flags = Read16 (Lib);
|
||||||
O->Header.OptionOffs = Read32 (Lib);
|
O->Header.OptionOffs = Read32 (Lib);
|
||||||
@ -281,7 +282,3 @@ void LibAdd (FILE* F, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ void CreateMapFile (void)
|
|||||||
/* We've linked this module */
|
/* We've linked this module */
|
||||||
if (O->LibName) {
|
if (O->LibName) {
|
||||||
/* The file is from a library */
|
/* The file is from a library */
|
||||||
fprintf (F, "%s(%s):\n", O->LibName, O->Name);
|
fprintf (F, "%s(%s):\n", O->LibName, GetObjFileName (O));
|
||||||
} else {
|
} else {
|
||||||
fprintf (F, "%s:\n", O->Name);
|
fprintf (F, "%s:\n", GetObjFileName (O));
|
||||||
}
|
}
|
||||||
for (I = 0; I < O->SectionCount; ++I) {
|
for (I = 0; I < O->SectionCount; ++I) {
|
||||||
const Section* S = O->Sections [I];
|
const Section* S = O->Sections [I];
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998 Ullrich von Bassewitz */
|
/* (C) 1998-2000 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@musoftware.de */
|
||||||
@ -35,8 +35,11 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../common/xmalloc.h"
|
/* common */
|
||||||
|
#include "check.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
/* ld65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "objdata.h"
|
#include "objdata.h"
|
||||||
|
|
||||||
@ -111,3 +114,38 @@ void FreeObjData (ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* GetObjFileName (const ObjData* O)
|
||||||
|
/* Get the name of the object file. Return "(linker generated)" if the object
|
||||||
|
* file is NULL.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return O? O->Name : "(linker generated)";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* GetSourceFileName (const ObjData* O, unsigned Index)
|
||||||
|
/* Get the name of the source file with the given index. If O is NULL, return
|
||||||
|
* "(linker generated)" as the file name.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Check if we have an object file */
|
||||||
|
if (O == 0) {
|
||||||
|
|
||||||
|
/* No object file */
|
||||||
|
return "(linker generated)";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Check the parameter */
|
||||||
|
PRECONDITION (Index < O->FileCount);
|
||||||
|
|
||||||
|
/* Return the name */
|
||||||
|
return O->Files[Index];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +97,16 @@ ObjData* NewObjData (void);
|
|||||||
void FreeObjData (ObjData* O);
|
void FreeObjData (ObjData* O);
|
||||||
/* Free a complete struct */
|
/* Free a complete struct */
|
||||||
|
|
||||||
|
const char* GetObjFileName (const ObjData* O);
|
||||||
|
/* Get the name of the object file. Return "(linker generated)" if the object
|
||||||
|
* file is NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char* GetSourceFileName (const ObjData* O, unsigned Index);
|
||||||
|
/* Get the name of the source file with the given index. If O is NULL, return
|
||||||
|
* "(linker generated)" as the file name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of objdata.h */
|
/* End of objdata.h */
|
||||||
|
@ -104,8 +104,14 @@ typedef enum {
|
|||||||
CFGTOK_CONDES,
|
CFGTOK_CONDES,
|
||||||
CFGTOK_SEGMENT,
|
CFGTOK_SEGMENT,
|
||||||
CFGTOK_LABEL,
|
CFGTOK_LABEL,
|
||||||
|
CFGTOK_COUNT,
|
||||||
|
CFGTOK_ORDER,
|
||||||
|
|
||||||
CFGTOK_CONSTRUCTOR,
|
CFGTOK_CONSTRUCTOR,
|
||||||
CFGTOK_DESTRUCTOR
|
CFGTOK_DESTRUCTOR,
|
||||||
|
|
||||||
|
CFGTOK_DECREASING,
|
||||||
|
CFGTOK_INCREASING
|
||||||
|
|
||||||
} cfgtok_t;
|
} cfgtok_t;
|
||||||
|
|
||||||
|
@ -75,7 +75,26 @@ static Segment* SegRoot = 0; /* List of all segments */
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Segment* NewSegment (const char* Name, unsigned char Type)
|
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)
|
||||||
/* Create a new segment and initialize it */
|
/* Create a new segment and initialize it */
|
||||||
{
|
{
|
||||||
/* Get the length of the symbol name */
|
/* Get the length of the symbol name */
|
||||||
@ -103,13 +122,50 @@ static Segment* NewSegment (const char* Name, unsigned char Type)
|
|||||||
SegRoot = S;
|
SegRoot = S;
|
||||||
++SegCount;
|
++SegCount;
|
||||||
|
|
||||||
|
/* Insert the segment into the segment hash list */
|
||||||
|
S->Next = HashTab [HashVal];
|
||||||
|
HashTab [HashVal] = S;
|
||||||
|
|
||||||
/* Return the new entry */
|
/* Return the new entry */
|
||||||
return S;
|
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 */
|
/* Create a new section for the given segment */
|
||||||
{
|
{
|
||||||
unsigned long V;
|
unsigned long V;
|
||||||
@ -150,29 +206,9 @@ 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)
|
Section* ReadSection (FILE* F, ObjData* O)
|
||||||
/* Read a section from a file */
|
/* Read a section from a file */
|
||||||
{
|
{
|
||||||
unsigned HashVal;
|
|
||||||
char* Name;
|
char* Name;
|
||||||
unsigned long Size;
|
unsigned long Size;
|
||||||
unsigned char Align;
|
unsigned char Align;
|
||||||
@ -195,22 +231,11 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
/* Print some data */
|
/* Print some data */
|
||||||
if (Verbose > 1) {
|
if (Verbose > 1) {
|
||||||
printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n",
|
printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n",
|
||||||
O->Name, Name, Size, Align, Type);
|
GetObjFileName (O), Name, Size, Align, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a hash over the name and try to locate the segment in the table */
|
/* Get the segment for this section */
|
||||||
HashVal = HashStr (Name) % HASHTAB_SIZE;
|
S = GetSegment (Name, Type, GetObjFileName (O));
|
||||||
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 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 */
|
/* We have the segment and don't need the name any longer */
|
||||||
xfree (Name);
|
xfree (Name);
|
||||||
@ -218,12 +243,6 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
/* Allocate the section we will return later */
|
/* Allocate the section we will return later */
|
||||||
Sec = NewSection (S, Align, Type);
|
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 */
|
/* Set up the minimum segment alignment */
|
||||||
if (Sec->Align > S->Align) {
|
if (Sec->Align > S->Align) {
|
||||||
/* Section needs larger alignment, use this one */
|
/* Section needs larger alignment, use this one */
|
||||||
@ -264,7 +283,7 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
|
Error ("Unknown fragment type in module `%s', segment `%s': %02X",
|
||||||
O->Name, S->Name, Type);
|
GetObjFileName (O), S->Name, Type);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -296,9 +315,6 @@ Section* ReadSection (FILE* F, ObjData* O)
|
|||||||
Size -= Frag->Size;
|
Size -= Frag->Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the segment size by the section size */
|
|
||||||
S->Size += Sec->Size;
|
|
||||||
|
|
||||||
/* Return the section */
|
/* Return the section */
|
||||||
return Sec;
|
return Sec;
|
||||||
}
|
}
|
||||||
@ -489,12 +505,14 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data)
|
|||||||
|
|
||||||
case SEG_EXPR_RANGE_ERROR:
|
case SEG_EXPR_RANGE_ERROR:
|
||||||
Error ("Range error in module `%s', line %lu",
|
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;
|
break;
|
||||||
|
|
||||||
case SEG_EXPR_TOO_COMPLEX:
|
case SEG_EXPR_TOO_COMPLEX:
|
||||||
Error ("Expression too complex in module `%s', line %lu",
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -107,6 +107,15 @@ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type);
|
||||||
|
/* Create a new section for the given segment */
|
||||||
|
|
||||||
Section* ReadSection (FILE* F, struct ObjData* O);
|
Section* ReadSection (FILE* F, struct ObjData* O);
|
||||||
/* Read a section from a file */
|
/* Read a section from a file */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user