Added assertions
git-svn-id: svn://svn.cc65.org/cc65/trunk@2202 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -111,6 +111,8 @@ void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
H->LineInfoSize = Read32 (Obj);
|
H->LineInfoSize = Read32 (Obj);
|
||||||
H->StrPoolOffs = Read32 (Obj);
|
H->StrPoolOffs = Read32 (Obj);
|
||||||
H->StrPoolSize = Read32 (Obj);
|
H->StrPoolSize = Read32 (Obj);
|
||||||
|
H->AssertOffs = Read32 (Obj);
|
||||||
|
H->AssertSize = Read32 (Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -137,6 +139,8 @@ void ObjWriteHeader (FILE* Obj, ObjHeader* H)
|
|||||||
Write32 (Obj, H->LineInfoSize);
|
Write32 (Obj, H->LineInfoSize);
|
||||||
Write32 (Obj, H->StrPoolOffs);
|
Write32 (Obj, H->StrPoolOffs);
|
||||||
Write32 (Obj, H->StrPoolSize);
|
Write32 (Obj, H->StrPoolSize);
|
||||||
|
Write32 (Obj, H->AssertOffs);
|
||||||
|
Write32 (Obj, H->AssertSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -201,7 +205,7 @@ void ObjAdd (const char* Name)
|
|||||||
O->StringCount = ReadVar (Obj);
|
O->StringCount = ReadVar (Obj);
|
||||||
O->Strings = xmalloc (O->StringCount * sizeof (char*));
|
O->Strings = xmalloc (O->StringCount * sizeof (char*));
|
||||||
for (I = 0; I < O->StringCount; ++I) {
|
for (I = 0; I < O->StringCount; ++I) {
|
||||||
O->Strings[I] = ReadStr (Obj);
|
O->Strings[I] = ReadStr (Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the object file header */
|
/* Skip the object file header */
|
||||||
@@ -219,6 +223,8 @@ void ObjAdd (const char* Name)
|
|||||||
H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
|
H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
|
||||||
fseek (Obj, H.LineInfoOffs, SEEK_SET);
|
fseek (Obj, H.LineInfoOffs, SEEK_SET);
|
||||||
H.LineInfoOffs = LibCopyTo (Obj, H.LineInfoSize) - O->Start;
|
H.LineInfoOffs = LibCopyTo (Obj, H.LineInfoSize) - O->Start;
|
||||||
|
fseek (Obj, H.AssertOffs, SEEK_SET);
|
||||||
|
H.AssertOffs = LibCopyTo (Obj, H.AssertSize) - O->Start;
|
||||||
|
|
||||||
/* Calculate the amount of data written */
|
/* Calculate the amount of data written */
|
||||||
O->Size = ftell (NewLib) - O->Start;
|
O->Size = ftell (NewLib) - O->Start;
|
||||||
@@ -270,7 +276,7 @@ void ObjExtract (const char* Name)
|
|||||||
Error ("Cannot open target file `%s': %s", Name, strerror (errno));
|
Error ("Cannot open target file `%s': %s", Name, strerror (errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the first four segments including the header to the new file */
|
/* Copy anything to the new file that has no special handling */
|
||||||
LibCopyFrom (O->Start, O->Size, Obj);
|
LibCopyFrom (O->Start, O->Size, Obj);
|
||||||
|
|
||||||
/* Write imports and exports */
|
/* Write imports and exports */
|
||||||
@@ -284,7 +290,7 @@ void ObjExtract (const char* Name)
|
|||||||
WriteVar (Obj, O->StringCount);
|
WriteVar (Obj, O->StringCount);
|
||||||
for (I = 0; I < O->StringCount; ++I) {
|
for (I = 0; I < O->StringCount; ++I) {
|
||||||
WriteStr (Obj, O->Strings[I]);
|
WriteStr (Obj, O->Strings[I]);
|
||||||
}
|
}
|
||||||
StrPoolSize = ftell (Obj) - StrPoolStart;
|
StrPoolSize = ftell (Obj) - StrPoolStart;
|
||||||
|
|
||||||
/* Seek back and read the header */
|
/* Seek back and read the header */
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ void ErrorMsg (const FilePos* Pos, unsigned ErrNum, va_list ap)
|
|||||||
"Illegal macro package name",
|
"Illegal macro package name",
|
||||||
"Illegal emulation feature",
|
"Illegal emulation feature",
|
||||||
"Illegal scope specifier",
|
"Illegal scope specifier",
|
||||||
|
"Illegal assert action",
|
||||||
"Syntax error",
|
"Syntax error",
|
||||||
"Symbol `%s' is already defined",
|
"Symbol `%s' is already defined",
|
||||||
"Undefined symbol `%s'",
|
"Undefined symbol `%s'",
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ enum Errors {
|
|||||||
ERR_ILLEGAL_MACPACK,
|
ERR_ILLEGAL_MACPACK,
|
||||||
ERR_ILLEGAL_FEATURE,
|
ERR_ILLEGAL_FEATURE,
|
||||||
ERR_ILLEGAL_SCOPE,
|
ERR_ILLEGAL_SCOPE,
|
||||||
|
ERR_ILLEGAL_ASSERT_ACTION,
|
||||||
ERR_SYNTAX,
|
ERR_SYNTAX,
|
||||||
ERR_SYM_ALREADY_DEFINED,
|
ERR_SYM_ALREADY_DEFINED,
|
||||||
ERR_SYM_UNDEFINED,
|
ERR_SYM_UNDEFINED,
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include "incpath.h"
|
#include "incpath.h"
|
||||||
#include "instr.h"
|
#include "instr.h"
|
||||||
#include "istack.h"
|
#include "istack.h"
|
||||||
|
#include "ldassert.h"
|
||||||
#include "lineinfo.h"
|
#include "lineinfo.h"
|
||||||
#include "listing.h"
|
#include "listing.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
@@ -484,6 +485,9 @@ static void CreateObjFile (void)
|
|||||||
/* Write the string pool */
|
/* Write the string pool */
|
||||||
WriteStrPool ();
|
WriteStrPool ();
|
||||||
|
|
||||||
|
/* Write the assertions */
|
||||||
|
WriteAssertions ();
|
||||||
|
|
||||||
/* Write an updated header and close the file */
|
/* Write an updated header and close the file */
|
||||||
ObjClose ();
|
ObjClose ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ OBJS = condasm.o \
|
|||||||
incpath.o \
|
incpath.o \
|
||||||
instr.o \
|
instr.o \
|
||||||
istack.o \
|
istack.o \
|
||||||
|
ldassert.o \
|
||||||
lineinfo.o \
|
lineinfo.o \
|
||||||
listing.o \
|
listing.o \
|
||||||
macpack.o \
|
macpack.o \
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ OBJS = condasm.obj \
|
|||||||
incpath.obj \
|
incpath.obj \
|
||||||
instr.obj \
|
instr.obj \
|
||||||
istack.obj \
|
istack.obj \
|
||||||
|
ldassert.obj \
|
||||||
lineinfo.obj \
|
lineinfo.obj \
|
||||||
listing.obj \
|
listing.obj \
|
||||||
macpack.obj \
|
macpack.obj \
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ static ObjHeader Header = {
|
|||||||
0, /* 32: Offset to list of line infos */
|
0, /* 32: Offset to list of line infos */
|
||||||
0, /* 32: Size of line infos */
|
0, /* 32: Size of line infos */
|
||||||
0, /* 32: Offset to string pool */
|
0, /* 32: Offset to string pool */
|
||||||
0 /* 32: Size of string pool */
|
0, /* 32: Size of string pool */
|
||||||
|
0, /* 32: Offset to assertion table */
|
||||||
|
0 /* 32: Size of assertion table */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -134,6 +136,8 @@ static void ObjWriteHeader (void)
|
|||||||
ObjWrite32 (Header.LineInfoSize);
|
ObjWrite32 (Header.LineInfoSize);
|
||||||
ObjWrite32 (Header.StrPoolOffs);
|
ObjWrite32 (Header.StrPoolOffs);
|
||||||
ObjWrite32 (Header.StrPoolSize);
|
ObjWrite32 (Header.StrPoolSize);
|
||||||
|
ObjWrite32 (Header.AssertOffs);
|
||||||
|
ObjWrite32 (Header.AssertSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -442,3 +446,19 @@ void ObjEndStrPool (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjStartAssertions (void)
|
||||||
|
/* Mark the start of the assertion table */
|
||||||
|
{
|
||||||
|
Header.AssertOffs = ftell (F);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjEndAssertions (void)
|
||||||
|
/* Mark the end of the assertion table */
|
||||||
|
{
|
||||||
|
Header.AssertSize = ftell (F) - Header.AssertOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,12 @@ void ObjStartStrPool (void);
|
|||||||
void ObjEndStrPool (void);
|
void ObjEndStrPool (void);
|
||||||
/* Mark the end of the string pool section */
|
/* Mark the end of the string pool section */
|
||||||
|
|
||||||
|
void ObjStartAssertions (void);
|
||||||
|
/* Mark the start of the assertion table */
|
||||||
|
|
||||||
|
void ObjEndAssertions (void);
|
||||||
|
/* Mark the end of the assertion table */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of objfile.h */
|
/* End of objfile.h */
|
||||||
|
|||||||
@@ -56,15 +56,17 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "incpath.h"
|
#include "incpath.h"
|
||||||
#include "instr.h"
|
#include "instr.h"
|
||||||
|
#include "ldassert.h"
|
||||||
#include "listing.h"
|
#include "listing.h"
|
||||||
#include "macpack.h"
|
#include "macpack.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "nexttok.h"
|
#include "nexttok.h"
|
||||||
#include "objcode.h"
|
#include "objcode.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "repeat.h"
|
|
||||||
#include "symtab.h"
|
|
||||||
#include "pseudo.h"
|
#include "pseudo.h"
|
||||||
|
#include "repeat.h"
|
||||||
|
#include "spool.h"
|
||||||
|
#include "symtab.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -326,6 +328,55 @@ static void DoASCIIZ (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void DoAssert (void)
|
||||||
|
/* Add an assertion */
|
||||||
|
{
|
||||||
|
static const char* ActionTab [] = {
|
||||||
|
"WARN", "WARNING",
|
||||||
|
"ERROR"
|
||||||
|
};
|
||||||
|
|
||||||
|
int Action;
|
||||||
|
|
||||||
|
|
||||||
|
/* First we have the expression that has to evaluated */
|
||||||
|
ExprNode* Expr = Expression ();
|
||||||
|
ConsumeComma ();
|
||||||
|
|
||||||
|
/* Action follows */
|
||||||
|
if (Tok != TOK_IDENT) {
|
||||||
|
ErrorSkip (ERR_IDENT_EXPECTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Action = GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]));
|
||||||
|
switch (Action) {
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
/* Warning */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
/* Error */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error (ERR_ILLEGAL_SEG_ATTR);
|
||||||
|
}
|
||||||
|
NextTok ();
|
||||||
|
ConsumeComma ();
|
||||||
|
|
||||||
|
/* Read the message */
|
||||||
|
if (Tok != TOK_STRCON) {
|
||||||
|
ErrorSkip (ERR_STRCON_EXPECTED);
|
||||||
|
} else {
|
||||||
|
AddAssertion (Expr, Action, GetStringId (SVal));
|
||||||
|
NextTok ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void DoAutoImport (void)
|
static void DoAutoImport (void)
|
||||||
/* Mark unresolved symbols as imported */
|
/* Mark unresolved symbols as imported */
|
||||||
{
|
{
|
||||||
@@ -1078,7 +1129,7 @@ static void DoMacPack (void)
|
|||||||
|
|
||||||
/* Insert the package */
|
/* Insert the package */
|
||||||
InsertMacPack (Package);
|
InsertMacPack (Package);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1403,11 +1454,11 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Control command table */
|
/* Control command table */
|
||||||
struct CtrlDesc_ {
|
typedef struct CtrlDesc CtrlDesc;
|
||||||
|
struct CtrlDesc {
|
||||||
unsigned Flags; /* Flags for this directive */
|
unsigned Flags; /* Flags for this directive */
|
||||||
void (*Handler) (void); /* Command handler */
|
void (*Handler) (void); /* Command handler */
|
||||||
};
|
};
|
||||||
typedef struct CtrlDesc_ CtrlDesc;
|
|
||||||
|
|
||||||
#define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
|
#define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
|
||||||
static CtrlDesc CtrlCmdTab [] = {
|
static CtrlDesc CtrlCmdTab [] = {
|
||||||
@@ -1416,6 +1467,7 @@ static CtrlDesc CtrlCmdTab [] = {
|
|||||||
{ ccNone, DoAddr }, /* .ADDR */
|
{ ccNone, DoAddr }, /* .ADDR */
|
||||||
{ ccNone, DoAlign },
|
{ ccNone, DoAlign },
|
||||||
{ ccNone, DoASCIIZ },
|
{ ccNone, DoASCIIZ },
|
||||||
|
{ ccNone, DoAssert },
|
||||||
{ ccNone, DoAutoImport },
|
{ ccNone, DoAutoImport },
|
||||||
{ ccNone, DoUnexpected }, /* .BLANK */
|
{ ccNone, DoUnexpected }, /* .BLANK */
|
||||||
{ ccNone, DoBss },
|
{ ccNone, DoBss },
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ struct DotKeyword {
|
|||||||
{ ".ALIGN", TOK_ALIGN },
|
{ ".ALIGN", TOK_ALIGN },
|
||||||
{ ".AND", TOK_BAND },
|
{ ".AND", TOK_BAND },
|
||||||
{ ".ASCIIZ", TOK_ASCIIZ },
|
{ ".ASCIIZ", TOK_ASCIIZ },
|
||||||
|
{ ".ASSERT", TOK_ASSERT },
|
||||||
{ ".AUTOIMPORT", TOK_AUTOIMPORT },
|
{ ".AUTOIMPORT", TOK_AUTOIMPORT },
|
||||||
{ ".BITAND", TOK_AND },
|
{ ".BITAND", TOK_AND },
|
||||||
{ ".BITNOT", TOK_NOT },
|
{ ".BITNOT", TOK_NOT },
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ enum Token {
|
|||||||
TOK_ADDR,
|
TOK_ADDR,
|
||||||
TOK_ALIGN,
|
TOK_ALIGN,
|
||||||
TOK_ASCIIZ,
|
TOK_ASCIIZ,
|
||||||
|
TOK_ASSERT,
|
||||||
TOK_AUTOIMPORT,
|
TOK_AUTOIMPORT,
|
||||||
TOK_BLANK,
|
TOK_BLANK,
|
||||||
TOK_BSS,
|
TOK_BSS,
|
||||||
@@ -235,7 +236,7 @@ extern int ForcedEnd; /* Force end of assembly */
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void NewInputFile (const char* Name);
|
void NewInputFile (const char* Name);
|
||||||
/* Open a new input file */
|
/* Open a new input file */
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
#define OBJ_VERSION 0x000A
|
#define OBJ_VERSION 0x000A
|
||||||
|
|
||||||
/* Size of an object file header */
|
/* Size of an object file header */
|
||||||
#define OBJ_HDR_SIZE 72
|
#define OBJ_HDR_SIZE (20*4)
|
||||||
|
|
||||||
/* Flag bits */
|
/* Flag bits */
|
||||||
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
|
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
|
||||||
@@ -78,6 +78,8 @@ struct ObjHeader {
|
|||||||
unsigned long LineInfoSize; /* 32: Size of line infos */
|
unsigned long LineInfoSize; /* 32: Size of line infos */
|
||||||
unsigned long StrPoolOffs; /* 32: Offset to string pool */
|
unsigned long StrPoolOffs; /* 32: Offset to string pool */
|
||||||
unsigned long StrPoolSize; /* 32: Size of string pool */
|
unsigned long StrPoolSize; /* 32: Size of string pool */
|
||||||
|
unsigned long AssertOffs; /* 32: Offset to assertion table */
|
||||||
|
unsigned long AssertSize; /* 32: Size of assertion table */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -287,18 +287,19 @@ static Memory* NewMemory (unsigned Name)
|
|||||||
M = xmalloc (sizeof (Memory));
|
M = xmalloc (sizeof (Memory));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
M->Name = Name;
|
M->Name = Name;
|
||||||
M->Next = 0;
|
M->Next = 0;
|
||||||
M->FNext = 0;
|
M->FNext = 0;
|
||||||
M->Attr = 0;
|
M->Attr = 0;
|
||||||
M->Flags = 0;
|
M->Flags = 0;
|
||||||
M->Start = 0;
|
M->Start = 0;
|
||||||
M->Size = 0;
|
M->Size = 0;
|
||||||
M->FillLevel = 0;
|
M->FillLevel = 0;
|
||||||
M->FillVal = 0;
|
M->FillVal = 0;
|
||||||
M->SegList = 0;
|
M->Relocatable = 0;
|
||||||
M->SegLast = 0;
|
M->SegList = 0;
|
||||||
M->F = 0;
|
M->SegLast = 0;
|
||||||
|
M->F = 0;
|
||||||
|
|
||||||
/* Insert the struct into the list */
|
/* Insert the struct into the list */
|
||||||
if (MemoryLast == 0) {
|
if (MemoryLast == 0) {
|
||||||
@@ -992,7 +993,7 @@ static void ParseFormats (void)
|
|||||||
/* Map the identifier to a token */
|
/* Map the identifier to a token */
|
||||||
cfgtok_t FormatTok;
|
cfgtok_t FormatTok;
|
||||||
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
|
CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format");
|
||||||
FormatTok = CfgTok;
|
FormatTok = CfgTok;
|
||||||
|
|
||||||
/* Skip the name and the following colon */
|
/* Skip the name and the following colon */
|
||||||
CfgNextTok ();
|
CfgNextTok ();
|
||||||
@@ -1432,11 +1433,16 @@ void CfgAssignSegments (void)
|
|||||||
Memory* M = MemoryList;
|
Memory* M = MemoryList;
|
||||||
while (M) {
|
while (M) {
|
||||||
|
|
||||||
|
MemListNode* N;
|
||||||
|
|
||||||
/* Get the start address of this memory area */
|
/* Get the start address of this memory area */
|
||||||
unsigned long Addr = M->Start;
|
unsigned long Addr = M->Start;
|
||||||
|
|
||||||
|
/* Remember if this is a relocatable memory area */
|
||||||
|
M->Relocatable = RelocatableBinFmt (M->F->Format);
|
||||||
|
|
||||||
/* Walk through the segments in this memory area */
|
/* Walk through the segments in this memory area */
|
||||||
MemListNode* N = M->SegList;
|
N = M->SegList;
|
||||||
while (N) {
|
while (N) {
|
||||||
|
|
||||||
/* Get the segment from the node */
|
/* Get the segment from the node */
|
||||||
@@ -1444,32 +1450,35 @@ void CfgAssignSegments (void)
|
|||||||
|
|
||||||
/* Handle ALIGN and OFFSET/START */
|
/* Handle ALIGN and OFFSET/START */
|
||||||
if (S->Flags & SF_ALIGN) {
|
if (S->Flags & SF_ALIGN) {
|
||||||
/* Align the address */
|
/* Align the address */
|
||||||
unsigned long Val = (0x01UL << S->Align) - 1;
|
unsigned long Val = (0x01UL << S->Align) - 1;
|
||||||
Addr = (Addr + Val) & ~Val;
|
Addr = (Addr + Val) & ~Val;
|
||||||
} else if (S->Flags & (SF_OFFSET | SF_START)) {
|
} else if (S->Flags & (SF_OFFSET | SF_START)) {
|
||||||
/* Give the segment a fixed starting address */
|
/* Give the segment a fixed starting address */
|
||||||
unsigned long NewAddr = S->Addr;
|
unsigned long NewAddr = S->Addr;
|
||||||
if (S->Flags & SF_OFFSET) {
|
if (S->Flags & SF_OFFSET) {
|
||||||
/* An offset was given, no address, make an address */
|
/* An offset was given, no address, make an address */
|
||||||
NewAddr += M->Start;
|
NewAddr += M->Start;
|
||||||
}
|
}
|
||||||
if (Addr > NewAddr) {
|
if (Addr > NewAddr) {
|
||||||
/* Offset already too large */
|
/* Offset already too large */
|
||||||
if (S->Flags & SF_OFFSET) {
|
if (S->Flags & SF_OFFSET) {
|
||||||
Error ("Offset too small in `%s', segment `%s'",
|
Error ("Offset too small in `%s', segment `%s'",
|
||||||
GetString (M->Name), GetString (S->Name));
|
GetString (M->Name), GetString (S->Name));
|
||||||
} else {
|
} else {
|
||||||
Error ("Start address too low in `%s', segment `%s'",
|
Error ("Start address too low in `%s', segment `%s'",
|
||||||
GetString (M->Name), GetString (S->Name));
|
GetString (M->Name), GetString (S->Name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Addr = NewAddr;
|
Addr = NewAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is the run area, set the start address of this segment */
|
/* If this is the run area, set the start address of this segment
|
||||||
|
* and remember if the segment is in a relocatable file or not.
|
||||||
|
*/
|
||||||
if (S->Run == M) {
|
if (S->Run == M) {
|
||||||
S->Seg->PC = Addr;
|
S->Seg->PC = Addr;
|
||||||
|
S->Seg->Relocatable = M->Relocatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Increment the fill level of the memory area and check for an
|
/* Increment the fill level of the memory area and check for an
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ struct Memory {
|
|||||||
unsigned long Size; /* Length of memory section */
|
unsigned long Size; /* Length of memory section */
|
||||||
unsigned long FillLevel; /* Actual fill level of segment */
|
unsigned long FillLevel; /* Actual fill level of segment */
|
||||||
unsigned char FillVal; /* Value used to fill rest of seg */
|
unsigned char FillVal; /* Value used to fill rest of seg */
|
||||||
|
unsigned char Relocatable; /* Memory are is relocatable */
|
||||||
MemListNode* SegList; /* List of segments for this section */
|
MemListNode* SegList; /* List of segments for this section */
|
||||||
MemListNode* SegLast; /* Last segment in this section */
|
MemListNode* SegLast; /* Last segment in this section */
|
||||||
File* F; /* File that contains the entry */
|
File* F; /* File that contains the entry */
|
||||||
|
|||||||
@@ -101,8 +101,9 @@ int IsConstExpr (ExprNode* Root)
|
|||||||
* with no references to external symbols.
|
* with no references to external symbols.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int Const;
|
int Const;
|
||||||
Export* E;
|
Export* E;
|
||||||
|
Section* S;
|
||||||
|
|
||||||
if (EXPR_IS_LEAF (Root->Op)) {
|
if (EXPR_IS_LEAF (Root->Op)) {
|
||||||
switch (Root->Op) {
|
switch (Root->Op) {
|
||||||
@@ -111,23 +112,39 @@ int IsConstExpr (ExprNode* Root)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case EXPR_SYMBOL:
|
case EXPR_SYMBOL:
|
||||||
/* Get the referenced export */
|
/* Get the referenced export */
|
||||||
E = GetExprExport (Root);
|
E = GetExprExport (Root);
|
||||||
/* If this export has a mark set, we've already encountered it.
|
/* If this export has a mark set, we've already encountered it.
|
||||||
* This means that the export is used to define it's own value,
|
* This means that the export is used to define it's own value,
|
||||||
* which in turn means, that we have a circular reference.
|
* which in turn means, that we have a circular reference.
|
||||||
*/
|
*/
|
||||||
if (ExportHasMark (E)) {
|
if (ExportHasMark (E)) {
|
||||||
CircularRefError (E);
|
CircularRefError (E);
|
||||||
Const = 0;
|
Const = 0;
|
||||||
} else {
|
} else {
|
||||||
MarkExport (E);
|
MarkExport (E);
|
||||||
Const = IsConstExport (E);
|
Const = IsConstExport (E);
|
||||||
UnmarkExport (E);
|
UnmarkExport (E);
|
||||||
}
|
}
|
||||||
return Const;
|
return Const;
|
||||||
|
|
||||||
|
case EXPR_SECTION:
|
||||||
|
/* A section expression is const if the segment it is in is
|
||||||
|
* not relocatable.
|
||||||
|
*/
|
||||||
|
S = GetExprSection (Root);
|
||||||
|
return !S->Seg->Relocatable;
|
||||||
|
|
||||||
|
case EXPR_SEGMENT:
|
||||||
|
/* A segment is const if it is not relocatable */
|
||||||
|
return !Root->V.Seg->Relocatable;
|
||||||
|
|
||||||
|
case EXPR_MEMAREA:
|
||||||
|
/* A memory area is const if it is not relocatable */
|
||||||
|
return !Root->V.Mem->Relocatable;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
/* Anything else is not const */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -213,7 +230,7 @@ Section* GetExprSection (ExprNode* Expr)
|
|||||||
*/
|
*/
|
||||||
if (Expr->Obj) {
|
if (Expr->Obj) {
|
||||||
/* Return the export */
|
/* Return the export */
|
||||||
return Expr->Obj->Sections [Expr->V.SegNum];
|
return Expr->Obj->Sections[Expr->V.SegNum];
|
||||||
} else {
|
} else {
|
||||||
return Expr->V.Sec;
|
return Expr->V.Sec;
|
||||||
}
|
}
|
||||||
@@ -231,47 +248,47 @@ long GetExprVal (ExprNode* Expr)
|
|||||||
switch (Expr->Op) {
|
switch (Expr->Op) {
|
||||||
|
|
||||||
case EXPR_LITERAL:
|
case EXPR_LITERAL:
|
||||||
return Expr->V.Val;
|
return Expr->V.Val;
|
||||||
|
|
||||||
case EXPR_SYMBOL:
|
case EXPR_SYMBOL:
|
||||||
/* Get the referenced export */
|
/* Get the referenced export */
|
||||||
E = GetExprExport (Expr);
|
E = GetExprExport (Expr);
|
||||||
/* If this export has a mark set, we've already encountered it.
|
/* If this export has a mark set, we've already encountered it.
|
||||||
* This means that the export is used to define it's own value,
|
* This means that the export is used to define it's own value,
|
||||||
* which in turn means, that we have a circular reference.
|
* which in turn means, that we have a circular reference.
|
||||||
*/
|
*/
|
||||||
if (ExportHasMark (E)) {
|
if (ExportHasMark (E)) {
|
||||||
CircularRefError (E);
|
CircularRefError (E);
|
||||||
Val = 0;
|
Val = 0;
|
||||||
} else {
|
} else {
|
||||||
MarkExport (E);
|
MarkExport (E);
|
||||||
Val = GetExportVal (E);
|
Val = GetExportVal (E);
|
||||||
UnmarkExport (E);
|
UnmarkExport (E);
|
||||||
}
|
}
|
||||||
return Val;
|
return Val;
|
||||||
|
|
||||||
case EXPR_SECTION:
|
case EXPR_SECTION:
|
||||||
S = GetExprSection (Expr);
|
S = GetExprSection (Expr);
|
||||||
return S->Offs + S->Seg->PC;
|
return S->Offs + S->Seg->PC;
|
||||||
|
|
||||||
case EXPR_SEGMENT:
|
case EXPR_SEGMENT:
|
||||||
return Expr->V.Seg->PC;
|
return Expr->V.Seg->PC;
|
||||||
|
|
||||||
case EXPR_MEMAREA:
|
case EXPR_MEMAREA:
|
||||||
return Expr->V.Mem->Start;
|
return Expr->V.Mem->Start;
|
||||||
|
|
||||||
case EXPR_PLUS:
|
case EXPR_PLUS:
|
||||||
return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
|
return GetExprVal (Expr->Left) + GetExprVal (Expr->Right);
|
||||||
|
|
||||||
case EXPR_MINUS:
|
case EXPR_MINUS:
|
||||||
return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
|
return GetExprVal (Expr->Left) - GetExprVal (Expr->Right);
|
||||||
|
|
||||||
case EXPR_MUL:
|
case EXPR_MUL:
|
||||||
return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
|
return GetExprVal (Expr->Left) * GetExprVal (Expr->Right);
|
||||||
|
|
||||||
case EXPR_DIV:
|
case EXPR_DIV:
|
||||||
Left = GetExprVal (Expr->Left);
|
Left = GetExprVal (Expr->Left);
|
||||||
Right = GetExprVal (Expr->Right);
|
Right = GetExprVal (Expr->Right);
|
||||||
if (Right == 0) {
|
if (Right == 0) {
|
||||||
Error ("Division by zero");
|
Error ("Division by zero");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,14 +60,14 @@ static FileInfo* NewFileInfo (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
FileInfo* ReadFileInfo (FILE* F, ObjData* O attribute ((unused)))
|
FileInfo* ReadFileInfo (FILE* F, ObjData* O)
|
||||||
/* Read a file info from a file and return it */
|
/* Read a file info from a file and return it */
|
||||||
{
|
{
|
||||||
/* Allocate a new FileInfo structure */
|
/* Allocate a new FileInfo structure */
|
||||||
FileInfo* FI = NewFileInfo ();
|
FileInfo* FI = NewFileInfo ();
|
||||||
|
|
||||||
/* Read the fields from the file */
|
/* Read the fields from the file */
|
||||||
FI->Name = ReadVar (F);
|
FI->Name = MakeGlobalStringId (O, ReadVar (F));
|
||||||
FI->MTime = Read32 (F);
|
FI->MTime = Read32 (F);
|
||||||
FI->Size = Read32 (F);
|
FI->Size = Read32 (F);
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
@@ -51,6 +52,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FileSetPos (FILE* F, unsigned long Pos)
|
||||||
|
/* Seek to the given absolute position, fail on errors */
|
||||||
|
{
|
||||||
|
if (fseek (F, Pos, SEEK_SET) != 0) {
|
||||||
|
Error ("Cannot seek: %s", strerror (errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long FileGetPos (FILE* F)
|
||||||
|
/* Return the current file position, fail on errors */
|
||||||
|
{
|
||||||
|
long Pos = ftell (F);
|
||||||
|
if (Pos < 0) {
|
||||||
|
Error ("Error in ftell: %s", strerror (errno));
|
||||||
|
}
|
||||||
|
return Pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Write8 (FILE* F, unsigned Val)
|
void Write8 (FILE* F, unsigned Val)
|
||||||
/* Write an 8 bit value to the file */
|
/* Write an 8 bit value to the file */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,6 +51,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FileSetPos (FILE* F, unsigned long Pos);
|
||||||
|
/* Seek to the given absolute position, fail on errors */
|
||||||
|
|
||||||
|
unsigned long FileGetPos (FILE* F);
|
||||||
|
/* Return the current file position, fail on errors */
|
||||||
|
|
||||||
void Write8 (FILE* F, unsigned Val);
|
void Write8 (FILE* F, unsigned Val);
|
||||||
/* Write an 8 bit value to the file */
|
/* Write an 8 bit value to the file */
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,8 @@ static void LibReadObjHeader (ObjData* O, const char* LibName)
|
|||||||
O->Header.LineInfoSize = Read32 (Lib);
|
O->Header.LineInfoSize = Read32 (Lib);
|
||||||
O->Header.StrPoolOffs = Read32 (Lib);
|
O->Header.StrPoolOffs = Read32 (Lib);
|
||||||
O->Header.StrPoolSize = Read32 (Lib);
|
O->Header.StrPoolSize = Read32 (Lib);
|
||||||
|
O->Header.AssertOffs = Read32 (Lib);
|
||||||
|
O->Header.AssertSize = Read32 (Lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,8 +114,6 @@ static void LibReadObjHeader (ObjData* O, const char* LibName)
|
|||||||
static ObjData* ReadIndexEntry (void)
|
static ObjData* ReadIndexEntry (void)
|
||||||
/* Read one entry in the index */
|
/* Read one entry in the index */
|
||||||
{
|
{
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Create a new entry and insert it into the list */
|
/* Create a new entry and insert it into the list */
|
||||||
ObjData* O = NewObjData ();
|
ObjData* O = NewObjData ();
|
||||||
|
|
||||||
@@ -127,23 +127,15 @@ static ObjData* ReadIndexEntry (void)
|
|||||||
Read32 (Lib); /* Skip Size */
|
Read32 (Lib); /* Skip Size */
|
||||||
|
|
||||||
/* Read the string pool */
|
/* Read the string pool */
|
||||||
ObjReadStrPool (Lib, O);
|
ObjReadStrPool (Lib, FileGetPos (Lib), O);
|
||||||
|
|
||||||
/* Skip the export size, then read the exports */
|
/* Skip the export size, then read the exports */
|
||||||
(void) ReadVar (Lib);
|
(void) ReadVar (Lib);
|
||||||
O->ExportCount = ReadVar (Lib);
|
ObjReadExports (Lib, FileGetPos (Lib), O);
|
||||||
O->Exports = xmalloc (O->ExportCount * sizeof (Export*));
|
|
||||||
for (I = 0; I < O->ExportCount; ++I) {
|
|
||||||
O->Exports[I] = ReadExport (Lib, O);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Skip the import size, then read the imports */
|
/* Skip the import size, then read the imports */
|
||||||
(void) ReadVar (Lib);
|
(void) ReadVar (Lib);
|
||||||
O->ImportCount = ReadVar (Lib);
|
ObjReadImports (Lib, FileGetPos (Lib), O);
|
||||||
O->Imports = xmalloc (O->ImportCount * sizeof (Import*));
|
|
||||||
for (I = 0; I < O->ImportCount; ++I) {
|
|
||||||
O->Imports[I] = ReadImport (Lib, O);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
return O;
|
return O;
|
||||||
@@ -158,7 +150,7 @@ static void ReadIndex (void)
|
|||||||
|
|
||||||
/* Read the object file count and allocate memory */
|
/* Read the object file count and allocate memory */
|
||||||
ModuleCount = ReadVar (Lib);
|
ModuleCount = ReadVar (Lib);
|
||||||
Index = xmalloc (ModuleCount * sizeof (ObjData*));
|
Index = xmalloc (ModuleCount * sizeof (Index[0]));
|
||||||
|
|
||||||
/* Read all entries in the index */
|
/* Read all entries in the index */
|
||||||
for (I = 0; I < ModuleCount; ++I) {
|
for (I = 0; I < ModuleCount; ++I) {
|
||||||
@@ -192,14 +184,7 @@ static void LibCheckExports (ObjData* O)
|
|||||||
|
|
||||||
/* If we need this module, insert the imports and exports */
|
/* If we need this module, insert the imports and exports */
|
||||||
if (O->Flags & OBJ_REF) {
|
if (O->Flags & OBJ_REF) {
|
||||||
/* Insert the exports */
|
InsertObjGlobals (O);
|
||||||
for (I = 0; I < O->ExportCount; ++I) {
|
|
||||||
InsertExport (O->Exports[I]);
|
|
||||||
}
|
|
||||||
/* Insert the imports */
|
|
||||||
for (I = 0; I < O->ImportCount; ++I) {
|
|
||||||
InsertImport (O->Imports[I]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,23 +250,22 @@ void LibAdd (FILE* F, const char* Name)
|
|||||||
LibReadObjHeader (O, Name);
|
LibReadObjHeader (O, Name);
|
||||||
|
|
||||||
/* Seek to the start of the files list and read the files list */
|
/* Seek to the start of the files list and read the files list */
|
||||||
fseek (Lib, O->Start + O->Header.FileOffs, SEEK_SET);
|
ObjReadFiles (Lib, O->Start + O->Header.FileOffs, O);
|
||||||
ObjReadFiles (Lib, O);
|
|
||||||
|
|
||||||
/* Seek to the start of the debug info and read the debug info */
|
/* Seek to the start of the debug info and read the debug info */
|
||||||
fseek (Lib, O->Start + O->Header.DbgSymOffs, SEEK_SET);
|
ObjReadDbgSyms (Lib, O->Start + O->Header.DbgSymOffs, O);
|
||||||
ObjReadDbgSyms (Lib, O);
|
|
||||||
|
|
||||||
/* Seek to the start of the line infos and read them */
|
/* Seek to the start of the line infos and read them */
|
||||||
fseek (Lib, O->Start + O->Header.LineInfoOffs, SEEK_SET);
|
ObjReadLineInfos (Lib, O->Start + O->Header.LineInfoOffs, O);
|
||||||
ObjReadLineInfos (Lib, O);
|
|
||||||
|
/* Read the assertions from the object file */
|
||||||
|
ObjReadAssertions (Lib, O->Start + O->Header.AssertOffs, O);
|
||||||
|
|
||||||
/* Seek to the start of the segment list and read the segments.
|
/* Seek to the start of the segment list and read the segments.
|
||||||
* This must be last, since the data here may reference other
|
* This must be last, since the data here may reference other
|
||||||
* stuff.
|
* stuff.
|
||||||
*/
|
*/
|
||||||
fseek (Lib, O->Start + O->Header.SegOffs, SEEK_SET);
|
ObjReadSections (Lib, O->Start + O->Header.SegOffs, O);
|
||||||
ObjReadSections (Lib, O);
|
|
||||||
|
|
||||||
/* Add a pointer to the library name */
|
/* Add a pointer to the library name */
|
||||||
O->LibName = LibName;
|
O->LibName = LibName;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
|
#include "asserts.h"
|
||||||
#include "binfmt.h"
|
#include "binfmt.h"
|
||||||
#include "condes.h"
|
#include "condes.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -509,6 +510,9 @@ int main (int argc, char* argv [])
|
|||||||
/* Assign start addresses for the segments, define linker symbols */
|
/* Assign start addresses for the segments, define linker symbols */
|
||||||
CfgAssignSegments ();
|
CfgAssignSegments ();
|
||||||
|
|
||||||
|
/* Check module assertions */
|
||||||
|
CheckAssertions ();
|
||||||
|
|
||||||
/* Create the output file */
|
/* Create the output file */
|
||||||
CfgWriteTarget ();
|
CfgWriteTarget ();
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ CVT=cfg/cvt-cfg.pl
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# List of all object files
|
# List of all object files
|
||||||
|
|
||||||
OBJS = bin.o \
|
OBJS = asserts.o \
|
||||||
|
bin.o \
|
||||||
binfmt.o \
|
binfmt.o \
|
||||||
condes.o \
|
condes.o \
|
||||||
config.o \
|
config.o \
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ CFLAGS += -i=..\common
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# All OBJ files
|
# All OBJ files
|
||||||
|
|
||||||
OBJS = bin.obj \
|
OBJS = asserts.obj \
|
||||||
|
bin.obj \
|
||||||
binfmt.obj \
|
binfmt.obj \
|
||||||
condes.obj \
|
condes.obj \
|
||||||
config.obj \
|
config.obj \
|
||||||
|
|||||||
@@ -88,6 +88,8 @@ ObjData* NewObjData (void)
|
|||||||
O->LineInfos = 0;
|
O->LineInfos = 0;
|
||||||
O->StringCount = 0;
|
O->StringCount = 0;
|
||||||
O->Strings = 0;
|
O->Strings = 0;
|
||||||
|
O->AssertionCount = 0;
|
||||||
|
O->Assertions = 0;
|
||||||
|
|
||||||
/* Return the new entry */
|
/* Return the new entry */
|
||||||
return O;
|
return O;
|
||||||
@@ -135,6 +137,24 @@ void InsertObjData (ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void InsertObjGlobals (ObjData* O)
|
||||||
|
/* Insert imports and exports from the object file into the global import and
|
||||||
|
* export lists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Insert exports and imports */
|
||||||
|
for (I = 0; I < O->ExportCount; ++I) {
|
||||||
|
InsertExport (O->Exports[I]);
|
||||||
|
}
|
||||||
|
for (I = 0; I < O->ImportCount; ++I) {
|
||||||
|
InsertImport (O->Imports[I]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index)
|
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index)
|
||||||
/* Convert a local string id into a global one and return it. */
|
/* Convert a local string id into a global one and return it. */
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -66,17 +66,19 @@ struct ObjData {
|
|||||||
unsigned FileCount; /* Input file count */
|
unsigned FileCount; /* Input file count */
|
||||||
struct FileInfo** Files; /* List of input files */
|
struct FileInfo** Files; /* List of input files */
|
||||||
unsigned SectionCount; /* Count of sections in this object */
|
unsigned SectionCount; /* Count of sections in this object */
|
||||||
struct Section** Sections; /* List of all sections */
|
struct Section** Sections; /* List of all sections */
|
||||||
unsigned ExportCount; /* Count of exports */
|
unsigned ExportCount; /* Count of exports */
|
||||||
struct Export** Exports; /* List of all exports */
|
struct Export** Exports; /* List of all exports */
|
||||||
unsigned ImportCount; /* Count of imports */
|
unsigned ImportCount; /* Count of imports */
|
||||||
struct Import** Imports; /* List of all imports */
|
struct Import** Imports; /* List of all imports */
|
||||||
unsigned DbgSymCount; /* Count of debug symbols */
|
unsigned DbgSymCount; /* Count of debug symbols */
|
||||||
struct DbgSym** DbgSyms; /* List of debug symbols */
|
struct DbgSym** DbgSyms; /* List of debug symbols */
|
||||||
unsigned LineInfoCount; /* Count of additional line infos */
|
unsigned LineInfoCount; /* Count of additional line infos */
|
||||||
struct LineInfo** LineInfos; /* List of additional line infos */
|
struct LineInfo** LineInfos; /* List of additional line infos */
|
||||||
unsigned StringCount; /* Count of strings */
|
unsigned StringCount; /* Count of strings */
|
||||||
unsigned* Strings; /* List of global string indices */
|
unsigned* Strings; /* List of global string indices */
|
||||||
|
unsigned AssertionCount; /* Count of module assertions */
|
||||||
|
struct Assertion** Assertions; /* List of module assertions */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +111,11 @@ void FreeObjStrings (ObjData* O);
|
|||||||
void InsertObjData (ObjData* O);
|
void InsertObjData (ObjData* O);
|
||||||
/* Insert the ObjData object into the collection of used ObjData objects. */
|
/* Insert the ObjData object into the collection of used ObjData objects. */
|
||||||
|
|
||||||
|
void InsertObjGlobals (ObjData* O);
|
||||||
|
/* Insert imports and exports from the object file into the global import and
|
||||||
|
* export lists.
|
||||||
|
*/
|
||||||
|
|
||||||
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index);
|
unsigned MakeGlobalStringId (const ObjData* O, unsigned Index);
|
||||||
/* Convert a local string id into a global one and return it. */
|
/* Convert a local string id into a global one and return it. */
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
|
#include "asserts.h"
|
||||||
#include "dbgsyms.h"
|
#include "dbgsyms.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "exports.h"
|
#include "exports.h"
|
||||||
@@ -101,15 +102,21 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
H->LineInfoSize = Read32 (Obj);
|
H->LineInfoSize = Read32 (Obj);
|
||||||
H->StrPoolOffs = Read32 (Obj);
|
H->StrPoolOffs = Read32 (Obj);
|
||||||
H->StrPoolSize = Read32 (Obj);
|
H->StrPoolSize = Read32 (Obj);
|
||||||
|
H->AssertOffs = Read32 (Obj);
|
||||||
|
H->AssertSize = Read32 (Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadFiles (FILE* F, ObjData* O)
|
void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the files list from a file at the current position */
|
/* Read the files list from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->FileCount = ReadVar (F);
|
O->FileCount = ReadVar (F);
|
||||||
O->Files = xmalloc (O->FileCount * sizeof (O->Files[0]));
|
O->Files = xmalloc (O->FileCount * sizeof (O->Files[0]));
|
||||||
for (I = 0; I < O->FileCount; ++I) {
|
for (I = 0; I < O->FileCount; ++I) {
|
||||||
@@ -119,41 +126,69 @@ void ObjReadFiles (FILE* F, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadImports (FILE* F, ObjData* O)
|
void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the imports from a file at the current position */
|
/* Read the section data from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
|
O->SectionCount = ReadVar (F);
|
||||||
|
O->Sections = xmalloc (O->SectionCount * sizeof (O->Sections[0]));
|
||||||
|
for (I = 0; I < O->SectionCount; ++I) {
|
||||||
|
O->Sections [I] = ReadSection (F, O);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
|
/* Read the imports from a file at the given position */
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->ImportCount = ReadVar (F);
|
O->ImportCount = ReadVar (F);
|
||||||
O->Imports = xmalloc (O->ImportCount * sizeof (O->Imports[0]));
|
O->Imports = xmalloc (O->ImportCount * sizeof (O->Imports[0]));
|
||||||
for (I = 0; I < O->ImportCount; ++I) {
|
for (I = 0; I < O->ImportCount; ++I) {
|
||||||
O->Imports [I] = ReadImport (F, O);
|
O->Imports [I] = ReadImport (F, O);
|
||||||
InsertImport (O->Imports [I]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadExports (FILE* F, ObjData* O)
|
void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the exports from a file at the current position */
|
/* Read the exports from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->ExportCount = ReadVar (F);
|
O->ExportCount = ReadVar (F);
|
||||||
O->Exports = xmalloc (O->ExportCount * sizeof (O->Exports[0]));
|
O->Exports = xmalloc (O->ExportCount * sizeof (O->Exports[0]));
|
||||||
for (I = 0; I < O->ExportCount; ++I) {
|
for (I = 0; I < O->ExportCount; ++I) {
|
||||||
O->Exports [I] = ReadExport (F, O);
|
O->Exports [I] = ReadExport (F, O);
|
||||||
InsertExport (O->Exports [I]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadDbgSyms (FILE* F, ObjData* O)
|
void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the debug symbols from a file at the current position */
|
/* Read the debug symbols from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->DbgSymCount = ReadVar (F);
|
O->DbgSymCount = ReadVar (F);
|
||||||
O->DbgSyms = xmalloc (O->DbgSymCount * sizeof (O->DbgSyms[0]));
|
O->DbgSyms = xmalloc (O->DbgSymCount * sizeof (O->DbgSyms[0]));
|
||||||
for (I = 0; I < O->DbgSymCount; ++I) {
|
for (I = 0; I < O->DbgSymCount; ++I) {
|
||||||
@@ -163,11 +198,15 @@ void ObjReadDbgSyms (FILE* F, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadLineInfos (FILE* F, ObjData* O)
|
void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the line infos from a file at the current position */
|
/* Read the line infos from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->LineInfoCount = ReadVar (F);
|
O->LineInfoCount = ReadVar (F);
|
||||||
O->LineInfos = xmalloc (O->LineInfoCount * sizeof (O->LineInfos[0]));
|
O->LineInfos = xmalloc (O->LineInfoCount * sizeof (O->LineInfos[0]));
|
||||||
for (I = 0; I < O->LineInfoCount; ++I) {
|
for (I = 0; I < O->LineInfoCount; ++I) {
|
||||||
@@ -177,11 +216,15 @@ void ObjReadLineInfos (FILE* F, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadStrPool (FILE* F, ObjData* O)
|
void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the string pool from a file at the current position */
|
/* Read the string pool from a file at the given position */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
O->StringCount = ReadVar (F);
|
O->StringCount = ReadVar (F);
|
||||||
O->Strings = xmalloc (O->StringCount * sizeof (O->Strings[0]));
|
O->Strings = xmalloc (O->StringCount * sizeof (O->Strings[0]));
|
||||||
for (I = 0; I < O->StringCount; ++I) {
|
for (I = 0; I < O->StringCount; ++I) {
|
||||||
@@ -191,15 +234,19 @@ void ObjReadStrPool (FILE* F, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadSections (FILE* F, ObjData* O)
|
void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
/* Read the section data from a file at the current position */
|
/* Read the assertions from a file at the given offset */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
O->SectionCount = ReadVar (F);
|
/* Seek to the correct position */
|
||||||
O->Sections = xmalloc (O->SectionCount * sizeof (O->Sections[0]));
|
FileSetPos (F, Pos);
|
||||||
for (I = 0; I < O->SectionCount; ++I) {
|
|
||||||
O->Sections [I] = ReadSection (F, O);
|
/* Read the data */
|
||||||
|
O->AssertionCount = ReadVar (F);
|
||||||
|
O->Assertions = xmalloc (O->AssertionCount * sizeof (O->Assertions[0]));
|
||||||
|
for (I = 0; I < O->AssertionCount; ++I) {
|
||||||
|
O->Assertions[I] = ReadAssertion (F, O);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,35 +268,31 @@ void ObjAdd (FILE* Obj, const char* Name)
|
|||||||
O->Name = GetModule (Name);
|
O->Name = GetModule (Name);
|
||||||
|
|
||||||
/* Read the string pool from the object file */
|
/* Read the string pool from the object file */
|
||||||
fseek (Obj, O->Header.StrPoolOffs, SEEK_SET);
|
ObjReadStrPool (Obj, O->Header.StrPoolOffs, O);
|
||||||
ObjReadStrPool (Obj, O);
|
|
||||||
|
|
||||||
/* Read the files list from the object file */
|
/* Read the files list from the object file */
|
||||||
fseek (Obj, O->Header.FileOffs, SEEK_SET);
|
ObjReadFiles (Obj, O->Header.FileOffs, O);
|
||||||
ObjReadFiles (Obj, O);
|
|
||||||
|
|
||||||
/* Read the imports list from the object file */
|
/* Read the imports list from the object file */
|
||||||
fseek (Obj, O->Header.ImportOffs, SEEK_SET);
|
ObjReadImports (Obj, O->Header.ImportOffs, O);
|
||||||
ObjReadImports (Obj, O);
|
|
||||||
|
|
||||||
/* Read the object file exports and insert them into the exports list */
|
/* Read the object file exports and insert them into the exports list */
|
||||||
fseek (Obj, O->Header.ExportOffs, SEEK_SET);
|
ObjReadExports (Obj, O->Header.ExportOffs, O);
|
||||||
ObjReadExports (Obj, O);
|
|
||||||
|
|
||||||
/* Read the object debug symbols from the object file */
|
/* Read the object debug symbols from the object file */
|
||||||
fseek (Obj, O->Header.DbgSymOffs, SEEK_SET);
|
ObjReadDbgSyms (Obj, O->Header.DbgSymOffs, O);
|
||||||
ObjReadDbgSyms (Obj, O);
|
|
||||||
|
|
||||||
/* Read the line infos from the object file */
|
/* Read the line infos from the object file */
|
||||||
fseek (Obj, O->Header.LineInfoOffs, SEEK_SET);
|
ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O);
|
||||||
ObjReadLineInfos (Obj, O);
|
|
||||||
|
/* Read the assertions from the object file */
|
||||||
|
ObjReadAssertions (Obj, O->Header.AssertOffs, O);
|
||||||
|
|
||||||
/* Read the segment list from the object file. This must be last, since
|
/* Read the segment list from the object file. This must be last, since
|
||||||
* the expressions stored in the code may reference segments or imported
|
* the expressions stored in the code may reference segments or imported
|
||||||
* symbols.
|
* symbols.
|
||||||
*/
|
*/
|
||||||
fseek (Obj, O->Header.SegOffs, SEEK_SET);
|
ObjReadSections (Obj, O->Header.SegOffs, O);
|
||||||
ObjReadSections (Obj, O);
|
|
||||||
|
|
||||||
/* Mark this object file as needed */
|
/* Mark this object file as needed */
|
||||||
O->Flags |= OBJ_REF;
|
O->Flags |= OBJ_REF;
|
||||||
@@ -257,13 +300,16 @@ void ObjAdd (FILE* Obj, const char* Name)
|
|||||||
/* Done, close the file (we read it only, so no error check) */
|
/* Done, close the file (we read it only, so no error check) */
|
||||||
fclose (Obj);
|
fclose (Obj);
|
||||||
|
|
||||||
|
/* Insert the imports and exports to the global lists */
|
||||||
|
InsertObjGlobals (O);
|
||||||
|
|
||||||
|
/* Insert the object into the list of all used object files */
|
||||||
|
InsertObjData (O);
|
||||||
|
|
||||||
/* All references to strings are now resolved, so we can delete the module
|
/* All references to strings are now resolved, so we can delete the module
|
||||||
* string pool.
|
* string pool.
|
||||||
*/
|
*/
|
||||||
FreeObjStrings (O);
|
FreeObjStrings (O);
|
||||||
|
|
||||||
/* Insert the object into the list of all used object files */
|
|
||||||
InsertObjData (O);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -54,26 +54,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjReadFiles (FILE* F, ObjData* O);
|
void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the files list from a file at the current position */
|
/* Read the files list from a file at the given position */
|
||||||
|
|
||||||
void ObjReadImports (FILE* F, ObjData* O);
|
void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the imports from a file at the current position */
|
/* Read the section data from a file at the given position */
|
||||||
|
|
||||||
void ObjReadExports (FILE* F, ObjData* O);
|
void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the exports from a file at the current position */
|
/* Read the imports from a file at the given position */
|
||||||
|
|
||||||
void ObjReadDbgSyms (FILE* F, ObjData* O);
|
void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the debug symbols from a file at the current position */
|
/* Read the exports from a file at the given position */
|
||||||
|
|
||||||
void ObjReadLineInfos (FILE* F, ObjData* O);
|
void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the line infos from a file at the current position */
|
/* Read the debug symbols from a file at the given position */
|
||||||
|
|
||||||
void ObjReadStrPool (FILE* F, ObjData* O);
|
void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the string pool from a file at the current position */
|
/* Read the line infos from a file at the given position */
|
||||||
|
|
||||||
void ObjReadSections (FILE* F, ObjData* O);
|
void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the section data from a file at the current position */
|
/* Read the string pool from a file at the given position */
|
||||||
|
|
||||||
|
void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
|
/* Read the assertions from a file at the given offset */
|
||||||
|
|
||||||
void ObjAdd (FILE* F, const char* Name);
|
void ObjAdd (FILE* F, const char* Name);
|
||||||
/* Add an object file to the module list */
|
/* Add an object file to the module list */
|
||||||
|
|||||||
@@ -89,17 +89,18 @@ static Segment* NewSegment (unsigned Name, unsigned char Type)
|
|||||||
Segment* S = xmalloc (sizeof (Segment));
|
Segment* S = xmalloc (sizeof (Segment));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
S->Name = Name;
|
S->Name = Name;
|
||||||
S->Next = 0;
|
S->Next = 0;
|
||||||
S->SecRoot = 0;
|
S->SecRoot = 0;
|
||||||
S->SecLast = 0;
|
S->SecLast = 0;
|
||||||
S->PC = 0;
|
S->PC = 0;
|
||||||
S->Size = 0;
|
S->Size = 0;
|
||||||
S->AlignObj = 0;
|
S->AlignObj = 0;
|
||||||
S->Align = 0;
|
S->Align = 0;
|
||||||
S->FillVal = 0;
|
S->FillVal = 0;
|
||||||
S->Type = Type;
|
S->Type = Type;
|
||||||
S->Dumped = 0;
|
S->Relocatable = 0;
|
||||||
|
S->Dumped = 0;
|
||||||
|
|
||||||
/* Insert the segment into the segment list */
|
/* Insert the segment into the segment list */
|
||||||
S->List = SegRoot;
|
S->List = SegRoot;
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ struct Segment {
|
|||||||
unsigned char Align; /* Alignment needed */
|
unsigned char Align; /* Alignment needed */
|
||||||
unsigned char FillVal; /* Value to use for fill bytes */
|
unsigned char FillVal; /* Value to use for fill bytes */
|
||||||
unsigned char Type; /* Type of segment */
|
unsigned char Type; /* Type of segment */
|
||||||
char Dumped; /* Did we dump this segment? */
|
unsigned char Relocatable; /* True if the segment is relocatable */
|
||||||
|
unsigned char Dumped; /* Did we dump this segment? */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -156,5 +157,5 @@ void CheckSegments (void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ void ReadObjHeader (FILE* F, ObjHeader* H)
|
|||||||
H->LineInfoSize = Read32 (F);
|
H->LineInfoSize = Read32 (F);
|
||||||
H->StrPoolOffs = Read32 (F);
|
H->StrPoolOffs = Read32 (F);
|
||||||
H->StrPoolSize = Read32 (F);
|
H->StrPoolSize = Read32 (F);
|
||||||
|
H->AssertOffs = Read32 (F);
|
||||||
|
H->AssertSize = Read32 (F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user