/* asmdebug.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Verwaltung der Debug-Informationen zur Assemblierzeit */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "strutil.h"
#include "be_le.h"
#include "chunks.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmpars.h"
#include "asmfnums.h"
#include "errmsg.h"
#include "asmdebug.h"
typedef struct
{
Boolean InMacro;
LongInt LineNum;
Integer FileName;
ShortInt Space;
LargeInt Address;
Word Code;
} TLineInfo;
typedef struct sLineInfoList
{
struct sLineInfoList *Next;
TLineInfo Contents;
} TLineInfoList, *PLineInfoList;
String TempFileName;
FILE *TempFile;
PLineInfoList LineInfoRoot;
void AddLineInfo(Boolean InMacro, LongInt LineNum, char *FileName,
ShortInt Space, LargeInt Address, LargeInt Len)
{
PLineInfoList PNeu, PFirst, PLast, Run, Link;
int RecCnt, z;
Integer FNum;
/* do not accept line infor for pseudo segments */
if (Space >= SegCount)
return;
/* wieviele Records schreiben ? */
RecCnt = ((DebugMode == DebugAtmel) && (CodeLen > 1)) ? CodeLen : 1;
FNum = GetFileNum(FileName);
/* Einfuegepunkt in Liste finden */
Run = LineInfoRoot;
if (!Run)
Link = NULL;
else
{
while ((Run->Next) && (Run->Next->Contents.Space < Space))
Run = Run->Next;
while ((Run->Next) && (Run->Next->Contents.FileName < FNum))
Run = Run->Next;
while ((Run->Next) && (Run->Next->Contents.Address < Address))
Run = Run->Next;
Link = Run->Next;
}
/* neue Teilliste bilden */
PLast = PFirst = NULL;
for (z = 0; z < RecCnt; z++)
{
PNeu
= (PLineInfoList
) malloc(sizeof(TLineInfoList
));
PNeu->Contents.InMacro = InMacro;
PNeu->Contents.LineNum = LineNum;
PNeu->Contents.FileName = FNum;
PNeu->Contents.Space = Space;
PNeu->Contents.Address = Address + z;
PNeu->Contents.Code = ((CodeLen < z + 1) || (DontPrint)) ? 0 : WAsmCode[z];
if (z == 0)
PFirst = PNeu;
if (PLast != NULL)
PLast->Next = PNeu;
PLast = PNeu;
}
/* Teilliste einhaengen */
if (!Run)
LineInfoRoot = PFirst;
else
Run->Next = PFirst;
PLast->Next = Link;
if (Space == SegCode)
AddAddressRange(FNum, Address, Len);
}
void InitLineInfo(void)
{
TempFileName[0] = '\0';
LineInfoRoot = NULL;
}
void ClearLineInfo(void)
{
PLineInfoList Run;
if (TempFileName[0] != '\0')
{
unlink(TempFileName);
}
while (LineInfoRoot)
{
Run = LineInfoRoot;
LineInfoRoot = LineInfoRoot->Next;
}
InitLineInfo();
}
static void DumpDebugInfo_MAP(void)
{
PLineInfoList Run;
Integer ActFile;
int ModZ;
ShortInt ActSeg;
FILE *MAPFile;
String MAPName;
char Tmp[30], Tmp2[30];
strmaxcpy(MAPName, SourceFile, STRINGSIZE);
KillSuffix(MAPName);
AddSuffix(MAPName, MapSuffix);
MAPFile
= fopen(MAPName
, "w");
if (!MAPFile)
ChkIO(ErrNum_OpeningFile);
Run = LineInfoRoot;
ActSeg = -1;
ActFile = -1;
ModZ = 0;
while (Run)
{
if (Run->Contents.Space != ActSeg)
{
ActSeg = Run->Contents.Space;
if (ModZ != 0)
{
errno
= 0; fprintf(MAPFile
, "\n"); ChkIO
(ErrNum_FileWriteError
);
}
ModZ = 0;
errno
= 0; fprintf(MAPFile
, "Segment %s\n", SegNames
[ActSeg
]); ChkIO
(ErrNum_FileWriteError
);
ActFile = -1;
}
if (Run->Contents.FileName != ActFile)
{
ActFile = Run->Contents.FileName;
if (ModZ != 0)
{
errno
= 0; fprintf(MAPFile
, "\n"); ChkIO
(ErrNum_FileWriteError
);
}
ModZ = 0;
errno
= 0; fprintf(MAPFile
, "File %s\n", GetFileName
(Run
->Contents.
FileName)); ChkIO
(ErrNum_FileWriteError
);
};
errno = 0;
as_snprintf(Tmp, sizeof(Tmp), LongIntFormat, Run->Contents.LineNum);
HexString(Tmp2, sizeof(Tmp2), Run->Contents.Address, 8);
fprintf(MAPFile
, "%5s:%s ", Tmp
, Tmp2
);
ChkIO(ErrNum_FileWriteError);
if (++ModZ == 5)
{
errno
= 0; fprintf(MAPFile
, "\n"); ChkIO
(ErrNum_FileWriteError
); ModZ
= 0;
}
Run = Run->Next;
}
if (ModZ != 0)
{
errno
= 0; fprintf(MAPFile
, "\n"); ChkIO
(ErrNum_FileWriteError
);
}
PrintDebSymbols(MAPFile);
PrintDebSections(MAPFile);
}
static void DumpDebugInfo_Atmel(void)
{
static const char *OBJString = "AVR Object File";
PLineInfoList Run;
LongInt FNamePos, RecPos;
FILE *OBJFile;
String OBJName;
const char *FName;
Byte TByte, TNum, NameCnt;
int z;
LongInt LTurn;
Word WTurn;
strmaxcpy(OBJName, SourceFile, STRINGSIZE);
KillSuffix(OBJName);
AddSuffix(OBJName, OBJSuffix);
OBJFile
= fopen(OBJName
, OPENWRMODE
);
if (!OBJFile)
ChkIO(ErrNum_OpeningFile);
/* initialer Kopf, Positionen noch unbekannt */
FNamePos = 0;
RecPos = 0;
if (!Write4(OBJFile, &FNamePos)) ChkIO(ErrNum_FileWriteError);
if (!Write4(OBJFile, &RecPos)) ChkIO(ErrNum_FileWriteError);
TByte = 9;
if (fwrite(&TByte
, 1, 1, OBJFile
) != 1) ChkIO
(ErrNum_FileWriteError
);
NameCnt = GetFileCount() - 1;
if (fwrite(&NameCnt
, 1, 1, OBJFile
) != 1) ChkIO
(ErrNum_FileWriteError
);
if ((int)fwrite(OBJString
, 1, strlen(OBJString
) + 1, OBJFile
) != (int)strlen(OBJString
) + 1) ChkIO
(ErrNum_FileWriteError
);
/* Objekt-Records */
for (Run = LineInfoRoot; Run; Run = Run->Next)
if (Run->Contents.Space == SegCode)
{
LTurn = Run->Contents.Address;
if (!HostBigEndian)
DSwap(<urn, 4);
if (fwrite(((Byte
*) <urn
)+1, 1, 3, OBJFile
) != 3) ChkIO
(ErrNum_FileWriteError
);
WTurn = Run->Contents.Code;
if (!HostBigEndian)
WSwap(&WTurn, 2);
if (fwrite(&WTurn
, 1, 2, OBJFile
) != 2) ChkIO
(ErrNum_FileWriteError
);
TNum = Run->Contents.FileName - 1;
if (fwrite(&TNum
, 1, 1, OBJFile
) != 1) ChkIO
(ErrNum_FileWriteError
);
WTurn = Run->Contents.LineNum;
if (!HostBigEndian)
WSwap(&WTurn, 2);
if (fwrite(&WTurn
, 1, 2, OBJFile
) != 2) ChkIO
(ErrNum_FileWriteError
);
TNum = Ord(Run->Contents.InMacro);
if (fwrite(&TNum
, 1, 1, OBJFile
) != 1) ChkIO
(ErrNum_FileWriteError
);
}
/* Dateinamen */
FNamePos
= ftell(OBJFile
);
for (z = 1; z <= NameCnt; z++)
{
FName = NamePart(GetFileName(z));
if ((int)fwrite(FName
, 1, strlen(FName
) + 1, OBJFile
) != (int)strlen(FName
) + 1) ChkIO
(ErrNum_FileWriteError
);
}
TByte = 0;
if (fwrite(&TByte
, 1, 1, OBJFile
) != 1) ChkIO
(ErrNum_FileWriteError
);
/* korrekte Positionen in Kopf schreiben */
if (!HostBigEndian) DSwap(&FNamePos, 4);
if (fwrite(&FNamePos
, 1, 4, OBJFile
) != 4) ChkIO
(ErrNum_FileWriteError
);
if (!HostBigEndian) DSwap(&RecPos, 4);
if (fwrite(&RecPos
, 1, 4, OBJFile
) != 4) ChkIO
(ErrNum_FileWriteError
);
}
static void DumpDebugInfo_NOICE(void)
{
PLineInfoList Run;
Integer ActFile;
FILE *MAPFile;
String MAPName, Tmp1, Tmp2;
LargeWord Start, End;
Boolean HadLines;
strmaxcpy(MAPName, SourceFile, STRINGSIZE);
KillSuffix(MAPName);
AddSuffix(MAPName, ".noi");
MAPFile
= fopen(MAPName
, "w");
if (!MAPFile)
ChkIO(ErrNum_OpeningFile);
fprintf(MAPFile
, "CASE %d\n", (CaseSensitive
) ? 1 : 0);
PrintNoISymbols(MAPFile);
for (ActFile = 0; ActFile < GetFileCount(); ActFile++)
{
HadLines = FALSE;
Run = LineInfoRoot;
while (Run)
{
if ((Run->Contents.Space == SegCode) && (Run->Contents.FileName == ActFile))
{
if (!HadLines)
{
GetAddressRange(ActFile, &Start, &End);
as_snprintf(Tmp1, sizeof(Tmp1), "%X", Start);
errno = 0;
fprintf(MAPFile
, "FILE %s 0x%s\n", GetFileName
(Run
->Contents.
FileName), Tmp1
);
ChkIO(ErrNum_FileWriteError);
}
errno = 0;
as_snprintf(Tmp1, sizeof(Tmp1), LongIntFormat, Run->Contents.LineNum);
as_snprintf(Tmp2, sizeof(Tmp2), "%X", Run->Contents.Address - Start);
fprintf(MAPFile
, "LINE %s 0x%s\n", Tmp1
, Tmp2
);
ChkIO(ErrNum_FileWriteError);
HadLines = TRUE;
}
Run = Run->Next;
}
if (HadLines)
{
as_snprintf(Tmp1, sizeof(Tmp1), "%X", End);
errno
= 0; fprintf(MAPFile
, "ENDFILE 0x%s\n", Tmp1
); ChkIO
(ErrNum_FileWriteError
);
}
}
}
void DumpDebugInfo(void)
{
switch (DebugMode)
{
case DebugMAP:
DumpDebugInfo_MAP();
break;
case DebugAtmel:
DumpDebugInfo_Atmel();
break;
case DebugNoICE:
DumpDebugInfo_NOICE();
break;
default:
break;
}
}
void asmdebug_init(void)
{
}