diff --git a/.gitignore b/.gitignore
index 145d8a0..ee2e9b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,5 @@
*.obj.enc
*.user
*.db*
+*.recipe
test/results/*
\ No newline at end of file
diff --git a/obj/x64Releasedump_x65/dump_x65.vcxproj.FileListAbsolute.txt b/obj/x64Releasedump_x65/dump_x65.vcxproj.FileListAbsolute.txt
new file mode 100644
index 0000000..e69de29
diff --git a/obj/x64Releasex65/x65.vcxproj.FileListAbsolute.txt b/obj/x64Releasex65/x65.vcxproj.FileListAbsolute.txt
new file mode 100644
index 0000000..e69de29
diff --git a/sln/dump_x65/dump_x65.vcxproj b/sln/dump_x65/dump_x65.vcxproj
index 996b984..433d851 100644
--- a/sln/dump_x65/dump_x65.vcxproj
+++ b/sln/dump_x65/dump_x65.vcxproj
@@ -23,32 +23,32 @@
{57EFF4A4-7BF2-43F0-AD62-A79092DA67D1}
Win32Proj
dump_x65
- 10.0.15063.0
+ 10.0
Application
true
- v141
+ v142
NotSet
Application
false
- v141
+ v142
true
NotSet
Application
true
- v141
+ v142
NotSet
Application
false
- v141
+ v142
true
NotSet
diff --git a/sln/x65.vcxproj b/sln/x65.vcxproj
index 5568169..8ab13a3 100644
--- a/sln/x65.vcxproj
+++ b/sln/x65.vcxproj
@@ -23,32 +23,32 @@
{2823019A-A423-4A40-BB9C-5CE242019BD0}
Win32Proj
x65
- 10.0.15063.0
+ 10.0
Application
true
- v141
+ v142
NotSet
Application
false
- v141
+ v142
true
NotSet
Application
true
- v141
+ v142
NotSet
Application
false
- v141
+ v142
true
NotSet
diff --git a/x65.cpp b/x65.cpp
index cdabb0c..368071c 100644
--- a/x65.cpp
+++ b/x65.cpp
@@ -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)
@@ -1431,7 +1432,7 @@ struct SourceDebugEntry {
int size;
int source_file_offset; // can be converted into line/column while linking
};
-typedef std::vector SourceDebug;
+typedef std::vector SourceDebug;
enum SectionType : int8_t { // enum order indicates fixed address linking priority
@@ -1513,6 +1514,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 +1539,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 +1822,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;
@@ -2143,8 +2147,12 @@ void Asm::Cleanup() {
free(str.string_value.charstr());
}
strings.clear();
- for (std::vector::iterator exti = externals.begin(); exti !=externals.end(); ++exti)
+ for (std::vector::iterator exti = externals.begin(); exti != externals.end(); ++exti) {
exti->labels.clear();
+ }
+ for (std::vector::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 +2167,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 +2930,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,24 +6730,45 @@ 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 (!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_assembly) {
+ if (!curr.pListing) { curr.pListing = new Listing; }
+ 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;
- lst.size = curr.address - start_address;
- lst.code = contextStack.curr().source_file;
- lst.column = (uint16_t)(data_line - code_line.get());
- lst.source_name = contextStack.curr().source_name;
- lst.line_offs = int(code_line.get() - lst.code.get());
- lst.flags = list_flags;
- curr.pListing->push_back(lst);
+ struct ListLine lst;
+ lst.address = start_address - curr.start_address;
+ lst.size = curr.address - start_address;
+ lst.code = contextStack.curr().source_file;
+ lst.column = (uint16_t)(data_line - code_line.get());
+ lst.source_name = contextStack.curr().source_name;
+ lst.line_offs = int(code_line.get() - lst.code.get());
+ lst.flags = list_flags;
+ 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) {
+ char* path = (char*)calloc(1, src.get_len()+1);
+ memcpy(path, src.get(), src.get_len());
+ source_files.push_back(path);
+ }
+ entry.source_file_index = (int)sf;
+ entry.source_file_offset = (int)(data_line - contextStack.curr().source_file.get());
+ curr.pSrcDbg->push_back(entry);
+ }
}
}
}
@@ -7205,6 +7249,7 @@ struct ObjFileHeader {
int16_t late_evals;
int16_t map_symbols;
uint32_t stringdata;
+ uint32_t srcdebug;
int bindata;
};
@@ -7224,7 +7269,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,6 +7324,7 @@ 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
@@ -7360,6 +7406,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 +7427,7 @@ StatusCode Asm::WriteObjectFile(strref filename) {
char *stringPool = nullptr;
uint32_t stringPoolCap = 0;
pairArray 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 +7445,11 @@ StatusCode Asm::WriteObjectFile(strref filename) {
}
sect = 0;
+ uint32_t srcDbgEntries = 0;
// write out sections and relocs
if (hdr.sections) {
for (std::vector::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 +7458,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 +7481,25 @@ StatusCode Asm::WriteObjectFile(strref filename) {
}
hdr.sections = (int16_t)sect;
+ struct ObjFileSrcRef* srcLines = srcDbgEntries ? (ObjFileSrcRef*)calloc(1, sizeof(ObjFileSrcRef) * srcDbgEntries) : nullptr;
+ if (srcLines) {
+ size_t srcDbgIdx = 0;
+ for (std::vector::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);
+ ObjFileSrcRef& 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; linumSources = (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 +7590,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(ObjFileSrcRef) * srcDbgEntries, 1, f);
+ }
+
+
// done with I/O
fclose(f);
if (aRemapSects) { free(aRemapSects); }
@@ -7978,6 +8063,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