shithub: rgbds

Download patch

ref: 9ab9d0f39c3bb9c263a1b117e020edb95c45c5cb
parent: 6e1a5dcc9ddc07fd27b440659f46c3af8a1f6d3e
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Sun May 2 13:40:43 EDT 2021

Output all SECTION UNION/FRAGMENT symbols in .sym files

Fixes #809

--- a/src/link/output.c
+++ b/src/link/output.c
@@ -6,6 +6,7 @@
  * SPDX-License-Identifier: MIT
  */
 
+#include <assert.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -33,6 +34,12 @@
 	struct SortedSection *next;
 };
 
+struct SortedSymbol {
+	struct Symbol const *sym;
+	uint32_t idx;
+	uint16_t addr;
+};
+
 static struct {
 	uint32_t nbBanks;
 	struct SortedSections {
@@ -268,69 +275,86 @@
 	return (*s1)->section->org < (*s2)->section->org ? s1 : s2;
 }
 
+/*
+ * Comparator function for `qsort` to sort symbols
+ * Symbols are ordered by address, or else by original index for a stable sort
+ */
+static int compareSymbols(void const *a, void const *b)
+{
+	struct SortedSymbol const *sym1 = (struct SortedSymbol const *)a;
+	struct SortedSymbol const *sym2 = (struct SortedSymbol const *)b;
+
+	if (sym1->addr != sym2->addr)
+		return sym1->addr < sym2->addr ? -1 : 1;
+
+	return sym1->idx < sym2->idx ? -1 : sym1->idx > sym2->idx ? 1 : 0;
+}
+
 /**
  * Write a bank's contents to the sym file
  * @param bankSections The bank's sections
  */
-static void writeSymBank(struct SortedSections const *bankSections)
+static void writeSymBank(struct SortedSections const *bankSections,
+			 enum SectionType type, uint32_t bank)
 {
 	if (!symFile)
 		return;
 
-	struct {
-		struct SortedSection const *sections;
-#define sect sections->section /* Fake member as a shortcut */
-		uint32_t i;
-		struct Symbol const *sym;
-		uint16_t addr;
-	} sectList = { .sections = bankSections->sections, .i = 0 },
-	zlSectList = { .sections = bankSections->zeroLenSections, .i = 0 },
-	  *minSectList;
+	uint32_t nbSymbols = 0;
 
-	for (;;) {
-		while (sectList.sections
-		    && sectList.i   == sectList.sect->nbSymbols) {
-			sectList.sections   = sectList.sections->next;
-			sectList.i   = 0;
+	for (struct SortedSection const *ptr = bankSections->sections; ptr; ptr = ptr->next) {
+		for (struct Section const *sect = ptr->section; sect; sect = sect->nextu)
+			nbSymbols += sect->nbSymbols;
+	}
+	for (struct SortedSection const *ptr = bankSections->zeroLenSections; ptr; ptr = ptr->next) {
+		for (struct Section const *sect = ptr->section; sect; sect = sect->nextu)
+			nbSymbols += sect->nbSymbols;
+	}
+
+	if (!nbSymbols)
+		return;
+
+	struct SortedSymbol *symList = malloc(sizeof(*symList) * nbSymbols);
+
+	if (!symList)
+		err(1, "Failed to allocate symbol list");
+
+	uint32_t idx = 0;
+
+	for (struct SortedSection const *ptr = bankSections->sections; ptr; ptr = ptr->next) {
+		for (struct Section const *sect = ptr->section; sect; sect = sect->nextu) {
+			for (uint32_t i = 0; i < sect->nbSymbols; i++) {
+				symList[idx].idx = idx;
+				symList[idx].sym = sect->symbols[i];
+				symList[idx].addr = symList[idx].sym->offset + sect->org;
+				idx++;
+			}
 		}
-		while (zlSectList.sections
-		    && zlSectList.i == zlSectList.sect->nbSymbols) {
-			zlSectList.sections = zlSectList.sections->next;
-			zlSectList.i = 0;
+	}
+	for (struct SortedSection const *ptr = bankSections->zeroLenSections; ptr; ptr = ptr->next) {
+		for (struct Section const *sect = ptr->section; sect; sect = sect->nextu) {
+			for (uint32_t i = 0; i < sect->nbSymbols; i++) {
+				symList[idx].idx = idx;
+				symList[idx].sym = sect->symbols[i];
+				symList[idx].addr = symList[idx].sym->offset + sect->org;
+				idx++;
+			}
 		}
+	}
+	assert(idx == nbSymbols);
 
-		if (!sectList.sections && !zlSectList.sections) {
-			break;
-		} else if (sectList.sections && zlSectList.sections) {
-			sectList.sym   = sectList.sect->symbols[sectList.i];
-			zlSectList.sym = zlSectList.sect->symbols[zlSectList.i];
-			sectList.addr =
-				sectList.sym->offset   + sectList.sect->org;
-			zlSectList.addr =
-				zlSectList.sym->offset + zlSectList.sect->org;
+	qsort(symList, nbSymbols, sizeof(*symList), compareSymbols);
 
-			minSectList = sectList.addr < zlSectList.addr
-								? &sectList
-								: &zlSectList;
-		} else if (sectList.sections) {
-			sectList.sym   = sectList.sect->symbols[sectList.i];
-			sectList.addr   =
-				sectList.sym->offset   + sectList.sect->org;
+	uint32_t symBank = bank + bankranges[type][0];
 
-			minSectList = &sectList;
-		} else {
-			zlSectList.sym = zlSectList.sect->symbols[zlSectList.i];
-			zlSectList.addr =
-				zlSectList.sym->offset + zlSectList.sect->org;
+	for (uint32_t i = 0; i < nbSymbols; i++) {
+		struct SortedSymbol *sym = &symList[i];
 
-			minSectList = &zlSectList;
-		}
 		fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " %s\n",
-			minSectList->sect->bank, minSectList->addr,
-			minSectList->sym->name);
-		minSectList->i++;
+			symBank, sym->addr, sym->sym->name);
 	}
-#undef sect
+
+	free(symList);
 }
 
 /**
@@ -443,7 +467,7 @@
 		for (uint32_t bank = 0; bank < sections[type].nbBanks; bank++) {
 			struct SortedSections const *sect = &sections[type].banks[bank];
 
-			writeSymBank(sect);
+			writeSymBank(sect, type, bank);
 			usedMap[type] += writeMapBank(sect, type, bank);
 		}
 	}