1
0
mirror of https://github.com/ksherlock/x65.git synced 2025-02-12 16:30:39 +00:00
- Sections got overwritten (reference vs pointer mistake)
- Check that relocs and late evals apply the adjustments within the
existing binary
This commit is contained in:
Carl-Henrik Skårstedt 2015-10-15 20:58:17 -07:00
parent ca604ad81c
commit 12cfe830f9
2 changed files with 62 additions and 35 deletions

File diff suppressed because one or more lines are too long

95
x65.cpp
View File

@ -117,6 +117,7 @@ enum StatusCode {
ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION, ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION,
ERROR_LINKER_CANT_LINK_TO_DUMMY_SECTION, ERROR_LINKER_CANT_LINK_TO_DUMMY_SECTION,
ERROR_UNABLE_TO_PROCESS, ERROR_UNABLE_TO_PROCESS,
ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE,
STATUSCODE_COUNT STATUSCODE_COUNT
}; };
@ -173,6 +174,7 @@ const char *aStatusStrings[STATUSCODE_COUNT] = {
"Link can only be used in a fixed address section", "Link can only be used in a fixed address section",
"Link can not be used in dummy sections", "Link can not be used in dummy sections",
"Can not process this line", "Can not process this line",
"Unexpected target offset for reloc or late evaluation",
}; };
// Assembler directives // Assembler directives
@ -728,6 +730,7 @@ public:
void SetSection(strref name); // relative address section void SetSection(strref name); // relative address section
StatusCode LinkSections(strref name); // link relative address sections with this name here StatusCode LinkSections(strref name); // link relative address sections with this name here
void LinkLabelsToAddress(int section_id, int section_address); void LinkLabelsToAddress(int section_id, int section_address);
StatusCode LinkRelocs(int section_id, int section_address);
void DummySection(int address); void DummySection(int address);
void DummySection(); void DummySection();
void EndSection(); void EndSection();
@ -1005,6 +1008,54 @@ void Asm::LinkLabelsToAddress(int section_id, int section_address)
} }
} }
// go through relocs in all sections to see if any targets this section
// relocate section to address!
StatusCode Asm::LinkRelocs(int section_id, int section_address)
{
for (std::vector<Section>::iterator j = allSections.begin(); j != allSections.end(); ++j) {
Section &s2 = *j;
if (s2.pRelocs) {
relocList *pList = s2.pRelocs;
relocList::iterator i = pList->end();
while (i != pList->begin()) {
--i;
if (i->target_section == section_id) {
Section *trg_sect = &s2;
size_t output_offs = 0;
while (trg_sect->merged_offset>=0) {
output_offs += trg_sect->merged_offset;
trg_sect = &allSections[trg_sect->merged_section];
}
unsigned char *trg = trg_sect->output + output_offs + i->section_offset;
int value = i->base_value + section_address;
if (i->value_type == Reloc::WORD) {
if ((trg+1) >= (trg_sect->output + trg_sect->size()))
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
*trg++ = (unsigned char)value;
*trg = (unsigned char)(value >> 8);
} else if (i->value_type == Reloc::LO_BYTE) {
if (trg >= (trg_sect->output + trg_sect->size()))
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
*trg = (unsigned char)value;
} else if (i->value_type == Reloc::HI_BYTE) {
if (trg >= (trg_sect->output + trg_sect->size()))
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
*trg = (unsigned char)(value >> 8);
}
i = pList->erase(i);
if (i != pList->end())
++i;
}
}
if (pList->empty()) {
free(pList);
s2.pRelocs = nullptr;
}
}
}
return STATUS_OK;
}
StatusCode Asm::LinkSections(strref name) { StatusCode Asm::LinkSections(strref name) {
if (CurrSection().IsRelativeSection()) if (CurrSection().IsRelativeSection())
return ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION; return ERROR_LINKER_MUST_BE_IN_FIXED_ADDRESS_SECTION;
@ -1040,34 +1091,9 @@ StatusCode Asm::LinkSections(strref name) {
// All labels in this section can now be assigned // All labels in this section can now be assigned
LinkLabelsToAddress(section_id, section_address); LinkLabelsToAddress(section_id, section_address);
// go through relocs in all sections to see if any targets this section StatusCode status = LinkRelocs(section_id, section_address);
// relocate section to address! if (status != STATUS_OK)
for (std::vector<Section>::iterator j = allSections.begin(); j != allSections.end(); ++j) { return status;
Section &s2 = *j;
if (s2.pRelocs) {
relocList *pList = s2.pRelocs;
relocList::iterator i = pList->end();
while (i != pList->begin()) {
--i;
if (i->target_section == section_id) {
unsigned char *trg = s2.merged_offset < 0 ? s2.output :
(allSections[s2.merged_section].output + s2.merged_offset);
trg += i->section_offset;
int value = i->base_value + section_address;
if (i->value_type == Reloc::WORD) {
*trg++ = (unsigned char)value;
*trg = (unsigned char)(value >> 8);
} else if (i->value_type == Reloc::LO_BYTE)
*trg = (unsigned char)value;
else if (i->value_type == Reloc::HI_BYTE)
*trg = (unsigned char)(value >> 8);
i = pList->erase(i);
if (i != pList->end())
++i;
}
}
}
}
} }
++section_id; ++section_id;
} }
@ -1124,9 +1150,6 @@ void Section::AddReloc(int base, int offset, int section, Reloc::Type type)
pRelocs = new relocList; pRelocs = new relocList;
if (pRelocs->size() == pRelocs->capacity()) if (pRelocs->size() == pRelocs->capacity())
pRelocs->reserve(pRelocs->size() + 32); pRelocs->reserve(pRelocs->size() + 32);
printf("Add reloc base = $0x%04x offs=$0x%04x section=$0x%04x type = %d\n", base, offset, section, type);
pRelocs->push_back(Reloc(base, offset, section, type)); pRelocs->push_back(Reloc(base, offset, section, type));
} }
@ -1803,6 +1826,8 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
value -= i->address+1; value -= i->address+1;
if (value<-128 || value>127) if (value<-128 || value>127)
return ERROR_BRANCH_OUT_OF_RANGE; return ERROR_BRANCH_OUT_OF_RANGE;
if (trg >= allSections[sec].size())
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
allSections[sec].SetByte(trg, value); allSections[sec].SetByte(trg, value);
break; break;
case LateEval::LET_BYTE: case LateEval::LET_BYTE:
@ -1815,6 +1840,8 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
value = 0; value = 0;
} }
} }
if (trg >= allSections[sec].size())
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
allSections[sec].SetByte(trg, value); allSections[sec].SetByte(trg, value);
break; break;
case LateEval::LET_ABS_REF: case LateEval::LET_ABS_REF:
@ -1826,6 +1853,8 @@ StatusCode Asm::CheckLateEval(strref added_label, int scope_end)
value = 0; value = 0;
} }
} }
if ((trg+1) >= allSections[sec].size())
return ERROR_SECTION_TARGET_OFFSET_OUT_OF_RANGE;
allSections[sec].SetWord(trg, value); allSections[sec].SetWord(trg, value);
break; break;
case LateEval::LET_LABEL: { case LateEval::LET_LABEL: {
@ -3150,8 +3179,6 @@ StatusCode Asm::AddOpcode(strref line, int group, int index, strref source_file)
if (evalLater) if (evalLater)
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF); AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_ABS_REF);
else if (error == STATUS_RELATIVE_SECTION) { else if (error == STATUS_RELATIVE_SECTION) {
printf("Reloc two byte op: ");
CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(), CurrSection().AddReloc(target_section_offs, CurrSection().DataOffset(),
target_section, target_section_type); target_section, target_section_type);
value = 0; value = 0;
@ -3675,7 +3702,7 @@ StatusCode Asm::ReadObjectFile(strref filename)
else else
SetSection(aSect[si].name.offs >= 0 ? strref(str_pool + aSect[si].name.offs) : strref()); SetSection(aSect[si].name.offs >= 0 ? strref(str_pool + aSect[si].name.offs) : strref());
if (aSect[si].output_size) { if (aSect[si].output_size) {
CurrSection().output = (unsigned char*)malloc(aSect[si].output_size+64); CurrSection().output = (unsigned char*)malloc(aSect[si].output_size);
memcpy(CurrSection().output, bin_data, aSect[si].output_size); memcpy(CurrSection().output, bin_data, aSect[si].output_size);
CurrSection().curr = CurrSection().output + aSect[si].output_size; CurrSection().curr = CurrSection().output + aSect[si].output_size;
CurrSection().output_capacity = aSect[si].output_size; CurrSection().output_capacity = aSect[si].output_size;