LEFT | RIGHT |
1 // Inferno utils/6l/asm.c | 1 // Inferno utils/6l/asm.c |
2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/asm.c | 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/asm.c |
3 // | 3 // |
4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. |
5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) |
6 // Portions Copyright © 1997-1999 Vita Nuova Limited | 6 // Portions Copyright © 1997-1999 Vita Nuova Limited |
7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) | 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov
a.com) |
8 // Portions Copyright © 2004,2006 Bruce Ellis | 8 // Portions Copyright © 2004,2006 Bruce Ellis |
9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) |
10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 datoff(vlong addr) | 67 datoff(vlong addr) |
68 { | 68 { |
69 if(addr >= segdata.vaddr) | 69 if(addr >= segdata.vaddr) |
70 return addr - segdata.vaddr + segdata.fileoff; | 70 return addr - segdata.vaddr + segdata.fileoff; |
71 if(addr >= segtext.vaddr) | 71 if(addr >= segtext.vaddr) |
72 return addr - segtext.vaddr + segtext.fileoff; | 72 return addr - segtext.vaddr + segtext.fileoff; |
73 diag("datoff %#llx", addr); | 73 diag("datoff %#llx", addr); |
74 return 0; | 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 ElfStrNoteOpenbsdIdent, | |
99 ElfStrNoteBuildInfo, | |
100 ElfStrNoPtrData, | |
101 ElfStrNoPtrBss, | |
102 NElfStr | |
103 }; | |
104 | |
105 vlong elfstr[NElfStr]; | |
106 | |
107 static int | 77 static int |
108 needlib(char *name) | 78 needlib(char *name) |
109 { | 79 { |
110 char *p; | 80 char *p; |
111 Sym *s; | 81 Sym *s; |
112 | 82 |
113 if(*name == '\0') | 83 if(*name == '\0') |
114 return 0; | 84 return 0; |
115 | 85 |
116 /* reuse hash code in symbol table */ | 86 /* reuse hash code in symbol table */ |
117 p = smprint(".elfload.%s", name); | 87 p = smprint(".elfload.%s", name); |
118 s = lookup(p, 0); | 88 s = lookup(p, 0); |
119 free(p); | 89 free(p); |
120 if(s->type == 0) { | 90 if(s->type == 0) { |
121 s->type = 100; // avoid SDATA, etc. | 91 s->type = 100; // avoid SDATA, etc. |
122 return 1; | 92 return 1; |
123 } | 93 } |
124 return 0; | 94 return 0; |
125 } | 95 } |
126 | 96 |
127 int nelfsym = 1; | 97 int nelfsym = 1; |
128 | 98 |
129 static void addpltsym(Sym*); | 99 static void addpltsym(Sym*); |
130 static void addgotsym(Sym*); | 100 static void addgotsym(Sym*); |
| 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 } |
131 | 115 |
132 void | 116 void |
133 adddynrel(Sym *s, Reloc *r) | 117 adddynrel(Sym *s, Reloc *r) |
134 { | 118 { |
135 Sym *targ, *rela, *got; | 119 Sym *targ, *rela, *got; |
136 ········ | 120 ········ |
137 targ = r->sym; | 121 targ = r->sym; |
138 cursym = s; | 122 cursym = s; |
139 | 123 |
140 switch(r->type) { | 124 switch(r->type) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 r->type = D_PCREL; | 167 r->type = D_PCREL; |
184 r->sym = lookup(".got", 0); | 168 r->sym = lookup(".got", 0); |
185 r->add += 4; | 169 r->add += 4; |
186 r->add += targ->got; | 170 r->add += targ->got; |
187 return; | 171 return; |
188 ········ | 172 ········ |
189 case 256 + R_X86_64_64: | 173 case 256 + R_X86_64_64: |
190 if(targ->dynimpname != nil && !targ->dynexport) | 174 if(targ->dynimpname != nil && !targ->dynexport) |
191 diag("unexpected R_X86_64_64 relocation for dynamic symb
ol %s", targ->name); | 175 diag("unexpected R_X86_64_64 relocation for dynamic symb
ol %s", targ->name); |
192 r->type = D_ADDR; | 176 r->type = D_ADDR; |
193 » » if (!debug['U']) | 177 » » return; |
194 » » » return; | |
195 » » else | |
196 » » » break; | |
197 ········ | 178 ········ |
198 // Handle relocations found in Mach-O object files. | 179 // Handle relocations found in Mach-O object files. |
199 case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 0: | 180 case 512 + MACHO_X86_64_RELOC_UNSIGNED*2 + 0: |
200 case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 0: | 181 case 512 + MACHO_X86_64_RELOC_SIGNED*2 + 0: |
201 case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0: | 182 case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0: |
202 // TODO: What is the difference between all these? | 183 // TODO: What is the difference between all these? |
203 r->type = D_ADDR; | 184 r->type = D_ADDR; |
204 if(targ->dynimpname != nil && !targ->dynexport) | 185 if(targ->dynimpname != nil && !targ->dynexport) |
205 diag("unexpected reloc for dynamic symbol %s", targ->nam
e); | 186 diag("unexpected reloc for dynamic symbol %s", targ->nam
e); |
206 return; | 187 return; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 if(targ->dynimpname == nil || targ->dynexport) | 222 if(targ->dynimpname == nil || targ->dynexport) |
242 diag("unexpected GOT reloc for non-dynamic symbol %s", t
arg->name); | 223 diag("unexpected GOT reloc for non-dynamic symbol %s", t
arg->name); |
243 addgotsym(targ); | 224 addgotsym(targ); |
244 r->type = D_PCREL; | 225 r->type = D_PCREL; |
245 r->sym = lookup(".got", 0); | 226 r->sym = lookup(".got", 0); |
246 r->add += targ->got; | 227 r->add += targ->got; |
247 return; | 228 return; |
248 } | 229 } |
249 ········ | 230 ········ |
250 // Handle references to ELF symbols from our own object files. | 231 // Handle references to ELF symbols from our own object files. |
251 » if((!debug['U'] || r->type != D_ADDR) && (targ->dynimpname == nil || tar
g->dynexport)) | 232 » if(targ->dynimpname == nil || targ->dynexport) |
252 return; | 233 return; |
253 | 234 |
254 switch(r->type) { | 235 switch(r->type) { |
255 case D_PCREL: | 236 case D_PCREL: |
256 addpltsym(targ); | 237 addpltsym(targ); |
257 r->sym = lookup(".plt", 0); | 238 r->sym = lookup(".plt", 0); |
258 r->add = targ->plt; | 239 r->add = targ->plt; |
259 return; | 240 return; |
260 ········ | 241 ········ |
261 case D_ADDR: | 242 case D_ADDR: |
262 » » if(!debug['U'] && s->type != SDATA) | 243 » » if(s->type != SDATA) |
263 break; | 244 break; |
264 if(iself) { | 245 if(iself) { |
265 adddynsym(targ); | 246 adddynsym(targ); |
266 rela = lookup(".rela", 0); | 247 rela = lookup(".rela", 0); |
267 addaddrplus(rela, s, r->off); | 248 addaddrplus(rela, s, r->off); |
268 if(r->siz == 8) | 249 if(r->siz == 8) |
269 adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_
64_64)); | 250 adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_
64_64)); |
270 else | 251 else |
271 adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_
64_32)); | 252 adduint64(rela, ELF64_R_INFO(targ->dynid, R_X86_
64_32)); |
272 adduint64(rela, r->add); | 253 adduint64(rela, r->add); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 | 286 |
306 int | 287 int |
307 archreloc(Reloc *r, Sym *s, vlong *val) | 288 archreloc(Reloc *r, Sym *s, vlong *val) |
308 { | 289 { |
309 USED(r); | 290 USED(r); |
310 USED(s); | 291 USED(s); |
311 USED(val); | 292 USED(val); |
312 return -1; | 293 return -1; |
313 } | 294 } |
314 | 295 |
315 static void | 296 void |
316 elfsetupplt(void) | 297 elfsetupplt(void) |
317 { | 298 { |
318 Sym *plt, *got; | 299 Sym *plt, *got; |
319 | 300 |
320 plt = lookup(".plt", 0); | 301 plt = lookup(".plt", 0); |
321 got = lookup(".got.plt", 0); | 302 got = lookup(".got.plt", 0); |
322 if(plt->size == 0) { | 303 if(plt->size == 0) { |
323 // pushq got+8(IP) | 304 // pushq got+8(IP) |
324 adduint8(plt, 0xff); | 305 adduint8(plt, 0xff); |
325 adduint8(plt, 0x35); | 306 adduint8(plt, 0x35); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 adddynsym(Sym *s) | 418 adddynsym(Sym *s) |
438 { | 419 { |
439 Sym *d, *str; | 420 Sym *d, *str; |
440 int t; | 421 int t; |
441 char *name; | 422 char *name; |
442 vlong off; | 423 vlong off; |
443 | 424 |
444 if(s->dynid >= 0) | 425 if(s->dynid >= 0) |
445 return; | 426 return; |
446 | 427 |
447 » if(!debug['U'] && s->dynimpname == nil) | 428 » if(s->dynimpname == nil) |
448 diag("adddynsym: no dynamic name for %s", s->name); | 429 diag("adddynsym: no dynamic name for %s", s->name); |
449 | 430 |
450 if(iself) { | 431 if(iself) { |
451 s->dynid = nelfsym++; | 432 s->dynid = nelfsym++; |
452 | 433 |
453 d = lookup(".dynsym", 0); | 434 d = lookup(".dynsym", 0); |
454 | 435 |
455 name = s->dynimpname; | 436 name = s->dynimpname; |
456 if(name == nil) | 437 if(name == nil) |
457 name = s->name; | 438 name = s->name; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 addstring(s, ""); | 553 addstring(s, ""); |
573 elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, li
b)); | 554 elfwritedynent(lookup(".dynamic", 0), DT_NEEDED, addstring(s, li
b)); |
574 } else if(HEADTYPE == Hdarwin) { | 555 } else if(HEADTYPE == Hdarwin) { |
575 machoadddynlib(lib); | 556 machoadddynlib(lib); |
576 } else { | 557 } else { |
577 diag("adddynlib: unsupported binary format"); | 558 diag("adddynlib: unsupported binary format"); |
578 } | 559 } |
579 } | 560 } |
580 | 561 |
581 void | 562 void |
582 doelf(void) | |
583 { | |
584 Sym *s, *shstrtab, *dynstr; | |
585 | |
586 if(HEADTYPE != Hlinux && HEADTYPE != Hfreebsd && HEADTYPE != Hopenbsd &&
HEADTYPE != Hnetbsd) | |
587 return; | |
588 | |
589 /* predefine strings we need for section headers */ | |
590 shstrtab = lookup(".shstrtab", 0); | |
591 shstrtab->type = SELFROSECT; | |
592 shstrtab->reachable = 1; | |
593 | |
594 elfstr[ElfStrEmpty] = addstring(shstrtab, ""); | |
595 elfstr[ElfStrText] = addstring(shstrtab, ".text"); | |
596 elfstr[ElfStrNoPtrData] = addstring(shstrtab, ".noptrdata"); | |
597 elfstr[ElfStrData] = addstring(shstrtab, ".data"); | |
598 elfstr[ElfStrBss] = addstring(shstrtab, ".bss"); | |
599 elfstr[ElfStrNoPtrBss] = addstring(shstrtab, ".noptrbss"); | |
600 if(HEADTYPE == Hnetbsd) | |
601 elfstr[ElfStrNoteNetbsdIdent] = addstring(shstrtab, ".note.netbs
d.ident"); | |
602 if(HEADTYPE == Hopenbsd) | |
603 elfstr[ElfStrNoteOpenbsdIdent] = addstring(shstrtab, ".note.open
bsd.ident"); | |
604 if(buildinfolen > 0) | |
605 elfstr[ElfStrNoteBuildInfo] = addstring(shstrtab, ".note.gnu.bui
ld-id"); | |
606 addstring(shstrtab, ".elfdata"); | |
607 addstring(shstrtab, ".rodata"); | |
608 addstring(shstrtab, ".typelink"); | |
609 if (debug['U']) | |
610 addstring(shstrtab, ".data.rel.ro"); | |
611 addstring(shstrtab, ".gcdata"); | |
612 addstring(shstrtab, ".gcbss"); | |
613 addstring(shstrtab, ".gosymtab"); | |
614 addstring(shstrtab, ".gopclntab"); | |
615 if(!debug['s']) { | |
616 elfstr[ElfStrSymtab] = addstring(shstrtab, ".symtab"); | |
617 elfstr[ElfStrStrtab] = addstring(shstrtab, ".strtab"); | |
618 dwarfaddshstrings(shstrtab); | |
619 } | |
620 elfstr[ElfStrShstrtab] = addstring(shstrtab, ".shstrtab"); | |
621 | |
622 if(!debug['d']) { /* -d suppresses dynamic loader format */ | |
623 elfstr[ElfStrInterp] = addstring(shstrtab, ".interp"); | |
624 elfstr[ElfStrHash] = addstring(shstrtab, ".hash"); | |
625 elfstr[ElfStrGot] = addstring(shstrtab, ".got"); | |
626 elfstr[ElfStrGotPlt] = addstring(shstrtab, ".got.plt"); | |
627 elfstr[ElfStrDynamic] = addstring(shstrtab, ".dynamic"); | |
628 elfstr[ElfStrDynsym] = addstring(shstrtab, ".dynsym"); | |
629 elfstr[ElfStrDynstr] = addstring(shstrtab, ".dynstr"); | |
630 elfstr[ElfStrRela] = addstring(shstrtab, ".rela"); | |
631 elfstr[ElfStrRelaPlt] = addstring(shstrtab, ".rela.plt"); | |
632 elfstr[ElfStrPlt] = addstring(shstrtab, ".plt"); | |
633 elfstr[ElfStrGnuVersion] = addstring(shstrtab, ".gnu.version"); | |
634 elfstr[ElfStrGnuVersionR] = addstring(shstrtab, ".gnu.version_r"
); | |
635 | |
636 /* dynamic symbol table - first entry all zeros */ | |
637 s = lookup(".dynsym", 0); | |
638 s->type = SELFROSECT; | |
639 s->reachable = 1; | |
640 s->size += ELF64SYMSIZE; | |
641 | |
642 /* dynamic string table */ | |
643 s = lookup(".dynstr", 0); | |
644 s->type = SELFROSECT; | |
645 s->reachable = 1; | |
646 if(s->size == 0) | |
647 addstring(s, ""); | |
648 dynstr = s; | |
649 | |
650 /* relocation table */ | |
651 s = lookup(".rela", 0); | |
652 s->reachable = 1; | |
653 s->type = SELFROSECT; | |
654 | |
655 /* global offset table */ | |
656 s = lookup(".got", 0); | |
657 s->reachable = 1; | |
658 s->type = SELFSECT; // writable | |
659 | |
660 /* hash */ | |
661 s = lookup(".hash", 0); | |
662 s->reachable = 1; | |
663 s->type = SELFROSECT; | |
664 | |
665 s = lookup(".got.plt", 0); | |
666 s->reachable = 1; | |
667 s->type = SELFSECT; // writable | |
668 | |
669 s = lookup(".plt", 0); | |
670 s->reachable = 1; | |
671 s->type = SELFROSECT; | |
672 ················ | |
673 elfsetupplt(); | |
674 ················ | |
675 s = lookup(".rela.plt", 0); | |
676 s->reachable = 1; | |
677 s->type = SELFROSECT; | |
678 ················ | |
679 s = lookup(".gnu.version", 0); | |
680 s->reachable = 1; | |
681 s->type = SELFROSECT; | |
682 ················ | |
683 s = lookup(".gnu.version_r", 0); | |
684 s->reachable = 1; | |
685 s->type = SELFROSECT; | |
686 | |
687 /* define dynamic elf table */ | |
688 s = lookup(".dynamic", 0); | |
689 s->reachable = 1; | |
690 s->type = SELFSECT; // writable | |
691 | |
692 /* | |
693 * .dynamic table | |
694 */ | |
695 elfwritedynentsym(s, DT_HASH, lookup(".hash", 0)); | |
696 elfwritedynentsym(s, DT_SYMTAB, lookup(".dynsym", 0)); | |
697 elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE); | |
698 elfwritedynentsym(s, DT_STRTAB, lookup(".dynstr", 0)); | |
699 elfwritedynentsymsize(s, DT_STRSZ, lookup(".dynstr", 0)); | |
700 elfwritedynentsym(s, DT_RELA, lookup(".rela", 0)); | |
701 elfwritedynentsymsize(s, DT_RELASZ, lookup(".rela", 0)); | |
702 elfwritedynent(s, DT_RELAENT, ELF64RELASIZE); | |
703 if(rpath) | |
704 elfwritedynent(s, DT_RUNPATH, addstring(dynstr, rpath)); | |
705 ················ | |
706 elfwritedynentsym(s, DT_PLTGOT, lookup(".got.plt", 0)); | |
707 elfwritedynent(s, DT_PLTREL, DT_RELA); | |
708 elfwritedynentsymsize(s, DT_PLTRELSZ, lookup(".rela.plt", 0)); | |
709 elfwritedynentsym(s, DT_JMPREL, lookup(".rela.plt", 0)); | |
710 ················ | |
711 elfwritedynent(s, DT_DEBUG, 0); | |
712 | |
713 if (debug['U']) { | |
714 Sym *init_sym = lookup(LIBINITENTRY, 0); | |
715 if(init_sym->type != STEXT) | |
716 diag("entry not text: %s", init_sym->name); | |
717 Reloc *r = addrel(s); | |
718 r->off = s->np + 8; | |
719 r->siz = PtrSize; | |
720 r->sym = init_sym; | |
721 r->type = D_ADDR; | |
722 r->add = 0; | |
723 elfwritedynent(s, DT_INIT, 0); | |
724 } | |
725 | |
726 // Do not write DT_NULL. elfdynhash will finish it. | |
727 } | |
728 } | |
729 | |
730 void | |
731 shsym(ElfShdr *sh, Sym *s) | |
732 { | |
733 vlong addr; | |
734 addr = symaddr(s); | |
735 if(sh->flags&SHF_ALLOC) | |
736 sh->addr = addr; | |
737 sh->off = datoff(addr); | |
738 sh->size = s->size; | |
739 } | |
740 | |
741 void | |
742 phsh(ElfPhdr *ph, ElfShdr *sh) | |
743 { | |
744 ph->vaddr = sh->addr; | |
745 ph->paddr = ph->vaddr; | |
746 ph->off = sh->off; | |
747 ph->filesz = sh->size; | |
748 ph->memsz = sh->size; | |
749 ph->align = sh->addralign; | |
750 } | |
751 | |
752 void | |
753 asmb(void) | 563 asmb(void) |
754 { | 564 { |
755 int32 magic; | 565 int32 magic; |
756 » int a, dynsym; | 566 » int i; |
757 » vlong vl, startva, symo, dwarfoff, machlink, resoff; | 567 » vlong vl, symo, dwarfoff, machlink; |
758 » ElfEhdr *eh; | |
759 » ElfPhdr *ph, *pph, *pnote; | |
760 » ElfShdr *sh; | |
761 Section *sect; | 568 Section *sect; |
762 Sym *sym; | 569 Sym *sym; |
763 int i, o; | |
764 | 570 |
765 if(debug['v']) | 571 if(debug['v']) |
766 Bprint(&bso, "%5.2f asmb\n", cputime()); | 572 Bprint(&bso, "%5.2f asmb\n", cputime()); |
767 Bflush(&bso); | 573 Bflush(&bso); |
768 | 574 |
769 elftextsh = 0; | |
770 ········ | |
771 if(debug['v']) | 575 if(debug['v']) |
772 Bprint(&bso, "%5.2f codeblk\n", cputime()); | 576 Bprint(&bso, "%5.2f codeblk\n", cputime()); |
773 Bflush(&bso); | 577 Bflush(&bso); |
| 578 |
| 579 if(iself) |
| 580 asmbelfsetup(); |
774 | 581 |
775 sect = segtext.sect; | 582 sect = segtext.sect; |
776 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); | 583 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); |
777 codeblk(sect->vaddr, sect->len); | 584 codeblk(sect->vaddr, sect->len); |
778 | 585 |
779 /* output read-only data in text segment (rodata, gosymtab, pclntab, ...
) */ | 586 /* output read-only data in text segment (rodata, gosymtab, pclntab, ...
) */ |
780 for(sect = sect->next; sect != nil; sect = sect->next) { | 587 for(sect = sect->next; sect != nil; sect = sect->next) { |
781 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); | 588 cseek(sect->vaddr - segtext.vaddr + segtext.fileoff); |
782 datblk(sect->vaddr, sect->len); | 589 datblk(sect->vaddr, sect->len); |
783 } | 590 } |
(...skipping 28 matching lines...) Expand all Loading... |
812 case Helf: | 619 case Helf: |
813 break; | 620 break; |
814 case Hdarwin: | 621 case Hdarwin: |
815 debug['8'] = 1; /* 64-bit addresses */ | 622 debug['8'] = 1; /* 64-bit addresses */ |
816 break; | 623 break; |
817 case Hlinux: | 624 case Hlinux: |
818 case Hfreebsd: | 625 case Hfreebsd: |
819 case Hnetbsd: | 626 case Hnetbsd: |
820 case Hopenbsd: | 627 case Hopenbsd: |
821 debug['8'] = 1; /* 64-bit addresses */ | 628 debug['8'] = 1; /* 64-bit addresses */ |
822 /* index of elf text section; needed by asmelfsym, double-checke
d below */ | |
823 /* !debug['d'] causes extra sections before the .text section */ | |
824 elftextsh = 2; | |
825 if(!debug['d']) { | |
826 elftextsh += 10; | |
827 if(elfverneed) | |
828 elftextsh += 2; | |
829 } | |
830 if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) | |
831 elftextsh += 1; | |
832 if(buildinfolen > 0) | |
833 elftextsh += 1; | |
834 break; | 629 break; |
835 case Hwindows: | 630 case Hwindows: |
836 break; | 631 break; |
837 } | 632 } |
838 | 633 |
839 symsize = 0; | 634 symsize = 0; |
840 spsize = 0; | 635 spsize = 0; |
841 lcsize = 0; | 636 lcsize = 0; |
842 symo = 0; | 637 symo = 0; |
843 if(!debug['s']) { | 638 if(!debug['s']) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 lputb(spsize); /* sp offsets */ | 729 lputb(spsize); /* sp offsets */ |
935 lputb(lcsize); /* line offsets */ | 730 lputb(lcsize); /* line offsets */ |
936 break; | 731 break; |
937 case Hdarwin: | 732 case Hdarwin: |
938 asmbmacho(); | 733 asmbmacho(); |
939 break; | 734 break; |
940 case Hlinux: | 735 case Hlinux: |
941 case Hfreebsd: | 736 case Hfreebsd: |
942 case Hnetbsd: | 737 case Hnetbsd: |
943 case Hopenbsd: | 738 case Hopenbsd: |
944 » » /* elf amd-64 */ | 739 » » asmbelf(symo); |
945 | |
946 » » eh = getElfEhdr(); | |
947 » » startva = INITTEXT - HEADR; | |
948 » » resoff = ELFRESERVE; | |
949 | |
950 » » /* This null SHdr must appear before all others */ | |
951 » » newElfShdr(elfstr[ElfStrEmpty]); | |
952 | |
953 » » /* program header info */ | |
954 » » pph = newElfPhdr(); | |
955 » » pph->type = PT_PHDR; | |
956 » » pph->flags = PF_R + PF_X; | |
957 » » pph->off = eh->ehsize; | |
958 » » pph->vaddr = INITTEXT - HEADR + pph->off; | |
959 » » pph->paddr = INITTEXT - HEADR + pph->off; | |
960 » » pph->align = INITRND; | |
961 | |
962 » » /* | |
963 » » * PHDR must be in a loaded segment. Adjust the text | |
964 » » * segment boundaries downwards to include it. | |
965 » » */ | |
966 » » o = segtext.vaddr - pph->vaddr; | |
967 » » segtext.vaddr -= o; | |
968 » » segtext.len += o; | |
969 » » o = segtext.fileoff - pph->off; | |
970 » » segtext.fileoff -= o; | |
971 » » segtext.filelen += o; | |
972 | |
973 » » if(!debug['d']) { | |
974 » » » /* interpreter */ | |
975 » » » sh = newElfShdr(elfstr[ElfStrInterp]); | |
976 » » » sh->type = SHT_PROGBITS; | |
977 » » » sh->flags = SHF_ALLOC; | |
978 » » » sh->addralign = 1; | |
979 » » » if(interpreter == nil) { | |
980 » » » » switch(HEADTYPE) { | |
981 » » » » case Hlinux: | |
982 » » » » » interpreter = linuxdynld; | |
983 » » » » » break; | |
984 » » » » case Hfreebsd: | |
985 » » » » » interpreter = freebsddynld; | |
986 » » » » » break; | |
987 » » » » case Hnetbsd: | |
988 » » » » » interpreter = netbsddynld; | |
989 » » » » » break; | |
990 » » » » case Hopenbsd: | |
991 » » » » » interpreter = openbsddynld; | |
992 » » » » » break; | |
993 » » » » } | |
994 » » » } | |
995 » » » resoff -= elfinterp(sh, startva, resoff, interpreter); | |
996 | |
997 » » » ph = newElfPhdr(); | |
998 » » » ph->type = PT_INTERP; | |
999 » » » ph->flags = PF_R; | |
1000 » » » phsh(ph, sh); | |
1001 » » } | |
1002 | |
1003 » » pnote = nil; | |
1004 » » if(HEADTYPE == Hnetbsd || HEADTYPE == Hopenbsd) { | |
1005 » » » sh = nil; | |
1006 » » » switch(HEADTYPE) { | |
1007 » » » case Hnetbsd: | |
1008 » » » » sh = newElfShdr(elfstr[ElfStrNoteNetbsdIdent]); | |
1009 » » » » resoff -= elfnetbsdsig(sh, startva, resoff); | |
1010 » » » » break; | |
1011 » » » case Hopenbsd: | |
1012 » » » » sh = newElfShdr(elfstr[ElfStrNoteOpenbsdIdent]); | |
1013 » » » » resoff -= elfopenbsdsig(sh, startva, resoff); | |
1014 » » » » break; | |
1015 » » » } | |
1016 | |
1017 » » » pnote = newElfPhdr(); | |
1018 » » » pnote->type = PT_NOTE; | |
1019 » » » pnote->flags = PF_R; | |
1020 » » » phsh(pnote, sh); | |
1021 » » } | |
1022 | |
1023 » » if(buildinfolen > 0) { | |
1024 » » » sh = newElfShdr(elfstr[ElfStrNoteBuildInfo]); | |
1025 » » » resoff -= elfbuildinfo(sh, startva, resoff); | |
1026 | |
1027 » » » if(pnote == nil) { | |
1028 » » » » pnote = newElfPhdr(); | |
1029 » » » » pnote->type = PT_NOTE; | |
1030 » » » » pnote->flags = PF_R; | |
1031 » » » } | |
1032 » » » phsh(pnote, sh); | |
1033 » » } | |
1034 | |
1035 » » elfphload(&segtext); | |
1036 » » elfphload(&segdata); | |
1037 | |
1038 » » /* Dynamic linking sections */ | |
1039 » » if(!debug['d']) {» /* -d suppresses dynamic loader format *
/ | |
1040 » » » /* S headers for dynamic linking */ | |
1041 » » » sh = newElfShdr(elfstr[ElfStrGot]); | |
1042 » » » sh->type = SHT_PROGBITS; | |
1043 » » » sh->flags = SHF_ALLOC+SHF_WRITE; | |
1044 » » » sh->entsize = 8; | |
1045 » » » sh->addralign = 8; | |
1046 » » » shsym(sh, lookup(".got", 0)); | |
1047 | |
1048 » » » sh = newElfShdr(elfstr[ElfStrGotPlt]); | |
1049 » » » sh->type = SHT_PROGBITS; | |
1050 » » » sh->flags = SHF_ALLOC+SHF_WRITE; | |
1051 » » » sh->entsize = 8; | |
1052 » » » sh->addralign = 8; | |
1053 » » » shsym(sh, lookup(".got.plt", 0)); | |
1054 » » »······· | |
1055 » » » dynsym = eh->shnum; | |
1056 » » » sh = newElfShdr(elfstr[ElfStrDynsym]); | |
1057 » » » sh->type = SHT_DYNSYM; | |
1058 » » » sh->flags = SHF_ALLOC; | |
1059 » » » sh->entsize = ELF64SYMSIZE; | |
1060 » » » sh->addralign = 8; | |
1061 » » » sh->link = dynsym+1;» // dynstr | |
1062 » » » // sh->info = index of first non-local symbol (number of
local symbols) | |
1063 » » » shsym(sh, lookup(".dynsym", 0)); | |
1064 | |
1065 » » » sh = newElfShdr(elfstr[ElfStrDynstr]); | |
1066 » » » sh->type = SHT_STRTAB; | |
1067 » » » sh->flags = SHF_ALLOC; | |
1068 » » » sh->addralign = 1; | |
1069 » » » shsym(sh, lookup(".dynstr", 0)); | |
1070 | |
1071 » » » if(elfverneed) { | |
1072 » » » » sh = newElfShdr(elfstr[ElfStrGnuVersion]); | |
1073 » » » » sh->type = SHT_GNU_VERSYM; | |
1074 » » » » sh->flags = SHF_ALLOC; | |
1075 » » » » sh->addralign = 2; | |
1076 » » » » sh->link = dynsym; | |
1077 » » » » sh->entsize = 2; | |
1078 » » » » shsym(sh, lookup(".gnu.version", 0)); | |
1079 » » » »······· | |
1080 » » » » sh = newElfShdr(elfstr[ElfStrGnuVersionR]); | |
1081 » » » » sh->type = SHT_GNU_VERNEED; | |
1082 » » » » sh->flags = SHF_ALLOC; | |
1083 » » » » sh->addralign = 8; | |
1084 » » » » sh->info = elfverneed; | |
1085 » » » » sh->link = dynsym+1; // dynstr | |
1086 » » » » shsym(sh, lookup(".gnu.version_r", 0)); | |
1087 » » » } | |
1088 | |
1089 » » » sh = newElfShdr(elfstr[ElfStrRelaPlt]); | |
1090 » » » sh->type = SHT_RELA; | |
1091 » » » sh->flags = SHF_ALLOC; | |
1092 » » » sh->entsize = ELF64RELASIZE; | |
1093 » » » sh->addralign = 8; | |
1094 » » » sh->link = dynsym; | |
1095 » » » sh->info = eh->shnum;» // .plt | |
1096 » » » shsym(sh, lookup(".rela.plt", 0)); | |
1097 | |
1098 » » » sh = newElfShdr(elfstr[ElfStrPlt]); | |
1099 » » » sh->type = SHT_PROGBITS; | |
1100 » » » sh->flags = SHF_ALLOC+SHF_EXECINSTR; | |
1101 » » » sh->entsize = 16; | |
1102 » » » sh->addralign = 4; | |
1103 » » » shsym(sh, lookup(".plt", 0)); | |
1104 | |
1105 » » » sh = newElfShdr(elfstr[ElfStrHash]); | |
1106 » » » sh->type = SHT_HASH; | |
1107 » » » sh->flags = SHF_ALLOC; | |
1108 » » » sh->entsize = 4; | |
1109 » » » sh->addralign = 8; | |
1110 » » » sh->link = dynsym; | |
1111 » » » shsym(sh, lookup(".hash", 0)); | |
1112 | |
1113 » » » sh = newElfShdr(elfstr[ElfStrRela]); | |
1114 » » » sh->type = SHT_RELA; | |
1115 » » » sh->flags = SHF_ALLOC; | |
1116 » » » sh->entsize = ELF64RELASIZE; | |
1117 » » » sh->addralign = 8; | |
1118 » » » sh->link = dynsym; | |
1119 » » » shsym(sh, lookup(".rela", 0)); | |
1120 | |
1121 » » » /* sh and PT_DYNAMIC for .dynamic section */ | |
1122 » » » sh = newElfShdr(elfstr[ElfStrDynamic]); | |
1123 » » » sh->type = SHT_DYNAMIC; | |
1124 » » » sh->flags = SHF_ALLOC+SHF_WRITE; | |
1125 » » » sh->entsize = 16; | |
1126 » » » sh->addralign = 8; | |
1127 » » » sh->link = dynsym+1;» // dynstr | |
1128 » » » shsym(sh, lookup(".dynamic", 0)); | |
1129 » » » ph = newElfPhdr(); | |
1130 » » » ph->type = PT_DYNAMIC; | |
1131 » » » ph->flags = PF_R + PF_W; | |
1132 » » » phsh(ph, sh); | |
1133 » » »······· | |
1134 » » » /* | |
1135 » » » * Thread-local storage segment (really just size). | |
1136 » » » */ | |
1137 » » » // Do not emit PT_TLS for OpenBSD since ld.so(1) does | |
1138 » » » // not currently support it. This is handled | |
1139 » » » // appropriately in runtime/cgo. | |
1140 » » » if(tlsoffset != 0 && HEADTYPE != Hopenbsd) { | |
1141 » » » » ph = newElfPhdr(); | |
1142 » » » » ph->type = PT_TLS; | |
1143 » » » » ph->flags = PF_R; | |
1144 » » » » ph->memsz = -tlsoffset; | |
1145 » » » » ph->align = 8; | |
1146 » » » } | |
1147 » » } | |
1148 | |
1149 » » ph = newElfPhdr(); | |
1150 » » ph->type = PT_GNU_STACK; | |
1151 » » ph->flags = PF_W+PF_R; | |
1152 » » ph->align = 8; | |
1153 » »······· | |
1154 » » ph = newElfPhdr(); | |
1155 » » ph->type = PT_PAX_FLAGS; | |
1156 » » ph->flags = 0x2a00; // mprotect, randexec, emutramp disabled | |
1157 » » ph->align = 8; | |
1158 | |
1159 » » sh = newElfShstrtab(elfstr[ElfStrShstrtab]); | |
1160 » » sh->type = SHT_STRTAB; | |
1161 » » sh->addralign = 1; | |
1162 » » shsym(sh, lookup(".shstrtab", 0)); | |
1163 | |
1164 » » if(elftextsh != eh->shnum) | |
1165 » » » diag("elftextsh = %d, want %d", elftextsh, eh->shnum); | |
1166 » » for(sect=segtext.sect; sect!=nil; sect=sect->next) | |
1167 » » » elfshbits(sect); | |
1168 » » for(sect=segdata.sect; sect!=nil; sect=sect->next) | |
1169 » » » elfshbits(sect); | |
1170 | |
1171 » » if(!debug['s']) { | |
1172 » » » sh = newElfShdr(elfstr[ElfStrSymtab]); | |
1173 » » » sh->type = SHT_SYMTAB; | |
1174 » » » sh->off = symo; | |
1175 » » » sh->size = symsize; | |
1176 » » » sh->addralign = 8; | |
1177 » » » sh->entsize = 24; | |
1178 » » » sh->link = eh->shnum;» // link to strtab | |
1179 | |
1180 » » » sh = newElfShdr(elfstr[ElfStrStrtab]); | |
1181 » » » sh->type = SHT_STRTAB; | |
1182 » » » sh->off = symo+symsize; | |
1183 » » » sh->size = elfstrsize; | |
1184 » » » sh->addralign = 1; | |
1185 | |
1186 » » » dwarfaddelfheaders(); | |
1187 » » } | |
1188 | |
1189 » » /* Main header */ | |
1190 » » eh->ident[EI_MAG0] = '\177'; | |
1191 » » eh->ident[EI_MAG1] = 'E'; | |
1192 » » eh->ident[EI_MAG2] = 'L'; | |
1193 » » eh->ident[EI_MAG3] = 'F'; | |
1194 » » if(HEADTYPE == Hfreebsd) | |
1195 » » » eh->ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
1196 » » else if(HEADTYPE == Hnetbsd) | |
1197 » » » eh->ident[EI_OSABI] = ELFOSABI_NETBSD; | |
1198 » » else if(HEADTYPE == Hopenbsd) | |
1199 » » » eh->ident[EI_OSABI] = ELFOSABI_OPENBSD; | |
1200 » » eh->ident[EI_CLASS] = ELFCLASS64; | |
1201 » » eh->ident[EI_DATA] = ELFDATA2LSB; | |
1202 » » eh->ident[EI_VERSION] = EV_CURRENT; | |
1203 | |
1204 » » if (debug['U']) | |
1205 » » » eh->type = ET_DYN; | |
1206 » » else | |
1207 » » » eh->type = ET_EXEC; | |
1208 » » eh->machine = EM_X86_64; | |
1209 » » eh->version = EV_CURRENT; | |
1210 » » eh->entry = entryvalue(); | |
1211 | |
1212 » » pph->filesz = eh->phnum * eh->phentsize; | |
1213 » » pph->memsz = pph->filesz; | |
1214 | |
1215 » » cseek(0); | |
1216 » » a = 0; | |
1217 » » a += elfwritehdr(); | |
1218 » » a += elfwritephdrs(); | |
1219 » » a += elfwriteshdrs(); | |
1220 » » a += elfwriteinterp(elfstr[ElfStrInterp]); | |
1221 » » if(HEADTYPE == Hnetbsd) | |
1222 » » » a += elfwritenetbsdsig(elfstr[ElfStrNoteNetbsdIdent]); | |
1223 » » if(HEADTYPE == Hopenbsd) | |
1224 » » » a += elfwriteopenbsdsig(elfstr[ElfStrNoteOpenbsdIdent]); | |
1225 » » if(buildinfolen > 0) | |
1226 » » » a += elfwritebuildinfo(elfstr[ElfStrNoteBuildInfo]); | |
1227 » » if(a > ELFRESERVE)»····· | |
1228 » » » diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); | |
1229 break; | 740 break; |
1230 case Hwindows: | 741 case Hwindows: |
1231 asmbpe(); | 742 asmbpe(); |
1232 break; | 743 break; |
1233 } | 744 } |
1234 cflush(); | 745 cflush(); |
1235 } | 746 } |
1236 | 747 |
1237 vlong | 748 vlong |
1238 rnd(vlong v, vlong r) | 749 rnd(vlong v, vlong r) |
1239 { | 750 { |
1240 vlong c; | 751 vlong c; |
1241 | 752 |
1242 if(r <= 0) | 753 if(r <= 0) |
1243 return v; | 754 return v; |
1244 v += r - 1; | 755 v += r - 1; |
1245 c = v % r; | 756 c = v % r; |
1246 if(c < 0) | 757 if(c < 0) |
1247 c += r; | 758 c += r; |
1248 v -= c; | 759 v -= c; |
1249 return v; | 760 return v; |
1250 } | 761 } |
1251 | |
1252 void | |
1253 genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*)) | |
1254 { | |
1255 Auto *a; | |
1256 Sym *s; | |
1257 | |
1258 s = lookup("etext", 0); | |
1259 if(s->type == STEXT) | |
1260 put(s, s->name, 'T', s->value, s->size, s->version, 0); | |
1261 | |
1262 for(s=allsym; s!=S; s=s->allsym) { | |
1263 if(s->hide) | |
1264 continue; | |
1265 switch(s->type&SMASK) { | |
1266 case SCONST: | |
1267 case SRODATA: | |
1268 case SSYMTAB: | |
1269 case SPCLNTAB: | |
1270 case SDATA: | |
1271 case SDATARELRO: | |
1272 case SNOPTRDATA: | |
1273 case SELFROSECT: | |
1274 case SMACHOGOT: | |
1275 case STYPE: | |
1276 case SSTRING: | |
1277 case SGOSTRING: | |
1278 case SWINDOWS: | |
1279 case SGCDATA: | |
1280 case SGCBSS: | |
1281 if(!s->reachable) | |
1282 continue; | |
1283 put(s, s->name, 'D', symaddr(s), s->size, s->version, s-
>gotype); | |
1284 continue; | |
1285 | |
1286 case SBSS: | |
1287 case SNOPTRBSS: | |
1288 if(!s->reachable) | |
1289 continue; | |
1290 if(s->np > 0) | |
1291 diag("%s should not be bss (size=%d type=%d spec
ial=%d)", s->name, (int)s->np, s->type, s->special); | |
1292 put(s, s->name, 'B', symaddr(s), s->size, s->version, s-
>gotype); | |
1293 continue; | |
1294 | |
1295 case SFILE: | |
1296 put(nil, s->name, 'f', s->value, 0, s->version, 0); | |
1297 continue; | |
1298 } | |
1299 } | |
1300 | |
1301 for(s = textp; s != nil; s = s->next) { | |
1302 if(s->text == nil) | |
1303 continue; | |
1304 | |
1305 /* filenames first */ | |
1306 for(a=s->autom; a; a=a->link) | |
1307 if(a->type == D_FILE) | |
1308 put(nil, a->asym->name, 'z', a->aoffset, 0, 0, 0
); | |
1309 else | |
1310 if(a->type == D_FILE1) | |
1311 put(nil, a->asym->name, 'Z', a->aoffset, 0, 0, 0
); | |
1312 | |
1313 put(s, s->name, 'T', s->value, s->size, s->version, s->gotype); | |
1314 | |
1315 /* frame, auto and param after */ | |
1316 put(nil, ".frame", 'm', s->text->to.offset+8, 0, 0, 0); | |
1317 | |
1318 for(a=s->autom; a; a=a->link) | |
1319 if(a->type == D_AUTO) | |
1320 put(nil, a->asym->name, 'a', -a->aoffset, 0, 0,
a->gotype); | |
1321 else | |
1322 if(a->type == D_PARAM) | |
1323 put(nil, a->asym->name, 'p', a->aoffset, 0, 0, a
->gotype); | |
1324 } | |
1325 if(debug['v'] || debug['n']) | |
1326 Bprint(&bso, "symsize = %ud\n", symsize); | |
1327 Bflush(&bso); | |
1328 } | |
LEFT | RIGHT |