From 48b2e94aa31b5d750797c17268c2c61af38ead77 Mon Sep 17 00:00:00 2001 From: Rangi42 Date: Tue, 27 Feb 2024 18:59:38 -0500 Subject: [PATCH] Use `std::string` for symbol/section/node names and assertion messages --- include/link/main.hpp | 5 +- include/link/patch.hpp | 2 +- include/link/section.hpp | 5 +- include/link/symbol.hpp | 5 +- src/link/assign.cpp | 10 +-- src/link/main.cpp | 8 +-- src/link/object.cpp | 130 ++++++++++++++++----------------------- src/link/output.cpp | 38 +++++------- src/link/patch.cpp | 26 ++++---- src/link/sdas_obj.cpp | 68 ++++++++++---------- src/link/section.cpp | 67 ++++++++++---------- src/link/symbol.cpp | 9 +-- 12 files changed, 172 insertions(+), 201 deletions(-) diff --git a/include/link/main.hpp b/include/link/main.hpp index 847a4763..65339c36 100644 --- a/include/link/main.hpp +++ b/include/link/main.hpp @@ -6,6 +6,7 @@ #include #include +#include #include #include "helpers.hpp" @@ -35,7 +36,7 @@ struct FileStackNode { enum FileStackNodeType type; union { - char *name; // NODE_FILE, NODE_MACRO + std::string *name; // NODE_FILE, NODE_MACRO std::vector *iters; // NODE_REPT }; }; @@ -50,7 +51,7 @@ struct FileStackNode { * Dump a file stack to stderr * @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, char const *fmt, ...) format_(printf, 3, 4); diff --git a/include/link/patch.hpp b/include/link/patch.hpp index 8a31cd64..666c7b9f 100644 --- a/include/link/patch.hpp +++ b/include/link/patch.hpp @@ -14,7 +14,7 @@ struct Assertion { 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! std::vector *fileSymbols; }; diff --git a/include/link/section.hpp b/include/link/section.hpp index c56edf65..cdcec6af 100644 --- a/include/link/section.hpp +++ b/include/link/section.hpp @@ -7,6 +7,7 @@ // GUIDELINE: external code MUST NOT BE AWARE of the data structure used! #include +#include #include #include "link/main.hpp" @@ -30,7 +31,7 @@ struct Patch { struct Section { // Info contained in the object files - char *name; + std::string *name; uint16_t size; uint16_t offset; enum SectionType type; @@ -70,7 +71,7 @@ void sect_AddSection(struct Section *section); * @param name The name of the section to look for * @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. diff --git a/include/link/symbol.hpp b/include/link/symbol.hpp index 013f106f..8c8be122 100644 --- a/include/link/symbol.hpp +++ b/include/link/symbol.hpp @@ -7,6 +7,7 @@ // GUIDELINE: external code MUST NOT BE AWARE of the data structure used! #include +#include #include "linkdefs.hpp" @@ -14,7 +15,7 @@ struct FileStackNode; struct Symbol { // Info contained in the object files - char *name; + std::string *name; enum ExportLevel type; char const *objFileName; struct FileStackNode const *src; @@ -36,7 +37,7 @@ void sym_AddSymbol(struct Symbol *symbol); * @param name The name of the symbol to look for * @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. diff --git a/src/link/assign.cpp b/src/link/assign.cpp index 93760057..231279b1 100644 --- a/src/link/assign.cpp +++ b/src/link/assign.cpp @@ -318,17 +318,17 @@ static void placeSection(struct Section *section) // If a section failed to go to several places, nothing we can report if (!section->isBankFixed || !section->isAddressFixed) 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 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)", - 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); // Otherwise there is overlap with another section else errx("Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"", - section->name, sectionTypeInfo[section->type].name.c_str(), where, - out_OverlappingSection(section)->name); + section->name->c_str(), sectionTypeInfo[section->type].name.c_str(), where, + out_OverlappingSection(section)->name->c_str()); } #define BANK_CONSTRAINED (1 << 2) @@ -396,7 +396,7 @@ void assign_AssignSections(void) constraints >= 0; constraints--) { for (struct Section *section : unassignedSections[constraints]) { fprintf(stderr, "%c \"%s\"", nbSections == 0 ? ';': ',', - section->name); + section->name->c_str()); nbSections++; if (nbSections == 10) goto max_out; diff --git a/src/link/main.cpp b/src/link/main.cpp index 967e0e4a..ec3dffcd 100644 --- a/src/link/main.cpp +++ b/src/link/main.cpp @@ -49,16 +49,16 @@ FILE *linkerScript; static uint32_t nbErrors = 0; // 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) { lastName = dumpFileStack(node->parent); // REPT nodes use their parent's name if (node->type != NODE_REPT) lastName = node->name; - fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName); + fprintf(stderr, "(%" PRIu32 ") -> %s", node->lineNo, lastName->c_str()); if (node->type == NODE_REPT) { for (uint32_t iter : *node->iters) fprintf(stderr, "::REPT~%" PRIu32, iter); @@ -66,7 +66,7 @@ char const *dumpFileStack(struct FileStackNode const *node) } else { assert(node->type != NODE_REPT); lastName = node->name; - fputs(lastName, stderr); + fputs(lastName->c_str(), stderr); } return lastName; diff --git a/src/link/object.cpp b/src/link/object.cpp index 4d9c6f40..6a8ec228 100644 --- a/src/link/object.cpp +++ b/src/link/object.cpp @@ -102,37 +102,25 @@ static int64_t readlong(FILE *file) * @return The string read, or NULL on failure. * 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 - 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) - return NULL; - } + std::string *str = new(std::nothrow) std::string(); + if (!str) + return NULL; + for (;;) { // Read char int byte = getc(file); if (byte == EOF) { - free(str); + delete str; return NULL; + } else if (byte == '\0') { + return str; + } else { + str->push_back(byte); } - str[index] = byte; - } while (str[index]); - return str; + }; } /* @@ -143,8 +131,8 @@ static char *readstr(FILE *file) * @param ... A format string and related arguments; note that an extra string * argument is provided, the reason for failure */ -#define tryReadstr(var, file, ...) \ - tryRead(readstr, char *, NULL, char *, var, file, __VA_ARGS__) +#define tryReadstring(var, file, ...) \ + tryRead(readstring, std::string *, NULL, std::string *, var, file, __VA_ARGS__) // Functions to parse object files @@ -171,8 +159,8 @@ static void readFileStackNode(FILE *file, std::vector &fil switch (node.type) { case NODE_FILE: case NODE_MACRO: - tryReadstr(node.name, file, - "%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i); + tryReadstring(node.name, file, + "%s: Cannot read node #%" PRIu32 "'s file name: %s", fileName, i); break; uint32_t depth; @@ -203,28 +191,23 @@ static void readFileStackNode(FILE *file, std::vector &fil static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName, std::vector const &fileNodes) { - tryReadstr(symbol->name, file, "%s: Cannot read symbol name: %s", - fileName); + tryReadstring(symbol->name, file, "%s: Cannot read symbol name: %s", fileName); 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 (symbol->type != SYMTYPE_IMPORT) { symbol->objFileName = fileName; uint32_t nodeID; - tryReadlong(nodeID, file, - "%s: Cannot read \"%s\"'s node ID: %s", - fileName, symbol->name); + tryReadlong(nodeID, file, "%s: Cannot read \"%s\"'s node ID: %s", + fileName, symbol->name->c_str()); symbol->src = &fileNodes[nodeID]; - tryReadlong(symbol->lineNo, file, - "%s: Cannot read \"%s\"'s line number: %s", - fileName, symbol->name); - tryReadlong(symbol->sectionID, file, - "%s: Cannot read \"%s\"'s section ID: %s", - fileName, symbol->name); - tryReadlong(symbol->offset, file, - "%s: Cannot read \"%s\"'s value: %s", - fileName, symbol->name); + tryReadlong(symbol->lineNo, file, "%s: Cannot read \"%s\"'s line number: %s", + fileName, symbol->name->c_str()); + tryReadlong(symbol->sectionID, file, "%s: Cannot read \"%s\"'s section ID: %s", + fileName, symbol->name->c_str()); + tryReadlong(symbol->offset, file, "%s: Cannot read \"%s\"'s value: %s", + fileName, symbol->name->c_str()); } else { symbol->sectionID = -1; } @@ -298,17 +281,14 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam int32_t tmp; uint8_t byte; - tryReadstr(section->name, file, "%s: Cannot read section name: %s", - fileName); - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", - fileName, section->name); + tryReadstring(section->name, file, "%s: Cannot read section name: %s", fileName); + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s' size: %s", fileName, section->name->c_str()); if (tmp < 0 || tmp > UINT16_MAX) - errx("\"%s\"'s section size (%" PRId32 ") is invalid", - section->name, tmp); + errx("\"%s\"'s section size (%" PRId32 ") is invalid", section->name->c_str(), tmp); section->size = tmp; section->offset = 0; - tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s type: %s", - fileName, section->name); + tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s type: %s", fileName, + section->name->c_str()); section->type = (enum SectionType)(byte & 0x3F); if (byte >> 7) section->modifier = SECTION_UNION; @@ -316,30 +296,27 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam section->modifier = SECTION_FRAGMENT; else section->modifier = SECTION_NORMAL; - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", - fileName, section->name); + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s", fileName, section->name->c_str()); section->isAddressFixed = tmp >= 0; if (tmp > UINT16_MAX) { - error(NULL, 0, "\"%s\"'s org is too large (%" PRId32 ")", - section->name, tmp); + error(NULL, 0, "\"%s\"'s org is too large (%" PRId32 ")", section->name->c_str(), tmp); tmp = UINT16_MAX; } section->org = tmp; - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s", - fileName, section->name); + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s", fileName, section->name->c_str()); section->isBankFixed = tmp >= 0; section->bank = tmp; - tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s alignment: %s", - fileName, section->name); + tryGetc(uint8_t, byte, file, "%s: Cannot read \"%s\"'s alignment: %s", fileName, + section->name->c_str()); if (byte > 16) byte = 16; section->isAlignFixed = byte != 0; section->alignMask = (1 << byte) - 1; - tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s", - fileName, section->name); + tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s", fileName, + section->name->c_str()); if (tmp > UINT16_MAX) { error(NULL, 0, "\"%s\"'s alignment offset is too large (%" PRId32 ")", - section->name, tmp); + section->name->c_str(), tmp); tmp = UINT16_MAX; } section->alignOfs = tmp; @@ -347,26 +324,27 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam if (sect_HasData(section->type)) { section->data = new(std::nothrow) std::vector(section->size); 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 (size_t nbRead = fread(&(*section->data)[0], 1, section->size, file); 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)); } uint32_t nbPatches; tryReadlong(nbPatches, file, - "%s: Cannot read \"%s\"'s number of patches: %s", - fileName, section->name); + "%s: Cannot read \"%s\"'s number of patches: %s", fileName, + section->name->c_str()); section->patches = new(std::nothrow) std::vector(); 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); 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 { 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 fileName The filename to report in errors */ -static void readAssertion(FILE *file, struct Assertion *assert, - char const *fileName, uint32_t i, +static void readAssertion(FILE *file, struct Assertion *assert, char const *fileName, uint32_t i, std::vector const &fileNodes) { 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); readPatch(file, &assert->patch, fileName, assertName, 0, fileNodes); - tryReadstr(assert->message, file, "%s: Cannot read assertion's message: %s", - fileName); + tryReadstring(assert->message, file, "%s: Cannot read assertion's message: %s", fileName); } static struct Section *getMainSection(struct Section *section) { if (section->modifier != SECTION_NORMAL) - section = sect_GetSection(section->name); + section = sect_GetSection(*section->name); return section; } @@ -453,7 +429,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) where.parent = NULL; where.type = NODE_FILE; - where.name = strdup(fileName); + where.name = new(std::nothrow) std::string(fileName); if (!where.name) 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) delete node.iters; else - free(node.name); + delete node.name; } static void freeSection(struct Section *section) @@ -607,7 +583,7 @@ static void freeSection(struct Section *section) do { struct Section *next = section->nextu; - free(section->name); + delete section->name; if (sect_HasData(section->type)) { delete section->data; delete section->patches; @@ -633,9 +609,9 @@ void obj_Cleanup(void) for (std::vector &fileSymbols : symbolLists) { for (struct Symbol &symbol : fileSymbols) - free(symbol.name); + delete symbol.name; } for (struct Assertion &assert : assertions) - free(assert.message); + delete assert.message; } diff --git a/src/link/output.cpp b/src/link/output.cpp index 54372567..3c68a912 100644 --- a/src/link/output.cpp +++ b/src/link/output.cpp @@ -71,7 +71,7 @@ void out_AddSection(struct Section const *section) if (minNbBanks > maxNbBanks[section->type]) errx("Section \"%s\" has an invalid bank range (%" PRIu32 " > %" PRIu32 ")", - section->name, section->bank, + section->name->c_str(), section->bank, maxNbBanks[section->type] - 1); 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) return sym1.addr < sym2.addr ? -1 : 1; - char const *sym1_name = sym1.sym->name; - char const *sym2_name = sym2.sym->name; - bool sym1_local = strchr(sym1_name, '.'); - bool sym2_local = strchr(sym2_name, '.'); + std::string const *sym1_name = sym1.sym->name; + std::string const *sym2_name = sym2.sym->name; + bool sym1_local = sym1_name->find(".") != std::string::npos; + bool sym2_local = sym2_name->find(".") != std::string::npos; if (sym1_local != sym2_local) { - size_t sym1_len = strlen(sym1_name); - size_t sym2_len = strlen(sym2_name); + size_t sym1_len = sym1_name->length(); + size_t sym2_len = sym2_name->length(); // 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; - 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; // Sort local labels before unrelated global labels return sym1_local ? -1 : 1; @@ -348,7 +348,7 @@ static void writeSymBank(struct SortedSections const &bankSections, forEachSortedSection(sect, { for (struct Symbol const *sym : *sect->symbols) { // 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) }); } }); @@ -361,7 +361,7 @@ static void writeSymBank(struct SortedSections const &bankSections, for (struct SortedSymbol &sym : symList) { fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr); - printSymName(sym.sym->name); + printSymName(sym.sym->name->c_str()); putc('\n', symFile); } } @@ -407,21 +407,19 @@ static void writeMapBank(struct SortedSections const §List, enum SectionType if (sect->size != 0) fprintf(mapFile, "\tSECTION: $%04" PRIx16 "-$%04x ($%04" PRIx16 " byte%s) [\"%s\"]\n", - sect->org, prevEndAddr - 1, - sect->size, sect->size == 1 ? "" : "s", - sect->name); + sect->org, prevEndAddr - 1, sect->size, sect->size == 1 ? "" : "s", + sect->name->c_str()); else fprintf(mapFile, "\tSECTION: $%04" PRIx16 " (0 bytes) [\"%s\"]\n", - sect->org, sect->name); + sect->org, sect->name->c_str()); if (!noSymInMap) { - uint16_t org = sect->org; - - while (sect) { + // Also print symbols in the following "pieces" + for (uint16_t org = sect->org; sect; sect = sect->nextu) { for (struct Symbol *sym : *sect->symbols) // Space matches "\tSECTION: $xxxx ..." fprintf(mapFile, "\t $%04" PRIx32 " = %s\n", - sym->offset + org, sym->name); + sym->offset + org, sym->name->c_str()); if (sect->nextu) { // Announce the following "piece" @@ -432,8 +430,6 @@ static void writeMapBank(struct SortedSections const §List, enum SectionType fprintf(mapFile, "\t ; Next fragment\n"); } - - sect = sect->nextu; // Also print symbols in the following "pieces" } } diff --git a/src/link/patch.cpp b/src/link/patch.cpp index 484b88fa..b2b1a2c0 100644 --- a/src/link/patch.cpp +++ b/src/link/patch.cpp @@ -63,7 +63,7 @@ static struct Symbol const *getSymbol(std::vector const &symbolLi // If the symbol is defined elsewhere... if (symbol.type == SYMTYPE_IMPORT) - return sym_GetSymbol(symbol.name); + return sym_GetSymbol(*symbol.name); return &symbol; } @@ -224,13 +224,13 @@ static int32_t computeRPNExpr(struct Patch const *patch, if (!symbol) { error(patch->src, patch->lineNo, "Requested BANK() of symbol \"%s\", which was not found", - fileSymbols[value].name); + fileSymbols[value].name->c_str()); isError = true; value = 1; } else if (!symbol->section) { error(patch->src, patch->lineNo, "Requested BANK() of non-label symbol \"%s\"", - fileSymbols[value].name); + fileSymbols[value].name->c_str()); isError = true; value = 1; } else { @@ -385,7 +385,7 @@ static int32_t computeRPNExpr(struct Patch const *patch, if (!symbol) { error(patch->src, patch->lineNo, - "Unknown symbol \"%s\"", fileSymbols[value].name); + "Unknown symbol \"%s\"", fileSymbols[value].name->c_str()); isError = true; } else { value = symbol->value; @@ -422,24 +422,24 @@ void patch_CheckAssertions(std::deque &assertions) switch (type) { case ASSERT_FATAL: fatal(assert.patch.src, assert.patch.lineNo, "%s", - assert.message[0] ? assert.message - : "assert failure"); + !assert.message->empty() ? assert.message->c_str() + : "assert failure"); case ASSERT_ERROR: error(assert.patch.src, assert.patch.lineNo, "%s", - assert.message[0] ? assert.message - : "assert failure"); + !assert.message->empty() ? assert.message->c_str() + : "assert failure"); break; case ASSERT_WARN: warning(assert.patch.src, assert.patch.lineNo, "%s", - assert.message[0] ? assert.message - : "assert failure"); + !assert.message->empty() ? assert.message->c_str() + : "assert failure"); break; } } else if (isError && type == ASSERT_FATAL) { fatal(assert.patch.src, assert.patch.lineNo, "Failed to evaluate assertion%s%s", - assert.message[0] ? ": " : "", - assert.message); + !assert.message->empty() ? ": " : "", + assert.message->c_str()); } } } @@ -451,7 +451,7 @@ void patch_CheckAssertions(std::deque &assertions) */ 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) { int32_t value = computeRPNExpr(&patch, *section->fileSymbols); uint16_t offset = patch.offset + section->offset; diff --git a/src/link/sdas_obj.cpp b/src/link/sdas_obj.cpp index d5ba351e..96d7968b 100644 --- a/src/link/sdas_obj.cpp +++ b/src/link/sdas_obj.cpp @@ -268,7 +268,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorname)) + if (!strcmp(token, fileSections[i].section->name->c_str())) fatal(where, lineNo, "Area \"%s\" already defined earlier", token); } @@ -282,7 +282,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector UINT16_MAX) fatal(where, lineNo, "Area \"%s\" is larger than the GB address space!?", - curSection->name); + curSection->name->c_str()); curSection->size = tmp; expectToken("flags", 'A'); @@ -295,21 +295,16 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorisBankFixed = curSection->isAddressFixed; curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE)) ? 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 (curSection->modifier == SECTION_NORMAL) { - size_t len = strlen(where->name) + 1 + strlen(token); - - 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(*where->name); + curSection->name->append(" "); } + curSection->name->append(sectionName); expectToken("addr", 'A'); @@ -372,7 +367,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorname; + symbol.objFileName = where->name->c_str(); symbol.src = where; symbol.lineNo = lineNo; @@ -380,7 +375,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorvalue != symbol.value) { error(where, lineNo, "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 { // Add a new definition @@ -485,7 +480,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorisAddressFixed) { if (addr < section->org) 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; } // 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::vectordata = new(std::nothrow) std::vector(section->size); if (!section->data) 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::vectorstarts_with("b_")) { // Look for the symbol being referenced, and use its index instead 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; } if (idx == nbSymbols) 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[0] = RPN_BANK_SYM; patch.rpnExpression[1] = idx; patch.rpnExpression[2] = idx >> 8; patch.rpnExpression[3] = idx >> 16; patch.rpnExpression[4] = idx >> 24; - } else if (sym.name[0] == 'l' && sym.name[1] == '_') { - patch.rpnExpression.resize(1 + strlen(&sym.name[2]) + 1); + } else if (sym.name->starts_with("l_")) { + patch.rpnExpression.resize(1 + sym.name->length() - 2 + 1); patch.rpnExpression[0] = RPN_SIZEOF_SECT; - strcpy((char *)&patch.rpnExpression[1], &sym.name[2]); - } else if (sym.name[0] == 's' && sym.name[1] == '_') { - patch.rpnExpression.resize(1 + strlen(&sym.name[2]) + 1); + memcpy((char *)&patch.rpnExpression[1], &sym.name->c_str()[2], sym.name->length() - 2 + 1); + } else if (sym.name->starts_with("s_")) { + patch.rpnExpression.resize(1 + sym.name->length() - 2 + 1); 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 { patch.rpnExpression.resize(5); patch.rpnExpression[0] = RPN_SYM; @@ -627,8 +623,8 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorisAddressFixed) baseValue -= fileSections[idx].section->org; - char const *name = fileSections[idx].section->name; - struct Section const *other = sect_GetSection(name); + std::string const *name = fileSections[idx].section->name; + struct Section const *other = sect_GetSection(*name); // Unlike with `s_`, referencing an area in this way // 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::vectorsize; - patch.rpnExpression.resize(1 + strlen(name) + 1); + patch.rpnExpression.resize(1 + name->length() + 1); patch.rpnExpression[0] = RPN_STARTOF_SECT; // 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); @@ -659,7 +655,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector section->size) 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) memcpy(&(*section->data)[*writeIndex], &data[writtenOfs], offset - writtenOfs + 1); *writeIndex += offset - writtenOfs + 1; @@ -708,7 +704,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector writtenOfs); if (*writeIndex + (nbBytes - writtenOfs) > section->size) 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); *writeIndex += nbBytes - writtenOfs; } @@ -739,7 +735,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vectorsize && fileSections[i].writeIndex != 0) 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 sect_AddSection(section); diff --git a/src/link/section.cpp b/src/link/section.cpp index 2960e921..8bc52ceb 100644 --- a/src/link/section.cpp +++ b/src/link/section.cpp @@ -27,14 +27,13 @@ static void checkSectUnionCompat(struct Section *target, struct Section *other) if (target->isAddressFixed) { if (target->org != other->org) errx("Section \"%s\" is defined with conflicting addresses $%04" - PRIx16 " and $%04" PRIx16, - other->name, target->org, other->org); + PRIx16 " and $%04" PRIx16, other->name->c_str(), target->org, + other->org); } else if (target->isAlignFixed) { if ((other->org - target->alignOfs) & target->alignMask) errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" - PRIu16 ") and address $%04" PRIx16, - other->name, target->alignMask + 1, - target->alignOfs, other->org); + PRIu16 ") and address $%04" PRIx16, other->name->c_str(), + target->alignMask + 1, target->alignOfs, other->org); } target->isAddressFixed = true; target->org = other->org; @@ -44,14 +43,14 @@ static void checkSectUnionCompat(struct Section *target, struct Section *other) if ((target->org - other->alignOfs) & other->alignMask) errx("Section \"%s\" is defined with conflicting address $%04" PRIx16 " and %d-byte alignment (offset %" PRIu16 ")", - other->name, target->org, - other->alignMask + 1, other->alignOfs); + other->name->c_str(), target->org, other->alignMask + 1, + other->alignOfs); } else if (target->isAlignFixed && (other->alignMask & target->alignOfs) != (target->alignMask & other->alignOfs)) { errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" 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); } else if (!target->isAlignFixed || (other->alignMask > target->alignMask)) { target->isAlignFixed = true; @@ -68,15 +67,14 @@ static void checkFragmentCompat(struct Section *target, struct Section *other) if (target->isAddressFixed) { if (target->org != org) errx("Section \"%s\" is defined with conflicting addresses $%04" - PRIx16 " and $%04" PRIx16, - other->name, target->org, other->org); + PRIx16 " and $%04" PRIx16, other->name->c_str(), target->org, + other->org); } else if (target->isAlignFixed) { if ((org - target->alignOfs) & target->alignMask) errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" - PRIu16 ") and address $%04" PRIx16, - other->name, target->alignMask + 1, - target->alignOfs, other->org); + PRIu16 ") and address $%04" PRIx16, other->name->c_str(), + target->alignMask + 1, target->alignOfs, other->org); } target->isAddressFixed = true; target->org = org; @@ -91,14 +89,14 @@ static void checkFragmentCompat(struct Section *target, struct Section *other) if ((target->org - ofs) & other->alignMask) errx("Section \"%s\" is defined with conflicting address $%04" PRIx16 " and %d-byte alignment (offset %" PRIu16 ")", - other->name, target->org, - other->alignMask + 1, other->alignOfs); + other->name->c_str(), target->org, other->alignMask + 1, + other->alignOfs); } else if (target->isAlignFixed && (other->alignMask & target->alignOfs) != (target->alignMask & ofs)) { errx("Section \"%s\" is defined with conflicting %d-byte alignment (offset %" 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); } 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) 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()); if (other->isBankFixed) { @@ -124,7 +122,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se target->bank = other->bank; } else if (target->bank != other->bank) { 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) { // 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) - 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]); 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 mergeSections(other, section, section->modifier); } else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) { 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 { // 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); return search != sections.end() ? search->second : NULL; @@ -205,27 +203,27 @@ static void doSanityChecks(struct Section *section) { // Sanity check the section's type 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; } if (is32kMode && section->type == SECTTYPE_ROMX) { if (section->isBankFixed && section->bank != 1) error(NULL, 0, "%s: ROMX sections must be in bank 1 (if any) with option -t", - section->name); + section->name->c_str()); else section->type = SECTTYPE_ROM0; } if (isWRA0Mode && section->type == SECTTYPE_WRAMX) { if (section->isBankFixed && section->bank != 1) error(NULL, 0, "%s: WRAMX sections must be in bank 1 with options -w or -d", - section->name); + section->name->c_str()); else section->type = SECTTYPE_WRAM0; } if (isDmgMode && section->type == SECTTYPE_VRAM && section->bank == 1) 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 // 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 if (section->isAlignFixed && (section->alignMask & sectionTypeInfo[section->type].startAddr)) 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; @@ -243,13 +242,13 @@ static void doSanityChecks(struct Section *section) 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 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 if (section->size > sectionTypeInfo[section->type].size) error(NULL, 0, "Section \"%s\" is bigger than the max size for that type: $%" 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 @@ -263,7 +262,7 @@ static void doSanityChecks(struct Section *section) if (section->isAlignFixed) { if ((section->org & section->alignMask) != section->alignOfs) error(NULL, 0, "Section \"%s\"'s fixed address doesn't match its alignment", - section->name); + section->name->c_str()); section->isAlignFixed = false; } @@ -271,12 +270,12 @@ static void doSanityChecks(struct Section *section) if (section->org < sectionTypeInfo[section->type].startAddr || section->org > endaddr(section->type)) 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)); if (section->org + section->size > endaddr(section->type) + 1) 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); } } diff --git a/src/link/symbol.cpp b/src/link/symbol.cpp index fa823561..5623925a 100644 --- a/src/link/symbol.cpp +++ b/src/link/symbol.cpp @@ -16,8 +16,9 @@ std::map symbols; void sym_AddSymbol(struct Symbol *symbol) { // Check if the symbol already exists - if (struct Symbol *other = sym_GetSymbol(symbol->name); other) { - fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name, symbol->objFileName); + if (struct Symbol *other = sym_GetSymbol(*symbol->name); other) { + fprintf(stderr, "error: \"%s\" both in %s from ", symbol->name->c_str(), + symbol->objFileName); dumpFileStack(symbol->src); fprintf(stderr, "(%" PRIu32 ") and in %s from ", symbol->lineNo, other->objFileName); @@ -27,10 +28,10 @@ void sym_AddSymbol(struct Symbol *symbol) } // 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); return search != symbols.end() ? search->second : NULL;