~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/cmd/ld/data.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include        "l.h"
34
34
#include        "../ld/lib.h"
35
35
#include        "../ld/elf.h"
 
36
#include        "../ld/macho.h"
36
37
#include        "../ld/pe.h"
 
38
#include        "../../pkg/runtime/mgc0.h"
37
39
 
38
40
void    dynreloc(void);
39
 
static vlong addaddrplus4(Sym *s, Sym *t, int32 add);
 
41
static vlong addaddrplus4(Sym *s, Sym *t, vlong add);
40
42
 
41
43
/*
42
44
 * divide-and-conquer list-link
57
59
}
58
60
 
59
61
Sym*
60
 
datsort(Sym *l)
 
62
listsort(Sym *l, int (*cmp)(Sym*, Sym*), int off)
61
63
{
62
64
        Sym *l1, *l2, *le;
 
65
        #define NEXT(l) (*(Sym**)((char*)(l)+off))
63
66
 
64
 
        if(l == 0 || l->next == 0)
 
67
        if(l == 0 || NEXT(l) == 0)
65
68
                return l;
66
69
 
67
70
        l1 = l;
68
71
        l2 = l;
69
72
        for(;;) {
70
 
                l2 = l2->next;
71
 
                if(l2 == 0)
72
 
                        break;
73
 
                l2 = l2->next;
74
 
                if(l2 == 0)
75
 
                        break;
76
 
                l1 = l1->next;
 
73
                l2 = NEXT(l2);
 
74
                if(l2 == 0)
 
75
                        break;
 
76
                l2 = NEXT(l2);
 
77
                if(l2 == 0)
 
78
                        break;
 
79
                l1 = NEXT(l1);
77
80
        }
78
81
 
79
 
        l2 = l1->next;
80
 
        l1->next = 0;
81
 
        l1 = datsort(l);
82
 
        l2 = datsort(l2);
 
82
        l2 = NEXT(l1);
 
83
        NEXT(l1) = 0;
 
84
        l1 = listsort(l, cmp, off);
 
85
        l2 = listsort(l2, cmp, off);
83
86
 
84
87
        /* set up lead element */
85
 
        if(datcmp(l1, l2) < 0) {
 
88
        if(cmp(l1, l2) < 0) {
86
89
                l = l1;
87
 
                l1 = l1->next;
 
90
                l1 = NEXT(l1);
88
91
        } else {
89
92
                l = l2;
90
 
                l2 = l2->next;
 
93
                l2 = NEXT(l2);
91
94
        }
92
95
        le = l;
93
96
 
94
97
        for(;;) {
95
98
                if(l1 == 0) {
96
99
                        while(l2) {
97
 
                                le->next = l2;
 
100
                                NEXT(le) = l2;
98
101
                                le = l2;
99
 
                                l2 = l2->next;
 
102
                                l2 = NEXT(l2);
100
103
                        }
101
 
                        le->next = 0;
 
104
                        NEXT(le) = 0;
102
105
                        break;
103
106
                }
104
107
                if(l2 == 0) {
105
108
                        while(l1) {
106
 
                                le->next = l1;
 
109
                                NEXT(le) = l1;
107
110
                                le = l1;
108
 
                                l1 = l1->next;
 
111
                                l1 = NEXT(l1);
109
112
                        }
110
113
                        break;
111
114
                }
112
 
                if(datcmp(l1, l2) < 0) {
113
 
                        le->next = l1;
 
115
                if(cmp(l1, l2) < 0) {
 
116
                        NEXT(le) = l1;
114
117
                        le = l1;
115
 
                        l1 = l1->next;
 
118
                        l1 = NEXT(l1);
116
119
                } else {
117
 
                        le->next = l2;
 
120
                        NEXT(le) = l2;
118
121
                        le = l2;
119
 
                        l2 = l2->next;
 
122
                        l2 = NEXT(l2);
120
123
                }
121
124
        }
122
 
        le->next = 0;
 
125
        NEXT(le) = 0;
123
126
        return l;
 
127
        
 
128
        #undef NEXT
124
129
}
125
130
 
126
131
Reloc*
131
136
                        s->maxr = 4;
132
137
                else
133
138
                        s->maxr <<= 1;
134
 
                s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
135
 
                if(s->r == 0) {
136
 
                        diag("out of memory");
137
 
                        errorexit();
138
 
                }
 
139
                s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
139
140
                memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
140
141
        }
141
142
        return &s->r[s->nr++];
145
146
relocsym(Sym *s)
146
147
{
147
148
        Reloc *r;
 
149
        Sym *rs;
148
150
        Prog p;
149
151
        int32 i, off, siz, fl;
150
152
        vlong o;
151
153
        uchar *cast;
152
 
        
 
154
 
153
155
        cursym = s;
154
156
        memset(&p, 0, sizeof p);
155
157
        for(r=s->r; r<s->r+s->nr; r++) {
 
158
                r->done = 1;
156
159
                off = r->off;
157
160
                siz = r->siz;
158
 
                if(off < 0 || off+(siz&~Rbig) > s->np) {
159
 
                        diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz&~Rbig, 0, s->np);
 
161
                if(off < 0 || off+siz > s->np) {
 
162
                        diag("%s: invalid relocation %d+%d not in [%d,%d)", s->name, off, siz, 0, s->np);
160
163
                        continue;
161
164
                }
162
 
                if(r->sym != S && (r->sym->type == 0 || r->sym->type == SXREF)) {
 
165
                if(r->sym != S && (r->sym->type & SMASK == 0 || r->sym->type & SMASK == SXREF)) {
163
166
                        diag("%s: not defined", r->sym->name);
164
167
                        continue;
165
168
                }
169
172
                if(r->sym != S && r->sym->type == SDYNIMPORT)
170
173
                        diag("unhandled relocation for %s (type %d rtype %d)", r->sym->name, r->sym->type, r->type);
171
174
 
172
 
                if(r->sym != S && !r->sym->reachable)
 
175
                if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable)
173
176
                        diag("unreachable sym in relocation: %s %s", s->name, r->sym->name);
174
177
 
175
178
                switch(r->type) {
176
179
                default:
177
180
                        o = 0;
178
 
                        if(archreloc(r, s, &o) < 0)
 
181
                        if(linkmode == LinkExternal || archreloc(r, s, &o) < 0)
179
182
                                diag("unknown reloc %d", r->type);
180
183
                        break;
 
184
                case D_TLS:
 
185
                        r->done = 0;
 
186
                        o = 0;
 
187
                        break;
181
188
                case D_ADDR:
 
189
                        if(linkmode == LinkExternal && r->sym->type != SCONST) {
 
190
                                r->done = 0;
 
191
 
 
192
                                // set up addend for eventual relocation via outer symbol.
 
193
                                rs = r->sym;
 
194
                                r->xadd = r->add;
 
195
                                while(rs->outer != nil) {
 
196
                                        r->xadd += symaddr(rs) - symaddr(rs->outer);
 
197
                                        rs = rs->outer;
 
198
                                }
 
199
                                if(rs->type != SHOSTOBJ && rs->sect == nil)
 
200
                                        diag("missing section for %s", rs->name);
 
201
                                r->xsym = rs;
 
202
 
 
203
                                o = r->xadd;
 
204
                                if(iself) {
 
205
                                        if(thechar == '6')
 
206
                                                o = 0;
 
207
                                } else if(HEADTYPE == Hdarwin) {
 
208
                                        if(rs->type != SHOSTOBJ)
 
209
                                                o += symaddr(rs);
 
210
                                } else {
 
211
                                        diag("unhandled pcrel relocation for %s", headtype);
 
212
                                }
 
213
                                break;
 
214
                        }
182
215
                        o = symaddr(r->sym) + r->add;
183
216
                        break;
184
217
                case D_PCREL:
185
 
                        // r->sym can be null when CALL $(constant) is transformed from absoulte PC to relative PC call.
 
218
                        // r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
 
219
                        if(linkmode == LinkExternal && r->sym && r->sym->type != SCONST && r->sym->sect != cursym->sect) {
 
220
                                r->done = 0;
 
221
 
 
222
                                // set up addend for eventual relocation via outer symbol.
 
223
                                rs = r->sym;
 
224
                                r->xadd = r->add;
 
225
                                while(rs->outer != nil) {
 
226
                                        r->xadd += symaddr(rs) - symaddr(rs->outer);
 
227
                                        rs = rs->outer;
 
228
                                }
 
229
                                r->xadd -= r->siz; // relative to address after the relocated chunk
 
230
                                if(rs->type != SHOSTOBJ && rs->sect == nil)
 
231
                                        diag("missing section for %s", rs->name);
 
232
                                r->xsym = rs;
 
233
 
 
234
                                o = r->xadd;
 
235
                                if(iself) {
 
236
                                        if(thechar == '6')
 
237
                                                o = 0;
 
238
                                } else if(HEADTYPE == Hdarwin) {
 
239
                                        if(rs->type != SHOSTOBJ)
 
240
                                                o += symaddr(rs) - rs->sect->vaddr;
 
241
                                        o -= r->off; // WTF?
 
242
                                } else {
 
243
                                        diag("unhandled pcrel relocation for %s", headtype);
 
244
                                }
 
245
                                break;
 
246
                        }
186
247
                        o = 0;
187
248
                        if(r->sym)
188
249
                                o += symaddr(r->sym);
189
 
                        o += r->add - (s->value + r->off + r->siz);
 
250
                        // NOTE: The (int32) cast on the next line works around a bug in Plan 9's 8c
 
251
                        // compiler. The expression s->value + r->off + r->siz is int32 + int32 +
 
252
                        // uchar, and Plan 9 8c incorrectly treats the expression as type uint32
 
253
                        // instead of int32, causing incorrect values when sign extended for adding
 
254
                        // to o. The bug only occurs on Plan 9, because this C program is compiled by
 
255
                        // the standard host compiler (gcc on most other systems).
 
256
                        o += r->add - (s->value + r->off + (int32)r->siz);
190
257
                        break;
191
258
                case D_SIZE:
192
259
                        o = r->sym->size + r->add;
197
264
                default:
198
265
                        cursym = s;
199
266
                        diag("bad reloc size %#ux for %s", siz, r->sym->name);
200
 
                case 4 + Rbig:
201
 
                        fl = o;
202
 
                        s->p[off] = fl>>24;
203
 
                        s->p[off+1] = fl>>16;
204
 
                        s->p[off+2] = fl>>8;
205
 
                        s->p[off+3] = fl;
206
 
                        break;
207
 
                case 4 + Rlittle:
208
 
                        fl = o;
209
 
                        s->p[off] = fl;
210
 
                        s->p[off+1] = fl>>8;
211
 
                        s->p[off+2] = fl>>16;
212
 
                        s->p[off+3] = fl>>24;
213
 
                        break;
214
267
                case 4:
 
268
                        if(r->type == D_PCREL) {
 
269
                                if(o != (int32)o)
 
270
                                        diag("pc-relative relocation address is too big: %#llx", o);
 
271
                        } else {
 
272
                                if(o != (int32)o && o != (uint32)o)
 
273
                                        diag("non-pc-relative relocation address is too big: %#llux", o);
 
274
                        }
215
275
                        fl = o;
216
276
                        cast = (uchar*)&fl;
217
277
                        for(i=0; i<4; i++)
222
282
                        for(i=0; i<8; i++)
223
283
                                s->p[off+i] = cast[inuxi8[i]];
224
284
                        break;
225
 
                }               
 
285
                }
226
286
        }
227
287
}
228
288
 
230
290
reloc(void)
231
291
{
232
292
        Sym *s;
233
 
        
 
293
 
234
294
        if(debug['v'])
235
295
                Bprint(&bso, "%5.2f reloc\n", cputime());
236
296
        Bflush(&bso);
245
305
dynrelocsym(Sym *s)
246
306
{
247
307
        Reloc *r;
 
308
        Sym *rel;
 
309
        Sym *got;
248
310
        
249
311
        if(HEADTYPE == Hwindows) {
250
312
                Sym *rel, *targ;
251
 
                
 
313
 
252
314
                rel = lookup(".rel", 0);
253
315
                if(s == rel)
254
316
                        return;
258
320
                                targ->plt = rel->size;
259
321
                                r->sym = rel;
260
322
                                r->add = targ->plt;
261
 
                                
 
323
 
262
324
                                // jmp *addr
263
325
                                if(thechar == '8') {
264
326
                                        adduint8(rel, 0xff);
281
343
                return;
282
344
        }
283
345
 
284
 
        for(r=s->r; r<s->r+s->nr; r++)
285
 
                if(r->sym->type == SDYNIMPORT || r->type >= 256)
 
346
        got = rel = nil;
 
347
        if(flag_shared) {
 
348
                rel = lookuprel();
 
349
                got = lookup(".got", 0);
 
350
        }
 
351
        s->rel_ro = 0;
 
352
        for(r=s->r; r<s->r+s->nr; r++) {
 
353
                if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
286
354
                        adddynrel(s, r);
 
355
                if(flag_shared && r->sym != S && s->type != SDYNIMPORT && r->type == D_ADDR
 
356
                                && (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
 
357
                        // Create address based RELATIVE relocation
 
358
                        adddynrela(rel, s, r);
 
359
                        if(s->type < SNOPTRDATA)
 
360
                                s->rel_ro = 1;
 
361
                }
 
362
        }
287
363
}
288
364
 
289
365
void
290
366
dynreloc(void)
291
367
{
292
368
        Sym *s;
293
 
        
 
369
 
294
370
        // -d supresses dynamic loader format, so we may as well not
295
371
        // compute these sections or mark their symbols as reachable.
296
372
        if(debug['d'] && HEADTYPE != Hwindows)
318
394
                        s->maxp = 8;
319
395
                while(s->maxp < siz)
320
396
                        s->maxp <<= 1;
321
 
                s->p = realloc(s->p, s->maxp);
322
 
                if(s->p == nil) {
323
 
                        diag("out of memory");
324
 
                        errorexit();
325
 
                }
 
397
                s->p = erealloc(s->p, s->maxp);
326
398
                memset(s->p+s->np, 0, s->maxp-s->np);
327
399
        }
328
400
        s->np = siz;
363
435
                        break;
364
436
                }
365
437
                break;
366
 
        
 
438
 
367
439
        case D_SCONST:
368
440
                for(i=0; i<siz; i++)
369
441
                        s->p[off+i] = p->to.scon[i];
370
442
                break;
371
 
        
 
443
 
372
444
        case D_CONST:
373
445
                if(p->to.sym)
374
446
                        goto Addr;
449
521
                        errorexit();
450
522
                }
451
523
        }
452
 
        
 
524
 
453
525
        for(; addr < eaddr; addr++)
454
526
                cput(0);
455
527
        cflush();
456
528
}
457
 
                        
 
529
 
458
530
void
459
531
codeblk(int32 addr, int32 size)
460
532
{
497
569
                        Bprint(&bso, "%.6llux\t%-20s | foreign text\n", (vlong)addr, sym->name);
498
570
                        n = sym->size;
499
571
                        q = sym->p;
500
 
                        
 
572
 
501
573
                        while(n >= 16) {
502
574
                                Bprint(&bso, "%.6ux\t%-20.16I\n", addr, q);
503
575
                                addr += 16;
509
581
                        addr += n;
510
582
                        continue;
511
583
                }
512
 
                        
 
584
 
513
585
                Bprint(&bso, "%.6llux\t%-20s | %P\n", (vlong)sym->value, sym->name, p);
514
586
                for(p = p->link; p != P; p = p->link) {
515
587
                        if(p->link != P)
531
603
        }
532
604
        Bflush(&bso);
533
605
}
534
 
                        
 
606
 
535
607
void
536
608
datblk(int32 addr, int32 size)
537
609
{
538
610
        Sym *sym;
539
 
        int32 eaddr;
 
611
        int32 i, eaddr;
540
612
        uchar *p, *ep;
 
613
        char *typ, *rsname;
 
614
        Reloc *r;
541
615
 
542
616
        if(debug['a'])
543
617
                Bprint(&bso, "datblk [%#x,%#x) at offset %#llx\n", addr, addr+size, cpos());
557
631
                if(sym->value >= eaddr)
558
632
                        break;
559
633
                if(addr < sym->value) {
560
 
                        Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(pre-pad)", addr);
 
634
                        Bprint(&bso, "\t%.8ux| 00 ...\n", addr);
561
635
                        addr = sym->value;
562
636
                }
563
 
                Bprint(&bso, "%-20s %.8ux|", sym->name, (uint)addr);
 
637
                Bprint(&bso, "%s\n\t%.8ux|", sym->name, (uint)addr);
564
638
                p = sym->p;
565
639
                ep = p + sym->np;
566
 
                while(p < ep)
 
640
                while(p < ep) {
 
641
                        if(p > sym->p && (int)(p-sym->p)%16 == 0)
 
642
                                Bprint(&bso, "\n\t%.8ux|", (uint)(addr+(p-sym->p)));
567
643
                        Bprint(&bso, " %.2ux", *p++);
 
644
                }
568
645
                addr += sym->np;
569
646
                for(; addr < sym->value+sym->size; addr++)
570
647
                        Bprint(&bso, " %.2ux", 0);
571
648
                Bprint(&bso, "\n");
 
649
                
 
650
                if(linkmode == LinkExternal) {
 
651
                        for(i=0; i<sym->nr; i++) {
 
652
                                r = &sym->r[i];
 
653
                                rsname = "";
 
654
                                if(r->sym)
 
655
                                        rsname = r->sym->name;
 
656
                                typ = "?";
 
657
                                switch(r->type) {
 
658
                                case D_ADDR:
 
659
                                        typ = "addr";
 
660
                                        break;
 
661
                                case D_PCREL:
 
662
                                        typ = "pcrel";
 
663
                                        break;
 
664
                                }
 
665
                                Bprint(&bso, "\treloc %.8ux/%d %s %s+%#llx [%#llx]\n",
 
666
                                        (uint)(sym->value+r->off), r->siz, typ, rsname, (vlong)r->add, (vlong)(r->sym->value+r->add));
 
667
                        }
 
668
                }                               
572
669
        }
573
670
 
574
671
        if(addr < eaddr)
575
 
                Bprint(&bso, "%-20s %.8ux| 00 ...\n", "(post-pad)", (uint)addr);
576
 
        Bprint(&bso, "%-20s %.8ux|\n", "", (uint)eaddr);
 
672
                Bprint(&bso, "\t%.8ux| 00 ...\n", (uint)addr);
 
673
        Bprint(&bso, "\t%.8ux|\n", (uint)eaddr);
577
674
}
578
675
 
579
676
void
580
677
strnput(char *s, int n)
581
678
{
582
 
        for(; *s && n > 0; s++) {
 
679
        for(; n > 0 && *s; s++) {
583
680
                cput(*s);
584
681
                n--;
585
682
        }
594
691
{
595
692
        Sym *s, *sp;
596
693
        char *p;
597
 
        
 
694
 
598
695
        p = smprint("%s.str", name);
599
696
        sp = lookup(p, 0);
600
697
        free(p);
601
698
        addstring(sp, value);
602
699
 
603
700
        s = lookup(name, 0);
 
701
        s->size = 0;
604
702
        s->dupok = 1;
605
703
        addaddr(s, sp);
606
704
        adduint32(s, strlen(value));
607
705
        if(PtrSize == 8)
608
706
                adduint32(s, 0);  // round struct to pointer width
 
707
 
 
708
        // in case reachability has already been computed
 
709
        sp->reachable = s->reachable;
609
710
}
610
711
 
611
712
vlong
628
729
}
629
730
 
630
731
vlong
631
 
adduintxx(Sym *s, uint64 v, int wid)
 
732
setuintxx(Sym *s, vlong off, uint64 v, vlong wid)
632
733
{
633
 
        int32 i, r, fl;
 
734
        int32 i, fl;
634
735
        vlong o;
635
736
        uchar *cast;
636
737
 
637
738
        if(s->type == 0)
638
739
                s->type = SDATA;
639
740
        s->reachable = 1;
640
 
        r = s->size;
641
 
        s->size += wid;
642
 
        symgrow(s, s->size);
643
 
        assert(r+wid <= s->size);
 
741
        if(s->size < off+wid) {
 
742
                s->size = off+wid;
 
743
                symgrow(s, s->size);
 
744
        }
644
745
        fl = v;
645
746
        cast = (uchar*)&fl;
646
747
        switch(wid) {
647
748
        case 1:
648
 
                s->p[r] = cast[inuxi1[0]];
 
749
                s->p[off] = cast[inuxi1[0]];
649
750
                break;
650
751
        case 2:
651
752
                for(i=0; i<2; i++)
652
 
                        s->p[r+i] = cast[inuxi2[i]];
 
753
                        s->p[off+i] = cast[inuxi2[i]];
653
754
                break;
654
755
        case 4:
655
756
                for(i=0; i<4; i++)
656
 
                        s->p[r+i] = cast[inuxi4[i]];
 
757
                        s->p[off+i] = cast[inuxi4[i]];
657
758
                break;
658
759
        case 8:
659
760
                o = v;
660
761
                cast = (uchar*)&o;
661
762
                for(i=0; i<8; i++)
662
 
                        s->p[r+i] = cast[inuxi8[i]];
 
763
                        s->p[off+i] = cast[inuxi8[i]];
663
764
                break;
664
765
        }
665
 
        return r;
 
766
        return off;
 
767
}
 
768
 
 
769
vlong
 
770
adduintxx(Sym *s, uint64 v, int wid)
 
771
{
 
772
        vlong off;
 
773
 
 
774
        off = s->size;
 
775
        setuintxx(s, off, v, wid);
 
776
        return off;
666
777
}
667
778
 
668
779
vlong
689
800
        return adduintxx(s, v, 8);
690
801
}
691
802
 
 
803
void
 
804
setuint8(Sym *s, vlong r, uint8 v)
 
805
{
 
806
        setuintxx(s, r, v, 1);
 
807
}
 
808
 
 
809
void
 
810
setuint16(Sym *s, vlong r, uint16 v)
 
811
{
 
812
        setuintxx(s, r, v, 2);
 
813
}
 
814
 
 
815
void
 
816
setuint32(Sym *s, vlong r, uint32 v)
 
817
{
 
818
        setuintxx(s, r, v, 4);
 
819
}
 
820
 
 
821
void
 
822
setuint64(Sym *s, vlong r, uint64 v)
 
823
{
 
824
        setuintxx(s, r, v, 8);
 
825
}
 
826
 
692
827
vlong
693
 
addaddrplus(Sym *s, Sym *t, int32 add)
 
828
addaddrplus(Sym *s, Sym *t, vlong add)
694
829
{
695
830
        vlong i;
696
831
        Reloc *r;
711
846
}
712
847
 
713
848
static vlong
714
 
addaddrplus4(Sym *s, Sym *t, int32 add)
 
849
addaddrplus4(Sym *s, Sym *t, vlong add)
715
850
{
716
851
        vlong i;
717
852
        Reloc *r;
732
867
}
733
868
 
734
869
vlong
735
 
addpcrelplus(Sym *s, Sym *t, int32 add)
 
870
addpcrelplus(Sym *s, Sym *t, vlong add)
736
871
{
737
872
        vlong i;
738
873
        Reloc *r;
739
 
        
 
874
 
740
875
        if(s->type == 0)
741
876
                s->type = SDATA;
742
877
        s->reachable = 1;
759
894
}
760
895
 
761
896
vlong
 
897
setaddrplus(Sym *s, vlong off, Sym *t, vlong add)
 
898
{
 
899
        Reloc *r;
 
900
 
 
901
        if(s->type == 0)
 
902
                s->type = SDATA;
 
903
        s->reachable = 1;
 
904
        if(off+PtrSize > s->size) {
 
905
                s->size = off + PtrSize;
 
906
                symgrow(s, s->size);
 
907
        }
 
908
        r = addrel(s);
 
909
        r->sym = t;
 
910
        r->off = off;
 
911
        r->siz = PtrSize;
 
912
        r->type = D_ADDR;
 
913
        r->add = add;
 
914
        return off;
 
915
}
 
916
 
 
917
vlong
 
918
setaddr(Sym *s, vlong off, Sym *t)
 
919
{
 
920
        return setaddrplus(s, off, t, 0);
 
921
}
 
922
 
 
923
vlong
762
924
addsize(Sym *s, Sym *t)
763
925
{
764
926
        vlong i;
793
955
        }
794
956
}
795
957
 
 
958
static int32
 
959
symalign(Sym *s)
 
960
{
 
961
        int32 align;
 
962
 
 
963
        if(s->align != 0)
 
964
                return s->align;
 
965
 
 
966
        align = MaxAlign;
 
967
        while(align > s->size && align > 1)
 
968
                align >>= 1;
 
969
        if(align < s->align)
 
970
                align = s->align;
 
971
        return align;
 
972
}
 
973
        
 
974
static vlong
 
975
aligndatsize(vlong datsize, Sym *s)
 
976
{
 
977
        return rnd(datsize, symalign(s));
 
978
}
 
979
 
 
980
// maxalign returns the maximum required alignment for
 
981
// the list of symbols s; the list stops when s->type exceeds type.
 
982
static int32
 
983
maxalign(Sym *s, int type)
 
984
{
 
985
        int32 align, max;
 
986
        
 
987
        max = 0;
 
988
        for(; s != S && s->type <= type; s = s->next) {
 
989
                align = symalign(s);
 
990
                if(max < align)
 
991
                        max = align;
 
992
        }
 
993
        return max;
 
994
}
 
995
 
 
996
static void
 
997
gcaddsym(Sym *gc, Sym *s, vlong off)
 
998
{
 
999
        vlong a;
 
1000
        Sym *gotype;
 
1001
 
 
1002
        if(s->size < PtrSize)
 
1003
                return;
 
1004
        if(strcmp(s->name, ".string") == 0)
 
1005
                return;
 
1006
 
 
1007
        gotype = s->gotype;
 
1008
        if(gotype != nil) {
 
1009
                //print("gcaddsym:    %s    %d    %s\n", s->name, s->size, gotype->name);
 
1010
                adduintxx(gc, GC_CALL, PtrSize);
 
1011
                adduintxx(gc, off, PtrSize);
 
1012
                addpcrelplus(gc, decodetype_gc(gotype), 3*PtrSize+4);
 
1013
                if(PtrSize == 8)
 
1014
                        adduintxx(gc, 0, 4);
 
1015
        } else {
 
1016
                //print("gcaddsym:    %s    %d    <unknown type>\n", s->name, s->size);
 
1017
                for(a = -off&(PtrSize-1); a+PtrSize<=s->size; a+=PtrSize) {
 
1018
                        adduintxx(gc, GC_APTR, PtrSize);
 
1019
                        adduintxx(gc, off+a, PtrSize);
 
1020
                }
 
1021
        }
 
1022
}
 
1023
 
 
1024
void
 
1025
growdatsize(vlong *datsizep, Sym *s)
 
1026
{
 
1027
        vlong datsize;
 
1028
        
 
1029
        datsize = *datsizep;
 
1030
        if(s->size < 0)
 
1031
                diag("negative size (datsize = %lld, s->size = %lld)", datsize, s->size);
 
1032
        if(datsize + s->size < datsize)
 
1033
                diag("symbol too large (datsize = %lld, s->size = %lld)", datsize, s->size);
 
1034
        *datsizep = datsize + s->size;
 
1035
}
 
1036
 
796
1037
void
797
1038
dodata(void)
798
1039
{
799
 
        int32 t, datsize;
800
 
        Section *sect, *noptr;
 
1040
        int32 n;
 
1041
        vlong datsize;
 
1042
        Section *sect;
801
1043
        Sym *s, *last, **l;
 
1044
        Sym *gcdata1, *gcbss1;
802
1045
 
803
1046
        if(debug['v'])
804
1047
                Bprint(&bso, "%5.2f dodata\n", cputime());
805
1048
        Bflush(&bso);
806
1049
 
 
1050
        // define garbage collection symbols
 
1051
        gcdata1 = lookup("gcdata", 0);
 
1052
        gcdata1->type = STYPE;
 
1053
        gcdata1->reachable = 1;
 
1054
        gcbss1 = lookup("gcbss", 0);
 
1055
        gcbss1->type = STYPE;
 
1056
        gcbss1->reachable = 1;
 
1057
 
 
1058
        // size of .data and .bss section. the zero value is later replaced by the actual size of the section.
 
1059
        adduintxx(gcdata1, 0, PtrSize);
 
1060
        adduintxx(gcbss1, 0, PtrSize);
 
1061
 
807
1062
        last = nil;
808
1063
        datap = nil;
809
1064
 
832
1087
         * to assign addresses, record all the necessary
833
1088
         * dynamic relocations.  these will grow the relocation
834
1089
         * symbol, which is itself data.
 
1090
         *
 
1091
         * on darwin, we need the symbol table numbers for dynreloc.
835
1092
         */
 
1093
        if(HEADTYPE == Hdarwin)
 
1094
                machosymorder();
836
1095
        dynreloc();
837
 
        
 
1096
 
838
1097
        /* some symbols may no longer belong in datap (Mach-O) */
839
1098
        for(l=&datap; (s=*l) != nil; ) {
840
1099
                if(s->type <= STEXT || SXREF <= s->type)
844
1103
        }
845
1104
        *l = nil;
846
1105
 
847
 
        datap = datsort(datap);
 
1106
        if(flag_shared) {
 
1107
                for(s=datap; s != nil; s = s->next) {
 
1108
                        if(s->rel_ro)
 
1109
                                s->type = SDATARELRO;
 
1110
                }
 
1111
        }
 
1112
        datap = listsort(datap, datcmp, offsetof(Sym, next));
848
1113
 
849
1114
        /*
850
 
         * allocate data sections.  list is sorted by type,
 
1115
         * allocate sections.  list is sorted by type,
851
1116
         * so we can just walk it for each piece we want to emit.
 
1117
         * segdata is processed before segtext, because we need
 
1118
         * to see all symbols in the .data and .bss sections in order
 
1119
         * to generate garbage collection information.
852
1120
         */
853
1121
 
 
1122
        /* begin segdata */
 
1123
 
 
1124
        /* skip symbols belonging to segtext */
 
1125
        s = datap;
 
1126
        for(; s != nil && s->type < SELFSECT; s = s->next)
 
1127
                ;
 
1128
 
 
1129
        /* writable ELF sections */
 
1130
        datsize = 0;
 
1131
        for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
 
1132
                sect = addsection(&segdata, s->name, 06);
 
1133
                sect->align = symalign(s);
 
1134
                datsize = rnd(datsize, sect->align);
 
1135
                sect->vaddr = datsize;
 
1136
                s->sect = sect;
 
1137
                s->type = SDATA;
 
1138
                s->value = datsize;
 
1139
                growdatsize(&datsize, s);
 
1140
                sect->len = datsize - sect->vaddr;
 
1141
        }
 
1142
 
 
1143
        /* pointer-free data */
 
1144
        sect = addsection(&segdata, ".noptrdata", 06);
 
1145
        sect->align = maxalign(s, SDATARELRO-1);
 
1146
        datsize = rnd(datsize, sect->align);
 
1147
        sect->vaddr = datsize;
 
1148
        lookup("noptrdata", 0)->sect = sect;
 
1149
        lookup("enoptrdata", 0)->sect = sect;
 
1150
        for(; s != nil && s->type < SDATARELRO; s = s->next) {
 
1151
                datsize = aligndatsize(datsize, s);
 
1152
                s->sect = sect;
 
1153
                s->type = SDATA;
 
1154
                s->value = datsize;
 
1155
                growdatsize(&datsize, s);
 
1156
        }
 
1157
        sect->len = datsize - sect->vaddr;
 
1158
 
 
1159
        /* dynamic relocated rodata */
 
1160
        if(flag_shared) {
 
1161
                sect = addsection(&segdata, ".data.rel.ro", 06);
 
1162
                sect->align = maxalign(s, SDATARELRO);
 
1163
                datsize = rnd(datsize, sect->align);
 
1164
                sect->vaddr = datsize;
 
1165
                lookup("datarelro", 0)->sect = sect;
 
1166
                lookup("edatarelro", 0)->sect = sect;
 
1167
                for(; s != nil && s->type == SDATARELRO; s = s->next) {
 
1168
                        datsize = aligndatsize(datsize, s);
 
1169
                        s->sect = sect;
 
1170
                        s->type = SDATA;
 
1171
                        s->value = datsize;
 
1172
                        growdatsize(&datsize, s);
 
1173
                }
 
1174
                sect->len = datsize - sect->vaddr;
 
1175
        }
 
1176
 
 
1177
        /* data */
 
1178
        sect = addsection(&segdata, ".data", 06);
 
1179
        sect->align = maxalign(s, SBSS-1);
 
1180
        datsize = rnd(datsize, sect->align);
 
1181
        sect->vaddr = datsize;
 
1182
        lookup("data", 0)->sect = sect;
 
1183
        lookup("edata", 0)->sect = sect;
 
1184
        for(; s != nil && s->type < SBSS; s = s->next) {
 
1185
                if(s->type == SDATARELRO) {
 
1186
                        cursym = s;
 
1187
                        diag("unexpected symbol type %d", s->type);
 
1188
                }
 
1189
                s->sect = sect;
 
1190
                s->type = SDATA;
 
1191
                datsize = aligndatsize(datsize, s);
 
1192
                s->value = datsize;
 
1193
                gcaddsym(gcdata1, s, datsize - sect->vaddr);  // gc
 
1194
                growdatsize(&datsize, s);
 
1195
        }
 
1196
        sect->len = datsize - sect->vaddr;
 
1197
 
 
1198
        adduintxx(gcdata1, GC_END, PtrSize);
 
1199
        setuintxx(gcdata1, 0, sect->len, PtrSize);
 
1200
 
 
1201
        /* bss */
 
1202
        sect = addsection(&segdata, ".bss", 06);
 
1203
        sect->align = maxalign(s, SNOPTRBSS-1);
 
1204
        datsize = rnd(datsize, sect->align);
 
1205
        sect->vaddr = datsize;
 
1206
        lookup("bss", 0)->sect = sect;
 
1207
        lookup("ebss", 0)->sect = sect;
 
1208
        for(; s != nil && s->type < SNOPTRBSS; s = s->next) {
 
1209
                s->sect = sect;
 
1210
                datsize = aligndatsize(datsize, s);
 
1211
                s->value = datsize;
 
1212
                gcaddsym(gcbss1, s, datsize - sect->vaddr);  // gc
 
1213
                growdatsize(&datsize, s);
 
1214
        }
 
1215
        sect->len = datsize - sect->vaddr;
 
1216
 
 
1217
        adduintxx(gcbss1, GC_END, PtrSize);
 
1218
        setuintxx(gcbss1, 0, sect->len, PtrSize);
 
1219
 
 
1220
        /* pointer-free bss */
 
1221
        sect = addsection(&segdata, ".noptrbss", 06);
 
1222
        sect->align = maxalign(s, SNOPTRBSS);
 
1223
        datsize = rnd(datsize, sect->align);
 
1224
        sect->vaddr = datsize;
 
1225
        lookup("noptrbss", 0)->sect = sect;
 
1226
        lookup("enoptrbss", 0)->sect = sect;
 
1227
        for(; s != nil && s->type == SNOPTRBSS; s = s->next) {
 
1228
                datsize = aligndatsize(datsize, s);
 
1229
                s->sect = sect;
 
1230
                s->value = datsize;
 
1231
                growdatsize(&datsize, s);
 
1232
        }
 
1233
        sect->len = datsize - sect->vaddr;
 
1234
        lookup("end", 0)->sect = sect;
 
1235
 
 
1236
        // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
 
1237
        if(datsize != (uint32)datsize) {
 
1238
                diag("data or bss segment too large");
 
1239
        }
 
1240
        
 
1241
        if(iself && linkmode == LinkExternal && s != nil && s->type == STLSBSS && HEADTYPE != Hopenbsd) {
 
1242
                sect = addsection(&segdata, ".tbss", 06);
 
1243
                sect->align = PtrSize;
 
1244
                sect->vaddr = 0;
 
1245
                datsize = 0;
 
1246
                for(; s != nil && s->type == STLSBSS; s = s->next) {
 
1247
                        datsize = aligndatsize(datsize, s);
 
1248
                        s->sect = sect;
 
1249
                        s->value = datsize;
 
1250
                        growdatsize(&datsize, s);
 
1251
                }
 
1252
                sect->len = datsize;
 
1253
        }
 
1254
        
 
1255
        if(s != nil) {
 
1256
                cursym = nil;
 
1257
                diag("unexpected symbol type %d for %s", s->type, s->name);
 
1258
        }
 
1259
 
 
1260
        /* we finished segdata, begin segtext */
 
1261
        s = datap;
 
1262
 
854
1263
        /* read-only data */
855
1264
        sect = addsection(&segtext, ".rodata", 04);
 
1265
        sect->align = maxalign(s, STYPELINK-1);
856
1266
        sect->vaddr = 0;
 
1267
        lookup("rodata", 0)->sect = sect;
 
1268
        lookup("erodata", 0)->sect = sect;
857
1269
        datsize = 0;
858
 
        s = datap;
859
 
        for(; s != nil && s->type < SSYMTAB; s = s->next) {
860
 
                if(s->align != 0)
861
 
                        datsize = rnd(datsize, s->align);
862
 
                s->type = SRODATA;
863
 
                s->value = datsize;
864
 
                datsize += rnd(s->size, PtrSize);
 
1270
        for(; s != nil && s->type < STYPELINK; s = s->next) {
 
1271
                datsize = aligndatsize(datsize, s);
 
1272
                s->sect = sect;
 
1273
                s->type = SRODATA;
 
1274
                s->value = datsize;
 
1275
                growdatsize(&datsize, s);
 
1276
        }
 
1277
        sect->len = datsize - sect->vaddr;
 
1278
 
 
1279
        /* typelink */
 
1280
        sect = addsection(&segtext, ".typelink", 04);
 
1281
        sect->align = maxalign(s, STYPELINK);
 
1282
        datsize = rnd(datsize, sect->align);
 
1283
        sect->vaddr = datsize;
 
1284
        lookup("typelink", 0)->sect = sect;
 
1285
        lookup("etypelink", 0)->sect = sect;
 
1286
        for(; s != nil && s->type == STYPELINK; s = s->next) {
 
1287
                datsize = aligndatsize(datsize, s);
 
1288
                s->sect = sect;
 
1289
                s->type = SRODATA;
 
1290
                s->value = datsize;
 
1291
                growdatsize(&datsize, s);
865
1292
        }
866
1293
        sect->len = datsize - sect->vaddr;
867
1294
 
868
1295
        /* gosymtab */
869
1296
        sect = addsection(&segtext, ".gosymtab", 04);
 
1297
        sect->align = maxalign(s, SPCLNTAB-1);
 
1298
        datsize = rnd(datsize, sect->align);
870
1299
        sect->vaddr = datsize;
 
1300
        lookup("symtab", 0)->sect = sect;
 
1301
        lookup("esymtab", 0)->sect = sect;
871
1302
        for(; s != nil && s->type < SPCLNTAB; s = s->next) {
 
1303
                datsize = aligndatsize(datsize, s);
 
1304
                s->sect = sect;
872
1305
                s->type = SRODATA;
873
1306
                s->value = datsize;
874
 
                datsize += s->size;
 
1307
                growdatsize(&datsize, s);
875
1308
        }
876
1309
        sect->len = datsize - sect->vaddr;
877
 
        datsize = rnd(datsize, PtrSize);
878
1310
 
879
1311
        /* gopclntab */
880
1312
        sect = addsection(&segtext, ".gopclntab", 04);
 
1313
        sect->align = maxalign(s, SELFROSECT-1);
 
1314
        datsize = rnd(datsize, sect->align);
881
1315
        sect->vaddr = datsize;
 
1316
        lookup("pclntab", 0)->sect = sect;
 
1317
        lookup("epclntab", 0)->sect = sect;
882
1318
        for(; s != nil && s->type < SELFROSECT; s = s->next) {
 
1319
                datsize = aligndatsize(datsize, s);
 
1320
                s->sect = sect;
883
1321
                s->type = SRODATA;
884
1322
                s->value = datsize;
885
 
                datsize += s->size;
 
1323
                growdatsize(&datsize, s);
886
1324
        }
887
1325
        sect->len = datsize - sect->vaddr;
888
 
        datsize = rnd(datsize, PtrSize);
889
1326
 
890
 
        /* read-only ELF sections */
 
1327
        /* read-only ELF, Mach-O sections */
891
1328
        for(; s != nil && s->type < SELFSECT; s = s->next) {
892
1329
                sect = addsection(&segtext, s->name, 04);
893
 
                if(s->align != 0)
894
 
                        datsize = rnd(datsize, s->align);
 
1330
                sect->align = symalign(s);
 
1331
                datsize = rnd(datsize, sect->align);
895
1332
                sect->vaddr = datsize;
 
1333
                s->sect = sect;
896
1334
                s->type = SRODATA;
897
1335
                s->value = datsize;
898
 
                datsize += rnd(s->size, PtrSize);
 
1336
                growdatsize(&datsize, s);
899
1337
                sect->len = datsize - sect->vaddr;
900
1338
        }
901
1339
 
902
 
        /* writable ELF sections */
903
 
        datsize = 0;
904
 
        for(; s != nil && s->type < SNOPTRDATA; s = s->next) {
905
 
                sect = addsection(&segdata, s->name, 06);
906
 
                if(s->align != 0)
907
 
                        datsize = rnd(datsize, s->align);
908
 
                sect->vaddr = datsize;
909
 
                s->type = SDATA;
910
 
                s->value = datsize;
911
 
                datsize += rnd(s->size, PtrSize);
912
 
                sect->len = datsize - sect->vaddr;
 
1340
        // 6g uses 4-byte relocation offsets, so the entire segment must fit in 32 bits.
 
1341
        if(datsize != (uint32)datsize) {
 
1342
                diag("text segment too large");
913
1343
        }
914
1344
        
915
 
        /* pointer-free data, then data */
916
 
        sect = addsection(&segdata, ".noptrdata", 06);
917
 
        sect->vaddr = datsize;
918
 
        noptr = sect;
919
 
        for(; ; s = s->next) {
920
 
                if((s == nil || s->type >= SDATA) && sect == noptr) {
921
 
                        // finish noptrdata, start data
922
 
                        datsize = rnd(datsize, 8);
923
 
                        sect->len = datsize - sect->vaddr;
924
 
                        sect = addsection(&segdata, ".data", 06);
925
 
                        sect->vaddr = datsize;
926
 
                }
927
 
                if(s == nil || s->type >= SBSS) {
928
 
                        // finish data
929
 
                        sect->len = datsize - sect->vaddr;
930
 
                        break;
931
 
                }
932
 
                s->type = SDATA;
933
 
                t = s->size;
934
 
                if(t >= PtrSize)
935
 
                        t = rnd(t, PtrSize);
936
 
                else if(t > 2)
937
 
                        t = rnd(t, 4);
938
 
                if(s->align != 0)
939
 
                        datsize = rnd(datsize, s->align);
940
 
                else if(t & 1) {
941
 
                        ;
942
 
                } else if(t & 2)
943
 
                        datsize = rnd(datsize, 2);
944
 
                else if(t & 4)
945
 
                        datsize = rnd(datsize, 4);
946
 
                else
947
 
                        datsize = rnd(datsize, 8);
948
 
                s->value = datsize;
949
 
                datsize += t;
950
 
        }
951
 
 
952
 
        /* bss, then pointer-free bss */
953
 
        noptr = nil;
954
 
        sect = addsection(&segdata, ".bss", 06);
955
 
        sect->vaddr = datsize;
956
 
        for(; ; s = s->next) {
957
 
                if((s == nil || s->type >= SNOPTRBSS) && noptr == nil) {
958
 
                        // finish bss, start noptrbss
959
 
                        datsize = rnd(datsize, 8);
960
 
                        sect->len = datsize - sect->vaddr;
961
 
                        sect = addsection(&segdata, ".noptrbss", 06);
962
 
                        sect->vaddr = datsize;
963
 
                        noptr = sect;
964
 
                }
965
 
                if(s == nil) {
966
 
                        sect->len = datsize - sect->vaddr;
967
 
                        break;
968
 
                }
969
 
                if(s->type > SNOPTRBSS) {
970
 
                        cursym = s;
971
 
                        diag("unexpected symbol type %d", s->type);
972
 
                }
973
 
                t = s->size;
974
 
                if(t >= PtrSize)
975
 
                        t = rnd(t, PtrSize);
976
 
                else if(t > 2)
977
 
                        t = rnd(t, 4);
978
 
                if(s->align != 0)
979
 
                        datsize = rnd(datsize, s->align);
980
 
                else if(t & 1) {
981
 
                        ;
982
 
                } else if(t & 2)
983
 
                        datsize = rnd(datsize, 2);
984
 
                else if(t & 4)
985
 
                        datsize = rnd(datsize, 4);
986
 
                else
987
 
                        datsize = rnd(datsize, 8);
988
 
                s->value = datsize;
989
 
                datsize += t;
990
 
        }
 
1345
        /* number the sections */
 
1346
        n = 1;
 
1347
        for(sect = segtext.sect; sect != nil; sect = sect->next)
 
1348
                sect->extnum = n++;
 
1349
        for(sect = segdata.sect; sect != nil; sect = sect->next)
 
1350
                sect->extnum = n++;
991
1351
}
992
1352
 
993
1353
// assign addresses to text
1002
1362
        addsection(&segtext, ".text", 05);
1003
1363
 
1004
1364
        // Assign PCs in text segment.
1005
 
        // Could parallelize, by assigning to text 
 
1365
        // Could parallelize, by assigning to text
1006
1366
        // and then letting threads copy down, but probably not worth it.
1007
1367
        sect = segtext.sect;
 
1368
        sect->align = FuncAlign;
 
1369
        lookup("text", 0)->sect = sect;
 
1370
        lookup("etext", 0)->sect = sect;
1008
1371
        va = INITTEXT;
1009
1372
        sect->vaddr = va;
1010
1373
        for(sym = textp; sym != nil; sym = sym->next) {
 
1374
                sym->sect = sect;
1011
1375
                if(sym->type & SSUB)
1012
1376
                        continue;
1013
1377
                if(sym->align != 0)
1014
1378
                        va = rnd(va, sym->align);
 
1379
                else if(sym->text != P)
 
1380
                        va = rnd(va, FuncAlign);
1015
1381
                sym->value = 0;
1016
1382
                for(sub = sym; sub != S; sub = sub->sub) {
1017
1383
                        sub->value += va;
1023
1389
                }
1024
1390
                va += sym->size;
1025
1391
        }
1026
 
        
1027
 
        // Align end of code so that rodata starts aligned.
1028
 
        // 128 bytes is likely overkill but definitely cheap.
1029
 
        va = rnd(va, 128);
1030
 
 
1031
1392
        sect->len = va - sect->vaddr;
1032
1393
}
1033
1394
 
1035
1396
void
1036
1397
address(void)
1037
1398
{
1038
 
        Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
 
1399
        Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss, *datarelro;
 
1400
        Section *typelink;
1039
1401
        Sym *sym, *sub;
1040
1402
        uvlong va;
 
1403
        vlong vlen;
1041
1404
 
1042
1405
        va = INITTEXT;
1043
1406
        segtext.rwx = 05;
1044
1407
        segtext.vaddr = va;
1045
1408
        segtext.fileoff = HEADR;
1046
1409
        for(s=segtext.sect; s != nil; s=s->next) {
 
1410
                va = rnd(va, s->align);
1047
1411
                s->vaddr = va;
1048
 
                va += rnd(s->len, PtrSize);
 
1412
                va += s->len;
1049
1413
        }
1050
1414
        segtext.len = va - INITTEXT;
1051
1415
        segtext.filelen = segtext.len;
1058
1422
        segdata.filelen = 0;
1059
1423
        if(HEADTYPE == Hwindows)
1060
1424
                segdata.fileoff = segtext.fileoff + rnd(segtext.len, PEFILEALIGN);
1061
 
        if(HEADTYPE == Hplan9x32)
 
1425
        if(HEADTYPE == Hplan9x64 || HEADTYPE == Hplan9x32)
1062
1426
                segdata.fileoff = segtext.fileoff + segtext.filelen;
1063
1427
        data = nil;
1064
1428
        noptr = nil;
1065
1429
        bss = nil;
1066
1430
        noptrbss = nil;
 
1431
        datarelro = nil;
1067
1432
        for(s=segdata.sect; s != nil; s=s->next) {
 
1433
                vlen = s->len;
 
1434
                if(s->next)
 
1435
                        vlen = s->next->vaddr - s->vaddr;
1068
1436
                s->vaddr = va;
1069
 
                va += s->len;
1070
 
                segdata.filelen += s->len;
 
1437
                va += vlen;
1071
1438
                segdata.len = va - segdata.vaddr;
1072
1439
                if(strcmp(s->name, ".data") == 0)
1073
1440
                        data = s;
1077
1444
                        bss = s;
1078
1445
                if(strcmp(s->name, ".noptrbss") == 0)
1079
1446
                        noptrbss = s;
 
1447
                if(strcmp(s->name, ".data.rel.ro") == 0)
 
1448
                        datarelro = s;
1080
1449
        }
1081
 
        segdata.filelen -= bss->len + noptrbss->len; // deduct .bss
 
1450
        segdata.filelen = bss->vaddr - segdata.vaddr;
1082
1451
 
1083
1452
        text = segtext.sect;
1084
1453
        rodata = text->next;
1085
 
        symtab = rodata->next;
 
1454
        typelink = rodata->next;
 
1455
        symtab = typelink->next;
1086
1456
        pclntab = symtab->next;
1087
1457
 
1088
1458
        for(sym = datap; sym != nil; sym = sym->next) {
1094
1464
                for(sub = sym->sub; sub != nil; sub = sub->sub)
1095
1465
                        sub->value += sym->value;
1096
1466
        }
1097
 
        
 
1467
 
1098
1468
        xdefine("text", STEXT, text->vaddr);
1099
1469
        xdefine("etext", STEXT, text->vaddr + text->len);
1100
1470
        xdefine("rodata", SRODATA, rodata->vaddr);
1101
1471
        xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
 
1472
        xdefine("typelink", SRODATA, typelink->vaddr);
 
1473
        xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
 
1474
        if(datarelro != nil) {
 
1475
                xdefine("datarelro", SRODATA, datarelro->vaddr);
 
1476
                xdefine("edatarelro", SRODATA, datarelro->vaddr + datarelro->len);
 
1477
        }
 
1478
 
 
1479
        sym = lookup("gcdata", 0);
 
1480
        xdefine("egcdata", STYPE, symaddr(sym) + sym->size);
 
1481
        lookup("egcdata", 0)->sect = sym->sect;
 
1482
 
 
1483
        sym = lookup("gcbss", 0);
 
1484
        xdefine("egcbss", STYPE, symaddr(sym) + sym->size);
 
1485
        lookup("egcbss", 0)->sect = sym->sect;
 
1486
 
1102
1487
        xdefine("symtab", SRODATA, symtab->vaddr);
1103
1488
        xdefine("esymtab", SRODATA, symtab->vaddr + symtab->len);
1104
1489
        xdefine("pclntab", SRODATA, pclntab->vaddr);