X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=symbol.c;h=f8a43d6ff62e189492914cf0646354ed1c994b58;hp=c1abfab58693aa0427abb641a9451c6929c6db4d;hb=HEAD;hpb=29fa5dcf504b966803063a1c2891f58f97126d04 diff --git a/symbol.c b/symbol.c index c1abfab..c9c34a4 100644 --- a/symbol.c +++ b/symbol.c @@ -1,7 +1,7 @@ // -// RMAC - Reboot's Macro Assembler for all Atari computers +// RMAC - Renamed Macro Assembler for all Atari computers // SYMBOL.C - Symbol Handling -// Copyright (C) 199x Landon Dyer, 2011-2019 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2022 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -39,7 +39,6 @@ static uint8_t tdb_text[8] = { // Internal function prototypes static uint16_t WriteLODSection(int, uint16_t); - // // Initialize symbol table // @@ -56,11 +55,10 @@ void InitSymbolTable(void) currentUID = 0; } - // // 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; @@ -75,11 +73,10 @@ int HashSymbol(uint8_t * name, int envno) return sum & (NBUCKETS - 1); } - // // 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)); @@ -91,7 +88,7 @@ SYM * NewSymbol(uint8_t * name, int type, int envno) } // Fill-in the symbol - symbol->sname = strdup(name); + symbol->sname = name ? strdup(name) : NULL; symbol->stype = (uint8_t)type; symbol->senv = (uint16_t)envno; // We don't set this as DEFINED, as it could be a forward reference! @@ -102,11 +99,22 @@ SYM * NewSymbol(uint8_t * name, int type, int envno) symbol->svalue = 0; symbol->sorder = NULL; symbol->uid = currentUID++; + // We don't set st_type, st_desc, or st_other here because they are only + // used by stabs debug symbols, which are always initialized by + // NewDebugSymbol(), which always sets these fields. Hence, initializing + // them here would be redundant. - // Install symbol in the symbol table - int hash = HashSymbol(name, envno); - symbol->snext = symbolTable[hash]; - symbolTable[hash] = symbol; + // Record filename the symbol is defined (Used by macro error reporting and some debug symbols) + symbol->cfileno = cfileno; + + // Don't hash debug symbols: they are never looked up and may have no name. + if (type != DBGSYM) + { + // Install symbol in the symbol table + int hash = HashSymbol(name, envno); + symbol->snext = symbolTable[hash]; + symbolTable[hash] = symbol; + } // Append symbol to the symbol-order list if (sorder == NULL) @@ -118,7 +126,6 @@ SYM * NewSymbol(uint8_t * name, int type, int envno) return symbol; } - // // Look up the symbol name by its UID and return the pointer to the name. // If it's not found, return NULL. @@ -143,7 +150,6 @@ uint8_t * GetSymbolNameByUID(uint32_t uid) return NULL; } - // // Lookup the symbol 'name', of the specified type, with the specified // enviroment level @@ -168,7 +174,6 @@ SYM * lookup(uint8_t * name, int type, int envno) return symbol; } - // // Put symbol on "order-of-declaration" list of symbols // @@ -192,7 +197,6 @@ void AddToSymbolDeclarationList(SYM * symbol) sdecltail = symbol; } - // // Make all referenced, undefined symbols global // @@ -212,7 +216,6 @@ void ForceUndefinedSymbolsGlobal(void) } } - // // Assign numbers to symbols that are to be exported or imported. The symbol // number is put in 'senv'. Returns the number of symbols that will be in the @@ -223,7 +226,7 @@ void ForceUndefinedSymbolsGlobal(void) // count of the # of symbols in the symbol table, and the second is to // actually create it. // -uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) +uint32_t AssignSymbolNos(uint8_t * buf, uint8_t *(* construct)()) { uint16_t scount = 0; @@ -240,10 +243,28 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) // them. We also pick which symbols should be global or not here. for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) { + // Always export debug symbols. Don't force them global. + if (DBGSYM == sy->stype) { + sy->senv = scount++; + + if (buf != NULL) + buf = construct(buf, sy, 0); + continue; + } + + // Skip non-labels. + if (sy->stype != LABEL) + continue; + + // Nuke equated register/CC symbols from orbit: + if (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) + continue; + // Export or import external references, and export COMMON blocks. - if ((sy->stype == LABEL) - && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) - || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) + // N.B.: This says to mark the symbol as global if either 1) the symbol + // is global AND the symbol is defined OR referenced, or 2) this + // symbol is a common symbol. + if (((sy->sattr & GLOBAL) && (sy->sattr & (DEFINED | REFERENCED))) || (sy->sattr & COMMON)) { sy->senv = scount++; @@ -253,9 +274,11 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) } // Export vanilla labels (but don't make them global). An exception is // made for equates, which are not exported unless they are referenced. - else if (sy->stype == LABEL && lsym_flag - && (sy->sattr & (DEFINED | REFERENCED)) != 0 - && (!as68_flag || *sy->sname != 'L')) + // ^^^ The above just might be bullshit. ^^^ + // N.B.: This says if the symbol is either defined OR referenced (but + // because of the above we know it *won't* be GLOBAL). And + // lsym_flag is always set true in Process() in rmac.c. + else if (lsym_flag && (sy->sattr & (DEFINED | REFERENCED))) { sy->senv = scount++; @@ -267,27 +290,22 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) return scount; } - // -// Custom version of sy_assign for ELF .o files. +// Custom version of AssignSymbolNos for ELF .o files. // The order that the symbols should be dumped is different. // (globals must be explicitly at the end of the table) // -// N.B.: It should be possible to merge this with sy_assign, as there's nothing -// really ELF specific in here, other than the "globals go at the end of -// the queue" thing, which doesn't break the others. :-P -uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) +// N.B.: It should be possible to merge this with AssignSymbolNos, as there's +// nothing really ELF specific in here, other than the "globals go at the +// end of the queue" thing, which doesn't break the others. :-P +uint32_t AssignSymbolNosELF(uint8_t * buf, uint8_t *(* construct)()) { uint16_t scount = 0; -// if (construct == (uint8_t *(*)())constr_elfsymtab) -// if (buf == NULL) - { - // Append all symbols not appearing on the .sdecl list to the end of - // the .sdecl list - for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder) - AddToSymbolDeclarationList(sy); - } + // Append all symbols not appearing on the .sdecl list to the end of + // the .sdecl list + for(SYM * sy=sorder; sy!=NULL; sy=sy->sorder) + AddToSymbolDeclarationList(sy); // Run through all symbols (now on the .sdecl list) and assign numbers to // them. We also pick which symbols should be global or not here. @@ -298,7 +316,8 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) if (sy->stype == LABEL && lsym_flag && (sy->sattr & (DEFINED | REFERENCED)) != 0 && (*sy->sname != '.') - && (sy->sattr & GLOBAL) == 0) + && (sy->sattr & GLOBAL) == 0 + && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0) { sy->senv = scount++; @@ -316,6 +335,7 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) { if ((sy->stype == LABEL) + && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0 && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) || (sy->sattr & COMMON)) @@ -325,9 +345,9 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) if (buf != NULL) buf = construct(buf, sy, 1); } - else if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL)) + else if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL) && (sy->sattre & (EQUATEDREG | UNDEF_EQUR | EQUATEDCC | UNDEF_CC)) == 0) { - buf = construct(buf, sy, 0); + buf = construct(buf, sy, 0); // <-- this creates a NON-global symbol... scount++; } } @@ -335,7 +355,6 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) return scount; } - // // Helper function for dsp_lod_symbols // @@ -359,7 +378,6 @@ static uint16_t WriteLODSection(int section, uint16_t symbolCount) return symbolCount; } - // // Dump LOD style symbols into the passed in buffer // @@ -382,7 +400,6 @@ void DumpLODSymbols(void) //WriteLODSection(M56001?, count); } - // // Convert string to uppercase // @@ -395,7 +412,6 @@ void ToUppercase(uint8_t * s) } } - // // Generate symbol table for listing file // @@ -549,3 +565,116 @@ int symtable(void) return 0; } +SYM * NewDebugSymbol(const uint8_t * str, uint8_t type, uint8_t other, uint16_t desc) +{ + SYM * symbol = NewSymbol(str, DBGSYM, 0); + + if (NULL == symbol) + fatal("Could not allocate space for debug symbol"); + + AddToSymbolDeclarationList(symbol); + + symbol->st_type = type; + symbol->st_other = other; + symbol->st_desc = 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; +}