mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Use std::string for symbol/section/node names and assertion messages
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
@@ -35,7 +36,7 @@ struct FileStackNode {
|
|||||||
|
|
||||||
enum FileStackNodeType type;
|
enum FileStackNodeType type;
|
||||||
union {
|
union {
|
||||||
char *name; // NODE_FILE, NODE_MACRO
|
std::string *name; // NODE_FILE, NODE_MACRO
|
||||||
std::vector<uint32_t> *iters; // NODE_REPT
|
std::vector<uint32_t> *iters; // NODE_REPT
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -50,7 +51,7 @@ struct FileStackNode {
|
|||||||
* Dump a file stack to stderr
|
* Dump a file stack to stderr
|
||||||
* @param node The leaf node to dump the context of
|
* @param node The leaf node to dump the context of
|
||||||
*/
|
*/
|
||||||
char const *dumpFileStack(struct FileStackNode const *node);
|
std::string const *dumpFileStack(struct FileStackNode const *node);
|
||||||
|
|
||||||
void warning(struct FileStackNode const *where, uint32_t lineNo,
|
void warning(struct FileStackNode const *where, uint32_t lineNo,
|
||||||
char const *fmt, ...) format_(printf, 3, 4);
|
char const *fmt, ...) format_(printf, 3, 4);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
struct Assertion {
|
struct Assertion {
|
||||||
struct Patch patch; // Also used for its `.type`
|
struct Patch patch; // Also used for its `.type`
|
||||||
char *message;
|
std::string *message;
|
||||||
// This would be redundant with `.section->fileSymbols`... but `section` is sometimes NULL!
|
// This would be redundant with `.section->fileSymbols`... but `section` is sometimes NULL!
|
||||||
std::vector<struct Symbol> *fileSymbols;
|
std::vector<struct Symbol> *fileSymbols;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
// GUIDELINE: external code MUST NOT BE AWARE of the data structure used!
|
// GUIDELINE: external code MUST NOT BE AWARE of the data structure used!
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "link/main.hpp"
|
#include "link/main.hpp"
|
||||||
@@ -30,7 +31,7 @@ struct Patch {
|
|||||||
|
|
||||||
struct Section {
|
struct Section {
|
||||||
// Info contained in the object files
|
// Info contained in the object files
|
||||||
char *name;
|
std::string *name;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
enum SectionType type;
|
enum SectionType type;
|
||||||
@@ -70,7 +71,7 @@ void sect_AddSection(struct Section *section);
|
|||||||
* @param name The name of the section to look for
|
* @param name The name of the section to look for
|
||||||
* @return A pointer to the section, or NULL if it wasn't found
|
* @return A pointer to the section, or NULL if it wasn't found
|
||||||
*/
|
*/
|
||||||
struct Section *sect_GetSection(char const *name);
|
struct Section *sect_GetSection(std::string const &name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* `free`s all section memory that was allocated.
|
* `free`s all section memory that was allocated.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
// GUIDELINE: external code MUST NOT BE AWARE of the data structure used!
|
// GUIDELINE: external code MUST NOT BE AWARE of the data structure used!
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "linkdefs.hpp"
|
#include "linkdefs.hpp"
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ struct FileStackNode;
|
|||||||
|
|
||||||
struct Symbol {
|
struct Symbol {
|
||||||
// Info contained in the object files
|
// Info contained in the object files
|
||||||
char *name;
|
std::string *name;
|
||||||
enum ExportLevel type;
|
enum ExportLevel type;
|
||||||
char const *objFileName;
|
char const *objFileName;
|
||||||
struct FileStackNode const *src;
|
struct FileStackNode const *src;
|
||||||
@@ -36,7 +37,7 @@ void sym_AddSymbol(struct Symbol *symbol);
|
|||||||
* @param name The name of the symbol to look for
|
* @param name The name of the symbol to look for
|
||||||
* @return A pointer to the symbol, or NULL if not found.
|
* @return A pointer to the symbol, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
struct Symbol *sym_GetSymbol(char const *name);
|
struct Symbol *sym_GetSymbol(std::string const &name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* `free`s all symbol memory that was allocated.
|
* `free`s all symbol memory that was allocated.
|
||||||
|
|||||||
@@ -318,17 +318,17 @@ static void placeSection(struct Section *section)
|
|||||||
// If a section failed to go to several places, nothing we can report
|
// If a section failed to go to several places, nothing we can report
|
||||||
if (!section->isBankFixed || !section->isAddressFixed)
|
if (!section->isBankFixed || !section->isAddressFixed)
|
||||||
errx("Unable to place \"%s\" (%s section) %s",
|
errx("Unable to place \"%s\" (%s section) %s",
|
||||||
section->name, sectionTypeInfo[section->type].name.c_str(), where);
|
section->name->c_str(), sectionTypeInfo[section->type].name.c_str(), where);
|
||||||
// If the section just can't fit the bank, report that
|
// If the section just can't fit the bank, report that
|
||||||
else if (section->org + section->size > endaddr(section->type) + 1)
|
else if (section->org + section->size > endaddr(section->type) + 1)
|
||||||
errx("Unable to place \"%s\" (%s section) %s: section runs past end of region ($%04x > $%04x)",
|
errx("Unable to place \"%s\" (%s section) %s: section runs past end of region ($%04x > $%04x)",
|
||||||
section->name, sectionTypeInfo[section->type].name.c_str(), where,
|
section->name->c_str(), sectionTypeInfo[section->type].name.c_str(), where,
|
||||||
section->org + section->size, endaddr(section->type) + 1);
|
section->org + section->size, endaddr(section->type) + 1);
|
||||||
// Otherwise there is overlap with another section
|
// Otherwise there is overlap with another section
|
||||||
else
|
else
|
||||||
errx("Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"",
|
errx("Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"",
|
||||||
section->name, sectionTypeInfo[section->type].name.c_str(), where,
|
section->name->c_str(), sectionTypeInfo[section->type].name.c_str(), where,
|
||||||
out_OverlappingSection(section)->name);
|
out_OverlappingSection(section)->name->c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BANK_CONSTRAINED (1 << 2)
|
#define BANK_CONSTRAINED (1 << 2)
|
||||||
@@ -396,7 +396,7 @@ void assign_AssignSections(void)
|
|||||||
constraints >= 0; constraints--) {
|
constraints >= 0; constraints--) {
|
||||||
for (struct Section *section : unassignedSections[constraints]) {
|
for (struct Section *section : unassignedSections[constraints]) {
|
||||||
fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';': ',',
|
fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';': ',',
|
||||||
section->name);
|
section->name->c_str());
|
||||||
nbSections++;
|
nbSections++;
|
||||||
if (nbSections == 10)
|
if (nbSections == 10)
|
||||||
goto max_out;
|
goto max_out;
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ FILE *linkerScript;
|
|||||||
static uint32_t nbErrors = 0;
|
static uint32_t nbErrors = 0;
|
||||||
|
|
||||||
// Helper function to dump a file stack to stderr
|
// Helper function to dump a file stack to stderr
|
||||||
char const *dumpFileStack(struct FileStackNode const *node)
|
std::string const *dumpFileStack(struct FileStackNode const *node)
|
||||||
{
|
{
|
||||||
char const *lastName;
|
std::string const *lastName;
|
||||||
|
|
||||||
if (node->parent) {
|
if (node->parent) {
|
||||||
lastName = dumpFileStack(node->parent);
|
lastName = dumpFileStack(node->parent);
|
||||||
// REPT nodes use their parent's name
|
// REPT nodes use their parent's name
|
||||||
if (node->type != NODE_REPT)
|
if (node->type != NODE_REPT)
|
||||||
lastName = node->name;
|
lastName = node->name;
|
||||||
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName);
|
fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str());
|
||||||
if (node->type == NODE_REPT) {
|
if (node->type == NODE_REPT) {
|
||||||
for (uint32_t iter : *node->iters)
|
for (uint32_t iter : *node->iters)
|
||||||
fprintf(stderr, "::REPT~%" PRIu32, iter);
|
fprintf(stderr, "::REPT~%" PRIu32, iter);
|
||||||
@@ -66,7 +66,7 @@ char const *dumpFileStack(struct FileStackNode const *node)
|
|||||||
} else {
|
} else {
|
||||||
assert(node->type != NODE_REPT);
|
assert(node->type != NODE_REPT);
|
||||||
lastName = node->name;
|
lastName = node->name;
|
||||||
fputs(lastName, stderr);
|
fputs(lastName->c_str(), stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lastName;
|
return lastName;
|
||||||
|
|||||||
@@ -102,37 +102,25 @@ static int64_t readlong(FILE *file)
|
|||||||
* @return The string read, or NULL on failure.
|
* @return The string read, or NULL on failure.
|
||||||
* If a non-NULL pointer is returned, make sure to `free` it when done!
|
* If a non-NULL pointer is returned, make sure to `free` it when done!
|
||||||
*/
|
*/
|
||||||
static char *readstr(FILE *file)
|
static std::string *readstring(FILE *file)
|
||||||
{
|
{
|
||||||
// Default buffer size, have it close to the average string length
|
std::string *str = new(std::nothrow) std::string();
|
||||||
size_t capacity = 32 / 2;
|
|
||||||
size_t index = -1;
|
|
||||||
// Force the first iteration to allocate
|
|
||||||
char *str = NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// Prepare going to next char
|
|
||||||
index++;
|
|
||||||
|
|
||||||
// If the buffer isn't suitable to write the next char...
|
|
||||||
if (index >= capacity || !str) {
|
|
||||||
capacity *= 2;
|
|
||||||
str = (char *)realloc(str, capacity);
|
|
||||||
// End now in case of error
|
|
||||||
if (!str)
|
if (!str)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
for (;;) {
|
||||||
|
|
||||||
// Read char
|
// Read char
|
||||||
int byte = getc(file);
|
int byte = getc(file);
|
||||||
|
|
||||||
if (byte == EOF) {
|
if (byte == EOF) {
|
||||||
free(str);
|
delete str;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
} else if (byte == '\0') {
|
||||||
str[index] = byte;
|
|
||||||
} while (str[index]);
|
|
||||||
return str;
|
return str;
|
||||||
|
} else {
|
||||||
|
str->push_back(byte);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -143,8 +131,8 @@ static char *readstr(FILE *file)
|
|||||||
* @param ... A format string and related arguments; note that an extra string
|
* @param ... A format string and related arguments; note that an extra string
|
||||||
* argument is provided, the reason for failure
|
* argument is provided, the reason for failure
|
||||||
*/
|
*/
|
||||||
#define tryReadstr(var, file, ...) \
|
#define tryReadstring(var, file, ...) \
|
||||||
tryRead(readstr, char *, NULL, char *, var, file, __VA_ARGS__)
|
tryRead(readstring, std::string *, NULL, std::string *, var, file, __VA_ARGS__)
|
||||||
|
|
||||||
// Functions to parse object files
|
// Functions to parse object files
|
||||||
|
|
||||||
@@ -171,7 +159,7 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
|
|||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case NODE_FILE:
|
case NODE_FILE:
|
||||||
case NODE_MACRO:
|
case NODE_MACRO:
|
||||||
tryReadstr(node.name, file,
|
tryReadstring(node.name, file,
|
||||||
"%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i);
|
"%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -203,28 +191,23 @@ static void readFileStackNode(FILE *file, std::vector<struct FileStackNode> &fil
|
|||||||
static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName,
|
static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName,
|
||||||
std::vector<struct FileStackNode> const &fileNodes)
|
std::vector<struct FileStackNode> const &fileNodes)
|
||||||
{
|
{
|
||||||
tryReadstr(symbol->name, file, "%s: Cannot read symbol name: %s",
|
tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName);
|
||||||
fileName);
|
|
||||||
tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s",
|
tryGetc(enum ExportLevel, symbol->type, file, "%s: Cannot read \"%s\"'s type: %s",
|
||||||
fileName, symbol->name);
|
fileName, symbol->name->c_str());
|
||||||
// If the symbol is defined in this file, read its definition
|
// If the symbol is defined in this file, read its definition
|
||||||
if (symbol->type != SYMTYPE_IMPORT) {
|
if (symbol->type != SYMTYPE_IMPORT) {
|
||||||
symbol->objFileName = fileName;
|
symbol->objFileName = fileName;
|
||||||
uint32_t nodeID;
|
uint32_t nodeID;
|
||||||
|
|
||||||
tryReadlong(nodeID, file,
|
tryReadlong(nodeID, file, "%s: Cannot read \"%s\"'s node ID: %s",
|
||||||
"%s: Cannot read \"%s\"'s node ID: %s",
|
fileName, symbol->name->c_str());
|
||||||
fileName, symbol->name);
|
|
||||||
symbol->src = &fileNodes[nodeID];
|
symbol->src = &fileNodes[nodeID];
|
||||||
tryReadlong(symbol->lineNo, file,
|
tryReadlong(symbol->lineNo, file, "%s: Cannot read \"%s\"'s line number: %s",
|
||||||
"%s: Cannot read \"%s\"'s line number: %s",
|
fileName, symbol->name->c_str());
|
||||||
fileName, symbol->name);
|
tryReadlong(symbol->sectionID, file, "%s: Cannot read \"%s\"'s section ID: %s",
|
||||||
tryReadlong(symbol->sectionID, file,
|
fileName, symbol->name->c_str());
|
||||||
"%s: Cannot read \"%s\"'s section ID: %s",
|
tryReadlong(symbol->offset, file, "%s: Cannot read \"%s\"'s value: %s",
|
||||||
fileName, symbol->name);
|
fileName, symbol->name->c_str());
|
||||||
tryReadlong(symbol->offset, file,
|
|
||||||
"%s: Cannot read \"%s\"'s value: %s",
|
|
||||||
fileName, symbol->name);
|
|
||||||
} else {
|
} else {
|
||||||
symbol->sectionID = -1;
|
symbol->sectionID = -1;
|
||||||
}
|
}
|
||||||
@@ -298,17 +281,14 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
int32_t tmp;
|
int32_t tmp;
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
|
|
||||||
tryReadstr(section->name, file, "%s: Cannot read section name: %s",
|
tryReadstring(section->name, file, "%s: Cannot read section name: %s", fileName);
|
||||||
fileName);
|
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section->name->c_str());
|
||||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s",
|
|
||||||
fileName, section->name);
|
|
||||||
if (tmp < 0 || tmp > UINT16_MAX)
|
if (tmp < 0 || tmp > UINT16_MAX)
|
||||||
errx("\"%s\"'s section size (%" PRId32 ") is invalid",
|
errx("\"%s\"'s section size (%" PRId32 ") is invalid", section->name->c_str(), tmp);
|
||||||
section->name, tmp);
|
|
||||||
section->size = tmp;
|
section->size = tmp;
|
||||||
section->offset = 0;
|
section->offset = 0;
|
||||||
tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s type: %s",
|
tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s type: %s", fileName,
|
||||||
fileName, section->name);
|
section->name->c_str());
|
||||||
section->type = (enum SectionType)(byte & 0x3F);
|
section->type = (enum SectionType)(byte & 0x3F);
|
||||||
if (byte >> 7)
|
if (byte >> 7)
|
||||||
section->modifier = SECTION_UNION;
|
section->modifier = SECTION_UNION;
|
||||||
@@ -316,30 +296,27 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
section->modifier = SECTION_FRAGMENT;
|
section->modifier = SECTION_FRAGMENT;
|
||||||
else
|
else
|
||||||
section->modifier = SECTION_NORMAL;
|
section->modifier = SECTION_NORMAL;
|
||||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s",
|
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", fileName, section->name->c_str());
|
||||||
fileName, section->name);
|
|
||||||
section->isAddressFixed = tmp >= 0;
|
section->isAddressFixed = tmp >= 0;
|
||||||
if (tmp > UINT16_MAX) {
|
if (tmp > UINT16_MAX) {
|
||||||
error(NULL, 0, "\"%s\"'s org is too large (%" PRId32 ")",
|
error(NULL, 0, "\"%s\"'s org is too large (%" PRId32 ")", section->name->c_str(), tmp);
|
||||||
section->name, tmp);
|
|
||||||
tmp = UINT16_MAX;
|
tmp = UINT16_MAX;
|
||||||
}
|
}
|
||||||
section->org = tmp;
|
section->org = tmp;
|
||||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s",
|
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s", fileName, section->name->c_str());
|
||||||
fileName, section->name);
|
|
||||||
section->isBankFixed = tmp >= 0;
|
section->isBankFixed = tmp >= 0;
|
||||||
section->bank = tmp;
|
section->bank = tmp;
|
||||||
tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s alignment: %s",
|
tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s alignment: %s", fileName,
|
||||||
fileName, section->name);
|
section->name->c_str());
|
||||||
if (byte > 16)
|
if (byte > 16)
|
||||||
byte = 16;
|
byte = 16;
|
||||||
section->isAlignFixed = byte != 0;
|
section->isAlignFixed = byte != 0;
|
||||||
section->alignMask = (1 << byte) - 1;
|
section->alignMask = (1 << byte) - 1;
|
||||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s",
|
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s", fileName,
|
||||||
fileName, section->name);
|
section->name->c_str());
|
||||||
if (tmp > UINT16_MAX) {
|
if (tmp > UINT16_MAX) {
|
||||||
error(NULL, 0, "\"%s\"'s alignment offset is too large (%" PRId32 ")",
|
error(NULL, 0, "\"%s\"'s alignment offset is too large (%" PRId32 ")",
|
||||||
section->name, tmp);
|
section->name->c_str(), tmp);
|
||||||
tmp = UINT16_MAX;
|
tmp = UINT16_MAX;
|
||||||
}
|
}
|
||||||
section->alignOfs = tmp;
|
section->alignOfs = tmp;
|
||||||
@@ -347,26 +324,27 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
if (sect_HasData(section->type)) {
|
if (sect_HasData(section->type)) {
|
||||||
section->data = new(std::nothrow) std::vector<uint8_t>(section->size);
|
section->data = new(std::nothrow) std::vector<uint8_t>(section->size);
|
||||||
if (!section->data)
|
if (!section->data)
|
||||||
err("%s: Unable to read \"%s\"'s data", fileName, section->name);
|
err("%s: Unable to read \"%s\"'s data", fileName, section->name->c_str());
|
||||||
if (section->size) {
|
if (section->size) {
|
||||||
if (size_t nbRead = fread(&(*section->data)[0], 1, section->size, file);
|
if (size_t nbRead = fread(&(*section->data)[0], 1, section->size, file);
|
||||||
nbRead != section->size)
|
nbRead != section->size)
|
||||||
errx("%s: Cannot read \"%s\"'s data: %s", fileName, section->name,
|
errx("%s: Cannot read \"%s\"'s data: %s", fileName, section->name->c_str(),
|
||||||
feof(file) ? "Unexpected end of file" : strerror(errno));
|
feof(file) ? "Unexpected end of file" : strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t nbPatches;
|
uint32_t nbPatches;
|
||||||
|
|
||||||
tryReadlong(nbPatches, file,
|
tryReadlong(nbPatches, file,
|
||||||
"%s: Cannot read \"%s\"'s number of patches: %s",
|
"%s: Cannot read \"%s\"'s number of patches: %s", fileName,
|
||||||
fileName, section->name);
|
section->name->c_str());
|
||||||
|
|
||||||
section->patches = new(std::nothrow) std::vector<struct Patch>();
|
section->patches = new(std::nothrow) std::vector<struct Patch>();
|
||||||
if (!section->patches)
|
if (!section->patches)
|
||||||
err("%s: Unable to read \"%s\"'s patches", fileName, section->name);
|
err("%s: Unable to read \"%s\"'s patches", fileName, section->name->c_str());
|
||||||
section->patches->resize(nbPatches);
|
section->patches->resize(nbPatches);
|
||||||
for (uint32_t i = 0; i < nbPatches; i++)
|
for (uint32_t i = 0; i < nbPatches; i++)
|
||||||
readPatch(file, &(*section->patches)[i], fileName, section->name, i, fileNodes);
|
readPatch(file, &(*section->patches)[i], fileName, section->name->c_str(),
|
||||||
|
i, fileNodes);
|
||||||
} else {
|
} else {
|
||||||
section->data = NULL; // `mergeSections()` expects to be able to always read the ptr
|
section->data = NULL; // `mergeSections()` expects to be able to always read the ptr
|
||||||
}
|
}
|
||||||
@@ -399,8 +377,7 @@ static void linkSymToSect(struct Symbol &symbol, struct Section *section)
|
|||||||
* @param assert The struct to fill
|
* @param assert The struct to fill
|
||||||
* @param fileName The filename to report in errors
|
* @param fileName The filename to report in errors
|
||||||
*/
|
*/
|
||||||
static void readAssertion(FILE *file, struct Assertion *assert,
|
static void readAssertion(FILE *file, struct Assertion *assert, char const *fileName, uint32_t i,
|
||||||
char const *fileName, uint32_t i,
|
|
||||||
std::vector<struct FileStackNode> const &fileNodes)
|
std::vector<struct FileStackNode> const &fileNodes)
|
||||||
{
|
{
|
||||||
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
char assertName[sizeof("Assertion #4294967295")]; // UINT32_MAX
|
||||||
@@ -408,14 +385,13 @@ static void readAssertion(FILE *file, struct Assertion *assert,
|
|||||||
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
snprintf(assertName, sizeof(assertName), "Assertion #%" PRIu32, i);
|
||||||
|
|
||||||
readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes);
|
readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes);
|
||||||
tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s",
|
tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName);
|
||||||
fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Section *getMainSection(struct Section *section)
|
static struct Section *getMainSection(struct Section *section)
|
||||||
{
|
{
|
||||||
if (section->modifier != SECTION_NORMAL)
|
if (section->modifier != SECTION_NORMAL)
|
||||||
section = sect_GetSection(section->name);
|
section = sect_GetSection(*section->name);
|
||||||
|
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
@@ -453,7 +429,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
|
|
||||||
where.parent = NULL;
|
where.parent = NULL;
|
||||||
where.type = NODE_FILE;
|
where.type = NODE_FILE;
|
||||||
where.name = strdup(fileName);
|
where.name = new(std::nothrow) std::string(fileName);
|
||||||
if (!where.name)
|
if (!where.name)
|
||||||
fatal(NULL, 0, "Failed to duplicate \"%s\"'s name: %s", fileName, strerror(errno));
|
fatal(NULL, 0, "Failed to duplicate \"%s\"'s name: %s", fileName, strerror(errno));
|
||||||
|
|
||||||
@@ -599,7 +575,7 @@ static void freeNode(struct FileStackNode &node)
|
|||||||
if (node.type == NODE_REPT)
|
if (node.type == NODE_REPT)
|
||||||
delete node.iters;
|
delete node.iters;
|
||||||
else
|
else
|
||||||
free(node.name);
|
delete node.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void freeSection(struct Section *section)
|
static void freeSection(struct Section *section)
|
||||||
@@ -607,7 +583,7 @@ static void freeSection(struct Section *section)
|
|||||||
do {
|
do {
|
||||||
struct Section *next = section->nextu;
|
struct Section *next = section->nextu;
|
||||||
|
|
||||||
free(section->name);
|
delete section->name;
|
||||||
if (sect_HasData(section->type)) {
|
if (sect_HasData(section->type)) {
|
||||||
delete section->data;
|
delete section->data;
|
||||||
delete section->patches;
|
delete section->patches;
|
||||||
@@ -633,9 +609,9 @@ void obj_Cleanup(void)
|
|||||||
|
|
||||||
for (std::vector<struct Symbol> &fileSymbols : symbolLists) {
|
for (std::vector<struct Symbol> &fileSymbols : symbolLists) {
|
||||||
for (struct Symbol &symbol : fileSymbols)
|
for (struct Symbol &symbol : fileSymbols)
|
||||||
free(symbol.name);
|
delete symbol.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (struct Assertion &assert : assertions)
|
for (struct Assertion &assert : assertions)
|
||||||
free(assert.message);
|
delete assert.message;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void out_AddSection(struct Section const *section)
|
|||||||
|
|
||||||
if (minNbBanks > maxNbBanks[section->type])
|
if (minNbBanks > maxNbBanks[section->type])
|
||||||
errx("Section \"%s\" has an invalid bank range (%" PRIu32 " > %" PRIu32 ")",
|
errx("Section \"%s\" has an invalid bank range (%" PRIu32 " > %" PRIu32 ")",
|
||||||
section->name, section->bank,
|
section->name->c_str(), section->bank,
|
||||||
maxNbBanks[section->type] - 1);
|
maxNbBanks[section->type] - 1);
|
||||||
|
|
||||||
for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++)
|
for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++)
|
||||||
@@ -293,19 +293,19 @@ static int compareSymbols(struct SortedSymbol const &sym1, struct SortedSymbol c
|
|||||||
if (sym1.addr != sym2.addr)
|
if (sym1.addr != sym2.addr)
|
||||||
return sym1.addr < sym2.addr ? -1 : 1;
|
return sym1.addr < sym2.addr ? -1 : 1;
|
||||||
|
|
||||||
char const *sym1_name = sym1.sym->name;
|
std::string const *sym1_name = sym1.sym->name;
|
||||||
char const *sym2_name = sym2.sym->name;
|
std::string const *sym2_name = sym2.sym->name;
|
||||||
bool sym1_local = strchr(sym1_name, '.');
|
bool sym1_local = sym1_name->find(".") != std::string::npos;
|
||||||
bool sym2_local = strchr(sym2_name, '.');
|
bool sym2_local = sym2_name->find(".") != std::string::npos;
|
||||||
|
|
||||||
if (sym1_local != sym2_local) {
|
if (sym1_local != sym2_local) {
|
||||||
size_t sym1_len = strlen(sym1_name);
|
size_t sym1_len = sym1_name->length();
|
||||||
size_t sym2_len = strlen(sym2_name);
|
size_t sym2_len = sym2_name->length();
|
||||||
|
|
||||||
// Sort parent labels before their child local labels
|
// Sort parent labels before their child local labels
|
||||||
if (!strncmp(sym1_name, sym2_name, sym1_len) && sym2_name[sym1_len] == '.')
|
if (sym2_name->starts_with(*sym1_name) && (*sym2_name)[sym1_len] == '.')
|
||||||
return -1;
|
return -1;
|
||||||
if (!strncmp(sym2_name, sym1_name, sym2_len) && sym1_name[sym2_len] == '.')
|
if (sym1_name->starts_with(*sym2_name) && (*sym1_name)[sym2_len] == '.')
|
||||||
return 1;
|
return 1;
|
||||||
// Sort local labels before unrelated global labels
|
// Sort local labels before unrelated global labels
|
||||||
return sym1_local ? -1 : 1;
|
return sym1_local ? -1 : 1;
|
||||||
@@ -348,7 +348,7 @@ static void writeSymBank(struct SortedSections const &bankSections,
|
|||||||
forEachSortedSection(sect, {
|
forEachSortedSection(sect, {
|
||||||
for (struct Symbol const *sym : *sect->symbols) {
|
for (struct Symbol const *sym : *sect->symbols) {
|
||||||
// Don't output symbols that begin with an illegal character
|
// Don't output symbols that begin with an illegal character
|
||||||
if (canStartSymName(sym->name[0]))
|
if (!sym->name->empty() && canStartSymName((*sym->name)[0]))
|
||||||
symList.push_back({ .sym = sym, .addr = (uint16_t)(sym->offset + sect->org) });
|
symList.push_back({ .sym = sym, .addr = (uint16_t)(sym->offset + sect->org) });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -361,7 +361,7 @@ static void writeSymBank(struct SortedSections const &bankSections,
|
|||||||
|
|
||||||
for (struct SortedSymbol &sym : symList) {
|
for (struct SortedSymbol &sym : symList) {
|
||||||
fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr);
|
fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr);
|
||||||
printSymName(sym.sym->name);
|
printSymName(sym.sym->name->c_str());
|
||||||
putc('\n', symFile);
|
putc('\n', symFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -407,21 +407,19 @@ static void writeMapBank(struct SortedSections const §List, enum SectionType
|
|||||||
if (sect->size != 0)
|
if (sect->size != 0)
|
||||||
fprintf(mapFile, "\tSECTION: $%04" PRIx16 "-$%04x ($%04" PRIx16
|
fprintf(mapFile, "\tSECTION: $%04" PRIx16 "-$%04x ($%04" PRIx16
|
||||||
" byte%s) [\"%s\"]\n",
|
" byte%s) [\"%s\"]\n",
|
||||||
sect->org, prevEndAddr - 1,
|
sect->org, prevEndAddr - 1, sect->size, sect->size == 1 ? "" : "s",
|
||||||
sect->size, sect->size == 1 ? "" : "s",
|
sect->name->c_str());
|
||||||
sect->name);
|
|
||||||
else
|
else
|
||||||
fprintf(mapFile, "\tSECTION: $%04" PRIx16 " (0 bytes) [\"%s\"]\n",
|
fprintf(mapFile, "\tSECTION: $%04" PRIx16 " (0 bytes) [\"%s\"]\n",
|
||||||
sect->org, sect->name);
|
sect->org, sect->name->c_str());
|
||||||
|
|
||||||
if (!noSymInMap) {
|
if (!noSymInMap) {
|
||||||
uint16_t org = sect->org;
|
// Also print symbols in the following "pieces"
|
||||||
|
for (uint16_t org = sect->org; sect; sect = sect->nextu) {
|
||||||
while (sect) {
|
|
||||||
for (struct Symbol *sym : *sect->symbols)
|
for (struct Symbol *sym : *sect->symbols)
|
||||||
// Space matches "\tSECTION: $xxxx ..."
|
// Space matches "\tSECTION: $xxxx ..."
|
||||||
fprintf(mapFile, "\t $%04" PRIx32 " = %s\n",
|
fprintf(mapFile, "\t $%04" PRIx32 " = %s\n",
|
||||||
sym->offset + org, sym->name);
|
sym->offset + org, sym->name->c_str());
|
||||||
|
|
||||||
if (sect->nextu) {
|
if (sect->nextu) {
|
||||||
// Announce the following "piece"
|
// Announce the following "piece"
|
||||||
@@ -432,8 +430,6 @@ static void writeMapBank(struct SortedSections const §List, enum SectionType
|
|||||||
fprintf(mapFile,
|
fprintf(mapFile,
|
||||||
"\t ; Next fragment\n");
|
"\t ; Next fragment\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sect = sect->nextu; // Also print symbols in the following "pieces"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ static struct Symbol const *getSymbol(std::vector<struct Symbol> const &symbolLi
|
|||||||
|
|
||||||
// If the symbol is defined elsewhere...
|
// If the symbol is defined elsewhere...
|
||||||
if (symbol.type == SYMTYPE_IMPORT)
|
if (symbol.type == SYMTYPE_IMPORT)
|
||||||
return sym_GetSymbol(symbol.name);
|
return sym_GetSymbol(*symbol.name);
|
||||||
|
|
||||||
return &symbol;
|
return &symbol;
|
||||||
}
|
}
|
||||||
@@ -224,13 +224,13 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
if (!symbol) {
|
if (!symbol) {
|
||||||
error(patch->src, patch->lineNo,
|
error(patch->src, patch->lineNo,
|
||||||
"Requested BANK() of symbol \"%s\", which was not found",
|
"Requested BANK() of symbol \"%s\", which was not found",
|
||||||
fileSymbols[value].name);
|
fileSymbols[value].name->c_str());
|
||||||
isError = true;
|
isError = true;
|
||||||
value = 1;
|
value = 1;
|
||||||
} else if (!symbol->section) {
|
} else if (!symbol->section) {
|
||||||
error(patch->src, patch->lineNo,
|
error(patch->src, patch->lineNo,
|
||||||
"Requested BANK() of non-label symbol \"%s\"",
|
"Requested BANK() of non-label symbol \"%s\"",
|
||||||
fileSymbols[value].name);
|
fileSymbols[value].name->c_str());
|
||||||
isError = true;
|
isError = true;
|
||||||
value = 1;
|
value = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -385,7 +385,7 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
|
|
||||||
if (!symbol) {
|
if (!symbol) {
|
||||||
error(patch->src, patch->lineNo,
|
error(patch->src, patch->lineNo,
|
||||||
"Unknown symbol \"%s\"", fileSymbols[value].name);
|
"Unknown symbol \"%s\"", fileSymbols[value].name->c_str());
|
||||||
isError = true;
|
isError = true;
|
||||||
} else {
|
} else {
|
||||||
value = symbol->value;
|
value = symbol->value;
|
||||||
@@ -422,24 +422,24 @@ void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case ASSERT_FATAL:
|
case ASSERT_FATAL:
|
||||||
fatal(assert.patch.src, assert.patch.lineNo, "%s",
|
fatal(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert.message[0] ? assert.message
|
!assert.message->empty() ? assert.message->c_str()
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
case ASSERT_ERROR:
|
case ASSERT_ERROR:
|
||||||
error(assert.patch.src, assert.patch.lineNo, "%s",
|
error(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert.message[0] ? assert.message
|
!assert.message->empty() ? assert.message->c_str()
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
break;
|
break;
|
||||||
case ASSERT_WARN:
|
case ASSERT_WARN:
|
||||||
warning(assert.patch.src, assert.patch.lineNo, "%s",
|
warning(assert.patch.src, assert.patch.lineNo, "%s",
|
||||||
assert.message[0] ? assert.message
|
!assert.message->empty() ? assert.message->c_str()
|
||||||
: "assert failure");
|
: "assert failure");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (isError && type == ASSERT_FATAL) {
|
} else if (isError && type == ASSERT_FATAL) {
|
||||||
fatal(assert.patch.src, assert.patch.lineNo,
|
fatal(assert.patch.src, assert.patch.lineNo,
|
||||||
"Failed to evaluate assertion%s%s",
|
"Failed to evaluate assertion%s%s",
|
||||||
assert.message[0] ? ": " : "",
|
!assert.message->empty() ? ": " : "",
|
||||||
assert.message);
|
assert.message->c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,7 +451,7 @@ void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
|
|||||||
*/
|
*/
|
||||||
static void applyFilePatches(struct Section *section, struct Section *dataSection)
|
static void applyFilePatches(struct Section *section, struct Section *dataSection)
|
||||||
{
|
{
|
||||||
verbosePrint("Patching section \"%s\"...\n", section->name);
|
verbosePrint("Patching section \"%s\"...\n", section->name->c_str());
|
||||||
for (struct Patch &patch : *section->patches) {
|
for (struct Patch &patch : *section->patches) {
|
||||||
int32_t value = computeRPNExpr(&patch, *section->fileSymbols);
|
int32_t value = computeRPNExpr(&patch, *section->fileSymbols);
|
||||||
uint16_t offset = patch.offset + section->offset;
|
uint16_t offset = patch.offset + section->offset;
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
||||||
// The following is required for fragment offsets to be reliably predicted
|
// The following is required for fragment offsets to be reliably predicted
|
||||||
for (size_t i = 0; i < nbSections; ++i) {
|
for (size_t i = 0; i < nbSections; ++i) {
|
||||||
if (!strcmp(token, fileSections[i].section->name))
|
if (!strcmp(token, fileSections[i].section->name->c_str()))
|
||||||
fatal(where, lineNo, "Area \"%s\" already defined earlier",
|
fatal(where, lineNo, "Area \"%s\" already defined earlier",
|
||||||
token);
|
token);
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
|
|
||||||
if (tmp > UINT16_MAX)
|
if (tmp > UINT16_MAX)
|
||||||
fatal(where, lineNo, "Area \"%s\" is larger than the GB address space!?",
|
fatal(where, lineNo, "Area \"%s\" is larger than the GB address space!?",
|
||||||
curSection->name);
|
curSection->name->c_str());
|
||||||
curSection->size = tmp;
|
curSection->size = tmp;
|
||||||
|
|
||||||
expectToken("flags", 'A');
|
expectToken("flags", 'A');
|
||||||
@@ -295,21 +295,16 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
curSection->isBankFixed = curSection->isAddressFixed;
|
curSection->isBankFixed = curSection->isAddressFixed;
|
||||||
curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
|
curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
|
||||||
? SECTION_NORMAL : SECTION_FRAGMENT;
|
? SECTION_NORMAL : SECTION_FRAGMENT;
|
||||||
|
curSection->name = new(std::nothrow) std::string();
|
||||||
|
if (!curSection->name)
|
||||||
|
fatal(where, lineNo, "Failed to alloc new area's name: %s",
|
||||||
|
strerror(errno));
|
||||||
// If the section is absolute, its name might not be unique; thus, mangle the name
|
// If the section is absolute, its name might not be unique; thus, mangle the name
|
||||||
if (curSection->modifier == SECTION_NORMAL) {
|
if (curSection->modifier == SECTION_NORMAL) {
|
||||||
size_t len = strlen(where->name) + 1 + strlen(token);
|
curSection->name->append(*where->name);
|
||||||
|
curSection->name->append(" ");
|
||||||
curSection->name = (char *)malloc(len + 1);
|
|
||||||
if (!curSection->name)
|
|
||||||
fatal(where, lineNo, "Failed to alloc new area's name: %s",
|
|
||||||
strerror(errno));
|
|
||||||
sprintf(curSection->name, "%s %s", where->name, sectionName);
|
|
||||||
} else {
|
|
||||||
curSection->name = strdup(sectionName); // We need a pointer that will live longer
|
|
||||||
if (!curSection->name)
|
|
||||||
fatal(where, lineNo, "Failed to alloc new area's name: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
curSection->name->append(sectionName);
|
||||||
|
|
||||||
expectToken("addr", 'A');
|
expectToken("addr", 'A');
|
||||||
|
|
||||||
@@ -372,7 +367,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
struct Symbol &symbol = fileSymbols.emplace_back();
|
struct Symbol &symbol = fileSymbols.emplace_back();
|
||||||
|
|
||||||
// Init other members
|
// Init other members
|
||||||
symbol.objFileName = where->name;
|
symbol.objFileName = where->name->c_str();
|
||||||
symbol.src = where;
|
symbol.src = where;
|
||||||
symbol.lineNo = lineNo;
|
symbol.lineNo = lineNo;
|
||||||
|
|
||||||
@@ -380,7 +375,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
symbol.section = nbSections != 0 ? fileSections[nbSections - 1].section : NULL;
|
symbol.section = nbSections != 0 ? fileSections[nbSections - 1].section : NULL;
|
||||||
|
|
||||||
getToken(line, "'S' line is too short");
|
getToken(line, "'S' line is too short");
|
||||||
symbol.name = strdup(token);
|
symbol.name = new(std::nothrow) std::string(token);
|
||||||
if (!symbol.name)
|
if (!symbol.name)
|
||||||
fatal(where, lineNo, "Failed to alloc symbol name: %s", strerror(errno));
|
fatal(where, lineNo, "Failed to alloc symbol name: %s", strerror(errno));
|
||||||
|
|
||||||
@@ -402,7 +397,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
} else {
|
} else {
|
||||||
// All symbols are exported
|
// All symbols are exported
|
||||||
symbol.type = SYMTYPE_EXPORT;
|
symbol.type = SYMTYPE_EXPORT;
|
||||||
struct Symbol const *other = sym_GetSymbol(symbol.name);
|
struct Symbol const *other = sym_GetSymbol(*symbol.name);
|
||||||
|
|
||||||
if (other) {
|
if (other) {
|
||||||
// The same symbol can only be defined twice if neither
|
// The same symbol can only be defined twice if neither
|
||||||
@@ -413,7 +408,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
} else if (other->value != symbol.value) {
|
} else if (other->value != symbol.value) {
|
||||||
error(where, lineNo,
|
error(where, lineNo,
|
||||||
"Definition of \"%s\" conflicts with definition in %s (%" PRId32 " != %" PRId32 ")",
|
"Definition of \"%s\" conflicts with definition in %s (%" PRId32 " != %" PRId32 ")",
|
||||||
symbol.name, other->objFileName, symbol.value, other->value);
|
symbol.name->c_str(), other->objFileName, symbol.value, other->value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Add a new definition
|
// Add a new definition
|
||||||
@@ -485,7 +480,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
if (section->isAddressFixed) {
|
if (section->isAddressFixed) {
|
||||||
if (addr < section->org)
|
if (addr < section->org)
|
||||||
fatal(where, lineNo, "'T' line reports address $%04" PRIx16 " in \"%s\", which starts at $%04" PRIx16,
|
fatal(where, lineNo, "'T' line reports address $%04" PRIx16 " in \"%s\", which starts at $%04" PRIx16,
|
||||||
addr, section->name, section->org);
|
addr, section->name->c_str(), section->org);
|
||||||
addr -= section->org;
|
addr -= section->org;
|
||||||
}
|
}
|
||||||
// Lines are emitted that violate this check but contain no "payload";
|
// Lines are emitted that violate this check but contain no "payload";
|
||||||
@@ -499,7 +494,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
section->data = new(std::nothrow) std::vector<uint8_t>(section->size);
|
section->data = new(std::nothrow) std::vector<uint8_t>(section->size);
|
||||||
if (!section->data)
|
if (!section->data)
|
||||||
fatal(where, lineNo, "Failed to alloc data for \"%s\": %s",
|
fatal(where, lineNo, "Failed to alloc data for \"%s\": %s",
|
||||||
section->name, strerror(errno));
|
section->name->c_str(), strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,29 +578,30 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
// SDCC has a bunch of "magic symbols" that start with a
|
// SDCC has a bunch of "magic symbols" that start with a
|
||||||
// letter and an underscore. These are not compatibility
|
// letter and an underscore. These are not compatibility
|
||||||
// hacks, this is how SDLD actually works.
|
// hacks, this is how SDLD actually works.
|
||||||
if (sym.name[0] == 'b' && sym.name[1] == '_') {
|
if (sym.name->starts_with("b_")) {
|
||||||
// Look for the symbol being referenced, and use its index instead
|
// Look for the symbol being referenced, and use its index instead
|
||||||
for (idx = 0; idx < nbSymbols; ++idx) {
|
for (idx = 0; idx < nbSymbols; ++idx) {
|
||||||
if (strcmp(&sym.name[1], fileSymbols[idx].name) == 0)
|
if (sym.name->ends_with(*fileSymbols[idx].name) &&
|
||||||
|
1 + sym.name->length() == fileSymbols[idx].name->length())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (idx == nbSymbols)
|
if (idx == nbSymbols)
|
||||||
fatal(where, lineNo, "\"%s\" is missing a reference to \"%s\"",
|
fatal(where, lineNo, "\"%s\" is missing a reference to \"%s\"",
|
||||||
sym.name, &sym.name[1]);
|
sym.name->c_str(), &sym.name->c_str()[1]);
|
||||||
patch.rpnExpression.resize(5);
|
patch.rpnExpression.resize(5);
|
||||||
patch.rpnExpression[0] = RPN_BANK_SYM;
|
patch.rpnExpression[0] = RPN_BANK_SYM;
|
||||||
patch.rpnExpression[1] = idx;
|
patch.rpnExpression[1] = idx;
|
||||||
patch.rpnExpression[2] = idx >> 8;
|
patch.rpnExpression[2] = idx >> 8;
|
||||||
patch.rpnExpression[3] = idx >> 16;
|
patch.rpnExpression[3] = idx >> 16;
|
||||||
patch.rpnExpression[4] = idx >> 24;
|
patch.rpnExpression[4] = idx >> 24;
|
||||||
} else if (sym.name[0] == 'l' && sym.name[1] == '_') {
|
} else if (sym.name->starts_with("l_")) {
|
||||||
patch.rpnExpression.resize(1 + strlen(&sym.name[2]) + 1);
|
patch.rpnExpression.resize(1 + sym.name->length() - 2 + 1);
|
||||||
patch.rpnExpression[0] = RPN_SIZEOF_SECT;
|
patch.rpnExpression[0] = RPN_SIZEOF_SECT;
|
||||||
strcpy((char *)&patch.rpnExpression[1], &sym.name[2]);
|
memcpy((char *)&patch.rpnExpression[1], &sym.name->c_str()[2], sym.name->length() - 2 + 1);
|
||||||
} else if (sym.name[0] == 's' && sym.name[1] == '_') {
|
} else if (sym.name->starts_with("s_")) {
|
||||||
patch.rpnExpression.resize(1 + strlen(&sym.name[2]) + 1);
|
patch.rpnExpression.resize(1 + sym.name->length() - 2 + 1);
|
||||||
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
||||||
strcpy((char *)&patch.rpnExpression[1], &sym.name[2]);
|
memcpy((char *)&patch.rpnExpression[1], &sym.name->c_str()[2], sym.name->length() - 2 + 1);
|
||||||
} else {
|
} else {
|
||||||
patch.rpnExpression.resize(5);
|
patch.rpnExpression.resize(5);
|
||||||
patch.rpnExpression[0] = RPN_SYM;
|
patch.rpnExpression[0] = RPN_SYM;
|
||||||
@@ -627,8 +623,8 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
// the section gets moved for any reason.
|
// the section gets moved for any reason.
|
||||||
if (fileSections[idx].section->isAddressFixed)
|
if (fileSections[idx].section->isAddressFixed)
|
||||||
baseValue -= fileSections[idx].section->org;
|
baseValue -= fileSections[idx].section->org;
|
||||||
char const *name = fileSections[idx].section->name;
|
std::string const *name = fileSections[idx].section->name;
|
||||||
struct Section const *other = sect_GetSection(name);
|
struct Section const *other = sect_GetSection(*name);
|
||||||
|
|
||||||
// Unlike with `s_<AREA>`, referencing an area in this way
|
// Unlike with `s_<AREA>`, referencing an area in this way
|
||||||
// wants the beginning of this fragment, so we must add the
|
// wants the beginning of this fragment, so we must add the
|
||||||
@@ -640,10 +636,10 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
// current size.
|
// current size.
|
||||||
if (other)
|
if (other)
|
||||||
baseValue += other->size;
|
baseValue += other->size;
|
||||||
patch.rpnExpression.resize(1 + strlen(name) + 1);
|
patch.rpnExpression.resize(1 + name->length() + 1);
|
||||||
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
||||||
// The cast is fine, it's just different signedness
|
// The cast is fine, it's just different signedness
|
||||||
strcpy((char *)&patch.rpnExpression[1], name);
|
memcpy((char *)&patch.rpnExpression[1], name->c_str(), name->length() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
patch.rpnExpression.push_back(RPN_CONST);
|
patch.rpnExpression.push_back(RPN_CONST);
|
||||||
@@ -659,7 +655,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
if (flags & 1 << RELOC_EXPR16) {
|
if (flags & 1 << RELOC_EXPR16) {
|
||||||
if (*writeIndex + (offset - writtenOfs) > section->size)
|
if (*writeIndex + (offset - writtenOfs) > section->size)
|
||||||
fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")",
|
fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%u > %" PRIu16 ")",
|
||||||
section->name, *writeIndex + (offset - writtenOfs), section->size);
|
section->name->c_str(), *writeIndex + (offset - writtenOfs), section->size);
|
||||||
// Copy all bytes up to those (plus the byte that we'll overwrite)
|
// Copy all bytes up to those (plus the byte that we'll overwrite)
|
||||||
memcpy(&(*section->data)[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1);
|
memcpy(&(*section->data)[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1);
|
||||||
*writeIndex += offset - writtenOfs + 1;
|
*writeIndex += offset - writtenOfs + 1;
|
||||||
@@ -708,7 +704,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
assert(nbBytes > writtenOfs);
|
assert(nbBytes > writtenOfs);
|
||||||
if (*writeIndex + (nbBytes - writtenOfs) > section->size)
|
if (*writeIndex + (nbBytes - writtenOfs) > section->size)
|
||||||
fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")",
|
fatal(where, lineNo, "'T' line writes past \"%s\"'s end (%zu > %" PRIu16 ")",
|
||||||
section->name, *writeIndex + (nbBytes - writtenOfs), section->size);
|
section->name->c_str(), *writeIndex + (nbBytes - writtenOfs), section->size);
|
||||||
memcpy(&(*section->data)[*writeIndex], &data[writtenOfs], nbBytes - writtenOfs);
|
memcpy(&(*section->data)[*writeIndex], &data[writtenOfs], nbBytes - writtenOfs);
|
||||||
*writeIndex += nbBytes - writtenOfs;
|
*writeIndex += nbBytes - writtenOfs;
|
||||||
}
|
}
|
||||||
@@ -739,7 +735,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<s
|
|||||||
// RAM sections can have a size, but don't get any data (they shouldn't have any)
|
// RAM sections can have a size, but don't get any data (they shouldn't have any)
|
||||||
if (fileSections[i].writeIndex != section->size && fileSections[i].writeIndex != 0)
|
if (fileSections[i].writeIndex != section->size && fileSections[i].writeIndex != 0)
|
||||||
fatal(where, lineNo, "\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")",
|
fatal(where, lineNo, "\"%s\" was not fully written (%" PRIu16 " < %" PRIu16 ")",
|
||||||
section->name, fileSections[i].writeIndex, section->size);
|
section->name->c_str(), fileSections[i].writeIndex, section->size);
|
||||||
|
|
||||||
// This must be done last, so that `->data` is not NULL anymore
|
// This must be done last, so that `->data` is not NULL anymore
|
||||||
sect_AddSection(section);
|
sect_AddSection(section);
|
||||||
|
|||||||
@@ -27,14 +27,13 @@ static void checkSectUnionCompat(struct Section *target, struct Section *other)
|
|||||||
if (target->isAddressFixed) {
|
if (target->isAddressFixed) {
|
||||||
if (target->org != other->org)
|
if (target->org != other->org)
|
||||||
errx("Section \"%s\" is defined with conflicting addresses $%04"
|
errx("Section \"%s\" is defined with conflicting addresses $%04"
|
||||||
PRIx16 " and $%04" PRIx16,
|
PRIx16 " and $%04" PRIx16, other->name->c_str(), target->org,
|
||||||
other->name, target->org, other->org);
|
other->org);
|
||||||
} else if (target->isAlignFixed) {
|
} else if (target->isAlignFixed) {
|
||||||
if ((other->org - target->alignOfs) & target->alignMask)
|
if ((other->org - target->alignOfs) & target->alignMask)
|
||||||
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
||||||
PRIu16 ") and address $%04" PRIx16,
|
PRIu16 ") and address $%04" PRIx16, other->name->c_str(),
|
||||||
other->name, target->alignMask + 1,
|
target->alignMask + 1, target->alignOfs, other->org);
|
||||||
target->alignOfs, other->org);
|
|
||||||
}
|
}
|
||||||
target->isAddressFixed = true;
|
target->isAddressFixed = true;
|
||||||
target->org = other->org;
|
target->org = other->org;
|
||||||
@@ -44,14 +43,14 @@ static void checkSectUnionCompat(struct Section *target, struct Section *other)
|
|||||||
if ((target->org - other->alignOfs) & other->alignMask)
|
if ((target->org - other->alignOfs) & other->alignMask)
|
||||||
errx("Section \"%s\" is defined with conflicting address $%04"
|
errx("Section \"%s\" is defined with conflicting address $%04"
|
||||||
PRIx16 " and %d-byte alignment (offset %" PRIu16 ")",
|
PRIx16 " and %d-byte alignment (offset %" PRIu16 ")",
|
||||||
other->name, target->org,
|
other->name->c_str(), target->org, other->alignMask + 1,
|
||||||
other->alignMask + 1, other->alignOfs);
|
other->alignOfs);
|
||||||
} else if (target->isAlignFixed
|
} else if (target->isAlignFixed
|
||||||
&& (other->alignMask & target->alignOfs)
|
&& (other->alignMask & target->alignOfs)
|
||||||
!= (target->alignMask & other->alignOfs)) {
|
!= (target->alignMask & other->alignOfs)) {
|
||||||
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
||||||
PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")",
|
PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")",
|
||||||
other->name, target->alignMask + 1, target->alignOfs,
|
other->name->c_str(), target->alignMask + 1, target->alignOfs,
|
||||||
other->alignMask + 1, other->alignOfs);
|
other->alignMask + 1, other->alignOfs);
|
||||||
} else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) {
|
} else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) {
|
||||||
target->isAlignFixed = true;
|
target->isAlignFixed = true;
|
||||||
@@ -68,15 +67,14 @@ static void checkFragmentCompat(struct Section *target, struct Section *other)
|
|||||||
if (target->isAddressFixed) {
|
if (target->isAddressFixed) {
|
||||||
if (target->org != org)
|
if (target->org != org)
|
||||||
errx("Section \"%s\" is defined with conflicting addresses $%04"
|
errx("Section \"%s\" is defined with conflicting addresses $%04"
|
||||||
PRIx16 " and $%04" PRIx16,
|
PRIx16 " and $%04" PRIx16, other->name->c_str(), target->org,
|
||||||
other->name, target->org, other->org);
|
other->org);
|
||||||
|
|
||||||
} else if (target->isAlignFixed) {
|
} else if (target->isAlignFixed) {
|
||||||
if ((org - target->alignOfs) & target->alignMask)
|
if ((org - target->alignOfs) & target->alignMask)
|
||||||
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
||||||
PRIu16 ") and address $%04" PRIx16,
|
PRIu16 ") and address $%04" PRIx16, other->name->c_str(),
|
||||||
other->name, target->alignMask + 1,
|
target->alignMask + 1, target->alignOfs, other->org);
|
||||||
target->alignOfs, other->org);
|
|
||||||
}
|
}
|
||||||
target->isAddressFixed = true;
|
target->isAddressFixed = true;
|
||||||
target->org = org;
|
target->org = org;
|
||||||
@@ -91,14 +89,14 @@ static void checkFragmentCompat(struct Section *target, struct Section *other)
|
|||||||
if ((target->org - ofs) & other->alignMask)
|
if ((target->org - ofs) & other->alignMask)
|
||||||
errx("Section \"%s\" is defined with conflicting address $%04"
|
errx("Section \"%s\" is defined with conflicting address $%04"
|
||||||
PRIx16 " and %d-byte alignment (offset %" PRIu16 ")",
|
PRIx16 " and %d-byte alignment (offset %" PRIu16 ")",
|
||||||
other->name, target->org,
|
other->name->c_str(), target->org, other->alignMask + 1,
|
||||||
other->alignMask + 1, other->alignOfs);
|
other->alignOfs);
|
||||||
|
|
||||||
} else if (target->isAlignFixed
|
} else if (target->isAlignFixed
|
||||||
&& (other->alignMask & target->alignOfs) != (target->alignMask & ofs)) {
|
&& (other->alignMask & target->alignOfs) != (target->alignMask & ofs)) {
|
||||||
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %"
|
||||||
PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")",
|
PRIu16 ") and %d-byte alignment (offset %" PRIu16 ")",
|
||||||
other->name, target->alignMask + 1, target->alignOfs,
|
other->name->c_str(), target->alignMask + 1, target->alignOfs,
|
||||||
other->alignMask + 1, other->alignOfs);
|
other->alignMask + 1, other->alignOfs);
|
||||||
|
|
||||||
} else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) {
|
} else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) {
|
||||||
@@ -115,7 +113,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
|
|||||||
|
|
||||||
if (target->type != other->type)
|
if (target->type != other->type)
|
||||||
errx("Section \"%s\" is defined with conflicting types %s and %s",
|
errx("Section \"%s\" is defined with conflicting types %s and %s",
|
||||||
other->name, sectionTypeInfo[target->type].name.c_str(),
|
other->name->c_str(), sectionTypeInfo[target->type].name.c_str(),
|
||||||
sectionTypeInfo[other->type].name.c_str());
|
sectionTypeInfo[other->type].name.c_str());
|
||||||
|
|
||||||
if (other->isBankFixed) {
|
if (other->isBankFixed) {
|
||||||
@@ -124,7 +122,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
|
|||||||
target->bank = other->bank;
|
target->bank = other->bank;
|
||||||
} else if (target->bank != other->bank) {
|
} else if (target->bank != other->bank) {
|
||||||
errx("Section \"%s\" is defined with conflicting banks %" PRIu32 " and %"
|
errx("Section \"%s\" is defined with conflicting banks %" PRIu32 " and %"
|
||||||
PRIu32, other->name, target->bank, other->bank);
|
PRIu32, other->name->c_str(), target->bank, other->bank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,24 +171,24 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
|
|||||||
void sect_AddSection(struct Section *section)
|
void sect_AddSection(struct Section *section)
|
||||||
{
|
{
|
||||||
// Check if the section already exists
|
// Check if the section already exists
|
||||||
if (struct Section *other = sect_GetSection(section->name); other) {
|
if (struct Section *other = sect_GetSection(*section->name); other) {
|
||||||
if (section->modifier != other->modifier)
|
if (section->modifier != other->modifier)
|
||||||
errx("Section \"%s\" defined as %s and %s", section->name,
|
errx("Section \"%s\" defined as %s and %s", section->name->c_str(),
|
||||||
sectionModNames[section->modifier], sectionModNames[other->modifier]);
|
sectionModNames[section->modifier], sectionModNames[other->modifier]);
|
||||||
else if (section->modifier == SECTION_NORMAL)
|
else if (section->modifier == SECTION_NORMAL)
|
||||||
errx("Section name \"%s\" is already in use", section->name);
|
errx("Section name \"%s\" is already in use", section->name->c_str());
|
||||||
else
|
else
|
||||||
mergeSections(other, section, section->modifier);
|
mergeSections(other, section, section->modifier);
|
||||||
} else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) {
|
} else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) {
|
||||||
errx("Section \"%s\" is of type %s, which cannot be unionized",
|
errx("Section \"%s\" is of type %s, which cannot be unionized",
|
||||||
section->name, sectionTypeInfo[section->type].name.c_str());
|
section->name->c_str(), sectionTypeInfo[section->type].name.c_str());
|
||||||
} else {
|
} else {
|
||||||
// If not, add it
|
// If not, add it
|
||||||
sections[section->name] = section;
|
sections[*section->name] = section;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Section *sect_GetSection(char const *name)
|
struct Section *sect_GetSection(std::string const &name)
|
||||||
{
|
{
|
||||||
auto search = sections.find(name);
|
auto search = sections.find(name);
|
||||||
return search != sections.end() ? search->second : NULL;
|
return search != sections.end() ? search->second : NULL;
|
||||||
@@ -205,27 +203,27 @@ static void doSanityChecks(struct Section *section)
|
|||||||
{
|
{
|
||||||
// Sanity check the section's type
|
// Sanity check the section's type
|
||||||
if (section->type < 0 || section->type >= SECTTYPE_INVALID) {
|
if (section->type < 0 || section->type >= SECTTYPE_INVALID) {
|
||||||
error(NULL, 0, "Section \"%s\" has an invalid type", section->name);
|
error(NULL, 0, "Section \"%s\" has an invalid type", section->name->c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is32kMode && section->type == SECTTYPE_ROMX) {
|
if (is32kMode && section->type == SECTTYPE_ROMX) {
|
||||||
if (section->isBankFixed && section->bank != 1)
|
if (section->isBankFixed && section->bank != 1)
|
||||||
error(NULL, 0, "%s: ROMX sections must be in bank 1 (if any) with option -t",
|
error(NULL, 0, "%s: ROMX sections must be in bank 1 (if any) with option -t",
|
||||||
section->name);
|
section->name->c_str());
|
||||||
else
|
else
|
||||||
section->type = SECTTYPE_ROM0;
|
section->type = SECTTYPE_ROM0;
|
||||||
}
|
}
|
||||||
if (isWRA0Mode && section->type == SECTTYPE_WRAMX) {
|
if (isWRA0Mode && section->type == SECTTYPE_WRAMX) {
|
||||||
if (section->isBankFixed && section->bank != 1)
|
if (section->isBankFixed && section->bank != 1)
|
||||||
error(NULL, 0, "%s: WRAMX sections must be in bank 1 with options -w or -d",
|
error(NULL, 0, "%s: WRAMX sections must be in bank 1 with options -w or -d",
|
||||||
section->name);
|
section->name->c_str());
|
||||||
else
|
else
|
||||||
section->type = SECTTYPE_WRAM0;
|
section->type = SECTTYPE_WRAM0;
|
||||||
}
|
}
|
||||||
if (isDmgMode && section->type == SECTTYPE_VRAM && section->bank == 1)
|
if (isDmgMode && section->type == SECTTYPE_VRAM && section->bank == 1)
|
||||||
error(NULL, 0, "%s: VRAM bank 1 can't be used with option -d",
|
error(NULL, 0, "%s: VRAM bank 1 can't be used with option -d",
|
||||||
section->name);
|
section->name->c_str());
|
||||||
|
|
||||||
// Check if alignment is reasonable, this is important to avoid UB
|
// Check if alignment is reasonable, this is important to avoid UB
|
||||||
// An alignment of zero is equivalent to no alignment, basically
|
// An alignment of zero is equivalent to no alignment, basically
|
||||||
@@ -235,7 +233,8 @@ static void doSanityChecks(struct Section *section)
|
|||||||
// Too large an alignment may not be satisfiable
|
// Too large an alignment may not be satisfiable
|
||||||
if (section->isAlignFixed && (section->alignMask & sectionTypeInfo[section->type].startAddr))
|
if (section->isAlignFixed && (section->alignMask & sectionTypeInfo[section->type].startAddr))
|
||||||
error(NULL, 0, "%s: %s sections cannot be aligned to $%04x bytes",
|
error(NULL, 0, "%s: %s sections cannot be aligned to $%04x bytes",
|
||||||
section->name, sectionTypeInfo[section->type].name.c_str(), section->alignMask + 1);
|
section->name->c_str(), sectionTypeInfo[section->type].name.c_str(),
|
||||||
|
section->alignMask + 1);
|
||||||
|
|
||||||
uint32_t minbank = sectionTypeInfo[section->type].firstBank, maxbank = sectionTypeInfo[section->type].lastBank;
|
uint32_t minbank = sectionTypeInfo[section->type].firstBank, maxbank = sectionTypeInfo[section->type].lastBank;
|
||||||
|
|
||||||
@@ -243,13 +242,13 @@ static void doSanityChecks(struct Section *section)
|
|||||||
error(NULL, 0, minbank == maxbank
|
error(NULL, 0, minbank == maxbank
|
||||||
? "Cannot place section \"%s\" in bank %" PRIu32 ", it must be %" PRIu32
|
? "Cannot place section \"%s\" in bank %" PRIu32 ", it must be %" PRIu32
|
||||||
: "Cannot place section \"%s\" in bank %" PRIu32 ", it must be between %" PRIu32 " and %" PRIu32,
|
: "Cannot place section \"%s\" in bank %" PRIu32 ", it must be between %" PRIu32 " and %" PRIu32,
|
||||||
section->name, section->bank, minbank, maxbank);
|
section->name->c_str(), section->bank, minbank, maxbank);
|
||||||
|
|
||||||
// Check if section has a chance to be placed
|
// Check if section has a chance to be placed
|
||||||
if (section->size > sectionTypeInfo[section->type].size)
|
if (section->size > sectionTypeInfo[section->type].size)
|
||||||
error(NULL, 0, "Section \"%s\" is bigger than the max size for that type: $%"
|
error(NULL, 0, "Section \"%s\" is bigger than the max size for that type: $%"
|
||||||
PRIx16 " > $%" PRIx16,
|
PRIx16 " > $%" PRIx16,
|
||||||
section->name, section->size, sectionTypeInfo[section->type].size);
|
section->name->c_str(), section->size, sectionTypeInfo[section->type].size);
|
||||||
|
|
||||||
// Translate loose constraints to strong ones when they're equivalent
|
// Translate loose constraints to strong ones when they're equivalent
|
||||||
|
|
||||||
@@ -263,7 +262,7 @@ static void doSanityChecks(struct Section *section)
|
|||||||
if (section->isAlignFixed) {
|
if (section->isAlignFixed) {
|
||||||
if ((section->org & section->alignMask) != section->alignOfs)
|
if ((section->org & section->alignMask) != section->alignOfs)
|
||||||
error(NULL, 0, "Section \"%s\"'s fixed address doesn't match its alignment",
|
error(NULL, 0, "Section \"%s\"'s fixed address doesn't match its alignment",
|
||||||
section->name);
|
section->name->c_str());
|
||||||
section->isAlignFixed = false;
|
section->isAlignFixed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,12 +270,12 @@ static void doSanityChecks(struct Section *section)
|
|||||||
if (section->org < sectionTypeInfo[section->type].startAddr
|
if (section->org < sectionTypeInfo[section->type].startAddr
|
||||||
|| section->org > endaddr(section->type))
|
|| section->org > endaddr(section->type))
|
||||||
error(NULL, 0, "Section \"%s\"'s fixed address $%04" PRIx16 " is outside of range [$%04"
|
error(NULL, 0, "Section \"%s\"'s fixed address $%04" PRIx16 " is outside of range [$%04"
|
||||||
PRIx16 "; $%04" PRIx16 "]", section->name, section->org,
|
PRIx16 "; $%04" PRIx16 "]", section->name->c_str(), section->org,
|
||||||
sectionTypeInfo[section->type].startAddr, endaddr(section->type));
|
sectionTypeInfo[section->type].startAddr, endaddr(section->type));
|
||||||
|
|
||||||
if (section->org + section->size > endaddr(section->type) + 1)
|
if (section->org + section->size > endaddr(section->type) + 1)
|
||||||
error(NULL, 0, "Section \"%s\"'s end address $%04x is greater than last address $%04x",
|
error(NULL, 0, "Section \"%s\"'s end address $%04x is greater than last address $%04x",
|
||||||
section->name, section->org + section->size,
|
section->name->c_str(), section->org + section->size,
|
||||||
endaddr(section->type) + 1);
|
endaddr(section->type) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ std::map<std::string, struct Symbol *> symbols;
|
|||||||
void sym_AddSymbol(struct Symbol *symbol)
|
void sym_AddSymbol(struct Symbol *symbol)
|
||||||
{
|
{
|
||||||
// Check if the symbol already exists
|
// Check if the symbol already exists
|
||||||
if (struct Symbol *other = sym_GetSymbol(symbol->name); other) {
|
if (struct Symbol *other = sym_GetSymbol(*symbol->name); other) {
|
||||||
fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name, symbol->objFileName);
|
fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name->c_str(),
|
||||||
|
symbol->objFileName);
|
||||||
dumpFileStack(symbol->src);
|
dumpFileStack(symbol->src);
|
||||||
fprintf(stderr, "(%" PRIu32 ") and in %s from ",
|
fprintf(stderr, "(%" PRIu32 ") and in %s from ",
|
||||||
symbol->lineNo, other->objFileName);
|
symbol->lineNo, other->objFileName);
|
||||||
@@ -27,10 +28,10 @@ void sym_AddSymbol(struct Symbol *symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If not, add it
|
// If not, add it
|
||||||
symbols[symbol->name] = symbol;
|
symbols[*symbol->name] = symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Symbol *sym_GetSymbol(char const *name)
|
struct Symbol *sym_GetSymbol(std::string const &name)
|
||||||
{
|
{
|
||||||
auto search = symbols.find(name);
|
auto search = symbols.find(name);
|
||||||
return search != symbols.end() ? search->second : NULL;
|
return search != symbols.end() ? search->second : NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user