Apply kernigh@'s fix to broken symbol tables in aelflod (via mailing list patch):

---snip---
The ELF spec at http://www.sco.com/developers/gabi/ says, "In each
symbol table, all symbols with STB_LOCAL binding precede the weak and
global symbols," and that sh_info is the index of the first non-local
symbol.

I was mixing local and global symbols and setting sh_info to zero. I
also forgot to set the type of the .shstrtab section.
---snip---
This commit is contained in:
David Given 2017-01-18 00:06:14 +01:00
parent 81c677d218
commit 01a61e0708

View file

@ -43,6 +43,7 @@ char* stringarea;
uint32_t ack_off_char; uint32_t ack_off_char;
int nstab = 0; /* S_STB symbol count */ int nstab = 0; /* S_STB symbol count */
int nsym = 0; /* other symbol count */ int nsym = 0; /* other symbol count */
int nlocal = 0; /* local symbols */
char* outputfile = NULL; /* Name of output file, or NULL */ char* outputfile = NULL; /* Name of output file, or NULL */
char* program; /* Name of current program: argv[0] */ char* program; /* Name of current program: argv[0] */
@ -347,17 +348,29 @@ void emit_stab(void)
void emit_symtab(void) void emit_symtab(void)
{ {
struct outname* n; struct outname* n;
int i; int i, pass;
bool global;
for (i = 0; i < outhead.oh_nname; i++) { /* ELF .symtab must have local symbols before other symbols.
n = &outname[i]; * We emit locals in pass 0, globals in pass 1. */
if (!(n->on_type & S_STB)) { for (pass = 0; pass < 2; pass++) {
emit32(cvname(n)); /* name index */ for (i = 0; i < outhead.oh_nname; i++) {
emit32(n->on_valu); /* value */ n = &outname[i];
emit32(0); /* size = unknown */
emit8(cvinfo(n)); /* info */ /* Don't emit .stab symbol in .symtab. */
emit8(0); /* other */ if (n->on_type & S_STB)
emit16(cvsect(n)); /* section */ continue;
global = (n->on_type & S_EXT);
if ((pass == 0 && !global) ||
(pass == 1 && global)) {
emit32(cvname(n)); /* name index */
emit32(n->on_valu); /* value */
emit32(0); /* size = unknown */
emit8(cvinfo(n)); /* info */
emit8(0); /* other */
emit16(cvsect(n)); /* section */
}
} }
} }
} }
@ -386,8 +399,8 @@ void emit_shstrtab(void)
void emit_sh(int i) void emit_sh(int i)
{ {
uint32_t name, type, flags, addr, offset, size, addralign, uint32_t name, type, flags, addr, offset, size, link, info,
link, entsize; addralign, entsize;
/* If no debugger symbols, skip .stab and .stabstr */ /* If no debugger symbols, skip .stab and .stabstr */
if (nstab == 0 && (i == N_STAB || i == N_STABSTR)) if (nstab == 0 && (i == N_STAB || i == N_STABSTR))
@ -412,6 +425,7 @@ void emit_sh(int i)
break; break;
case N_STABSTR: case N_STABSTR:
case N_STRTAB: case N_STRTAB:
case N_SHSTRTAB:
type = 3; /* SHT_STRTAB */ type = 3; /* SHT_STRTAB */
break; break;
default: default:
@ -495,6 +509,15 @@ void emit_sh(int i)
break; break;
} }
switch (i) {
case N_SYMTAB:
info = nlocal;
break;
default:
info = 0;
break;
}
emit32(name); emit32(name);
emit32(type); emit32(type);
emit32(flags); emit32(flags);
@ -502,7 +525,7 @@ void emit_sh(int i)
emit32(offset); emit32(offset);
emit32(size); emit32(size);
emit32(link); emit32(link);
emit32(0); /* info */ emit32(info);
emit32(addralign); emit32(addralign);
emit32(entsize); emit32(entsize);
} }
@ -585,10 +608,13 @@ int rnames(FILE* f)
outname[i].on_type = uget2(c); c += 2; outname[i].on_type = uget2(c); c += 2;
outname[i].on_desc = uget2(c); c += 2; outname[i].on_desc = uget2(c); c += 2;
outname[i].on_valu = get4(c); outname[i].on_valu = get4(c);
if (outname[i].on_type & S_STB) if (outname[i].on_type & S_STB) {
nstab++; nstab++;
else } else {
nsym++; nsym++;
if (!(outname[i].on_type & S_EXT))
nlocal++;
}
} }
stringarea = malloc(outhead.oh_nchar); stringarea = malloc(outhead.oh_nchar);