Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Escape characters in section names in map files #1551

Merged
merged 2 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 44 additions & 30 deletions src/link/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,15 @@ static bool isLegalForSymName(char c) {
|| c == '@' || c == '#' || c == '$' || c == '.';
}

// Prints a symbol's name to `symFile`, assuming that the first character is legal.
// Prints a symbol's name to a file, assuming that the first character is legal.
// Illegal characters are UTF-8-decoded (errors are replaced by U+FFFD) and emitted as `\u`/`\U`.
static void printSymName(char const *name) {
for (char const *ptr = name; *ptr != '\0';) {
static void printSymName(std::string const &name, FILE *file) {
for (char const *ptr = name.c_str(); *ptr != '\0';) {
char c = *ptr;

if (isLegalForSymName(c)) {
// Output legal ASCII characters as-is
putc(c, symFile);
putc(c, file);
++ptr;
} else {
// Output illegal characters using Unicode escapes
Expand All @@ -295,7 +295,7 @@ static void printSymName(char const *name) {
++ptr;
} while (state != 0);

fprintf(symFile, codepoint <= 0xFFFF ? "\\u%04" PRIx32 : "\\U%08" PRIx32, codepoint);
fprintf(file, codepoint <= 0xFFFF ? "\\u%04" PRIx32 : "\\U%08" PRIx32, codepoint);
}
}
}
Expand Down Expand Up @@ -376,7 +376,7 @@ static void writeSymBank(SortedSections const &bankSections, SectionType type, u

for (SortedSymbol &sym : symList) {
fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym.addr);
printSymName(sym.sym->name.c_str());
printSymName(sym.sym->name, symFile);
putc('\n', symFile);
}
}
Expand All @@ -396,6 +396,31 @@ static void writeEmptySpace(uint16_t begin, uint16_t end) {
}
}

// Prints a section's name to a file.
static void printSectionName(std::string const &name, FILE *file) {
for (char c : name) {
// Escape characters that need escaping
switch (c) {
case '\n':
fputs("\\n", file);
break;
case '\r':
fputs("\\r", file);
break;
case '\t':
fputs("\\t", file);
break;
case '\\':
case '"':
putc('\\', file);
[[fallthrough]];
default:
putc(c, file);
break;
}
}
}

/*
* Write a bank's contents to the map file
*/
Expand Down Expand Up @@ -427,35 +452,22 @@ static void writeMapBank(SortedSections const &sectList, SectionType type, uint3

prevEndAddr = sect->org + sect->size;

fprintf(mapFile, "\tSECTION: $%04" PRIx16, sect->org);
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.c_str()
);
else
fprintf(
mapFile,
"\tSECTION: $%04" PRIx16 " (0 bytes) [\"%s\"]\n",
sect->org,
sect->name.c_str()
);
fprintf(mapFile, "-$%04x", prevEndAddr - 1);
fprintf(mapFile, " ($%04" PRIx16 " byte%s) [\"", sect->size, sect->size == 1 ? "" : "s");
printSectionName(sect->name, mapFile);
fputs("\"]\n", mapFile);

if (!noSymInMap) {
// Also print symbols in the following "pieces"
for (uint16_t org = sect->org; sect; sect = sect->nextu.get()) {
for (Symbol *sym : sect->symbols)
for (Symbol *sym : sect->symbols) {
// Space matches "\tSECTION: $xxxx ..."
fprintf(
mapFile,
"\t $%04" PRIx32 " = %s\n",
sym->label().offset + org,
sym->name.c_str()
);
fprintf(mapFile, "\t $%04" PRIx32 " = ", sym->label().offset + org);
printSymName(sym->name, mapFile);
putc('\n', mapFile);
}

if (sect->nextu) {
// Announce the following "piece"
Expand Down Expand Up @@ -579,7 +591,9 @@ static void writeSym() {
for (Symbol *sym : constants) {
int32_t val = sym->data.get<int32_t>();
int width = val < 0x100 ? 2 : val < 0x10000 ? 4 : 8;
fprintf(symFile, "%0*" PRIx32 " %s\n", width, val, sym->name.c_str());
fprintf(symFile, "%0*" PRIx32 " ", width, val);
printSymName(sym->name, symFile);
putc('\n', symFile);
}
}

Expand Down
2 changes: 2 additions & 0 deletions test/link/map-file/a.asm
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ wLabel1:: ds 6
SECTION "hram", HRAM
hLabel:: ds 7
.local::

SECTION "\n\r\t\"\\", ROM0[1]
1 change: 1 addition & 0 deletions test/link/map-file/ref.out.map
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ROM0 bank #0:
SECTION: $0000-$0000 ($0001 byte) ["rom0"]
$0000 = Label0
$0001 = Label0.local
SECTION: $0001 ($0000 bytes) ["\n\r\t\"\\"]
EMPTY: $0001-$3fff ($3fff bytes)
TOTAL EMPTY: $3fff bytes

Expand Down