Use std::vector for reading object file symbols

This commit is contained in:
Rangi42
2024-02-27 11:28:12 -05:00
committed by Sylvie
parent 9a51fbafb3
commit f47ce337bf
6 changed files with 31 additions and 58 deletions

View File

@@ -6,6 +6,7 @@
#include <deque> #include <deque>
#include <stdint.h> #include <stdint.h>
#include <vector>
#include "link/section.hpp" #include "link/section.hpp"
@@ -15,7 +16,7 @@ struct Assertion {
struct Patch patch; // Also used for its `.type` struct Patch patch; // Also used for its `.type`
char *message; char *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!
struct Symbol **fileSymbols; std::vector<struct Symbol *> *fileSymbols;
}; };
/* /*

View File

@@ -5,9 +5,11 @@
#define RGBDS_LINK_SDAS_OBJ_H #define RGBDS_LINK_SDAS_OBJ_H
#include <stdio.h> #include <stdio.h>
#include <vector>
struct FileStackNode; struct FileStackNode;
struct Symbol;
void sdobj_ReadFile(struct FileStackNode const *fileName, FILE *file); void sdobj_ReadFile(struct FileStackNode const *fileName, FILE *file, std::vector<struct Symbol *> &fileSymbols);
#endif // RGBDS_LINK_SDAS_OBJ_H #endif // RGBDS_LINK_SDAS_OBJ_H

View File

@@ -47,7 +47,7 @@ struct Section {
uint8_t *data; // Array of size `size` uint8_t *data; // Array of size `size`
std::vector<struct Patch> *patches; std::vector<struct Patch> *patches;
// Extra info computed during linking // Extra info computed during linking
struct Symbol **fileSymbols; std::vector<struct Symbol *> *fileSymbols;
uint32_t nbSymbols; uint32_t nbSymbols;
struct Symbol **symbols; struct Symbol **symbols;
struct Section *nextu; // The next "component" of this unionized sect struct Section *nextu; // The next "component" of this unionized sect

View File

@@ -24,13 +24,7 @@
#include "linkdefs.hpp" #include "linkdefs.hpp"
#include "version.hpp" #include "version.hpp"
struct SymbolList { static std::deque<std::vector<struct Symbol *>> symbolLists;
size_t nbSymbols;
struct Symbol **symbolList;
};
static std::deque<struct SymbolList> symbolLists;
static std::vector<std::vector<struct FileStackNode>> nodes; static std::vector<std::vector<struct FileStackNode>> nodes;
static std::deque<struct Assertion> assertions; static std::deque<struct Assertion> assertions;
@@ -478,7 +472,9 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
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));
sdobj_ReadFile(&where, file); std::vector<struct Symbol *> &fileSymbols = symbolLists.emplace_front();
sdobj_ReadFile(&where, file, fileSymbols);
return; return;
} }
@@ -516,13 +512,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
readFileStackNode(file, nodes[fileID], i, fileName); readFileStackNode(file, nodes[fileID], i, fileName);
// This file's symbols, kept to link sections to them // This file's symbols, kept to link sections to them
struct Symbol **fileSymbols = (struct Symbol **)malloc(sizeof(*fileSymbols) * nbSymbols + 1); std::vector<struct Symbol *> &fileSymbols = symbolLists.emplace_front(nbSymbols);
if (!fileSymbols)
err("Failed to get memory for %s's symbols", fileName);
symbolLists.push_front({ .nbSymbols = nbSymbols, .symbolList = fileSymbols });
std::vector<uint32_t> nbSymPerSect(nbSections, 0); std::vector<uint32_t> nbSymPerSect(nbSections, 0);
verbosePrint("Reading %" PRIu32 " symbols...\n", nbSymbols); verbosePrint("Reading %" PRIu32 " symbols...\n", nbSymbols);
@@ -553,7 +543,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
fileSections[i]->nextu = NULL; fileSections[i]->nextu = NULL;
readSection(file, fileSections[i], fileName, nodes[fileID]); readSection(file, fileSections[i], fileName, nodes[fileID]);
fileSections[i]->fileSymbols = fileSymbols; fileSections[i]->fileSymbols = &fileSymbols;
if (nbSymPerSect[i]) { if (nbSymPerSect[i]) {
fileSections[i]->symbols = fileSections[i]->symbols =
(struct Symbol **)malloc(nbSymPerSect[i] * sizeof(*fileSections[i]->symbols)); (struct Symbol **)malloc(nbSymPerSect[i] * sizeof(*fileSections[i]->symbols));
@@ -606,7 +596,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
readAssertion(file, &assertion, fileName, i, nodes[fileID]); readAssertion(file, &assertion, fileName, i, nodes[fileID]);
linkPatchToPCSect(&assertion.patch, fileSections); linkPatchToPCSect(&assertion.patch, fileSections);
assertion.fileSymbols = fileSymbols; assertion.fileSymbols = &fileSymbols;
} }
fclose(file); fclose(file);
@@ -670,10 +660,9 @@ void obj_Cleanup(void)
sect_ForEach(freeSection); sect_ForEach(freeSection);
sect_CleanupSections(); sect_CleanupSections();
for (struct SymbolList &list : symbolLists) { for (std::vector<struct Symbol *> &fileSymbols : symbolLists) {
for (size_t i = 0; i < list.nbSymbols; i++) for (struct Symbol *symbol : fileSymbols)
freeSymbol(list.symbolList[i]); freeSymbol(symbol);
free(list.symbolList);
} }
for (struct Assertion &assert : assertions) for (struct Assertion &assert : assertions)

View File

@@ -56,11 +56,10 @@ static uint32_t getRPNByte(uint8_t const **expression, int32_t *size,
return *(*expression)++; return *(*expression)++;
} }
static struct Symbol const *getSymbol(struct Symbol const * const *symbolList, static struct Symbol const *getSymbol(std::vector<struct Symbol *> const &symbolList, uint32_t index)
uint32_t index)
{ {
assert(index != (uint32_t)-1); // PC needs to be handled specially, not here assert(index != (uint32_t)-1); // PC needs to be handled specially, not here
struct Symbol const *symbol = symbolList[index]; struct Symbol *symbol = symbolList[index];
// If the symbol is defined elsewhere... // If the symbol is defined elsewhere...
if (symbol->type == SYMTYPE_IMPORT) if (symbol->type == SYMTYPE_IMPORT)
@@ -78,7 +77,7 @@ static struct Symbol const *getSymbol(struct Symbol const * const *symbolList,
* errors caused by the value should be suppressed. * errors caused by the value should be suppressed.
*/ */
static int32_t computeRPNExpr(struct Patch const *patch, static int32_t computeRPNExpr(struct Patch const *patch,
struct Symbol const * const *fileSymbols) std::vector<struct Symbol *> const &fileSymbols)
{ {
// Small shortcut to avoid a lot of repetition // Small shortcut to avoid a lot of repetition
#define popRPN() popRPN(patch->src, patch->lineNo) #define popRPN() popRPN(patch->src, patch->lineNo)
@@ -416,8 +415,7 @@ void patch_CheckAssertions(std::deque<struct Assertion> &assertions)
verbosePrint("Checking assertions...\n"); verbosePrint("Checking assertions...\n");
for (struct Assertion &assert : assertions) { for (struct Assertion &assert : assertions) {
int32_t value = computeRPNExpr(&assert.patch, int32_t value = computeRPNExpr(&assert.patch, *assert.fileSymbols);
(struct Symbol const * const *)assert.fileSymbols);
enum AssertionType type = (enum AssertionType)assert.patch.type; enum AssertionType type = (enum AssertionType)assert.patch.type;
if (!isError && !value) { if (!isError && !value) {
@@ -455,9 +453,7 @@ static void applyFilePatches(struct Section *section, struct Section *dataSectio
{ {
verbosePrint("Patching section \"%s\"...\n", section->name); verbosePrint("Patching section \"%s\"...\n", section->name);
for (struct Patch &patch : *section->patches) { for (struct Patch &patch : *section->patches) {
int32_t value = computeRPNExpr(&patch, int32_t value = computeRPNExpr(&patch, *section->fileSymbols);
(struct Symbol const * const *)
section->fileSymbols);
uint16_t offset = patch.offset + section->offset; uint16_t offset = patch.offset + section->offset;
// `jr` is quite unlike the others... // `jr` is quite unlike the others...

View File

@@ -144,7 +144,7 @@ enum RelocFlags {
| 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE, | 1 << RELOC_EXPR24 | 1 << RELOC_BANKBYTE,
}; };
void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) { void sdobj_ReadFile(struct FileStackNode const *where, FILE *file, std::vector<struct Symbol *> &fileSymbols) {
size_t bufLen = 256; size_t bufLen = 256;
char *line = (char *)malloc(bufLen); char *line = (char *)malloc(bufLen);
char const *token; char const *token;
@@ -234,11 +234,7 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
uint16_t writeIndex; uint16_t writeIndex;
}; };
std::vector<struct FileSection> fileSections; std::vector<struct FileSection> fileSections;
struct Symbol **fileSymbols = (struct Symbol **)malloc(sizeof(*fileSymbols) * expectedNbSymbols);
size_t nbSections = 0, nbSymbols = 0; size_t nbSections = 0, nbSymbols = 0;
if (!fileSymbols)
fatal(where, lineNo, "Failed to alloc file symbols table: %s", strerror(errno));
size_t nbBytes = 0; // How many bytes are in `data`, including the ADDR_SIZE "header" bytes size_t nbBytes = 0; // How many bytes are in `data`, including the ADDR_SIZE "header" bytes
size_t dataCapacity = 16 + ADDR_SIZE; // SDCC object files usually contain 16 bytes per T line size_t dataCapacity = 16 + ADDR_SIZE; // SDCC object files usually contain 16 bytes per T line
uint8_t *data = (uint8_t *)malloc(sizeof(*data) * dataCapacity); uint8_t *data = (uint8_t *)malloc(sizeof(*data) * dataCapacity);
@@ -262,10 +258,11 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
expectedNbAreas); expectedNbAreas);
fileSections.resize(nbSections + 1); fileSections.resize(nbSections + 1);
fileSections[nbSections].writeIndex = 0; fileSections[nbSections].writeIndex = 0;
#define curSection (fileSections[nbSections].section) struct Section *curSection = (struct Section *)malloc(sizeof(*curSection));
curSection = (struct Section *)malloc(sizeof(*curSection));
if (!curSection) if (!curSection)
fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno)); fatal(where, lineNo, "Failed to alloc new area: %s", strerror(errno));
fileSections[nbSections].section = curSection;
getToken(line, "'A' line is too short"); getToken(line, "'A' line is too short");
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
@@ -357,36 +354,24 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
if (!curSection->patches) if (!curSection->patches)
fatal(where, lineNo, "Failed to alloc new area's patches: %s", fatal(where, lineNo, "Failed to alloc new area's patches: %s",
strerror(errno)); strerror(errno));
curSection->fileSymbols = fileSymbols; // IDs are instead per-section curSection->fileSymbols = &fileSymbols; // IDs are instead per-section
curSection->nbSymbols = 0; curSection->nbSymbols = 0;
curSection->symbols = NULL; // Will be allocated on demand as well curSection->symbols = NULL; // Will be allocated on demand as well
curSection->nextu = NULL; curSection->nextu = NULL;
#undef curSection
++nbSections; ++nbSections;
break; break;
} }
case 'S': case 'S': {
if (nbSymbols == expectedNbSymbols) if (nbSymbols == expectedNbSymbols)
warning(where, lineNo, "Got more 'S' lines than the expected %" PRIu32, warning(where, lineNo, "Got more 'S' lines than the expected %" PRIu32,
expectedNbSymbols); expectedNbSymbols);
// `realloc` is dangerous, as sections contain a pointer to `fileSymbols`. struct Symbol *symbol = (struct Symbol *)malloc(sizeof(*symbol));
// We can try to be nice, but if the pointer moves, it's game over!
if (nbSymbols >= expectedNbSymbols) {
struct Symbol **newFileSymbols = (struct Symbol **)realloc(fileSymbols,
sizeof(*fileSymbols) * (nbSymbols + 1));
if (!newFileSymbols)
fatal(where, lineNo, "Failed to alloc extra symbols: %s",
strerror(errno));
if (newFileSymbols != fileSymbols)
fatal(where, lineNo, "Failed to handle extra 'S' lines (pointer moved)");
// No need to assign, obviously
}
#define symbol (fileSymbols[nbSymbols])
symbol = (struct Symbol *)malloc(sizeof(*symbol));
if (!symbol) if (!symbol)
fatal(where, lineNo, "Failed to alloc symbol: %s", strerror(errno)); fatal(where, lineNo, "Failed to alloc symbol: %s", strerror(errno));
fileSymbols.push_back(symbol);
// Init other members // Init other members
symbol->objFileName = where->name; symbol->objFileName = where->name;
@@ -453,12 +438,12 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
section->name, strerror(errno)); section->name, strerror(errno));
section->symbols[section->nbSymbols - 1] = symbol; section->symbols[section->nbSymbols - 1] = symbol;
} }
#undef symbol
expectEol("'S' line is too long"); expectEol("'S' line is too long");
++nbSymbols; ++nbSymbols;
break; break;
}
case 'T': case 'T':
// Now, time to parse the data! // Now, time to parse the data!