mirror of http://shamusworld.gotdns.org/git/rmac
Support -g debug info generation
-Add GenLineNoSym(), which will generate debug symbols for file names and line numbers when debug info generation is requested. -Replace code that warns -g is not supported with code to set a flag. -Complain if -g is specified for non-BSD output formats, as only stabs-in-symbol-table/a.out format debug information is supported currently. -Document -g flag in usage information function. -Document -g flag in manual. v2: -Only call debug symbol generation functions when dbg_sym != 0
This commit is contained in:
parent
e8f9d55bc7
commit
526716329c
2
6502.c
2
6502.c
|
@ -423,6 +423,8 @@ badmode:
|
|||
DEBUG printf("inf[op][amode]=%d\n", (int)inf[op][amode]);
|
||||
#endif
|
||||
|
||||
GENLINENOSYM();
|
||||
|
||||
switch (inf[op][amode])
|
||||
{
|
||||
case A65_IMPL: // Just leave the instruction
|
||||
|
|
|
@ -125,6 +125,7 @@ Switch Description
|
|||
-fe ELF output object file format.
|
||||
-fr Absolute address. Source code is required to have one .org statement.
|
||||
-fx Atari 800 com/exe/xex output object file format.
|
||||
-g Generate source level debug info. Requires BSD COFF object file format.
|
||||
-i\ *path* Set include-file directory search path.
|
||||
-l\ *[file[prn]]* Construct and direct assembly listing to the specified file.
|
||||
-l\ *\*[filename]* Create an output listing file without pagination.
|
||||
|
@ -235,6 +236,19 @@ the table.
|
|||
file is created. Beware! If an assembly produces no errors, any error file from
|
||||
a previous assembly is not removed.
|
||||
|
||||
**-g**
|
||||
The **-g** switch causes RMAC to generate source-level debug symbols using the
|
||||
stabs format. When linked with a compatible linker such as RLN, these symbols
|
||||
can be used by source-level debuggers such as rdbjag, wdb, or gdb to step
|
||||
through assembly code line-by-line with all the additional context of labels,
|
||||
macros, constants, register equates, etc. available in the original assembly
|
||||
listings rather than relying on the simple disassembly or raw machine code
|
||||
available when stepping through instruction-by-instruction. This option only
|
||||
works with the BSD COFF object file format, as the others do not use the
|
||||
a.out-style symbol tables required by stabs, and RMAC does not currently
|
||||
support placing stabs debug symbols in their own dedicated section in ELF
|
||||
format object files.
|
||||
|
||||
**-i**
|
||||
The **-i** switch allows automatic directory searching for include files. A list of
|
||||
semi-colon seperated directory search paths may be mentioned immediately
|
||||
|
|
5
op.c
5
op.c
|
@ -46,6 +46,11 @@ int GenerateOPCode(int state)
|
|||
if (!robjproc)
|
||||
return error("opcode only valid in OP mode");
|
||||
|
||||
// It's OK to call this before validating state. If the state is invalid, an
|
||||
// error will be generated and no object file will be produced, so it
|
||||
// doesn't matter if the line number symbols are a little off.
|
||||
GENLINENOSYM();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case MO_BITMAP:
|
||||
|
|
3
procln.c
3
procln.c
|
@ -739,6 +739,7 @@ When checking to see if it's already been equated, issue a warning.
|
|||
while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0)
|
||||
md = &dsp56k_machtab[md->mncont];
|
||||
|
||||
GENLINENOSYM();
|
||||
(*md->mnfunc)(md->mninst | (parcode << 8));
|
||||
goto loop;
|
||||
}
|
||||
|
@ -784,6 +785,7 @@ When checking to see if it's already been equated, issue a warning.
|
|||
// Call special-mode handler
|
||||
if (m->mnattr & CGSPECIAL)
|
||||
{
|
||||
GENLINENOSYM();
|
||||
(*m->mnfunc)(m->mninst, siz);
|
||||
goto loop;
|
||||
}
|
||||
|
@ -818,6 +820,7 @@ When checking to see if it's already been equated, issue a warning.
|
|||
|
||||
DEBUG { printf(" 68K: mninst=$%X, siz=$%X, mnattr=$%X, amsk0=$%X, mn0=$%X, amsk1=$%X, mn1=$%X\n", m->mninst, siz, m->mnattr, amsk0, m->mn0, amsk1, m->mn1); }
|
||||
|
||||
GENLINENOSYM();
|
||||
(*m->mnfunc)(m->mninst, siz);
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -190,6 +190,7 @@ static void DepositRISCInstructionWord(uint16_t opcode, int reg1, int reg2)
|
|||
}
|
||||
|
||||
int value = ((opcode & 0x3F) << 10) + ((reg1 & 0x1F) << 5) + (reg2 & 0x1F);
|
||||
GENLINENOSYM();
|
||||
D_word(value);
|
||||
}
|
||||
|
||||
|
|
54
rmac.c
54
rmac.c
|
@ -31,6 +31,7 @@ int verb_flag; // Be verbose about what's going on
|
|||
int m6502; // 1, assembling 6502 code
|
||||
int glob_flag; // Assume undefined symbols are global
|
||||
int lsym_flag; // Include local symbols in object file (ALWAYS true)
|
||||
int dsym_flag; // Gen debug syms (Requires obj_format = BSD)
|
||||
int optim_warn_flag; // Warn about possible short branches
|
||||
int prg_flag; // !=0, produce .PRG executable (2=symbols)
|
||||
int prg_extend; // !=0, output extended .PRG symbols
|
||||
|
@ -167,6 +168,7 @@ void DisplayHelp(void)
|
|||
" l: LOD (use this for DSP56001 only)\n"
|
||||
" x: com/exe/xex (Atari 800)\n"
|
||||
" r: absolute address\n"
|
||||
" -g Output source level debug information (BSD object only)\n"
|
||||
" -i[path] Directory to search for include files\n"
|
||||
" -l[filename] Create an output listing file\n"
|
||||
" -l*[filename] Create an output listing file without pagination\n"
|
||||
|
@ -290,6 +292,42 @@ int ParseOptimization(char * optstring)
|
|||
return OK;
|
||||
}
|
||||
|
||||
static void ProcessFile(int fd, char *fname)
|
||||
{
|
||||
char *dbgname = fname;
|
||||
|
||||
if (NULL == fname)
|
||||
{
|
||||
fname = defname; // Kludge first filename
|
||||
dbgname = "(stdin)";
|
||||
}
|
||||
|
||||
// First file operations:
|
||||
if (firstfname == NULL)
|
||||
{
|
||||
// Record first filename.
|
||||
firstfname = fname;
|
||||
|
||||
// Validate option compatibility
|
||||
if (dsym_flag)
|
||||
{
|
||||
if (obj_format != BSD)
|
||||
{
|
||||
printf("-g: debug information only supported with BSD object file format\n");
|
||||
dsym_flag = 0;
|
||||
errcnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
GenMainFileSym(dbgname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include(fd, dbgname);
|
||||
Assemble();
|
||||
}
|
||||
|
||||
extern int reg68base[53];
|
||||
extern int reg68tab[222];
|
||||
extern int reg68check[222];
|
||||
|
@ -326,6 +364,7 @@ int Process(int argc, char ** argv)
|
|||
rdsp = 0; // Initialize DSP assembly flag
|
||||
robjproc = 0; // Initialize OP assembly flag
|
||||
lsym_flag = 1; // Include local symbols in object file
|
||||
dsym_flag = 0; // No debug sym generation by default
|
||||
orgactive = 0; // Not in RISC org section
|
||||
orgwarning = 0; // No ORG warning issued
|
||||
segpadsize = 2; // Initialize segment padding size
|
||||
|
@ -432,7 +471,7 @@ int Process(int argc, char ** argv)
|
|||
break;
|
||||
case 'g': // Debugging flag
|
||||
case 'G':
|
||||
printf("Debugging flag (-g) not yet implemented\n");
|
||||
dsym_flag = 1;
|
||||
break;
|
||||
case 'i': // Set directory search path
|
||||
case 'I':
|
||||
|
@ -607,11 +646,7 @@ int Process(int argc, char ** argv)
|
|||
|
||||
break;
|
||||
case EOS: // Input is stdin
|
||||
if (firstfname == NULL) // Kludge first filename
|
||||
firstfname = defname;
|
||||
|
||||
include(0, "(stdin)");
|
||||
Assemble();
|
||||
ProcessFile(0, NULL);
|
||||
break;
|
||||
case 'h': // Display command line usage
|
||||
case 'H':
|
||||
|
@ -646,10 +681,6 @@ int Process(int argc, char ** argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Record first filename.
|
||||
if (firstfname == NULL)
|
||||
firstfname = argv[argno];
|
||||
|
||||
strcpy(fnbuf, argv[argno]);
|
||||
fext(fnbuf, ".s", 0);
|
||||
fd = open(fnbuf, 0);
|
||||
|
@ -661,8 +692,7 @@ int Process(int argc, char ** argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
include(fd, fnbuf);
|
||||
Assemble();
|
||||
ProcessFile(fd, fnbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
rmac.h
2
rmac.h
|
@ -28,6 +28,7 @@
|
|||
#define _OPEN_INC _O_RDONLY|_O_BINARY
|
||||
#define _PERM_MODE _S_IREAD|_S_IWRITE
|
||||
#define PATH_SEPS ";"
|
||||
#define realpath(_fn, _abs) _fullpath((_abs), (_fn), _MAX_PATH)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if _MSC_VER > 1000
|
||||
|
@ -302,6 +303,7 @@ extern int m6502;
|
|||
extern int list_flag;
|
||||
extern int glob_flag;
|
||||
extern int lsym_flag;
|
||||
extern int dsym_flag;
|
||||
extern int optim_warn_flag;
|
||||
extern int obj_format;
|
||||
extern int legacy_flag;
|
||||
|
|
106
symbol.c
106
symbol.c
|
@ -58,7 +58,7 @@ void InitSymbolTable(void)
|
|||
//
|
||||
// Hash the ASCII name and enviroment number
|
||||
//
|
||||
int HashSymbol(uint8_t * name, int envno)
|
||||
int HashSymbol(const uint8_t * name, int envno)
|
||||
{
|
||||
int sum = envno, k = 0;
|
||||
|
||||
|
@ -76,7 +76,7 @@ int HashSymbol(uint8_t * name, int envno)
|
|||
//
|
||||
// Make a new symbol of type 'type' in enviroment 'envno'
|
||||
//
|
||||
SYM * NewSymbol(uint8_t * name, int type, int envno)
|
||||
SYM * NewSymbol(const uint8_t * name, int type, int envno)
|
||||
{
|
||||
// Allocate the symbol
|
||||
SYM * symbol = malloc(sizeof(SYM));
|
||||
|
@ -565,12 +565,12 @@ int symtable(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SYM * NewDebugSymbol(uint8_t * str, uint8_t type, uint8_t other, uint16_t desc)
|
||||
SYM * NewDebugSymbol(const uint8_t * str, uint8_t type, uint8_t other, uint16_t desc)
|
||||
{
|
||||
SYM * symbol = NewSymbol(str, DBGSYM, 0);
|
||||
|
||||
if (NULL == symbol)
|
||||
return NULL;
|
||||
fatal("Could not allocate space for debug symbol");
|
||||
|
||||
AddToSymbolDeclarationList(symbol);
|
||||
|
||||
|
@ -580,3 +580,101 @@ SYM * NewDebugSymbol(uint8_t * str, uint8_t type, uint8_t other, uint16_t desc)
|
|||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
char *FilePath(const char * fname)
|
||||
{
|
||||
char buf1[256];
|
||||
char * fpath;
|
||||
int i, j;
|
||||
|
||||
if ((fpath = realpath(fname, NULL)) != NULL)
|
||||
return fpath;
|
||||
|
||||
for(i=0; nthpath("RMACPATH", i, buf1)!=0; i++)
|
||||
{
|
||||
j = strlen(buf1);
|
||||
|
||||
// Append path char if necessary
|
||||
if (j > 0 && buf1[j - 1] != SLASHCHAR)
|
||||
strcat(buf1, SLASHSTRING);
|
||||
|
||||
strcat(buf1, fname);
|
||||
|
||||
if ((fpath = realpath(buf1, NULL)) != NULL)
|
||||
return fpath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void GenFileSym(const char * fname, uint8_t type, uint32_t addr, uint32_t sattr)
|
||||
{
|
||||
char *fpath;
|
||||
|
||||
if (!(fpath = FilePath(fname)))
|
||||
{
|
||||
// Don't treat this as an error. Any file rmac can read is valid enough.
|
||||
// Just use the relative filename in place of an absolute path for the
|
||||
// debug information.
|
||||
fpath = strdup(fname);
|
||||
|
||||
if (!fpath)
|
||||
fatal("Could not allocate memory for fake path name");
|
||||
}
|
||||
|
||||
SYM * symbol = NewDebugSymbol(fpath, type, 0, 0);
|
||||
|
||||
free(fpath);
|
||||
|
||||
symbol->svalue = addr;
|
||||
symbol->sattr |= sattr;
|
||||
}
|
||||
|
||||
void GenMainFileSym(const char * fname)
|
||||
{
|
||||
GenFileSym(fname, 0x64 /* N_SO */, 0, DEFINED | TEXT);
|
||||
}
|
||||
|
||||
void GenLineNoSym(void)
|
||||
{
|
||||
uint32_t addr;
|
||||
uint32_t sattr;
|
||||
uint8_t type;
|
||||
SYM * symbol;
|
||||
|
||||
static uint16_t prevlineno = -1;
|
||||
static uint32_t prevaddr = -1;
|
||||
static uint16_t prevfileno = 0;
|
||||
|
||||
if (orgactive)
|
||||
{
|
||||
addr = orgaddr;
|
||||
sattr = ABS | DEFINED | EQUATED;
|
||||
// 0x4c is N_FLINE, function start/body/end line number, repurposed by
|
||||
// MADMAC/ALN for ABS line numbers.
|
||||
type = 0x4c;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = pcloc;
|
||||
sattr = DEFINED | cursect;
|
||||
type = 0x44; // N_SLINE, text section line number
|
||||
}
|
||||
|
||||
if ((addr == prevaddr) || ((curlineno == prevlineno) && (prevfileno == cfileno)))
|
||||
return;
|
||||
|
||||
prevaddr = addr;
|
||||
prevlineno = curlineno;
|
||||
|
||||
if (prevfileno != cfileno)
|
||||
GenFileSym(curfname, 0x84 /* N_SOL */, addr, sattr);
|
||||
|
||||
prevfileno = cfileno;
|
||||
|
||||
/* MADMAC counts lines starting at 0. Offset curlineno accordingly */
|
||||
symbol = NewDebugSymbol(NULL, type, 0, curlineno - 1);
|
||||
|
||||
symbol->svalue = addr;
|
||||
symbol->sattr |= sattr;
|
||||
}
|
||||
|
|
9
symbol.h
9
symbol.h
|
@ -49,7 +49,7 @@ extern uint32_t firstglobal;// Index of the fist global symbol in an ELF object.
|
|||
// Exported functions
|
||||
SYM * lookup(uint8_t *, int, int);
|
||||
void InitSymbolTable(void);
|
||||
SYM * NewSymbol(uint8_t *, int, int);
|
||||
SYM * NewSymbol(const uint8_t *, int, int);
|
||||
void AddToSymbolDeclarationList(SYM *);
|
||||
void ForceUndefinedSymbolsGlobal(void);
|
||||
int symtable(void);
|
||||
|
@ -57,7 +57,12 @@ uint32_t AssignSymbolNos(uint8_t *, uint8_t *(*)());
|
|||
uint32_t AssignSymbolNosELF(uint8_t *, uint8_t *(*)());
|
||||
void DumpLODSymbols(void);
|
||||
uint8_t * GetSymbolNameByUID(uint32_t);
|
||||
SYM * NewDebugSymbol(uint8_t *, uint8_t, uint8_t, uint16_t);
|
||||
SYM * NewDebugSymbol(const uint8_t *, uint8_t, uint8_t, uint16_t);
|
||||
void GenMainFileSym(const char *);
|
||||
void GenLineNoSym(void);
|
||||
|
||||
// Helper to avoid unnecessary branches:
|
||||
#define GENLINENOSYM() if (dsym_flag) GenLineNoSym()
|
||||
|
||||
#endif // __SYMBOL_H__
|
||||
|
||||
|
|
Loading…
Reference in New Issue