elf2ecoff endianness bugs

Steve Rumble <[email protected]> Fri, 5 Dec 2025 10:33:10 -0800
Newsgroups gmane.os.netbsd.ports.mips.devel
Message-ID <CAL4_dAQFm=uJf+bB0j1hScizDaSOT9f0bbF4JEgsX6X3Tv9B1g@mail.gmail.com>
Hello,

elf2ecoff isn't generating valid symbol tables. It's both byte swapping
when it shouldn't (same host and target endianness) and not swapping when
it should.

For example, my crosstool objdump doesn't like an elf2ecoff'd sgimips
kernel generated on amd64:

$ mipseb--netbsd-objdump -x netbsd.ecoff > /dev/null
mipseb--netbsd-objdump: failed to read symbol table from: netbsd.ecoff
mipseb--netbsd-objdump: error message was: file truncated

Same goes for an hpcmips (mipsel) kernel generated on amd64:
$ mipsel--netbsd-objdump -x netbsd.ecoff > /dev/null
mipsel--netbsd-objdump: netbsd.ecoff: bad value

The attached patch makes objdump able to read the ecoff symbol tables again.

Steve
elf2ecoff.c.diff (application/octet-stream, 2.6 KB)
Index: elf2ecoff.c
===================================================================
RCS file: /cvsroot/src/usr.bin/elf2ecoff/elf2ecoff.c,v
retrieving revision 1.38
diff -u -r1.38 elf2ecoff.c
--- elf2ecoff.c	13 Sep 2025 17:08:47 -0000	1.38
+++ elf2ecoff.c	5 Dec 2025 17:19:37 -0000
@@ -425,9 +425,12 @@
 	}
 
 
-	if (debug)
-		fprintf(stderr, "writing syms at offset %#x\n",
-		    (uint32_t)(ep.f.f_symptr + sizeof(symhdr)));
+	if (debug) {
+		uint32_t symptr = needswap ? bswap32(ep.f.f_symptr) : ep.f.f_symptr;
+		fprintf(stderr, "writing symhdr at offset %#x, "
+		    "syms at offset %#x\n", symptr,
+		    (uint32_t)(symptr + sizeof(symhdr)));
+	}
 
 	/* Copy and translate the symbol table... */
 	elf_symbol_table_to_ecoff(outfile, infile, &ep,
@@ -591,10 +594,12 @@
     int32_t extsymoff, int32_t extstroff, int32_t strsize)
 {
 
-	if (debug)
+	if (debug) {
+		uint32_t symptr = needswap ? bswap32(ep->f.f_symptr) : ep->f.f_symptr;
 		fprintf(stderr,
 		    "writing symhdr for %d entries at offset %#x\n",
-		    nesyms, ep->f.f_symptr);
+		    nesyms, symptr);
+	}
 
 	ep->f.f_nsyms = sizeof(struct ecoff32_symhdr);
 
@@ -614,9 +619,9 @@
 	if (needswap) {
 		bswap32_region(&symhdrp->ilineMax,
 		    sizeof(*symhdrp) -  sizeof(symhdrp->magic) -
-		    sizeof(symhdrp->ilineMax));
+		    sizeof(symhdrp->vstamp));
 		symhdrp->magic = bswap16(symhdrp->magic);
-		symhdrp->ilineMax = bswap16(symhdrp->ilineMax);
+		symhdrp->vstamp = bswap16(symhdrp->vstamp);
 	}
 
 	safewrite(out, symhdrp, sizeof(*symhdrp),
@@ -675,7 +680,7 @@
 	nsyms = ecoffsymtab.nsymbols;
 
 	/* Compute output ECOFF symbol- and string-table offsets. */
-	ecoff_symhdr_off = ep->f.f_symptr;
+	ecoff_symhdr_off = needswap ? bswap32(ep->f.f_symptr) : ep->f.f_symptr;
 
 	nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr);
 	stringtaboff = nextoff;
@@ -703,12 +708,15 @@
 	/* Write out the symbol table... */
 	padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym));
 
-	for (i = 0; i < nsyms; i++) {
-		struct ecoff_extsym *es = &ecoffsymtab.ecoff_syms[i];
-		es->es_flags	= bswap16(es->es_flags);
-		es->es_ifd	= bswap16(es->es_ifd);
-		bswap32_region(&es->es_strindex,
-		    sizeof(*es) - sizeof(es->es_flags) - sizeof(es->es_ifd));
+	if (needswap) {
+		for (i = 0; i < nsyms; i++) {
+			struct ecoff_extsym *es = &ecoffsymtab.ecoff_syms[i];
+			es->es_flags	= bswap16(es->es_flags);
+			es->es_ifd	= bswap16(es->es_ifd);
+			bswap32_region(&es->es_strindex,
+			    sizeof(*es) - sizeof(es->es_flags) -
+			    sizeof(es->es_ifd));
+		}
 	}
 	safewrite(out, ecoffsymtab.ecoff_syms,
 	    nsyms * sizeof(struct ecoff_extsym),