~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/cmd/6l/asm.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:
74
74
        return 0;
75
75
}
76
76
 
77
 
enum {
78
 
        ElfStrEmpty,
79
 
        ElfStrInterp,
80
 
        ElfStrHash,
81
 
        ElfStrGot,
82
 
        ElfStrGotPlt,
83
 
        ElfStrDynamic,
84
 
        ElfStrDynsym,
85
 
        ElfStrDynstr,
86
 
        ElfStrRela,
87
 
        ElfStrText,
88
 
        ElfStrData,
89
 
        ElfStrBss,
90
 
        ElfStrShstrtab,
91
 
        ElfStrSymtab,
92
 
        ElfStrStrtab,
93
 
        ElfStrRelaPlt,
94
 
        ElfStrPlt,
95
 
        ElfStrGnuVersion,
96
 
        ElfStrGnuVersionR,
97
 
        ElfStrNoteNetbsdIdent,
98
 
        ElfStrNoPtrData,
99
 
        ElfStrNoPtrBss,
100
 
        NElfStr
101
 
};
102
 
 
103
 
vlong elfstr[NElfStr];
104
 
 
105
77
static int
106
78
needlib(char *name)
107
79
{
127
99
static void addpltsym(Sym*);
128
100
static void addgotsym(Sym*);
129
101
 
 
102
Sym *
 
103
lookuprel(void)
 
104
{
 
105
        return lookup(".rela", 0);
 
106
}
 
107
 
 
108
void
 
109
adddynrela(Sym *rela, Sym *s, Reloc *r)
 
110
{
 
111
        addaddrplus(rela, s, r->off);
 
112
        adduint64(rela, R_X86_64_RELATIVE);
 
113
        addaddrplus(rela, r->sym, r->add); // Addend
 
114
}
 
115
 
130
116
void
131
117
adddynrel(Sym *s, Reloc *r)
132
118
{
145
131
 
146
132
        // Handle relocations found in ELF object files.
147
133
        case 256 + R_X86_64_PC32:
148
 
                if(targ->dynimpname != nil && !targ->dynexport)
 
134
                if(targ->type == SDYNIMPORT)
149
135
                        diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
150
136
                if(targ->type == 0 || targ->type == SXREF)
151
137
                        diag("unknown symbol %s in pcrel", targ->name);
156
142
        case 256 + R_X86_64_PLT32:
157
143
                r->type = D_PCREL;
158
144
                r->add += 4;
159
 
                if(targ->dynimpname != nil && !targ->dynexport) {
 
145
                if(targ->type == SDYNIMPORT) {
160
146
                        addpltsym(targ);
161
147
                        r->sym = lookup(".plt", 0);
162
148
                        r->add += targ->plt;
164
150
                return;
165
151
        
166
152
        case 256 + R_X86_64_GOTPCREL:
167
 
                if(targ->dynimpname == nil || targ->dynexport) {
 
153
                if(targ->type != SDYNIMPORT) {
168
154
                        // have symbol
169
155
                        if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
170
156
                                // turn MOVQ of GOT entry into LEAQ of symbol itself
175
161
                        }
176
162
                        // fall back to using GOT and hope for the best (CMOV*)
177
163
                        // TODO: just needs relocation, no need to put in .dynsym
178
 
                        targ->dynimpname = targ->name;
179
164
                }
180
165
                addgotsym(targ);
181
166
                r->type = D_PCREL;
185
170
                return;
186
171
        
187
172
        case 256 + R_X86_64_64:
188
 
                if(targ->dynimpname != nil && !targ->dynexport)
 
173
                if(targ->type == SDYNIMPORT)
189
174
                        diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
190
175
                r->type = D_ADDR;
191
176
                return;
196
181
        case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
197
182
                // TODO: What is the difference between all these?
198
183
                r->type = D_ADDR;
199
 
                if(targ->dynimpname != nil && !targ->dynexport)
 
184
                if(targ->type == SDYNIMPORT)
200
185
                        diag("unexpected reloc for dynamic symbol %s", targ->name);
201
186
                return;
202
187
 
203
188
        case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
204
 
                if(targ->dynimpname != nil && !targ->dynexport) {
 
189
                if(targ->type == SDYNIMPORT) {
205
190
                        addpltsym(targ);
206
191
                        r->sym = lookup(".plt", 0);
207
192
                        r->add = targ->plt;
215
200
        case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
216
201
        case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
217
202
                r->type = D_PCREL;
218
 
                if(targ->dynimpname != nil && !targ->dynexport)
 
203
                if(targ->type == SDYNIMPORT)
219
204
                        diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
220
205
                return;
221
206
 
222
207
        case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
223
 
                if(targ->dynimpname == nil || targ->dynexport) {
 
208
                if(targ->type != SDYNIMPORT) {
224
209
                        // have symbol
225
210
                        // turn MOVQ of GOT entry into LEAQ of symbol itself
226
211
                        if(r->off < 2 || s->p[r->off-2] != 0x8b) {
233
218
                }
234
219
                // fall through
235
220
        case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
236
 
                if(targ->dynimpname == nil || targ->dynexport)
 
221
                if(targ->type != SDYNIMPORT)
237
222
                        diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
238
223
                addgotsym(targ);
239
224
                r->type = D_PCREL;
243
228
        }
244
229
        
245
230
        // Handle references to ELF symbols from our own object files.
246
 
        if(targ->dynimpname == nil || targ->dynexport)
 
231
        if(targ->type != SDYNIMPORT)
247
232
                return;
248
233
 
249
234
        switch(r->type) {
299
284
}
300
285
 
301
286
int
 
287
elfreloc1(Reloc *r, vlong sectoff)
 
288
{
 
289
        int32 elfsym;
 
290
 
 
291
        VPUT(sectoff);
 
292
 
 
293
        elfsym = r->xsym->elfsym;
 
294
        switch(r->type) {
 
295
        default:
 
296
                return -1;
 
297
 
 
298
        case D_ADDR:
 
299
                if(r->siz == 4)
 
300
                        VPUT(R_X86_64_32 | (uint64)elfsym<<32);
 
301
                else if(r->siz == 8)
 
302
                        VPUT(R_X86_64_64 | (uint64)elfsym<<32);
 
303
                else
 
304
                        return -1;
 
305
                break;
 
306
 
 
307
        case D_PCREL:
 
308
                if(r->siz == 4)
 
309
                        VPUT(R_X86_64_PC32 | (uint64)elfsym<<32);
 
310
                else
 
311
                        return -1;
 
312
                break;
 
313
        
 
314
        case D_TLS:
 
315
                if(r->siz == 4)
 
316
                        VPUT(R_X86_64_TPOFF32 | (uint64)elfsym<<32);
 
317
                else
 
318
                        return -1;
 
319
                break;          
 
320
        }
 
321
 
 
322
        VPUT(r->xadd);
 
323
        return 0;
 
324
}
 
325
 
 
326
int
 
327
machoreloc1(Reloc *r, vlong sectoff)
 
328
{
 
329
        uint32 v;
 
330
        Sym *rs;
 
331
        
 
332
        rs = r->xsym;
 
333
 
 
334
        if(rs->type == SHOSTOBJ) {
 
335
                if(rs->dynid < 0) {
 
336
                        diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
 
337
                        return -1;
 
338
                }
 
339
                v = rs->dynid;                  
 
340
                v |= 1<<27; // external relocation
 
341
        } else {
 
342
                v = rs->sect->extnum;
 
343
                if(v == 0) {
 
344
                        diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
 
345
                        return -1;
 
346
                }
 
347
        }
 
348
 
 
349
        switch(r->type) {
 
350
        default:
 
351
                return -1;
 
352
        case D_ADDR:
 
353
                v |= MACHO_X86_64_RELOC_UNSIGNED<<28;
 
354
                break;
 
355
        case D_PCREL:
 
356
                v |= 1<<24; // pc-relative bit
 
357
                v |= MACHO_X86_64_RELOC_BRANCH<<28;
 
358
                break;
 
359
        }
 
360
        
 
361
        switch(r->siz) {
 
362
        default:
 
363
                return -1;
 
364
        case 1:
 
365
                v |= 0<<25;
 
366
                break;
 
367
        case 2:
 
368
                v |= 1<<25;
 
369
                break;
 
370
        case 4:
 
371
                v |= 2<<25;
 
372
                break;
 
373
        case 8:
 
374
                v |= 3<<25;
 
375
                break;
 
376
        }
 
377
 
 
378
        LPUT(sectoff);
 
379
        LPUT(v);
 
380
        return 0;
 
381
}
 
382
 
 
383
int
302
384
archreloc(Reloc *r, Sym *s, vlong *val)
303
385
{
304
386
        USED(r);
307
389
        return -1;
308
390
}
309
391
 
310
 
static void
 
392
void
311
393
elfsetupplt(void)
312
394
{
313
395
        Sym *plt, *got;
431
513
void
432
514
adddynsym(Sym *s)
433
515
{
434
 
        Sym *d, *str;
 
516
        Sym *d;
435
517
        int t;
436
518
        char *name;
437
519
 
438
520
        if(s->dynid >= 0)
439
521
                return;
440
522
 
441
 
        if(s->dynimpname == nil)
442
 
                diag("adddynsym: no dynamic name for %s", s->name);
443
 
 
444
523
        if(iself) {
445
524
                s->dynid = nelfsym++;
446
525
 
447
526
                d = lookup(".dynsym", 0);
448
527
 
449
 
                name = s->dynimpname;
450
 
                if(name == nil)
451
 
                        name = s->name;
 
528
                name = s->extname;
452
529
                adduint32(d, addstring(lookup(".dynstr", 0), name));
453
530
                /* type */
454
531
                t = STB_GLOBAL << 4;
455
 
                if(s->dynexport && s->type == STEXT)
 
532
                if(s->cgoexport && (s->type&SMASK) == STEXT)
456
533
                        t |= STT_FUNC;
457
534
                else
458
535
                        t |= STT_OBJECT;
462
539
                adduint8(d, 0);
463
540
        
464
541
                /* section where symbol is defined */
465
 
                if(!s->dynexport && s->dynimpname != nil)
 
542
                if(s->type == SDYNIMPORT)
466
543
                        adduint16(d, SHN_UNDEF);
467
544
                else {
468
545
                        switch(s->type) {
490
567
                        addaddr(d, s);
491
568
        
492
569
                /* size of object */
493
 
                adduint64(d, 0);
 
570
                adduint64(d, s->size);
494
571
        
495
 
                if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
 
572
                if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) {
496
573
                        elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
497
574
                                addstring(lookup(".dynstr", 0), s->dynimplib));
498
575
                }
499
576
        } else if(HEADTYPE == Hdarwin) {
500
 
                // Mach-o symbol nlist64
501
 
                d = lookup(".dynsym", 0);
502
 
                name = s->dynimpname;
503
 
                if(name == nil)
504
 
                        name = s->name;
505
 
                s->dynid = d->size/16;
506
 
                // darwin still puts _ prefixes on all C symbols
507
 
                str = lookup(".dynstr", 0);
508
 
                adduint32(d, str->size);
509
 
                adduint8(str, '_');
510
 
                addstring(str, name);
511
 
                if(s->type == SDYNIMPORT) {
512
 
                        adduint8(d, 0x01);      // type - N_EXT - external symbol
513
 
                        adduint8(d, 0); // section
514
 
                } else {
515
 
                        adduint8(d, 0x0f);
516
 
                        switch(s->type) {
517
 
                        default:
518
 
                        case STEXT:
519
 
                                adduint8(d, 1);
520
 
                                break;
521
 
                        case SDATA:
522
 
                                adduint8(d, 2);
523
 
                                break;
524
 
                        case SBSS:
525
 
                                adduint8(d, 4);
526
 
                                break;
527
 
                        }
528
 
                }
529
 
                adduint16(d, 0);        // desc
530
 
                if(s->type == SDYNIMPORT)
531
 
                        adduint64(d, 0);        // value
532
 
                else
533
 
                        addaddr(d, s);
534
 
        } else if(HEADTYPE != Hwindows) {
 
577
                diag("adddynsym: missed symbol %s (%s)", s->name, s->extname);
 
578
        } else if(HEADTYPE == Hwindows) {
 
579
                // already taken care of
 
580
        } else {
535
581
                diag("adddynsym: unsupported binary format");
536
582
        }
537
583
}
557
603
}
558
604
 
559
605
void
560
 
doelf(void)
561
 
{
562
 
        Sym *s, *shstrtab, *dynstr;
563
 
 
564
 
        if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd && HEADTYPE != Hnetbsd)
565
 
                return;
566
 
 
567
 
        /* predefine strings we need for section headers */
568
 
        shstrtab = lookup(".shstrtab", 0);
569
 
        shstrtab->type = SELFROSECT;
570
 
        shstrtab->reachable = 1;
571
 
 
572
 
        elfstr[ElfStrEmpty] = addstring(shstrtab, "");
573
 
        elfstr[ElfStrText] = addstring(shstrtab, ".text");
574
 
        elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata");
575
 
        elfstr[ElfStrData] = addstring(shstrtab, ".data");
576
 
        elfstr[ElfStrBss] = addstring(shstrtab, ".bss");
577
 
        elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss");
578
 
        if(HEADTYPE == Hnetbsd)
579
 
                elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbsd.ident");
580
 
        addstring(shstrtab, ".elfdata");
581
 
        addstring(shstrtab, ".rodata");
582
 
        addstring(shstrtab, ".gosymtab");
583
 
        addstring(shstrtab, ".gopclntab");
584
 
        if(!debug['s']) {
585
 
                elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab");
586
 
                elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab");
587
 
                dwarfaddshstrings(shstrtab);
588
 
        }
589
 
        elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab");
590
 
 
591
 
        if(!debug['d']) {       /* -d suppresses dynamic loader format */
592
 
                elfstr[ElfStrInterp] = addstring(shstrtab, ".interp");
593
 
                elfstr[ElfStrHash] = addstring(shstrtab, ".hash");
594
 
                elfstr[ElfStrGot] = addstring(shstrtab, ".got");
595
 
                elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt");
596
 
                elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic");
597
 
                elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym");
598
 
                elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr");
599
 
                elfstr[ElfStrRela] = addstring(shstrtab, ".rela");
600
 
                elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt");
601
 
                elfstr[ElfStrPlt] = addstring(shstrtab, ".plt");
602
 
                elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version");
603
 
                elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r");
604
 
 
605
 
                /* dynamic symbol table - first entry all zeros */
606
 
                s = lookup(".dynsym", 0);
607
 
                s->type = SELFROSECT;
608
 
                s->reachable = 1;
609
 
                s->size += ELF64SYMSIZE;
610
 
 
611
 
                /* dynamic string table */
612
 
                s = lookup(".dynstr", 0);
613
 
                s->type = SELFROSECT;
614
 
                s->reachable = 1;
615
 
                if(s->size == 0)
616
 
                        addstring(s, "");
617
 
                dynstr = s;
618
 
 
619
 
                /* relocation table */
620
 
                s = lookup(".rela", 0);
621
 
                s->reachable = 1;
622
 
                s->type = SELFROSECT;
623
 
 
624
 
                /* global offset table */
625
 
                s = lookup(".got", 0);
626
 
                s->reachable = 1;
627
 
                s->type = SELFSECT; // writable
628
 
 
629
 
                /* hash */
630
 
                s = lookup(".hash", 0);
631
 
                s->reachable = 1;
632
 
                s->type = SELFROSECT;
633
 
 
634
 
                s = lookup(".got.plt", 0);
635
 
                s->reachable = 1;
636
 
                s->type = SELFSECT; // writable
637
 
 
638
 
                s = lookup(".plt", 0);
639
 
                s->reachable = 1;
640
 
                s->type = SELFROSECT;
641
 
                
642
 
                elfsetupplt();
643
 
                
644
 
                s = lookup(".rela.plt", 0);
645
 
                s->reachable = 1;
646
 
                s->type = SELFROSECT;
647
 
                
648
 
                s = lookup(".gnu.version", 0);
649
 
                s->reachable = 1;
650
 
                s->type = SELFROSECT;
651
 
                
652
 
                s = lookup(".gnu.version_r", 0);
653
 
                s->reachable = 1;
654
 
                s->type = SELFROSECT;
655
 
 
656
 
                /* define dynamic elf table */
657
 
                s = lookup(".dynamic", 0);
658
 
                s->reachable = 1;
659
 
                s->type = SELFSECT; // writable
660
 
 
661
 
                /*
662
 
                 * .dynamic table
663
 
                 */
664
 
                elfwritedynentsym(s, DT_HASH, lookup(".hash", 0));
665
 
                elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0));
666
 
                elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE);
667
 
                elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0));
668
 
                elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0));
669
 
                elfwritedynentsym(s, DT_RELA, lookup(".rela", 0));
670
 
                elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0));
671
 
                elfwritedynent(s, DT_RELAENT, ELF64RELASIZE);
672
 
                if(rpath)
673
 
                        elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath));
674
 
                
675
 
                elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0));
676
 
                elfwritedynent(s, DT_PLTREL, DT_RELA);
677
 
                elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0));
678
 
                elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0));
679
 
                
680
 
                elfwritedynent(s, DT_DEBUG, 0);
681
 
 
682
 
                // Do not write DT_NULL.  elfdynhash will finish it.
683
 
        }
684
 
}
685
 
 
686
 
void
687
 
shsym(ElfShdr *sh, Sym *s)
688
 
{
689
 
        vlong addr;
690
 
        addr = symaddr(s);
691
 
        if(sh->flags&SHF_ALLOC)
692
 
                sh->addr = addr;
693
 
        sh->off = datoff(addr);
694
 
        sh->size = s->size;
695
 
}
696
 
 
697
 
void
698
 
phsh(ElfPhdr *ph, ElfShdr *sh)
699
 
{
700
 
        ph->vaddr = sh->addr;
701
 
        ph->paddr = ph->vaddr;
702
 
        ph->off = sh->off;
703
 
        ph->filesz = sh->size;
704
 
        ph->memsz = sh->size;
705
 
        ph->align = sh->addralign;
706
 
}
707
 
 
708
 
void
709
606
asmb(void)
710
607
{
711
608
        int32 magic;
712
 
        int a, dynsym;
713
 
        vlong vl, startva, symo, dwarfoff, machlink, resoff;
714
 
        ElfEhdr *eh;
715
 
        ElfPhdr *ph, *pph;
716
 
        ElfShdr *sh;
 
609
        int i;
 
610
        vlong vl, symo, dwarfoff, machlink;
717
611
        Section *sect;
718
 
        int o;
 
612
        Sym *sym;
719
613
 
720
614
        if(debug['v'])
721
615
                Bprint(&bso, "%5.2f asmb\n", cputime());
722
616
        Bflush(&bso);
723
617
 
724
 
        elftextsh = 0;
725
 
        
726
618
        if(debug['v'])
727
619
                Bprint(&bso, "%5.2f codeblk\n", cputime());
728
620
        Bflush(&bso);
729
621
 
 
622
        if(iself)
 
623
                asmbelfsetup();
 
624
 
730
625
        sect = segtext.sect;
731
626
        cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
732
627
        codeblk(sect->vaddr, sect->len);
733
628
 
734
 
        /* output read-only data in text segment (rodata, gosymtab and pclntab) */
 
629
        /* output read-only data in text segment (rodata, gosymtab, pclntab, ...) */
735
630
        for(sect = sect->next; sect != nil; sect = sect->next) {
736
631
                cseek(sect->vaddr - segtext.vaddr + segtext.fileoff);
737
632
                datblk(sect->vaddr, sect->len);
763
658
        default:
764
659
                diag("unknown header type %d", HEADTYPE);
765
660
        case Hplan9x32:
 
661
        case Hplan9x64:
766
662
        case Helf:
767
663
                break;
768
664
        case Hdarwin:
773
669
        case Hnetbsd:
774
670
        case Hopenbsd:
775
671
                debug['8'] = 1; /* 64-bit addresses */
776
 
                /* index of elf text section; needed by asmelfsym, double-checked below */
777
 
                /* !debug['d'] causes extra sections before the .text section */
778
 
                elftextsh = 2;
779
 
                if(!debug['d']) {
780
 
                        elftextsh += 10;
781
 
                        if(elfverneed)
782
 
                                elftextsh += 2;
783
 
                }
784
 
                if(HEADTYPE == Hnetbsd)
785
 
                        elftextsh += 1;
786
672
                break;
787
673
        case Hwindows:
788
674
                break;
798
684
                Bflush(&bso);
799
685
                switch(HEADTYPE) {
800
686
                default:
801
 
                case Hplan9x32:
 
687
                case Hplan9x64:
802
688
                case Helf:
803
689
                        debug['s'] = 1;
804
690
                        symo = HEADR+segtext.len+segdata.filelen;
831
717
                                       Bprint(&bso, "%5.2f dwarf\n", cputime());
832
718
 
833
719
                                dwarfemitdebugsections();
 
720
                                
 
721
                                if(linkmode == LinkExternal)
 
722
                                        elfemitreloc();
 
723
                        }
 
724
                        break;
 
725
                case Hplan9x64:
 
726
                        asmplan9sym();
 
727
                        cflush();
 
728
 
 
729
                        sym = lookup("pclntab", 0);
 
730
                        if(sym != nil) {
 
731
                                lcsize = sym->np;
 
732
                                for(i=0; i < lcsize; i++)
 
733
                                        cput(sym->p[i]);
 
734
                                
 
735
                                cflush();
834
736
                        }
835
737
                        break;
836
738
                case Hwindows:
839
741
 
840
742
                        dwarfemitdebugsections();
841
743
                        break;
 
744
                case Hdarwin:
 
745
                        if(linkmode == LinkExternal)
 
746
                                machoemitreloc();
 
747
                        break;
842
748
                }
843
749
        }
844
750
 
848
754
        cseek(0L);
849
755
        switch(HEADTYPE) {
850
756
        default:
851
 
        case Hplan9x32: /* plan9 */
 
757
        case Hplan9x64: /* plan9 */
852
758
                magic = 4*26*26+7;
853
759
                magic |= 0x00008000;            /* fat header */
854
760
                lputb(magic);                   /* magic */
862
768
                lputb(lcsize);                  /* line offsets */
863
769
                vputb(vl);                      /* va of entry */
864
770
                break;
865
 
        case Hplan9x64: /* plan9 */
 
771
        case Hplan9x32: /* plan9 */
866
772
                magic = 4*26*26+7;
867
773
                lputb(magic);                   /* magic */
868
774
                lputb(segtext.filelen);         /* sizes */
880
786
        case Hfreebsd:
881
787
        case Hnetbsd:
882
788
        case Hopenbsd:
883
 
                /* elf amd-64 */
884
 
 
885
 
                eh = getElfEhdr();
886
 
                startva = INITTEXT - HEADR;
887
 
                resoff = ELFRESERVE;
888
 
 
889
 
                /* This null SHdr must appear before all others */
890
 
                newElfShdr(elfstr[ElfStrEmpty]);
891
 
 
892
 
                /* program header info */
893
 
                pph = newElfPhdr();
894
 
                pph->type = PT_PHDR;
895
 
                pph->flags = PF_R + PF_X;
896
 
                pph->off = eh->ehsize;
897
 
                pph->vaddr = INITTEXT - HEADR + pph->off;
898
 
                pph->paddr = INITTEXT - HEADR + pph->off;
899
 
                pph->align = INITRND;
900
 
 
901
 
                /*
902
 
                 * PHDR must be in a loaded segment. Adjust the text
903
 
                 * segment boundaries downwards to include it.
904
 
                 */
905
 
                o = segtext.vaddr - pph->vaddr;
906
 
                segtext.vaddr -= o;
907
 
                segtext.len += o;
908
 
                o = segtext.fileoff - pph->off;
909
 
                segtext.fileoff -= o;
910
 
                segtext.filelen += o;
911
 
 
912
 
                if(!debug['d']) {
913
 
                        /* interpreter */
914
 
                        sh = newElfShdr(elfstr[ElfStrInterp]);
915
 
                        sh->type = SHT_PROGBITS;
916
 
                        sh->flags = SHF_ALLOC;
917
 
                        sh->addralign = 1;
918
 
                        if(interpreter == nil) {
919
 
                                switch(HEADTYPE) {
920
 
                                case Hlinux:
921
 
                                        interpreter = linuxdynld;
922
 
                                        break;
923
 
                                case Hfreebsd:
924
 
                                        interpreter = freebsddynld;
925
 
                                        break;
926
 
                                case Hnetbsd:
927
 
                                        interpreter = netbsddynld;
928
 
                                        break;
929
 
                                case Hopenbsd:
930
 
                                        interpreter = openbsddynld;
931
 
                                        break;
932
 
                                }
933
 
                        }
934
 
                        resoff -= elfinterp(sh, startva, resoff, interpreter);
935
 
 
936
 
                        ph = newElfPhdr();
937
 
                        ph->type = PT_INTERP;
938
 
                        ph->flags = PF_R;
939
 
                        phsh(ph, sh);
940
 
                }
941
 
 
942
 
                if(HEADTYPE == Hnetbsd) {
943
 
                        sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]);
944
 
                        sh->type = SHT_NOTE;
945
 
                        sh->flags = SHF_ALLOC;
946
 
                        sh->addralign = 4;
947
 
                        resoff -= elfnetbsdsig(sh, startva, resoff);
948
 
 
949
 
                        ph = newElfPhdr();
950
 
                        ph->type = PT_NOTE;
951
 
                        ph->flags = PF_R;
952
 
                        phsh(ph, sh);
953
 
                }
954
 
 
955
 
                elfphload(&segtext);
956
 
                elfphload(&segdata);
957
 
 
958
 
                /* Dynamic linking sections */
959
 
                if(!debug['d']) {       /* -d suppresses dynamic loader format */
960
 
                        /* S headers for dynamic linking */
961
 
                        sh = newElfShdr(elfstr[ElfStrGot]);
962
 
                        sh->type = SHT_PROGBITS;
963
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
964
 
                        sh->entsize = 8;
965
 
                        sh->addralign = 8;
966
 
                        shsym(sh, lookup(".got", 0));
967
 
 
968
 
                        sh = newElfShdr(elfstr[ElfStrGotPlt]);
969
 
                        sh->type = SHT_PROGBITS;
970
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
971
 
                        sh->entsize = 8;
972
 
                        sh->addralign = 8;
973
 
                        shsym(sh, lookup(".got.plt", 0));
974
 
                        
975
 
                        dynsym = eh->shnum;
976
 
                        sh = newElfShdr(elfstr[ElfStrDynsym]);
977
 
                        sh->type = SHT_DYNSYM;
978
 
                        sh->flags = SHF_ALLOC;
979
 
                        sh->entsize = ELF64SYMSIZE;
980
 
                        sh->addralign = 8;
981
 
                        sh->link = dynsym+1;    // dynstr
982
 
                        // sh->info = index of first non-local symbol (number of local symbols)
983
 
                        shsym(sh, lookup(".dynsym", 0));
984
 
 
985
 
                        sh = newElfShdr(elfstr[ElfStrDynstr]);
986
 
                        sh->type = SHT_STRTAB;
987
 
                        sh->flags = SHF_ALLOC;
988
 
                        sh->addralign = 1;
989
 
                        shsym(sh, lookup(".dynstr", 0));
990
 
 
991
 
                        if(elfverneed) {
992
 
                                sh = newElfShdr(elfstr[ElfStrGnuVersion]);
993
 
                                sh->type = SHT_GNU_VERSYM;
994
 
                                sh->flags = SHF_ALLOC;
995
 
                                sh->addralign = 2;
996
 
                                sh->link = dynsym;
997
 
                                sh->entsize = 2;
998
 
                                shsym(sh, lookup(".gnu.version", 0));
999
 
                                
1000
 
                                sh = newElfShdr(elfstr[ElfStrGnuVersionR]);
1001
 
                                sh->type = SHT_GNU_VERNEED;
1002
 
                                sh->flags = SHF_ALLOC;
1003
 
                                sh->addralign = 8;
1004
 
                                sh->info = elfverneed;
1005
 
                                sh->link = dynsym+1;  // dynstr
1006
 
                                shsym(sh, lookup(".gnu.version_r", 0));
1007
 
                        }
1008
 
 
1009
 
                        sh = newElfShdr(elfstr[ElfStrRelaPlt]);
1010
 
                        sh->type = SHT_RELA;
1011
 
                        sh->flags = SHF_ALLOC;
1012
 
                        sh->entsize = ELF64RELASIZE;
1013
 
                        sh->addralign = 8;
1014
 
                        sh->link = dynsym;
1015
 
                        sh->info = eh->shnum;   // .plt
1016
 
                        shsym(sh, lookup(".rela.plt", 0));
1017
 
 
1018
 
                        sh = newElfShdr(elfstr[ElfStrPlt]);
1019
 
                        sh->type = SHT_PROGBITS;
1020
 
                        sh->flags = SHF_ALLOC+SHF_EXECINSTR;
1021
 
                        sh->entsize = 16;
1022
 
                        sh->addralign = 4;
1023
 
                        shsym(sh, lookup(".plt", 0));
1024
 
 
1025
 
                        sh = newElfShdr(elfstr[ElfStrHash]);
1026
 
                        sh->type = SHT_HASH;
1027
 
                        sh->flags = SHF_ALLOC;
1028
 
                        sh->entsize = 4;
1029
 
                        sh->addralign = 8;
1030
 
                        sh->link = dynsym;
1031
 
                        shsym(sh, lookup(".hash", 0));
1032
 
 
1033
 
                        sh = newElfShdr(elfstr[ElfStrRela]);
1034
 
                        sh->type = SHT_RELA;
1035
 
                        sh->flags = SHF_ALLOC;
1036
 
                        sh->entsize = ELF64RELASIZE;
1037
 
                        sh->addralign = 8;
1038
 
                        sh->link = dynsym;
1039
 
                        shsym(sh, lookup(".rela", 0));
1040
 
 
1041
 
                        /* sh and PT_DYNAMIC for .dynamic section */
1042
 
                        sh = newElfShdr(elfstr[ElfStrDynamic]);
1043
 
                        sh->type = SHT_DYNAMIC;
1044
 
                        sh->flags = SHF_ALLOC+SHF_WRITE;
1045
 
                        sh->entsize = 16;
1046
 
                        sh->addralign = 8;
1047
 
                        sh->link = dynsym+1;    // dynstr
1048
 
                        shsym(sh, lookup(".dynamic", 0));
1049
 
                        ph = newElfPhdr();
1050
 
                        ph->type = PT_DYNAMIC;
1051
 
                        ph->flags = PF_R + PF_W;
1052
 
                        phsh(ph, sh);
1053
 
                        
1054
 
                        /*
1055
 
                         * Thread-local storage segment (really just size).
1056
 
                         */
1057
 
                        if(tlsoffset != 0) {
1058
 
                                ph = newElfPhdr();
1059
 
                                ph->type = PT_TLS;
1060
 
                                ph->flags = PF_R;
1061
 
                                ph->memsz = -tlsoffset;
1062
 
                                ph->align = 8;
1063
 
                        }
1064
 
                }
1065
 
 
1066
 
                ph = newElfPhdr();
1067
 
                ph->type = PT_GNU_STACK;
1068
 
                ph->flags = PF_W+PF_R;
1069
 
                ph->align = 8;
1070
 
 
1071
 
                sh = newElfShstrtab(elfstr[ElfStrShstrtab]);
1072
 
                sh->type = SHT_STRTAB;
1073
 
                sh->addralign = 1;
1074
 
                shsym(sh, lookup(".shstrtab", 0));
1075
 
 
1076
 
                if(elftextsh != eh->shnum)
1077
 
                        diag("elftextsh = %d, want %d", elftextsh, eh->shnum);
1078
 
                for(sect=segtext.sect; sect!=nil; sect=sect->next)
1079
 
                        elfshbits(sect);
1080
 
                for(sect=segdata.sect; sect!=nil; sect=sect->next)
1081
 
                        elfshbits(sect);
1082
 
 
1083
 
                if(!debug['s']) {
1084
 
                        sh = newElfShdr(elfstr[ElfStrSymtab]);
1085
 
                        sh->type = SHT_SYMTAB;
1086
 
                        sh->off = symo;
1087
 
                        sh->size = symsize;
1088
 
                        sh->addralign = 8;
1089
 
                        sh->entsize = 24;
1090
 
                        sh->link = eh->shnum;   // link to strtab
1091
 
 
1092
 
                        sh = newElfShdr(elfstr[ElfStrStrtab]);
1093
 
                        sh->type = SHT_STRTAB;
1094
 
                        sh->off = symo+symsize;
1095
 
                        sh->size = elfstrsize;
1096
 
                        sh->addralign = 1;
1097
 
 
1098
 
                        dwarfaddelfheaders();
1099
 
                }
1100
 
 
1101
 
                /* Main header */
1102
 
                eh->ident[EI_MAG0] = '\177';
1103
 
                eh->ident[EI_MAG1] = 'E';
1104
 
                eh->ident[EI_MAG2] = 'L';
1105
 
                eh->ident[EI_MAG3] = 'F';
1106
 
                if(HEADTYPE == Hfreebsd)
1107
 
                        eh->ident[EI_OSABI] = ELFOSABI_FREEBSD;
1108
 
                else if(HEADTYPE == Hnetbsd)
1109
 
                        eh->ident[EI_OSABI] = ELFOSABI_NETBSD;
1110
 
                else if(HEADTYPE == Hopenbsd)
1111
 
                        eh->ident[EI_OSABI] = ELFOSABI_OPENBSD;
1112
 
                eh->ident[EI_CLASS] = ELFCLASS64;
1113
 
                eh->ident[EI_DATA] = ELFDATA2LSB;
1114
 
                eh->ident[EI_VERSION] = EV_CURRENT;
1115
 
 
1116
 
                eh->type = ET_EXEC;
1117
 
                eh->machine = EM_X86_64;
1118
 
                eh->version = EV_CURRENT;
1119
 
                eh->entry = entryvalue();
1120
 
 
1121
 
                pph->filesz = eh->phnum * eh->phentsize;
1122
 
                pph->memsz = pph->filesz;
1123
 
 
1124
 
                cseek(0);
1125
 
                a = 0;
1126
 
                a += elfwritehdr();
1127
 
                a += elfwritephdrs();
1128
 
                a += elfwriteshdrs();
1129
 
                a += elfwriteinterp(elfstr[ElfStrInterp]);
1130
 
                if(HEADTYPE == Hnetbsd)
1131
 
                        a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]);
1132
 
                if(a > ELFRESERVE)      
1133
 
                        diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
 
789
                asmbelf(symo);
1134
790
                break;
1135
791
        case Hwindows:
1136
792
                asmbpe();
1153
809
        v -= c;
1154
810
        return v;
1155
811
}
1156
 
 
1157
 
void
1158
 
genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
1159
 
{
1160
 
        Auto *a;
1161
 
        Sym *s;
1162
 
 
1163
 
        s = lookup("etext", 0);
1164
 
        if(s->type == STEXT)
1165
 
                put(s, s->name, 'T', s->value, s->size, s->version, 0);
1166
 
 
1167
 
        for(s=allsym; s!=S; s=s->allsym) {
1168
 
                if(s->hide)
1169
 
                        continue;
1170
 
                switch(s->type&~SSUB) {
1171
 
                case SCONST:
1172
 
                case SRODATA:
1173
 
                case SSYMTAB:
1174
 
                case SPCLNTAB:
1175
 
                case SDATA:
1176
 
                case SNOPTRDATA:
1177
 
                case SELFROSECT:
1178
 
                case SMACHOGOT:
1179
 
                case STYPE:
1180
 
                case SSTRING:
1181
 
                case SGOSTRING:
1182
 
                case SWINDOWS:
1183
 
                        if(!s->reachable)
1184
 
                                continue;
1185
 
                        put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
1186
 
                        continue;
1187
 
 
1188
 
                case SBSS:
1189
 
                case SNOPTRBSS:
1190
 
                        if(!s->reachable)
1191
 
                                continue;
1192
 
                        if(s->np > 0)
1193
 
                                diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
1194
 
                        put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
1195
 
                        continue;
1196
 
 
1197
 
                case SFILE:
1198
 
                        put(nil, s->name, 'f', s->value, 0, s->version, 0);
1199
 
                        continue;
1200
 
                }
1201
 
        }
1202
 
 
1203
 
        for(s = textp; s != nil; s = s->next) {
1204
 
                if(s->text == nil)
1205
 
                        continue;
1206
 
 
1207
 
                /* filenames first */
1208
 
                for(a=s->autom; a; a=a->link)
1209
 
                        if(a->type == D_FILE)
1210
 
                                put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
1211
 
                        else
1212
 
                        if(a->type == D_FILE1)
1213
 
                                put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
1214
 
 
1215
 
                put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
1216
 
 
1217
 
                /* frame, auto and param after */
1218
 
                put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0);
1219
 
 
1220
 
                for(a=s->autom; a; a=a->link)
1221
 
                        if(a->type == D_AUTO)
1222
 
                                put(nil, a->asym->name, 'a', -a->aoffset, 0, 0, a->gotype);
1223
 
                        else
1224
 
                        if(a->type == D_PARAM)
1225
 
                                put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a->gotype);
1226
 
        }
1227
 
        if(debug['v'] || debug['n'])
1228
 
                Bprint(&bso, "symsize = %ud\n", symsize);
1229
 
        Bflush(&bso);
1230
 
}