xref: /plan9-contrib/sys/src/cmd/ld/mod.c (revision 40d015479ed36701ae6dcfd8814f849fc6285e8d)
1 #include	"l.h"
2 
3 void
readundefs(char * f,int t)4 readundefs(char *f, int t)
5 {
6 	int i, n;
7 	Sym *s;
8 	Biobuf *b;
9 	char *l, buf[256], *fields[64];
10 
11 	if(f == nil)
12 		return;
13 	b = Bopen(f, OREAD);
14 	if(b == nil){
15 		diag("could not open %s: %r", f);
16 		errorexit();
17 	}
18 	while((l = Brdline(b, '\n')) != nil){
19 		n = Blinelen(b);
20 		if(n >= sizeof(buf)){
21 			diag("%s: line too long", f);
22 			errorexit();
23 		}
24 		memmove(buf, l, n);
25 		buf[n-1] = '\0';
26 		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
27 		if(n == nelem(fields)){
28 			diag("%s: bad format", f);
29 			errorexit();
30 		}
31 		for(i = 0; i < n; i++){
32 			s = lookup(fields[i], 0);
33 			s->type = SXREF;
34 			s->subtype = t;
35 			if(t == SIMPORT)
36 				nimports++;
37 			else
38 				nexports++;
39 		}
40 	}
41 	Bterm(b);
42 }
43 
44 void
undefsym(Sym * s)45 undefsym(Sym *s)
46 {
47 	int n;
48 
49 	n = imports;
50 	if(s->value != 0)
51 		diag("value != 0 on SXREF");
52 	if(n >= 1<<Rindex)
53 		diag("import index %d out of range", n);
54 	s->value = n<<Roffset;
55 	s->type = SUNDEF;
56 	imports++;
57 }
58 
59 void
zerosig(char * sp)60 zerosig(char *sp)
61 {
62 	Sym *s;
63 
64 	s = lookup(sp, 0);
65 	s->sig = 0;
66 }
67 
68 void
import(void)69 import(void)
70 {
71 	int i;
72 	Sym *s;
73 
74 	for(i = 0; i < NHASH; i++)
75 		for(s = hash[i]; s != S; s = s->link)
76 			if(s->sig != 0 && s->type == SXREF && (nimports == 0 || s->subtype == SIMPORT)){
77 				undefsym(s);
78 				Bprint(&bso, "IMPORT: %s sig=%lux v=%lld\n", s->name, s->sig, (vlong)s->value);
79 			}
80 }
81 
82 void
ckoff(Sym * s,long v)83 ckoff(Sym *s, long v)
84 {
85 	if(v < 0 || v >= 1<<Roffset)
86 		diag("relocation offset %ld for %s out of range", v, s->name);
87 }
88 
89 static Prog*
newdata(Sym * s,int o,int w,int t)90 newdata(Sym *s, int o, int w, int t)
91 {
92 	Prog *p;
93 
94 	p = prg();
95 	p->link = datap;
96 	datap = p;
97 	p->as = ADATA;
98 	p->reg = w;
99 	p->from.type = D_OREG;
100 	p->from.name = t;
101 	p->from.sym = s;
102 	p->from.offset = o;
103 	p->to.type = D_CONST;
104 	p->to.name = D_NONE;
105 	return p;
106 }
107 
108 void
export(void)109 export(void)
110 {
111 	int i, j, n, off, nb, sv, ne;
112 	Sym *s, *et, *str, **esyms;
113 	Prog *p;
114 	char buf[NSNAME], *t;
115 
116 	n = 0;
117 	for(i = 0; i < NHASH; i++)
118 		for(s = hash[i]; s != S; s = s->link)
119 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
120 				n++;
121 	esyms = malloc(n*sizeof(Sym*));
122 	ne = n;
123 	n = 0;
124 	for(i = 0; i < NHASH; i++)
125 		for(s = hash[i]; s != S; s = s->link)
126 			if(s->sig != 0 && s->type != SXREF && s->type != SUNDEF && (nexports == 0 || s->subtype == SEXPORT))
127 				esyms[n++] = s;
128 	for(i = 0; i < ne-1; i++)
129 		for(j = i+1; j < ne; j++)
130 			if(strcmp(esyms[i]->name, esyms[j]->name) > 0){
131 				s = esyms[i];
132 				esyms[i] = esyms[j];
133 				esyms[j] = s;
134 			}
135 
136 	nb = 0;
137 	off = 0;
138 	et = lookup(EXPTAB, 0);
139 	if(et->type != 0 && et->type != SXREF)
140 		diag("%s already defined", EXPTAB);
141 	et->type = SDATA;
142 	str = lookup(".string", 0);
143 	if(str->type == 0)
144 		str->type = SDATA;
145 	sv = str->value;
146 	for(i = 0; i < ne; i++){
147 		s = esyms[i];
148 		Bprint(&bso, "EXPORT: %s sig=%lux t=%d\n", s->name, s->sig, s->type);
149 
150 		/* signature */
151 		p = newdata(et, off, sizeof(long), D_EXTERN);
152 		off += sizeof(long);
153 		p->to.offset = s->sig;
154 
155 		/* address */
156 		p = newdata(et, off, sizeof(long), D_EXTERN);
157 		off += sizeof(long);
158 		p->to.name = D_EXTERN;
159 		p->to.sym = s;
160 
161 		/* string */
162 		t = s->name;
163 		n = strlen(t)+1;
164 		for(;;){
165 			buf[nb++] = *t;
166 			sv++;
167 			if(nb >= NSNAME){
168 				p = newdata(str, sv-NSNAME, NSNAME, D_STATIC);
169 				p->to.type = D_SCONST;
170 				p->to.sval = malloc(NSNAME);
171 				memmove(p->to.sval, buf, NSNAME);
172 				nb = 0;
173 			}
174 			if(*t++ == 0)
175 				break;
176 		}
177 
178 		/* name */
179 		p = newdata(et, off, sizeof(long), D_EXTERN);
180 		off += sizeof(long);
181 		p->to.name = D_STATIC;
182 		p->to.sym = str;
183 		p->to.offset = sv-n;
184 	}
185 
186 	if(nb > 0){
187 		p = newdata(str, sv-nb, nb, D_STATIC);
188 		p->to.type = D_SCONST;
189 		p->to.sval = malloc(NSNAME);
190 		memmove(p->to.sval, buf, nb);
191 	}
192 
193 	for(i = 0; i < 3; i++){
194 		newdata(et, off, sizeof(long), D_EXTERN);
195 		off += sizeof(long);
196 	}
197 	et->value = off;
198 	if(sv == 0)
199 		sv = 1;
200 	str->value = sv;
201 	exports = ne;
202 	free(esyms);
203 }
204