1
0
mirror of https://github.com/ksherlock/x65.git synced 2024-12-27 13:29:18 +00:00

Merge pull request #20 from Sakrac/source-debug

Source debug
This commit is contained in:
Carl-Henrik Skårstedt 2021-01-14 20:33:43 +01:00 committed by GitHub
commit dc53ab5174
7 changed files with 270 additions and 48 deletions

1
.gitignore vendored
View File

@ -19,4 +19,5 @@
*.obj.enc
*.user
*.db*
*.recipe
test/results/*

View File

@ -102,6 +102,7 @@ Primarily tested with personal archive of sources written for Kick assmebler, DA
* irp (indefinite repeat)
**FIXED**
* Source Debug output file including linkable object files, C64Debugger format
* Adding MERGE directive, Label Pools rewrite, TEXT data can be indexed from a string symbol
* Label Pools were destroyed after each scope so they did not work in include files which defeated their purpose. Label pools are now persistent through scopes.
* Labels reserved from label pools now distinguish between global and local. Use [.!@$] as a prefix to reserve a local label from a label pool (previously always local)

View File

@ -23,32 +23,32 @@
<ProjectGuid>{57EFF4A4-7BF2-43F0-AD62-A79092DA67D1}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>dump_x65</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>

View File

@ -23,32 +23,32 @@
<ProjectGuid>{2823019A-A423-4A40-BB9C-5CE242019BD0}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>x65</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>

276
x65.cpp
View File

@ -47,6 +47,7 @@
// Command line arguments
static const strref cmdarg_listing("lst"); // -lst / -lst=(file.lst) : generate disassembly text from result(file or stdout)
static const strref cmdarg_srcdebug("srcdbg"); // -srcdbg : generate debug, -srcdbg=(file) : save debug file
static const strref cmdarg_tass_listing("tsl"); // -tsl=(file) : generate listing file in TASS style
static const strref cmdarg_tass_labels("tl"); // -tl=(file) : generate labels in TASS style
static const strref cmdarg_allinstr("opcodes"); // -opcodes / -opcodes=(file.s) : dump all available opcodes(file or stdout)
@ -1133,6 +1134,13 @@ uint32_t FindLabelIndex(uint32_t hash, uint32_t *table, uint32_t count)
return count;
}
char* StringCopy(strref str)
{
char* buf = (char*)calloc(1, (size_t)str.get_len() + 1);
if (buf && str.get_len()) { memcpy(buf, str.get(), str.get_len()); }
return buf;
}
//
@ -1431,7 +1439,7 @@ struct SourceDebugEntry {
int size;
int source_file_offset; // can be converted into line/column while linking
};
typedef std::vector<struct SLDEntry> SourceDebug;
typedef std::vector<struct SourceDebugEntry> SourceDebug;
enum SectionType : int8_t { // enum order indicates fixed address linking priority
@ -1513,6 +1521,8 @@ typedef struct Section {
pRelocs = nullptr;
if (pListing) delete pListing;
pListing = nullptr;
if (pSrcDbg) delete pSrcDbg;
pSrcDbg = nullptr;
}
void Cleanup() { if (output) free(output); reset(); }
@ -1536,11 +1546,11 @@ typedef struct Section {
void AddReloc(int base, int offset, int section, int8_t bytes, int8_t shift);
Section() : pRelocs(nullptr), pListing(nullptr) { reset(); }
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr) {
Section(strref _name, int _address) : pRelocs(nullptr), pListing(nullptr), pSrcDbg(nullptr) {
reset(); name = _name; start_address = load_address = address = _address;
address_assigned = true;
}
Section(strref _name) : pRelocs(nullptr), pListing(nullptr) {
Section(strref _name) : pRelocs(nullptr), pListing(nullptr), pSrcDbg(nullptr) {
reset(); name = _name;
start_address = load_address = address = 0; address_assigned = false;
}
@ -1819,6 +1829,7 @@ public:
int8_t cycle_counter_level; // merlin toggles the cycle counter rather than hierarchically evals
bool error_encountered; // if any error encountered, don't export binary
bool list_assembly; // generate assembler listing
bool src_debug; // generate source debug info
bool end_macro_directive; // whether to use { } or macro / endmacro for macro scope
bool import_means_xref;
@ -1835,6 +1846,9 @@ public:
// Mimic TASS listing
bool ListTassStyle( strref filename );
// Export C64Debugger dbg xml file
bool SourceDebugExport(strref filename);
// Generate source for all valid instructions and addressing modes for current CPU
bool AllOpcodes(strref filename);
@ -2034,9 +2048,7 @@ void SymbolStackTable::PushSymbol(StringSymbol* string)
ValueOrString val;
val.string = nullptr;
if (string->string_value) {
val.string = (char*)malloc(string->string_value.get_len() + 1);
memcpy(val.string, string->string_value.get(), string->string_value.get_len());
val.string[string->string_value.get_len()] = 0;
val.string = StringCopy(string->string_value.get_strref());
}
(*ppStack)->push_back(val);
}
@ -2143,8 +2155,12 @@ void Asm::Cleanup() {
free(str.string_value.charstr());
}
strings.clear();
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
for (std::vector<ExtLabels>::iterator exti = externals.begin(); exti != externals.end(); ++exti) {
exti->labels.clear();
}
for (std::vector<char*>::iterator src = source_files.begin(); src != source_files.end(); ++src) {
free(*src);
}
externals.clear();
// this section is relocatable but is assigned address $1000 if exporting without directives
SetSection(strref("default,code"));
@ -2159,6 +2175,7 @@ void Asm::Cleanup() {
directive_scope_depth = 0;
error_encountered = false;
list_assembly = false;
src_debug = false;
end_macro_directive = false;
import_means_xref = false;
accumulator_16bit = false; // default 65816 8 bit immediate mode
@ -2921,6 +2938,20 @@ StatusCode Asm::MergeSections(int section_id, int section_merge) {
delete m.pListing;
m.pListing = nullptr;
}
// go through source debug
if (m.pSrcDbg) {
if (!s.pSrcDbg) { s.pSrcDbg = new SourceDebug; }
if (s.pSrcDbg->capacity() < (m.pSrcDbg->size() + s.pSrcDbg->size())) {
s.pSrcDbg->reserve((m.pSrcDbg->size() + s.pSrcDbg->size()));
}
for (SourceDebug::iterator i = m.pSrcDbg->begin(); i != m.pSrcDbg->end(); ++i) {
SourceDebugEntry l = *i;
l.address += addr_start;
s.pSrcDbg->push_back(l);
}
delete m.pSrcDbg;
m.pSrcDbg = nullptr;
}
m.type = ST_REMOVED;
return STATUS_OK;
}
@ -6707,14 +6738,12 @@ StatusCode Asm::BuildLine(strref line) {
}
}
// update listing
if (error == STATUS_OK && list_assembly) {
if (error == STATUS_OK) {
if (SectionId() == start_section) {
Section &curr = CurrSection();
if (list_assembly) {
if (!curr.pListing) { curr.pListing = new Listing; }
if (curr.pListing && curr.pListing->size()==curr.pListing->capacity()) {
curr.pListing->reserve(curr.pListing->size()+256);
}
if (((list_flags&(ListLine::KEYWORD|ListLine::CYCLES_START|ListLine::CYCLES_STOP)) ||
if (((list_flags & (ListLine::KEYWORD | ListLine::CYCLES_START | ListLine::CYCLES_STOP)) ||
(curr.address != start_address && curr.size())) && !curr.IsDummySection()) {
struct ListLine lst;
lst.address = start_address - curr.start_address;
@ -6727,6 +6756,27 @@ StatusCode Asm::BuildLine(strref line) {
curr.pListing->push_back(lst);
}
}
if (src_debug) {
if (!curr.pSrcDbg) { curr.pSrcDbg = new SourceDebug; }
if (curr.address != start_address && curr.size()) {
SourceDebugEntry entry;
entry.address = start_address - curr.start_address;
entry.size = curr.address - start_address;
size_t sf = 0, nsf = source_files.size();
strref src = contextStack.curr().source_name;
for (; sf < nsf; ++sf) {
if (src.same_str_case(source_files[sf])) { break; }
}
if (sf == nsf) {
source_files.push_back(StringCopy(src));
}
entry.source_file_index = (int)sf;
entry.source_file_offset = (int)(data_line - contextStack.curr().source_file.get());
curr.pSrcDbg->push_back(entry);
}
}
}
}
return error;
}
@ -6888,6 +6938,95 @@ bool Asm::ListTassStyle( strref filename ) {
return true;
}
bool Asm::SourceDebugExport(strref filename) {
FILE* f = stdout;
bool opened = false;
if (filename) {
f = fopen(strown<512>(filename).c_str(), "w");
if (!f) { return false; }
opened = true;
} else {
return false;
}
std::vector<strovl> source_code; source_code.reserve(source_files.size());
fprintf(f, "<C64debugger version=\"1.0\">\n\t<Sources values=\"INDEX,FILE\">\n");
for (size_t i = 0, n = source_files.size(); i < n; ++i) {
fprintf(f, "\t\t%d,%s\n", (int)i+1, source_files[i]);
size_t size = 0;
char* src = LoadText(source_files[i], size);
source_code.push_back(strovl(src, (strl_t)size, (strl_t)size));
}
fprintf(f, "\t</Sources>\n\n");
for (size_t i = 0, n = allSections.size(); i < n; ++i) {
Section& s = allSections[i];
if (s.pSrcDbg && s.pSrcDbg->size()) {
fprintf(f, "\t<Segment name=\"" STRREF_FMT "\" dest=\"\" values=\"START,END,FILE_IDX,LINE1,COL1,LINE2,COL2\">\n\t\t<Block name=\"Unnamed\">\n",
STRREF_ARG(s.name));
for (size_t d = 0, nd = s.pSrcDbg->size(); d < nd; ++d) {
SourceDebugEntry& e = s.pSrcDbg->at(d);
int line = 0, col0 = 0, col1 = 0;
if ((e.source_file_index) < source_code.size()) {
strref src = source_code[e.source_file_index].get_strref();
if (src.get_len() > strl_t(e.source_file_offset)) {
line = strref(src.get(), e.source_file_offset).count_lines();
strl_t offs = e.source_file_offset;
while (src.get_at(offs) != 0x0a && src.get_at(offs) != 0x0d && offs) { --offs; ++col0; }
col1 = col0;
offs = e.source_file_offset;
while (src.get_at(offs) != 0x0a && src.get_at(offs) != 0x0d && offs<src.get_len()) { ++offs; ++col1; }
}
}
fprintf(f, "\t\t\t$%04x,$%04x,%d,%d,%d,%d,%d\n",
e.address+s.start_address, e.address+e.size+s.start_address-1, e.source_file_index+1,
line+1, col0 ? (col0-1) : 0, line+1, col1 );
}
fprintf(f, "\t\t</Block>\n\t</Segment>\n\n");
}
}
fprintf(f, "\t<Labels values=\"SEGMENT,ADDRESS,NAME,START,END,FILE_IDX,LINE1,COL1,LINE2,COL2\">\n");
for (MapSymbolArray::iterator i = map.begin(); i != map.end(); ++i) {
if (i->name.same_str("debugbreak")) { continue; }
uint32_t value = (uint32_t)i->value;
strref sectName;
if (size_t(i->section) < allSections.size()) {
value += allSections[i->section].start_address;
sectName = allSections[i->section].name;
}
fprintf(f, "\t\t" STRREF_FMT ",$%04x," STRREF_FMT ",0,0,0,0,0\n", STRREF_ARG(sectName), value, STRREF_ARG(i->name));
}
fprintf(f, "\t</Labels>\n\n");
fprintf(f, "\t<Breakpoints values=\"SEGMENT,ADDRESS,ARGUMENT\">\n");
for (MapSymbolArray::iterator i = map.begin(); i != map.end(); ++i) {
uint32_t value = (uint32_t)i->value;
strref sectName;
if (size_t(i->section) < allSections.size()) {
value += allSections[i->section].start_address;
sectName = allSections[i->section].name;
}
if (i->name.same_str("debugbreak")) {
fprintf(f, "\t\t" STRREF_FMT ",$%04x,\n", STRREF_ARG(sectName), value);
}
}
fprintf(f, "\t</Breakpoints>\n\n");
fprintf(f, "\t<Watchpoints values=\"SEGMENT,ADDRESS1,ADDRESS2,ARGUMENT\">\n");
fprintf(f, "\t</Watchpoints>\n\n");
fprintf(f, "</C64debugger>\n");
fclose(f);
for (size_t i = 0, n = source_code.size(); i < n; ++i) {
if (source_code[i].get()) { free(source_code[i].charstr()); }
}
return true;
}
bool Asm::List(strref filename) {
FILE *f = stdout;
bool opened = false;
@ -7205,6 +7344,7 @@ struct ObjFileHeader {
int16_t late_evals;
int16_t map_symbols;
uint32_t stringdata;
uint32_t srcdebug;
int bindata;
};
@ -7224,7 +7364,7 @@ struct ObjFileSection {
int end_address; // address size
int output_size; // assembled binary size
int align_address;
int list_count; // how many addresses included in debugger listing
int srcdebug_count; // how many addresses included in debugger listing
int16_t next_group; // next section of group
int16_t first_group; // first section of group
int16_t relocs;
@ -7279,10 +7419,11 @@ struct ObjFileMapSymbol {
// this struct is follwed by numSources x ObjFileStr
struct ObjFileSourceList {
uint32_t numSources;
ObjFileStr sourceFile[1];
};
// after that one long array of all sections worth of source references
struct ObjFileSrcRef {
struct ObjFileSrcDbg {
uint16_t addr; // relative to section
uint16_t src_idx;
uint16_t size;
@ -7360,6 +7501,7 @@ StatusCode Asm::WriteObjectFile(strref filename) {
hdr.late_evals = (int16_t)lateEval.size();
hdr.map_symbols = (int16_t)map.size();
hdr.stringdata = 0;
hdr.srcdebug = 0;
// labels don't include XREF labels
hdr.labels = 0;
@ -7380,7 +7522,7 @@ StatusCode Asm::WriteObjectFile(strref filename) {
char *stringPool = nullptr;
uint32_t stringPoolCap = 0;
pairArray<uint32_t, int> stringArray;
stringArray.reserve(hdr.labels * 2 + hdr.sections + hdr.late_evals*2);
stringArray.reserve(hdr.labels * 2 + hdr.sections + hdr.late_evals*2 + (uint32_t)source_files.size());
struct ObjFileSection *aSects = hdr.sections ? (struct ObjFileSection*)calloc(hdr.sections, sizeof(struct ObjFileSection)) : nullptr;
struct ObjFileReloc *aRelocs = hdr.relocs ? (struct ObjFileReloc*)calloc(hdr.relocs, sizeof(struct ObjFileReloc)) : nullptr;
@ -7398,11 +7540,11 @@ StatusCode Asm::WriteObjectFile(strref filename) {
}
sect = 0;
uint32_t srcDbgEntries = 0;
// write out sections and relocs
if (hdr.sections) {
for (std::vector<Section>::iterator si = allSections.begin(); si!=allSections.end(); ++si) {
if (si->type == ST_REMOVED)
continue;
if (si->type == ST_REMOVED) { continue; }
struct ObjFileSection &s = aSects[sect++];
s.name.offs = _AddStrPool(si->name, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
s.exp_app.offs = _AddStrPool(si->export_append, &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
@ -7411,6 +7553,8 @@ StatusCode Asm::WriteObjectFile(strref filename) {
s.next_group = si->next_group >= 0 ? aRemapSects[si->next_group] : -1;
s.first_group = si->first_group >= 0 ? aRemapSects[si->first_group] : -1;
s.relocs = si->pRelocs ? (int16_t)(si->pRelocs->size()) : 0;
s.srcdebug_count = si->pSrcDbg ? (int)si->pSrcDbg->size() : 0;
srcDbgEntries += s.srcdebug_count;
s.start_address = si->start_address;
s.end_address = si->address;
s.type = si->type;
@ -7432,6 +7576,25 @@ StatusCode Asm::WriteObjectFile(strref filename) {
}
hdr.sections = (int16_t)sect;
struct ObjFileSrcDbg* srcLines = srcDbgEntries ? (ObjFileSrcDbg*)calloc(1, sizeof(ObjFileSrcDbg) * srcDbgEntries) : nullptr;
if (srcLines) {
size_t srcDbgIdx = 0;
for (std::vector<Section>::iterator si = allSections.begin(); si != allSections.end(); ++si) {
if (si->type == ST_REMOVED) { continue; }
if (si->pSrcDbg && si->pSrcDbg->size()) {
for (size_t src = 0, nsrc = si->pSrcDbg->size(); src < nsrc; ++src) {
SourceDebugEntry& entry = si->pSrcDbg->at(src);
ObjFileSrcDbg& ref = srcLines[srcDbgIdx++];
ref.addr = entry.address;
ref.src_idx = entry.source_file_index;
ref.size = entry.size;
ref.file_offs = entry.source_file_offset;
}
}
}
assert(srcDbgIdx == srcDbgEntries);
}
// write out labels
if (hdr.labels) {
for (uint32_t li = 0; li<labels.count(); li++) {
@ -7498,6 +7661,17 @@ StatusCode Asm::WriteObjectFile(strref filename) {
}
}
struct ObjFileSourceList* sourceList = nullptr;
if (source_files.size() && srcLines) {
sourceList = (struct ObjFileSourceList*)calloc(1, sizeof(ObjFileSourceList) + sizeof(ObjFileStr) * (source_files.size() - 1));
sourceList->numSources = (uint32_t)source_files.size();
for (size_t src = 0, nsrc = source_files.size(); src < nsrc; ++src) {
sourceList->sourceFile[src].offs = _AddStrPool(strref(source_files[src]), &stringArray, &stringPool, hdr.stringdata, stringPoolCap);
}
}
hdr.srcdebug = srcDbgEntries;
// write out the file
fwrite(&hdr, sizeof(hdr), 1, f);
fwrite(aSects, sizeof(aSects[0]), sect, f);
@ -7511,6 +7685,12 @@ StatusCode Asm::WriteObjectFile(strref filename) {
fwrite(si->output, si->size(), 1, f);
}
}
if (sourceList) {
fwrite(sourceList, sizeof(ObjFileSourceList) + sizeof(ObjFileStr) * (source_files.size() - 1), 1, f);
fwrite(srcLines, sizeof(ObjFileSrcDbg) * srcDbgEntries, 1, f);
}
// done with I/O
fclose(f);
if (aRemapSects) { free(aRemapSects); }
@ -7539,6 +7719,14 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
hdr.relocs * sizeof(struct ObjFileReloc) + hdr.labels * sizeof(struct ObjFileLabel) +
hdr.late_evals * sizeof(struct ObjFileLateEval) +
hdr.map_symbols * sizeof(struct ObjFileMapSymbol) + hdr.stringdata + hdr.bindata;
const struct ObjFileSourceList* pSrcDbgInfo = hdr.srcdebug ? (struct ObjFileSourceList*)(data + sum) : nullptr;
const struct ObjFileSrcDbg* pSrcDbgEntry = pSrcDbgInfo ? (const struct ObjFileSrcDbg*)(pSrcDbgInfo->sourceFile + pSrcDbgInfo->numSources) : nullptr;
if (pSrcDbgInfo) {
sum += sizeof(ObjFileSourceList) + (pSrcDbgInfo->numSources - 1) * sizeof(ObjFileStr);
sum += sizeof(ObjFileSrcDbg) * hdr.srcdebug;
}
if (hdr.id == 0x7836 && sum == size) {
struct ObjFileSection *aSect = (struct ObjFileSection*)(&hdr + 1);
struct ObjFileReloc *aReloc = (struct ObjFileReloc*)(aSect + hdr.sections);
@ -7552,6 +7740,23 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
memcpy(str_pool, str_orig, hdr.stringdata);
loadedData.push_back(str_pool);
// source files
std::vector<size_t> source_file_remap;
if (pSrcDbgInfo) {
source_file_remap.reserve(pSrcDbgInfo->numSources);
for (size_t s = 0, n = pSrcDbgInfo->numSources; s < n; ++s) {
strref source_file(str_pool + pSrcDbgInfo->sourceFile[s].offs);
size_t i = 0, sz = source_files.size();
for (; i < sz; ++i) {
if (source_file.same_str(source_files[i])) { break; }
}
if (i == sz) {
source_files.push_back(StringCopy(source_file));
}
source_file_remap.push_back(i);
}
}
int prevSection = SectionId();
int16_t *aSctRmp = (int16_t*)malloc(hdr.sections * sizeof(int16_t));
int last_linked_section = link_to_section;
@ -7596,6 +7801,19 @@ StatusCode Asm::ReadObjectFile(strref filename, int link_to_section)
s.first_group = allSections[last_linked_section].first_group >=0 ? allSections[last_linked_section].first_group : last_linked_section;
last_linked_section = SectionId();
}
// add source debug entries from object file
if (aSect[si].srcdebug_count) {
if (!s.pSrcDbg) { s.pSrcDbg = new SourceDebug; }
for (int sd = 0, nsd = aSect[si].srcdebug_count; sd < nsd; ++sd) {
SourceDebugEntry entry;
entry.address = pSrcDbgEntry->addr;
entry.size = pSrcDbgEntry->size;
entry.source_file_index = (int)source_file_remap[pSrcDbgEntry->src_idx];
entry.source_file_offset = pSrcDbgEntry->file_offs;
s.pSrcDbg->push_back(entry);
++pSrcDbgEntry;
}
}
}
aSctRmp[si] = (int16_t)allSections.size()-1;
}
@ -7978,6 +8196,7 @@ int main(int argc, char **argv) {
const char *sym_file = nullptr, *vs_file = nullptr, *cmdarg_tass_labels_file = nullptr;
strref list_file, allinstr_file;
strref tass_list_file;
strref srcdebug_file;
for (int a = 1; a<argc; a++) {
if (argv[a][0]=='-') {
strref arg(argv[a]+1);
@ -8017,11 +8236,14 @@ int main(int argc, char **argv) {
assembler.import_means_xref = true;
} else if (arg.same_str(cmdarg_references)) {
show_refs_before_link = true;
} else if (arg.has_prefix(cmdarg_listing)&&(arg.get_len()==cmdarg_listing.get_len()||arg[cmdarg_listing.get_len()]=='=')) {
} else if (arg.has_prefix(cmdarg_listing) && (arg.get_len() == cmdarg_listing.get_len() || arg[cmdarg_listing.get_len()] == '=')) {
assembler.list_assembly = true;
list_output = true;
list_file = arg.after( '=' );
} else if (arg.has_prefix(cmdarg_tass_listing)&&(arg.get_len()==cmdarg_listing.get_len()||arg[cmdarg_listing.get_len()]=='=')) {
list_file = arg.after('=');
} else if (arg.has_prefix(cmdarg_srcdebug) && (arg.get_len() == cmdarg_srcdebug.get_len() || arg[cmdarg_srcdebug.get_len()] == '=')) {
assembler.src_debug = true;
srcdebug_file = arg.after('=');
} else if (arg.has_prefix(cmdarg_tass_listing)&&(arg.get_len()== cmdarg_tass_listing.get_len()||arg[cmdarg_tass_listing.get_len()]=='=')) {
assembler.list_assembly = true;
tass_list_output = true;
tass_list_file = arg.after( '=' );
@ -8092,7 +8314,8 @@ int main(int argc, char **argv) {
" * -mrg : Force merge all sections (use with -a2o)\n"
" * -sym (file.sym) : symbol file\n"
" * -lst / -lst = (file.lst) : generate disassembly text from result(file or stdout)\n"
" * -opcodes / -opcodes = (file.s) : dump all available opcodes(file or stdout)\n"
" * -opcodes / -opcodes=(file.s) : dump all available opcodes(file or stdout)\n"
" * -srcdbg / -srcdbg=(file.dbg) : generate a source level debugging file for object files or linked files"
" * -sect: display sections loaded and built\n"
" * -vice (file.vs) : export a vice symbol file\n"
" * -merlin: use Merlin syntax\n"
@ -8179,11 +8402,11 @@ int main(int argc, char **argv) {
}
// listing after export since addresses are now resolved
if ( list_output )
assembler.List(list_file);
if (list_output) { assembler.List(list_file); }
if( tass_list_output )
assembler.ListTassStyle(tass_list_file);
if (srcdebug_file) { assembler.SourceDebugExport(srcdebug_file); }
if (tass_list_output) { assembler.ListTassStyle(tass_list_file); }
// export .sym file
if (sym_file && !srcname.same_str(sym_file) && !assembler.map.empty()) {
@ -8234,9 +8457,6 @@ int main(int argc, char **argv) {
fclose( f );
}
}
}
// free some memory
assembler.Cleanup();