~ubuntu-branches/ubuntu/trusty/golang/trusty

« back to all changes in this revision

Viewing changes to src/cmd/ld/lib.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:
31
31
 
32
32
#include        "l.h"
33
33
#include        "lib.h"
 
34
#include        "../ld/elf.h"
34
35
#include        "../../pkg/runtime/stack.h"
35
36
 
36
37
#include        <ar.h>
44
45
static int      maxlibdir = 0;
45
46
static int      cout = -1;
46
47
 
 
48
// Set if we see an object compiled by the host compiler that is not
 
49
// from a package that is known to support internal linking mode.
 
50
static int      externalobj = 0;
 
51
 
 
52
static  void    hostlinksetup(void);
 
53
 
47
54
char*   goroot;
48
55
char*   goarch;
49
56
char*   goos;
59
66
                        maxlibdir = 8;
60
67
                else
61
68
                        maxlibdir *= 2;
62
 
                p = realloc(libdir, maxlibdir * sizeof(*p));
63
 
                if (p == nil) {
64
 
                        print("too many -L's: %d\n", nlibdir);
65
 
                        usage();
66
 
                }
 
69
                p = erealloc(libdir, maxlibdir * sizeof(*p));
67
70
                libdir = p;
68
71
        }
69
72
        libdir[nlibdir++] = arg;
72
75
void
73
76
libinit(void)
74
77
{
 
78
        char *race;
 
79
 
75
80
        fmtinstall('i', iconv);
76
81
        fmtinstall('Y', Yconv);
77
82
        fmtinstall('Z', Zconv);
80
85
                print("goarch is not known: %s\n", goarch);
81
86
 
82
87
        // add goroot to the end of the libdir list.
83
 
        Lflag(smprint("%s/pkg/%s_%s", goroot, goos, goarch));
 
88
        race = "";
 
89
        if(flag_race)
 
90
                race = "_race";
 
91
        Lflag(smprint("%s/pkg/%s_%s%s", goroot, goos, goarch, race));
84
92
 
85
93
        // Unix doesn't like it when we write to a running (or, sometimes,
86
94
        // recently run) binary, so remove the output file before writing it.
90
98
#endif
91
99
        cout = create(outfile, 1, 0775);
92
100
        if(cout < 0) {
93
 
                diag("cannot create %s", outfile);
 
101
                diag("cannot create %s: %r", outfile);
94
102
                errorexit();
95
103
        }
96
104
 
99
107
                sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
100
108
        }
101
109
        lookup(INITENTRY, 0)->type = SXREF;
 
110
        if(flag_shared) {
 
111
                if(LIBINITENTRY == nil) {
 
112
                        LIBINITENTRY = mal(strlen(goarch)+strlen(goos)+20);
 
113
                        sprint(LIBINITENTRY, "_rt0_%s_%s_lib", goarch, goos);
 
114
                }
 
115
                lookup(LIBINITENTRY, 0)->type = SXREF;
 
116
        }
102
117
}
103
118
 
104
119
void
230
245
 
231
246
        if(libraryp == nlibrary){
232
247
                nlibrary = 50 + 2*libraryp;
233
 
                library = realloc(library, sizeof library[0] * nlibrary);
 
248
                library = erealloc(library, sizeof library[0] * nlibrary);
234
249
        }
235
250
 
236
251
        l = &library[libraryp++];
276
291
void
277
292
loadlib(void)
278
293
{
279
 
        int i;
 
294
        int i, w, x;
 
295
        Sym *s;
280
296
 
281
297
        loadinternal("runtime");
282
298
        if(thechar == '5')
283
299
                loadinternal("math");
 
300
        if(flag_race)
 
301
                loadinternal("runtime/race");
 
302
        if(linkmode == LinkExternal) {
 
303
                // This indicates a user requested -linkmode=external.
 
304
                // The startup code uses an import of runtime/cgo to decide
 
305
                // whether to initialize the TLS.  So give it one.  This could
 
306
                // be handled differently but it's an unusual case.
 
307
                loadinternal("runtime/cgo");
 
308
                // Pretend that we really imported the package.
 
309
                // This will do no harm if we did in fact import it.
 
310
                s = lookup("go.importpath.runtime/cgo.", 0);
 
311
                s->type = SDATA;
 
312
                s->dupok = 1;
 
313
                s->reachable = 1;
 
314
        }
284
315
 
285
316
        for(i=0; i<libraryp; i++) {
286
317
                if(debug['v'])
289
320
                objfile(library[i].file, library[i].pkg);
290
321
        }
291
322
        
 
323
        if(linkmode == LinkAuto) {
 
324
                if(iscgo && externalobj)
 
325
                        linkmode = LinkExternal;
 
326
                else
 
327
                        linkmode = LinkInternal;
 
328
        }
 
329
 
 
330
        if(linkmode == LinkInternal) {
 
331
                // Drop all the cgo_import_static declarations.
 
332
                // Turns out we won't be needing them.
 
333
                for(s = allsym; s != S; s = s->allsym)
 
334
                        if(s->type == SHOSTOBJ) {
 
335
                                // If a symbol was marked both
 
336
                                // cgo_import_static and cgo_import_dynamic,
 
337
                                // then we want to make it cgo_import_dynamic
 
338
                                // now.
 
339
                                if(s->extname != nil && s->dynimplib != nil && s->cgoexport == 0) {
 
340
                                        s->type = SDYNIMPORT;
 
341
                                } else
 
342
                                        s->type = 0;
 
343
                        }
 
344
        }
 
345
        
 
346
        // Now that we know the link mode, trim the dynexp list.
 
347
        x = CgoExportDynamic;
 
348
        if(linkmode == LinkExternal)
 
349
                x = CgoExportStatic;
 
350
        w = 0;
 
351
        for(i=0; i<ndynexp; i++)
 
352
                if(dynexp[i]->cgoexport & x)
 
353
                        dynexp[w++] = dynexp[i];
 
354
        ndynexp = w;
 
355
        
 
356
        // In internal link mode, read the host object files.
 
357
        if(linkmode == LinkInternal)
 
358
                hostobjs();
 
359
        else
 
360
                hostlinksetup();
 
361
 
292
362
        // We've loaded all the code now.
293
363
        // If there are no dynamic libraries needed, gcc disables dynamic linking.
294
364
        // Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
298
368
        //
299
369
        // Exception: on OS X, programs such as Shark only work with dynamic
300
370
        // binaries, so leave it enabled on OS X (Mach-O) binaries.
301
 
        if(!havedynamic && HEADTYPE != Hdarwin)
 
371
        if(!flag_shared && !havedynamic && HEADTYPE != Hdarwin)
302
372
                debug['d'] = 1;
303
373
        
304
374
        importcycles();
360
430
                /* load it as a regular file */
361
431
                l = Bseek(f, 0L, 2);
362
432
                Bseek(f, 0L, 0);
363
 
                ldobj(f, pkg, l, file, FileObj);
 
433
                ldobj(f, pkg, l, file, file, FileObj);
364
434
                Bterm(f);
365
435
                free(pkg);
366
436
                return;
367
437
        }
368
438
        
369
 
        /* skip over __.SYMDEF */
 
439
        /* skip over __.GOSYMDEF */
370
440
        off = Boffset(f);
371
441
        if((l = nextar(f, off, &arhdr)) <= 0) {
372
442
                diag("%s: short read on archive file symbol header", file);
402
472
         * the individual symbols that are unused.
403
473
         *
404
474
         * loading every object will also make it possible to
405
 
         * load foreign objects not referenced by __.SYMDEF.
 
475
         * load foreign objects not referenced by __.GOSYMDEF.
406
476
         */
407
477
        for(;;) {
408
478
                l = nextar(f, off, &arhdr);
419
489
                        l--;
420
490
                snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
421
491
                l = atolwhex(arhdr.size);
422
 
                ldobj(f, pkg, l, pname, ArchiveObj);
 
492
                ldobj(f, pkg, l, pname, file, ArchiveObj);
423
493
        }
424
494
 
425
495
out:
427
497
        free(pkg);
428
498
}
429
499
 
430
 
void
431
 
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
 
500
static void
 
501
dowrite(int fd, char *p, int n)
 
502
{
 
503
        int m;
 
504
        
 
505
        while(n > 0) {
 
506
                m = write(fd, p, n);
 
507
                if(m <= 0) {
 
508
                        cursym = S;
 
509
                        diag("write error: %r");
 
510
                        errorexit();
 
511
                }
 
512
                n -= m;
 
513
                p += m;
 
514
        }
 
515
}
 
516
 
 
517
typedef struct Hostobj Hostobj;
 
518
 
 
519
struct Hostobj
 
520
{
 
521
        void (*ld)(Biobuf*, char*, int64, char*);
 
522
        char *pkg;
 
523
        char *pn;
 
524
        char *file;
 
525
        int64 off;
 
526
        int64 len;
 
527
};
 
528
 
 
529
Hostobj *hostobj;
 
530
int nhostobj;
 
531
int mhostobj;
 
532
 
 
533
// These packages can use internal linking mode.
 
534
// Others trigger external mode.
 
535
const char *internalpkg[] = {
 
536
        "crypto/x509",
 
537
        "net",
 
538
        "os/user",
 
539
        "runtime/cgo",
 
540
        "runtime/race"
 
541
};
 
542
 
 
543
void
 
544
ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
 
545
{
 
546
        int i, isinternal;
 
547
        Hostobj *h;
 
548
 
 
549
        isinternal = 0;
 
550
        for(i=0; i<nelem(internalpkg); i++) {
 
551
                if(strcmp(pkg, internalpkg[i]) == 0) {
 
552
                        isinternal = 1;
 
553
                        break;
 
554
                }
 
555
        }
 
556
 
 
557
        if(!isinternal)
 
558
                externalobj = 1;
 
559
 
 
560
        if(nhostobj >= mhostobj) {
 
561
                if(mhostobj == 0)
 
562
                        mhostobj = 16;
 
563
                else
 
564
                        mhostobj *= 2;
 
565
                hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
 
566
        }
 
567
        h = &hostobj[nhostobj++];
 
568
        h->ld = ld;
 
569
        h->pkg = estrdup(pkg);
 
570
        h->pn = estrdup(pn);
 
571
        h->file = estrdup(file);
 
572
        h->off = Boffset(f);
 
573
        h->len = len;
 
574
}
 
575
 
 
576
void
 
577
hostobjs(void)
 
578
{
 
579
        int i;
 
580
        Biobuf *f;
 
581
        Hostobj *h;
 
582
        
 
583
        for(i=0; i<nhostobj; i++) {
 
584
                h = &hostobj[i];
 
585
                f = Bopen(h->file, OREAD);
 
586
                if(f == nil) {
 
587
                        cursym = S;
 
588
                        diag("cannot reopen %s: %r", h->pn);
 
589
                        errorexit();
 
590
                }
 
591
                Bseek(f, h->off, 0);
 
592
                h->ld(f, h->pkg, h->len, h->pn);
 
593
                Bterm(f);
 
594
        }
 
595
}
 
596
 
 
597
// provided by lib9
 
598
int runcmd(char**);
 
599
char* mktempdir(void);
 
600
void removeall(char*);
 
601
 
 
602
static void
 
603
rmtemp(void)
 
604
{
 
605
        removeall(tmpdir);
 
606
}
 
607
 
 
608
static void
 
609
hostlinksetup(void)
 
610
{
 
611
        char *p;
 
612
 
 
613
        if(linkmode != LinkExternal)
 
614
                return;
 
615
 
 
616
        // create temporary directory and arrange cleanup
 
617
        if(tmpdir == nil) {
 
618
                tmpdir = mktempdir();
 
619
                atexit(rmtemp);
 
620
        }
 
621
 
 
622
        // change our output to temporary object file
 
623
        close(cout);
 
624
        p = smprint("%s/go.o", tmpdir);
 
625
        cout = create(p, 1, 0775);
 
626
        if(cout < 0) {
 
627
                diag("cannot create %s: %r", p);
 
628
                errorexit();
 
629
        }
 
630
        free(p);
 
631
}
 
632
 
 
633
void
 
634
hostlink(void)
 
635
{
 
636
        char *p, **argv;
 
637
        int c, i, w, n, argc, len;
 
638
        Hostobj *h;
 
639
        Biobuf *f;
 
640
        static char buf[64<<10];
 
641
 
 
642
        if(linkmode != LinkExternal || nerrors > 0)
 
643
                return;
 
644
 
 
645
        c = 0;
 
646
        p = extldflags;
 
647
        while(p != nil) {
 
648
                while(*p == ' ')
 
649
                        p++;
 
650
                if(*p == '\0')
 
651
                        break;
 
652
                c++;
 
653
                p = strchr(p + 1, ' ');
 
654
        }
 
655
 
 
656
        argv = malloc((10+nhostobj+nldflag+c)*sizeof argv[0]);
 
657
        argc = 0;
 
658
        if(extld == nil)
 
659
                extld = "gcc";
 
660
        argv[argc++] = extld;
 
661
        switch(thechar){
 
662
        case '8':
 
663
                argv[argc++] = "-m32";
 
664
                break;
 
665
        case '6':
 
666
                argv[argc++] = "-m64";
 
667
                break;
 
668
        }
 
669
        if(!debug['s'])
 
670
                argv[argc++] = "-gdwarf-2"; 
 
671
        if(HEADTYPE == Hdarwin)
 
672
                argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
 
673
        argv[argc++] = "-o";
 
674
        argv[argc++] = outfile;
 
675
        
 
676
        if(rpath)
 
677
                argv[argc++] = smprint("-Wl,-rpath,%s", rpath);
 
678
 
 
679
        // Force global symbols to be exported for dlopen, etc.
 
680
        if(iself)
 
681
                argv[argc++] = "-rdynamic";
 
682
 
 
683
        // already wrote main object file
 
684
        // copy host objects to temporary directory
 
685
        for(i=0; i<nhostobj; i++) {
 
686
                h = &hostobj[i];
 
687
                f = Bopen(h->file, OREAD);
 
688
                if(f == nil) {
 
689
                        cursym = S;
 
690
                        diag("cannot reopen %s: %r", h->pn);
 
691
                        errorexit();
 
692
                }
 
693
                Bseek(f, h->off, 0);
 
694
                p = smprint("%s/%06d.o", tmpdir, i);
 
695
                argv[argc++] = p;
 
696
                w = create(p, 1, 0775);
 
697
                if(w < 0) {
 
698
                        cursym = S;
 
699
                        diag("cannot create %s: %r", p);
 
700
                        errorexit();
 
701
                }
 
702
                len = h->len;
 
703
                while(len > 0 && (n = Bread(f, buf, sizeof buf)) > 0){
 
704
                        if(n > len)
 
705
                                n = len;
 
706
                        dowrite(w, buf, n);
 
707
                        len -= n;
 
708
                }
 
709
                if(close(w) < 0) {
 
710
                        cursym = S;
 
711
                        diag("cannot write %s: %r", p);
 
712
                        errorexit();
 
713
                }
 
714
                Bterm(f);
 
715
        }
 
716
        
 
717
        argv[argc++] = smprint("%s/go.o", tmpdir);
 
718
        for(i=0; i<nldflag; i++)
 
719
                argv[argc++] = ldflag[i];
 
720
 
 
721
        p = extldflags;
 
722
        while(p != nil) {
 
723
                while(*p == ' ')
 
724
                        *p++ = '\0';
 
725
                if(*p == '\0')
 
726
                        break;
 
727
                argv[argc++] = p;
 
728
                p = strchr(p + 1, ' ');
 
729
        }
 
730
 
 
731
        argv[argc] = nil;
 
732
 
 
733
        quotefmtinstall();
 
734
        if(debug['v']) {
 
735
                Bprint(&bso, "host link:");
 
736
                for(i=0; i<argc; i++)
 
737
                        Bprint(&bso, " %q", argv[i]);
 
738
                Bprint(&bso, "\n");
 
739
                Bflush(&bso);
 
740
        }
 
741
 
 
742
        if(runcmd(argv) < 0) {
 
743
                cursym = S;
 
744
                diag("%s: running %s failed: %r", argv0, argv[0]);
 
745
                errorexit();
 
746
        }
 
747
}
 
748
 
 
749
void
 
750
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
432
751
{
433
752
        char *line;
434
753
        int n, c1, c2, c3, c4;
438
757
 
439
758
        eof = Boffset(f) + len;
440
759
 
441
 
        pn = strdup(pn);
 
760
        pn = estrdup(pn);
442
761
 
443
762
        c1 = Bgetc(f);
444
763
        c2 = Bgetc(f);
451
770
 
452
771
        magic = c1<<24 | c2<<16 | c3<<8 | c4;
453
772
        if(magic == 0x7f454c46) {       // \x7F E L F
454
 
                ldelf(f, pkg, len, pn);
455
 
                free(pn);
 
773
                ldhostobj(ldelf, f, pkg, len, pn, file);
456
774
                return;
457
775
        }
458
776
        if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
459
 
                ldmacho(f, pkg, len, pn);
460
 
                free(pn);
 
777
                ldhostobj(ldmacho, f, pkg, len, pn, file);
461
778
                return;
462
779
        }
463
780
        if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
464
 
                ldpe(f, pkg, len, pn);
465
 
                free(pn);
 
781
                ldhostobj(ldpe, f, pkg, len, pn, file);
466
782
                return;
467
783
        }
468
784
 
509
825
        line[n] = '\0';
510
826
        if(n-10 > strlen(t)) {
511
827
                if(theline == nil)
512
 
                        theline = strdup(line+10);
 
828
                        theline = estrdup(line+10);
513
829
                else if(strcmp(theline, line+10) != 0) {
514
830
                        line[n] = '\0';
515
831
                        diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
548
864
        free(pn);
549
865
}
550
866
 
 
867
Sym*
 
868
newsym(char *symb, int v)
 
869
{
 
870
        Sym *s;
 
871
        int l;
 
872
 
 
873
        l = strlen(symb) + 1;
 
874
        s = mal(sizeof(*s));
 
875
        if(debug['v'] > 1)
 
876
                Bprint(&bso, "newsym %s\n", symb);
 
877
 
 
878
        s->dynid = -1;
 
879
        s->plt = -1;
 
880
        s->got = -1;
 
881
        s->name = mal(l + 1);
 
882
        memmove(s->name, symb, l);
 
883
 
 
884
        s->type = 0;
 
885
        s->version = v;
 
886
        s->value = 0;
 
887
        s->sig = 0;
 
888
        s->size = 0;
 
889
        nsymbol++;
 
890
 
 
891
        s->allsym = allsym;
 
892
        allsym = s;
 
893
 
 
894
        return s;
 
895
}
 
896
 
551
897
static Sym*
552
898
_lookup(char *symb, int v, int creat)
553
899
{
554
900
        Sym *s;
555
901
        char *p;
556
902
        int32 h;
557
 
        int l, c;
 
903
        int c;
558
904
 
559
905
        h = v;
560
906
        for(p=symb; c = *p; p++)
561
907
                h = h+h+h + c;
562
 
        l = (p - symb) + 1;
563
908
        // not if(h < 0) h = ~h, because gcc 4.3 -O2 miscompiles it.
564
909
        h &= 0xffffff;
565
910
        h %= NHASH;
566
911
        for(s = hash[h]; s != S; s = s->hash)
567
 
                if(memcmp(s->name, symb, l) == 0)
 
912
                if(strcmp(s->name, symb) == 0)
568
913
                        return s;
569
914
        if(!creat)
570
915
                return nil;
571
916
 
572
 
        s = mal(sizeof(*s));
573
 
        if(debug['v'] > 1)
574
 
                Bprint(&bso, "lookup %s\n", symb);
575
 
 
576
 
        s->dynid = -1;
577
 
        s->plt = -1;
578
 
        s->got = -1;
579
 
        s->name = mal(l + 1);
580
 
        memmove(s->name, symb, l);
581
 
 
 
917
        s = newsym(symb, v);
 
918
        s->extname = s->name;
582
919
        s->hash = hash[h];
583
 
        s->type = 0;
584
 
        s->version = v;
585
 
        s->value = 0;
586
 
        s->sig = 0;
587
 
        s->size = 0;
588
920
        hash[h] = s;
589
 
        nsymbol++;
590
921
 
591
 
        s->allsym = allsym;
592
 
        allsym = s;
593
922
        return s;
594
923
}
595
924
 
999
1328
        sect->rwx = rwx;
1000
1329
        sect->name = name;
1001
1330
        sect->seg = seg;
 
1331
        sect->align = PtrSize; // everything is at least pointer-aligned
1002
1332
        *l = sect;
1003
1333
        return sect;
1004
1334
}
1372
1702
        return -1;  // not reached
1373
1703
}
1374
1704
 
 
1705
char*
 
1706
headstr(int v)
 
1707
{
 
1708
        static char buf[20];
 
1709
        int i;
 
1710
 
 
1711
        for(i=0; headers[i].name; i++)
 
1712
                if(v == headers[i].val)
 
1713
                        return headers[i].name;
 
1714
        snprint(buf, sizeof buf, "%d", v);
 
1715
        return buf;
 
1716
}
 
1717
 
1375
1718
void
1376
1719
undef(void)
1377
1720
{
1427
1770
        if(cbpmax < cbp)
1428
1771
                cbpmax = cbp;
1429
1772
        n = cbpmax - buf.cbuf;
1430
 
        if(n) {
1431
 
                if(write(cout, buf.cbuf, n) != n) {
1432
 
                        diag("write error: %r");
1433
 
                        errorexit();
1434
 
                }
1435
 
                coutpos += n;
1436
 
        }
 
1773
        dowrite(cout, buf.cbuf, n);
 
1774
        coutpos += n;
1437
1775
        cbp = buf.cbuf;
1438
1776
        cbc = sizeof(buf.cbuf);
1439
1777
        cbpmax = cbp;
1472
1810
cwrite(void *buf, int n)
1473
1811
{
1474
1812
        cflush();
1475
 
        if(write(cout, buf, n) != n) {
1476
 
                diag("write error: %r");
1477
 
                errorexit();
1478
 
        }
 
1813
        if(n <= 0)
 
1814
                return;
 
1815
        dowrite(cout, buf, n);
1479
1816
        coutpos += n;
1480
1817
}
 
1818
 
 
1819
void
 
1820
usage(void)
 
1821
{
 
1822
        fprint(2, "usage: %cl [options] main.%c\n", thechar, thechar);
 
1823
        flagprint(2);
 
1824
        exits("usage");
 
1825
}
 
1826
 
 
1827
void
 
1828
setheadtype(char *s)
 
1829
{
 
1830
        HEADTYPE = headtype(s);
 
1831
}
 
1832
 
 
1833
void
 
1834
setinterp(char *s)
 
1835
{
 
1836
        debug['I'] = 1; // denote cmdline interpreter override
 
1837
        interpreter = s;
 
1838
}
 
1839
 
 
1840
void
 
1841
doversion(void)
 
1842
{
 
1843
        print("%cl version %s\n", thechar, getgoversion());
 
1844
        errorexit();
 
1845
}
 
1846
 
 
1847
void
 
1848
genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
 
1849
{
 
1850
        Auto *a;
 
1851
        Sym *s;
 
1852
        int32 off;
 
1853
 
 
1854
        // These symbols won't show up in the first loop below because we
 
1855
        // skip STEXT symbols. Normal STEXT symbols are emitted by walking textp.
 
1856
        s = lookup("text", 0);
 
1857
        if(s->type == STEXT)
 
1858
                put(s, s->name, 'T', s->value, s->size, s->version, 0);
 
1859
        s = lookup("etext", 0);
 
1860
        if(s->type == STEXT)
 
1861
                put(s, s->name, 'T', s->value, s->size, s->version, 0);
 
1862
 
 
1863
        for(s=allsym; s!=S; s=s->allsym) {
 
1864
                if(s->hide || (s->name[0] == '.' && s->version == 0 && strcmp(s->name, ".rathole") != 0))
 
1865
                        continue;
 
1866
                switch(s->type&SMASK) {
 
1867
                case SCONST:
 
1868
                case SRODATA:
 
1869
                case SSYMTAB:
 
1870
                case SPCLNTAB:
 
1871
                case SDATA:
 
1872
                case SNOPTRDATA:
 
1873
                case SELFROSECT:
 
1874
                case SMACHOGOT:
 
1875
                case STYPE:
 
1876
                case SSTRING:
 
1877
                case SGOSTRING:
 
1878
                case SWINDOWS:
 
1879
                        if(!s->reachable)
 
1880
                                continue;
 
1881
                        put(s, s->name, 'D', symaddr(s), s->size, s->version, s->gotype);
 
1882
                        continue;
 
1883
 
 
1884
                case SBSS:
 
1885
                case SNOPTRBSS:
 
1886
                        if(!s->reachable)
 
1887
                                continue;
 
1888
                        if(s->np > 0)
 
1889
                                diag("%s should not be bss (size=%d type=%d special=%d)", s->name, (int)s->np, s->type, s->special);
 
1890
                        put(s, s->name, 'B', symaddr(s), s->size, s->version, s->gotype);
 
1891
                        continue;
 
1892
 
 
1893
                case SFILE:
 
1894
                        put(nil, s->name, 'f', s->value, 0, s->version, 0);
 
1895
                        continue;
 
1896
                }
 
1897
        }
 
1898
 
 
1899
        for(s = textp; s != nil; s = s->next) {
 
1900
                if(s->text == nil)
 
1901
                        continue;
 
1902
 
 
1903
                /* filenames first */
 
1904
                for(a=s->autom; a; a=a->link)
 
1905
                        if(a->type == D_FILE)
 
1906
                                put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0);
 
1907
                        else
 
1908
                        if(a->type == D_FILE1)
 
1909
                                put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0);
 
1910
 
 
1911
                put(s, s->name, 'T', s->value, s->size, s->version, s->gotype);
 
1912
 
 
1913
                /* frame, locals, args, auto and param after */
 
1914
                put(nil, ".frame", 'm', (uint32)s->text->to.offset+PtrSize, 0, 0, 0);
 
1915
                put(nil, ".locals", 'm', s->locals, 0, 0, 0);
 
1916
                if(s->text->textflag & NOSPLIT)
 
1917
                        put(nil, ".args", 'm', ArgsSizeUnknown, 0, 0, 0);
 
1918
                else
 
1919
                        put(nil, ".args", 'm', s->args, 0, 0, 0);
 
1920
 
 
1921
                for(a=s->autom; a; a=a->link) {
 
1922
                        // Emit a or p according to actual offset, even if label is wrong.
 
1923
                        // This avoids negative offsets, which cannot be encoded.
 
1924
                        if(a->type != D_AUTO && a->type != D_PARAM)
 
1925
                                continue;
 
1926
                        
 
1927
                        // compute offset relative to FP
 
1928
                        if(a->type == D_PARAM)
 
1929
                                off = a->aoffset;
 
1930
                        else
 
1931
                                off = a->aoffset - PtrSize;
 
1932
                        
 
1933
                        // FP
 
1934
                        if(off >= 0) {
 
1935
                                put(nil, a->asym->name, 'p', off, 0, 0, a->gotype);
 
1936
                                continue;
 
1937
                        }
 
1938
                        
 
1939
                        // SP
 
1940
                        if(off <= -PtrSize) {
 
1941
                                put(nil, a->asym->name, 'a', -(off+PtrSize), 0, 0, a->gotype);
 
1942
                                continue;
 
1943
                        }
 
1944
                        
 
1945
                        // Otherwise, off is addressing the saved program counter.
 
1946
                        // Something underhanded is going on. Say nothing.
 
1947
                }
 
1948
        }
 
1949
        if(debug['v'] || debug['n'])
 
1950
                Bprint(&bso, "symsize = %ud\n", symsize);
 
1951
        Bflush(&bso);
 
1952
}
 
1953
 
 
1954
char*
 
1955
estrdup(char *p)
 
1956
{
 
1957
        p = strdup(p);
 
1958
        if(p == nil) {
 
1959
                cursym = S;
 
1960
                diag("out of memory");
 
1961
                errorexit();
 
1962
        }
 
1963
        return p;
 
1964
}
 
1965
 
 
1966
void*
 
1967
erealloc(void *p, long n)
 
1968
{
 
1969
        p = realloc(p, n);
 
1970
        if(p == nil) {
 
1971
                cursym = S;
 
1972
                diag("out of memory");
 
1973
                errorexit();
 
1974
        }
 
1975
        return p;
 
1976
}