summaryrefslogtreecommitdiff
path: root/src/liblink/objfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/liblink/objfile.c')
-rw-r--r--src/liblink/objfile.c78
1 files changed, 61 insertions, 17 deletions
diff --git a/src/liblink/objfile.c b/src/liblink/objfile.c
index 610f87954..b2478ec17 100644
--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -38,7 +38,8 @@
// - type [int]
// - name [string]
// - version [int]
-// - dupok [int]
+// - flags [int]
+// 1 dupok
// - size [int]
// - gotype [symbol reference]
// - p [data block]
@@ -50,7 +51,9 @@
// - args [int]
// - locals [int]
// - nosplit [int]
-// - leaf [int]
+// - flags [int]
+// 1 leaf
+// 2 C function
// - nlocal [int]
// - local [nlocal automatics]
// - pcln [pcln table]
@@ -100,6 +103,7 @@
#include <bio.h>
#include <link.h>
#include "../cmd/ld/textflag.h"
+#include "../runtime/funcdata.h"
static void writesym(Link*, Biobuf*, LSym*);
static void wrint(Biobuf*, int64);
@@ -121,7 +125,7 @@ static LSym *rdsym(Link*, Biobuf*, char*);
void
writeobj(Link *ctxt, Biobuf *b)
{
- int flag;
+ int flag, found;
Hist *h;
LSym *s, *text, *etext, *curtext, *data, *edata;
Plist *pl;
@@ -183,12 +187,7 @@ writeobj(Link *ctxt, Biobuf *b)
s->size = p->to.offset;
if(s->type == 0 || s->type == SXREF)
s->type = SBSS;
-
- if(ctxt->arch->thechar == '5')
- flag = p->reg;
- else
- flag = p->from.scale;
-
+ flag = ctxt->arch->textflag(p);
if(flag & DUPOK)
s->dupok = 1;
if(flag & RODATA)
@@ -221,10 +220,7 @@ writeobj(Link *ctxt, Biobuf *b)
else
etext->next = s;
etext = s;
- if(ctxt->arch->thechar == '5')
- flag = p->reg;
- else
- flag = p->from.scale;
+ flag = ctxt->arch->textflag(p);
if(flag & DUPOK)
s->dupok = 1;
if(flag & NOSPLIT)
@@ -237,6 +233,17 @@ writeobj(Link *ctxt, Biobuf *b)
continue;
}
+ if(p->as == ctxt->arch->AFUNCDATA) {
+ // Rewrite reference to go_args_stackmap(SB) to the Go-provided declaration information.
+ if(curtext == nil) // func _() {}
+ continue;
+ if(strcmp(p->to.sym->name, "go_args_stackmap") == 0) {
+ if(p->from.type != ctxt->arch->D_CONST || p->from.offset != FUNCDATA_ArgsPointerMaps)
+ ctxt->diag("FUNCDATA use of go_args_stackmap(SB) without FUNCDATA_ArgsPointerMaps");
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", curtext->name), curtext->version);
+ }
+ }
+
if(curtext == nil)
continue;
s = curtext;
@@ -244,6 +251,32 @@ writeobj(Link *ctxt, Biobuf *b)
s->etext = p;
}
}
+
+ // Add reference to Go arguments for C or assembly functions without them.
+ for(s = text; s != nil; s = s->next) {
+ if(strncmp(s->name, "\"\".", 3) != 0)
+ continue;
+ found = 0;
+ for(p = s->text; p != nil; p = p->link) {
+ if(p->as == ctxt->arch->AFUNCDATA && p->from.type == ctxt->arch->D_CONST && p->from.offset == FUNCDATA_ArgsPointerMaps) {
+ found = 1;
+ break;
+ }
+ }
+ if(!found) {
+ p = appendp(ctxt, s->text);
+ p->as = ctxt->arch->AFUNCDATA;
+ p->from.type = ctxt->arch->D_CONST;
+ p->from.offset = FUNCDATA_ArgsPointerMaps;
+ if(ctxt->arch->thechar == '6' || ctxt->arch->thechar == '8')
+ p->to.type = ctxt->arch->D_EXTERN;
+ else {
+ p->to.type = ctxt->arch->D_OREG;
+ p->to.name = ctxt->arch->D_EXTERN;
+ }
+ p->to.sym = linklookup(ctxt, smprint("%s.args_stackmap", s->name), s->version);
+ }
+ }
// Turn functions into machine code images.
for(s = text; s != nil; s = s->next) {
@@ -297,6 +330,8 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
Bprint(ctxt->bso, "t=%d ", s->type);
if(s->dupok)
Bprint(ctxt->bso, "dupok ");
+ if(s->cfunc)
+ Bprint(ctxt->bso, "cfunc ");
if(s->nosplit)
Bprint(ctxt->bso, "nosplit ");
Bprint(ctxt->bso, "size=%lld value=%lld", (vlong)s->size, (vlong)s->value);
@@ -359,7 +394,7 @@ writesym(Link *ctxt, Biobuf *b, LSym *s)
wrint(b, s->args);
wrint(b, s->locals);
wrint(b, s->nosplit);
- wrint(b, s->leaf);
+ wrint(b, s->leaf | s->cfunc<<1);
n = 0;
for(a = s->autom; a != nil; a = a->link)
n++;
@@ -515,7 +550,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
static int ndup;
char *name;
Reloc *r;
- LSym *s, *dup;
+ LSym *s, *dup, *typ;
Pcln *pc;
Auto *a;
@@ -527,6 +562,7 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
if(v != 0 && v != 1)
sysfatal("invalid symbol version %d", v);
dupok = rdint(f);
+ dupok &= 1;
size = rdint(f);
if(v != 0)
@@ -550,7 +586,11 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->type = t;
if(s->size < size)
s->size = size;
- s->gotype = rdsym(ctxt, f, pkg);
+ typ = rdsym(ctxt, f, pkg);
+ if(typ != nil) // if bss sym defined multiple times, take type from any one def
+ s->gotype = typ;
+ if(dup != nil && typ != nil)
+ dup->gotype = typ;
rddata(f, &s->p, &s->np);
s->maxp = s->np;
n = rdint(f);
@@ -581,7 +621,9 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
s->args = rdint(f);
s->locals = rdint(f);
s->nosplit = rdint(f);
- s->leaf = rdint(f);
+ v = rdint(f);
+ s->leaf = v&1;
+ s->cfunc = v&2;
n = rdint(f);
for(i=0; i<n; i++) {
a = emallocz(sizeof *a);
@@ -637,6 +679,8 @@ readsym(Link *ctxt, Biobuf *f, char *pkg, char *pn)
Bprint(ctxt->bso, "t=%d ", s->type);
if(s->dupok)
Bprint(ctxt->bso, "dupok ");
+ if(s->cfunc)
+ Bprint(ctxt->bso, "cfunc ");
if(s->nosplit)
Bprint(ctxt->bso, "nosplit ");
Bprint(ctxt->bso, "size=%lld value=%lld", (vlong)s->size, (vlong)s->value);