summaryrefslogtreecommitdiff
path: root/src/cmd/6l/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6l/asm.c')
-rw-r--r--src/cmd/6l/asm.c77
1 files changed, 46 insertions, 31 deletions
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 1fc3db98d..af00f5594 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -351,50 +351,65 @@ doelf(void)
nsym = 1; // sym 0 is reserved
for(h=0; h<NHASH; h++) {
for(s=hash[h]; s!=S; s=s->link) {
- if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
+ if(!s->reachable || (s->type != STEXT && s->type != SDATA && s->type != SBSS) || s->dynimpname == nil)
continue;
- d = lookup(".rela", 0);
- addaddr(d, s);
- adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
- adduint64(d, 0);
+ if(!s->dynexport) {
+ d = lookup(".rela", 0);
+ addaddr(d, s);
+ adduint64(d, ELF64_R_INFO(nsym, R_X86_64_64));
+ adduint64(d, 0);
+ }
+
nsym++;
d = lookup(".dynsym", 0);
adduint32(d, addstring(lookup(".dynstr", 0), s->dynimpname));
+ /* type */
t = STB_GLOBAL << 4;
- t |= STT_OBJECT; // works for func too, empirically
+ if(s->dynexport && s->type == STEXT)
+ t |= STT_FUNC;
+ else
+ t |= STT_OBJECT;
adduint8(d, t);
- adduint8(d, 0); /* reserved */
- adduint16(d, SHN_UNDEF); /* section where symbol is defined */
- adduint64(d, 0); /* value */
- adduint64(d, 0); /* size of object */
- if(needlib(s->dynimplib))
+ /* reserved */
+ adduint8(d, 0);
+
+ /* section where symbol is defined */
+ if(!s->dynexport)
+ adduint16(d, SHN_UNDEF);
+ else {
+ switch(s->type) {
+ default:
+ case STEXT:
+ t = 9;
+ break;
+ case SDATA:
+ t = 10;
+ break;
+ case SBSS:
+ t = 11;
+ break;
+ }
+ adduint16(d, t);
+ }
+
+ /* value */
+ if(!s->dynexport)
+ adduint64(d, 0);
+ else
+ addaddr(d, s);
+
+ /* size of object */
+ adduint64(d, 0);
+
+ if(!s->dynexport && needlib(s->dynimplib))
elfwritedynent(dynamic, DT_NEEDED, addstring(dynstr, s->dynimplib));
}
}
- /*
- * hash table.
- * only entries that other objects need to find when
- * linking us need to be in the table. right now that is
- * no entries.
- *
- * freebsd insists on having chains enough for all
- * the local symbols, though. for now, we just lay
- * down a trivial hash table with 1 bucket and a long chain,
- * because no one is actually looking for our symbols.
- */
- s = lookup(".hash", 0);
- s->type = SDATA; // TODO: rodata
- s->reachable = 1;
- adduint32(s, 1); // nbucket
- adduint32(s, nsym); // nchain
- adduint32(s, nsym-1); // bucket 0
- adduint32(s, 0); // chain 0
- for(h=1; h<nsym; h++) // chain nsym-1 -> nsym-2 -> ... -> 2 -> 1 -> 0
- adduint32(s, h-1);
+ elfdynhash(nsym);
/*
* .dynamic table