作者:xslonepiec
项目:goio
func reloc() {
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
}
Bflush(&Bso)
for s := Ctxt.Textp; s != nil; s = s.Next {
relocsym(s)
}
for s := datap; s != nil; s = s.Next {
relocsym(s)
}
}
作者:xslonepiec
项目:goio
func dynreloc() {
// -d suppresses dynamic loader format, so we may as well not
// compute these sections or mark their symbols as reachable.
if Debug['d'] != 0 && HEADTYPE != Hwindows {
return
}
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f reloc\n", obj.Cputime())
}
Bflush(&Bso)
for s := Ctxt.Textp; s != nil; s = s.Next {
dynrelocsym(s)
}
for s := datap; s != nil; s = s.Next {
dynrelocsym(s)
}
if Iself {
elfdynhash()
}
}
作者:korl
项目:g
//.........这里部分代码省略.........
if Buildmode != BuildmodeShared && flag.NArg() != 1 {
usage()
}
if outfile == "" {
outfile = "a.out"
if HEADTYPE == obj.Hwindows {
outfile += ".exe"
}
}
libinit() // creates outfile
if HEADTYPE == -1 {
HEADTYPE = int32(headtype(goos))
}
Ctxt.Headtype = int(HEADTYPE)
if headstring == "" {
headstring = Headstr(int(HEADTYPE))
}
if HEADTYPE == obj.Hhaiku {
Linkmode = LinkExternal
}
Thearch.Archinit()
if Linkshared && !Iself {
Exitf("-linkshared can only be used on elf systems")
}
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(INITTEXT), uint64(INITDAT), uint32(INITRND))
}
Bso.Flush()
if Buildmode == BuildmodeShared {
for i := 0; i < flag.NArg(); i++ {
arg := flag.Arg(i)
parts := strings.SplitN(arg, "=", 2)
var pkgpath, file string
if len(parts) == 1 {
pkgpath, file = "main", arg
} else {
pkgpath, file = parts[0], parts[1]
}
pkglistfornote = append(pkglistfornote, pkgpath...)
pkglistfornote = append(pkglistfornote, '\n')
addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
}
} else {
addlibpath(Ctxt, "command line", "command line", flag.Arg(0), "main", "")
}
loadlib()
if Thearch.Thechar == '5' {
// mark some functions that are only referenced after linker code editing
if Ctxt.Goarm == 5 {
mark(Linkrlookup(Ctxt, "_sfloat", 0))
}
mark(Linklookup(Ctxt, "runtime.read_tls_fallback", 0))
}
checkgo()
checkstrdata()
deadcode()
callgraph()
doelf()
if HEADTYPE == obj.Hdarwin {
domacho()
}
dostkcheck()
if HEADTYPE == obj.Hwindows {
dope()
}
addexport()
Thearch.Gentext() // trampolines, call stubs, etc.
textbuildid()
textaddress()
pclntab()
findfunctab()
symtab()
dodata()
address()
doweak()
reloc()
Thearch.Asmb()
undef()
hostlink()
archive()
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f cpu time\n", obj.Cputime())
fmt.Fprintf(&Bso, "%d symbols\n", Ctxt.Nsymbol)
fmt.Fprintf(&Bso, "%d liveness data\n", liveness)
}
Bso.Flush()
errorexit()
}
作者:Harvey-O
项目:g
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
// a switch for enabling/disabling instruction scheduling
nosched := true
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
textstksiz := p.To.Offset
cursym.Args = p.To.Val.(int32)
cursym.Locals = int32(textstksiz)
/*
* find leaf subroutines
* strip NOPs
* expand RET
* expand BECOME pseudo
*/
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f noops\n", obj.Cputime())
}
var q *obj.Prog
var q1 *obj.Prog
for p := cursym.Text; p != nil; p = p.Link {
switch p.As {
/* too hard, just leave alone */
case obj.ATEXT:
q = p
p.Mark |= LABEL | LEAF | SYNC
if p.Link != nil {
p.Link.Mark |= LABEL
}
/* too hard, just leave alone */
case AMOVW,
AMOVV:
q = p
if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
p.Mark |= LABEL | SYNC
break
}
if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
p.Mark |= LABEL | SYNC
}
/* too hard, just leave alone */
case ASYSCALL,
AWORD,
ATLBWR,
ATLBWI,
ATLBP,
ATLBR:
q = p
p.Mark |= LABEL | SYNC
case ANOR:
q = p
if p.To.Type == obj.TYPE_REG {
if p.To.Reg == REGZERO {
p.Mark |= LABEL | SYNC
}
}
case ABGEZAL,
ABLTZAL,
AJAL,
obj.ADUFFZERO,
obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF
fallthrough
case AJMP,
ABEQ,
ABGEZ,
ABGTZ,
ABLEZ,
ABLTZ,
ABNE,
ABFPT, ABFPF:
if p.As == ABFPT || p.As == ABFPF {
// We don't treat ABFPT and ABFPF as branches here,
// so that we will always fill nop (0x0) in their
// delay slot during assembly.
// This is to workaround a kernel FPU emulator bug
// where it uses the user stack to simulate the
// instruction in the delay slot if it's not 0x0,
// and somehow that leads to SIGSEGV when the kernel
// jump to the stack.
p.Mark |= SYNC
} else {
p.Mark |= BRANCH
}
q = p
//.........这里部分代码省略.........
作者:achand
项目:g
func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f ldelf %s\n", obj.Cputime(), pn)
}
localSymVersion := ctxt.Syms.IncVersion()
base := f.Offset()
var add uint64
var e binary.ByteOrder
var elfobj *ElfObj
var err error
var flag int
var hdr *ElfHdrBytes
var hdrbuf [64]uint8
var info uint64
var is64 int
var j int
var n int
var name string
var p []byte
var r []Reloc
var rela int
var rp *Reloc
var rsect *ElfSect
var s *Symbol
var sect *ElfSect
var sym ElfSym
var symbols []*Symbol
if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
goto bad
}
hdr = new(ElfHdrBytes)
binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
if string(hdr.Ident[:4]) != "\x7FELF" {
goto bad
}
switch hdr.Ident[5] {
case ElfDataLsb:
e = binary.LittleEndian
case ElfDataMsb:
e = binary.BigEndian
default:
goto bad
}
// read header
elfobj = new(ElfObj)
elfobj.e = e
elfobj.f = f
elfobj.base = base
elfobj.length = length
elfobj.name = pn
is64 = 0
if hdr.Ident[4] == ElfClass64 {
is64 = 1
hdr := new(ElfHdrBytes64)
binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
elfobj.version = e.Uint32(hdr.Version[:])
elfobj.phoff = e.Uint64(hdr.Phoff[:])
elfobj.shoff = e.Uint64(hdr.Shoff[:])
elfobj.flags = e.Uint32(hdr.Flags[:])
elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
} else {
elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
elfobj.version = e.Uint32(hdr.Version[:])
elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
elfobj.flags = e.Uint32(hdr.Flags[:])
elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
}
elfobj.is64 = is64
if uint32(hdr.Ident[6]) != elfobj.version {
goto bad
}
if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
Errorf(nil, "%s: elf but not elf relocatable object", pn)
return
}
//.........这里部分代码省略.........
作者:hurkg
项目:g
//.........这里部分代码省略.........
if flagShared {
if Buildmode == BuildmodeUnset {
Buildmode = BuildmodeCShared
} else if Buildmode != BuildmodeCShared {
Exitf("-shared and -buildmode=%s are incompatible", Buildmode.String())
}
}
if Buildmode == BuildmodeUnset {
Buildmode = BuildmodeExe
}
if Buildmode != BuildmodeShared && flag.NArg() != 1 {
usage()
}
if *flagOutfile == "" {
*flagOutfile = "a.out"
if HEADTYPE == obj.Hwindows {
*flagOutfile += ".exe"
}
}
interpreter = *flagInterpreter
libinit(ctxt) // creates outfile
if HEADTYPE == -1 {
HEADTYPE = int32(headtype(goos))
}
ctxt.Headtype = int(HEADTYPE)
if headstring == "" {
headstring = Headstr(int(HEADTYPE))
}
Thearch.Archinit(ctxt)
if *FlagLinkshared && !Iself {
Exitf("-linkshared can only be used on elf systems")
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", HEADTYPE, uint64(*FlagTextAddr), uint64(*FlagDataAddr), uint32(*FlagRound))
}
if Buildmode == BuildmodeShared {
for i := 0; i < flag.NArg(); i++ {
arg := flag.Arg(i)
parts := strings.SplitN(arg, "=", 2)
var pkgpath, file string
if len(parts) == 1 {
pkgpath, file = "main", arg
} else {
pkgpath, file = parts[0], parts[1]
}
pkglistfornote = append(pkglistfornote, pkgpath...)
pkglistfornote = append(pkglistfornote, '\n')
addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
}
} else {
addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
}
ctxt.loadlib()
ctxt.checkstrdata()
deadcode(ctxt)
fieldtrack(ctxt)
ctxt.callgraph()
ctxt.doelf()
if HEADTYPE == obj.Hdarwin {
ctxt.domacho()
}
ctxt.dostkcheck()
if HEADTYPE == obj.Hwindows {
ctxt.dope()
}
ctxt.addexport()
Thearch.Gentext(ctxt) // trampolines, call stubs, etc.
ctxt.textbuildid()
ctxt.textaddress()
ctxt.pclntab()
ctxt.findfunctab()
ctxt.symtab()
ctxt.dodata()
ctxt.address()
ctxt.reloc()
Thearch.Asmb(ctxt)
ctxt.undef()
ctxt.hostlink()
ctxt.archive()
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f cpu time\n", obj.Cputime())
ctxt.Logf("%d symbols\n", len(ctxt.Allsym))
ctxt.Logf("%d liveness data\n", liveness)
}
ctxt.Bso.Flush()
errorexit()
}
作者:danny800
项目:g
func span0(ctxt *obj.Link, cursym *obj.LSym) {
p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return
}
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset + 8)
if oprange[AOR&obj.AMask].start == nil {
buildop(ctxt)
}
c := int64(0)
p.Pc = c
var m int
var o *Optab
for p = p.Link; p != nil; p = p.Link {
ctxt.Curp = p
p.Pc = c
o = oplook(ctxt, p)
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
/*
* if any procedure is large enough to
* generate a large SBRA branch, then
* generate extra passes putting branches
* around jmps to fix. this is rare.
*/
bflag := 1
var otxt int64
var q *obj.Prog
for bflag != 0 {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
}
bflag = 0
c = 0
for p = cursym.Text.Link; p != nil; p = p.Link {
p.Pc = c
o = oplook(ctxt, p)
// very large conditional branches
if o.type_ == 6 && p.Pcond != nil {
otxt = p.Pcond.Pc - c
if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = AJMP
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = p.Pcond
p.Pcond = q
q = ctxt.NewProg()
q.Link = p.Link
p.Link = q
q.As = AJMP
q.Lineno = p.Lineno
q.To.Type = obj.TYPE_BRANCH
q.Pcond = q.Link.Link
addnop(ctxt, p.Link)
addnop(ctxt, p)
bflag = 1
}
}
m = int(o.size)
if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
ctxt.Diag("zero-width instruction\n%v", p)
}
continue
}
c += int64(m)
}
cursym.Size = c
}
c += -c & (FuncAlign - 1)
cursym.Size = c
/*
* lay out the code, emitting code and data relocations.
*/
//.........这里部分代码省略.........
作者:achand
项目:g
//.........这里部分代码省略.........
obj.Flagcount("v", "print link trace", &ctxt.Debugvlog)
obj.Flagparse(usage)
startProfile()
if Buildmode == BuildmodeUnset {
Buildmode = BuildmodeExe
}
if Buildmode != BuildmodeShared && flag.NArg() != 1 {
usage()
}
if *flagOutfile == "" {
*flagOutfile = "a.out"
if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
*flagOutfile += ".exe"
}
}
interpreter = *flagInterpreter
libinit(ctxt) // creates outfile
if Headtype == obj.Hunknown {
Headtype.Set(obj.GOOS)
}
ctxt.computeTLSOffset()
Thearch.Archinit(ctxt)
if *FlagLinkshared && !Iself {
Exitf("-linkshared can only be used on elf systems")
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("HEADER = -H%d -T0x%x -D0x%x -R0x%x\n", Headtype, uint64(*FlagTextAddr), uint64(*FlagDataAddr), uint32(*FlagRound))
}
switch Buildmode {
case BuildmodeShared:
for i := 0; i < flag.NArg(); i++ {
arg := flag.Arg(i)
parts := strings.SplitN(arg, "=", 2)
var pkgpath, file string
if len(parts) == 1 {
pkgpath, file = "main", arg
} else {
pkgpath, file = parts[0], parts[1]
}
pkglistfornote = append(pkglistfornote, pkgpath...)
pkglistfornote = append(pkglistfornote, '\n')
addlibpath(ctxt, "command line", "command line", file, pkgpath, "")
}
case BuildmodePlugin:
pluginName := strings.TrimSuffix(filepath.Base(flag.Arg(0)), ".a")
addlibpath(ctxt, "command line", "command line", flag.Arg(0), pluginName, "")
default:
addlibpath(ctxt, "command line", "command line", flag.Arg(0), "main", "")
}
ctxt.loadlib()
ctxt.checkstrdata()
deadcode(ctxt)
fieldtrack(ctxt)
ctxt.callgraph()
ctxt.doelf()
if Headtype == obj.Hdarwin {
ctxt.domacho()
}
ctxt.dostkcheck()
if Headtype == obj.Hwindows || Headtype == obj.Hwindowsgui {
ctxt.dope()
}
ctxt.addexport()
Thearch.Gentext(ctxt) // trampolines, call stubs, etc.
ctxt.textbuildid()
ctxt.textaddress()
ctxt.pclntab()
ctxt.findfunctab()
ctxt.typelink()
ctxt.symtab()
ctxt.dodata()
ctxt.address()
ctxt.reloc()
Thearch.Asmb(ctxt)
ctxt.undef()
ctxt.hostlink()
ctxt.archive()
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f cpu time\n", obj.Cputime())
ctxt.Logf("%d symbols\n", len(ctxt.Syms.Allsym))
ctxt.Logf("%d liveness data\n", liveness)
}
ctxt.Bso.Flush()
errorexit()
}
作者:andradeandre
项目:gorum
func ldshlibsyms(shlib string) {
libpath := findshlib(shlib)
if libpath == "" {
return
}
for _, processedlib := range Ctxt.Shlibs {
if processedlib.Path == libpath {
return
}
}
if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil {
fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath)
Ctxt.Bso.Flush()
}
f, err := elf.Open(libpath)
if err != nil {
Diag("cannot open shared library: %s", libpath)
return
}
hash, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GOABIHASH_TAG)
if err != nil {
Diag("cannot read ABI hash from shared library %s: %v", libpath, err)
return
}
depsbytes, err := readnote(f, ELF_NOTE_GO_NAME, ELF_NOTE_GODEPS_TAG)
if err != nil {
Diag("cannot read dep list from shared library %s: %v", libpath, err)
return
}
deps := strings.Split(string(depsbytes), "\n")
syms, err := f.DynamicSymbols()
if err != nil {
Diag("cannot read symbols from shared library: %s", libpath)
return
}
for _, elfsym := range syms {
if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
continue
}
lsym := Linklookup(Ctxt, elfsym.Name, 0)
if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 {
if (lsym.Type != obj.SBSS && lsym.Type != obj.SNOPTRBSS) || len(lsym.R) != 0 || len(lsym.P) != 0 || f.Sections[elfsym.Section].Type != elf.SHT_NOBITS {
Diag("Found duplicate symbol %s reading from %s, first found in %s", elfsym.Name, shlib, lsym.File)
}
if lsym.Size > int64(elfsym.Size) {
// If the existing symbol is a BSS value that is
// larger than the one read from the shared library,
// keep references to that. Conversely, if the
// version from the shared libray is larger, we want
// to make all references be to that.
continue
}
}
lsym.Type = obj.SDYNIMPORT
lsym.ElfType = elf.ST_TYPE(elfsym.Info)
lsym.Size = int64(elfsym.Size)
if elfsym.Section != elf.SHN_UNDEF {
// Set .File for the library that actually defines the symbol.
lsym.File = libpath
// The decodetype_* functions in decodetype.go need access to
// the type data.
if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
lsym.P = readelfsymboldata(f, &elfsym)
}
}
}
// We might have overwritten some functions above (this tends to happen for the
// autogenerated type equality/hashing functions) and we don't want to generated
// pcln table entries for these any more so unstitch them from the Textp linked
// list.
var last *LSym
for s := Ctxt.Textp; s != nil; s = s.Next {
if s.Type == obj.SDYNIMPORT {
continue
}
if last == nil {
Ctxt.Textp = s
} else {
last.Next = s
}
last = s
}
if last == nil {
Ctxt.Textp = nil
Ctxt.Etextp = nil
} else {
last.Next = nil
Ctxt.Etextp = last
}
Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
}
作者:gmw
项目:g
func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
// TODO(minux): add morestack short-cuts with small fixed frame-size.
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil {
return
}
p := cursym.Text
textstksiz := p.To.Offset
if textstksiz == -8 {
// Compatibility hack.
p.From3.Offset |= obj.NOFRAME
textstksiz = 0
}
if textstksiz%8 != 0 {
ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
}
if p.From3.Offset&obj.NOFRAME != 0 {
if textstksiz != 0 {
ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
}
}
cursym.Args = p.To.Val.(int32)
cursym.Locals = int32(textstksiz)
/*
* find leaf subroutines
* strip NOPs
* expand RET
* expand BECOME pseudo
*/
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f noops\n", obj.Cputime())
}
ctxt.Bso.Flush()
var q *obj.Prog
var q1 *obj.Prog
for p := cursym.Text; p != nil; p = p.Link {
switch p.As {
/* too hard, just leave alone */
case obj.ATEXT:
q = p
p.Mark |= LABEL | LEAF | SYNC
if p.Link != nil {
p.Link.Mark |= LABEL
}
case ANOR:
q = p
if p.To.Type == obj.TYPE_REG {
if p.To.Reg == REGZERO {
p.Mark |= LABEL | SYNC
}
}
case ALWAR,
ASTWCCC,
AECIWX,
AECOWX,
AEIEIO,
AICBI,
AISYNC,
ATLBIE,
ATLBIEL,
ASLBIA,
ASLBIE,
ASLBMFEE,
ASLBMFEV,
ASLBMTE,
ADCBF,
ADCBI,
ADCBST,
ADCBT,
ADCBTST,
ADCBZ,
ASYNC,
ATLBSYNC,
APTESYNC,
ATW,
AWORD,
ARFI,
ARFCI,
ARFID,
AHRFID:
q = p
p.Mark |= LABEL | SYNC
continue
case AMOVW, AMOVWZ, AMOVD:
q = p
if p.From.Reg >= REG_SPECIAL || p.To.Reg >= REG_SPECIAL {
p.Mark |= LABEL | SYNC
}
continue
case AFABS,
//.........这里部分代码省略.........
作者:srei
项目:g
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f codeblk\n", obj.Cputime())
}
ld.Bso.Flush()
if ld.Iself {
ld.Asmbelfsetup()
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
machlink := int64(0)
if ld.HEADTYPE == obj.Hdarwin {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
}
dwarfoff := ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND))
ld.Cseek(dwarfoff)
ld.Segdwarf.Fileoff = uint64(ld.Cpos())
ld.Dwarfemitdebugsections()
ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
machlink = ld.Domacholink()
}
switch ld.HEADTYPE {
default:
ld.Diag("unknown header type %d", ld.HEADTYPE)
fallthrough
case obj.Hplan9,
obj.Helf:
break
case obj.Hdarwin:
ld.Debug['8'] = 1 /* 64-bit addresses */
case obj.Hlinux,
obj.Hfreebsd,
obj.Hnetbsd,
obj.Hopenbsd,
obj.Hdragonfly,
obj.Hsolaris:
ld.Debug['8'] = 1 /* 64-bit addresses */
case obj.Hnacl,
obj.Hwindows:
break
}
ld.Symsize = 0
ld.Spsize = 0
ld.Lcsize = 0
symo := int64(0)
if ld.Debug['s'] == 0 {
if ld.Debug['v'] != 0 {
fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
case obj.Hplan9,
obj.Helf:
ld.Debug['s'] = 1
symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(ld.INITRND))) + uint64(machlink))
//.........这里部分代码省略.........
作者:SpiderOa
项目:g
func asmb(ctxt *ld.Link) {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f asmb\n", obj.Cputime())
}
ctxt.Bso.Flush()
if ld.Iself {
ld.Asmbelfsetup(ctxt)
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
// 0xCC is INT $3 - breakpoint instruction
ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ctxt.Bso.Flush()
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f datblk\n", obj.Cputime())
}
ctxt.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
ld.Cseek(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
machlink := uint32(0)
if ld.HEADTYPE == obj.Hdarwin {
machlink = uint32(ld.Domacholink(ctxt))
}
ld.Symsize = 0
ld.Spsize = 0
ld.Lcsize = 0
symo := uint32(0)
if !*ld.FlagS {
// TODO: rationalize
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f sym\n", obj.Cputime())
}
ctxt.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
}
case obj.Hplan9:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
symo = uint32(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
case obj.Hwindows:
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), ld.PEFILEALIGN))
}
ld.Cseek(int64(symo))
switch ld.HEADTYPE {
default:
if ld.Iself {
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym(ctxt)
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc(ctxt)
}
}
case obj.Hplan9:
ld.Asmplan9sym(ctxt)
ld.Cflush()
sym := ld.Linklookup(ctxt, "pclntab", 0)
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
ld.Cput(sym.P[i])
}
//.........这里部分代码省略.........
作者:xslonepiec
项目:goio
func ldshlibsyms(shlib string) {
found := false
libpath := ""
for _, libdir := range Ctxt.Libdir {
libpath = filepath.Join(libdir, shlib)
if _, err := os.Stat(libpath); err == nil {
found = true
break
}
}
if !found {
Diag("cannot find shared library: %s", shlib)
return
}
for _, processedname := range Ctxt.Shlibs {
if processedname == libpath {
return
}
}
if Ctxt.Debugvlog > 1 && Ctxt.Bso != nil {
fmt.Fprintf(Ctxt.Bso, "%5.2f ldshlibsyms: found library with name %s at %s\n", obj.Cputime(), shlib, libpath)
Bflush(Ctxt.Bso)
}
f, err := elf.Open(libpath)
if err != nil {
Diag("cannot open shared library: %s", libpath)
return
}
defer f.Close()
syms, err := f.DynamicSymbols()
if err != nil {
Diag("cannot read symbols from shared library: %s", libpath)
return
}
for _, s := range syms {
if elf.ST_TYPE(s.Info) == elf.STT_NOTYPE || elf.ST_TYPE(s.Info) == elf.STT_SECTION {
continue
}
if s.Section == elf.SHN_UNDEF {
continue
}
if strings.HasPrefix(s.Name, "_") {
continue
}
lsym := Linklookup(Ctxt, s.Name, 0)
if lsym.Type != 0 && lsym.Dupok == 0 {
Diag(
"Found duplicate symbol %s reading from %s, first found in %s",
s.Name, shlib, lsym.File)
}
lsym.Type = SDYNIMPORT
lsym.File = libpath
}
// We might have overwritten some functions above (this tends to happen for the
// autogenerated type equality/hashing functions) and we don't want to generated
// pcln table entries for these any more so unstitch them from the Textp linked
// list.
var last *LSym
for s := Ctxt.Textp; s != nil; s = s.Next {
if s.Type == SDYNIMPORT {
continue
}
if last == nil {
Ctxt.Textp = s
} else {
last.Next = s
}
last = s
}
if last == nil {
Ctxt.Textp = nil
Ctxt.Etextp = nil
} else {
last.Next = nil
Ctxt.Etextp = last
}
Ctxt.Shlibs = append(Ctxt.Shlibs, libpath)
}
作者:danny800
项目:g
//.........这里部分代码省略.........
off = funcstart
end = funcstart + int32(Thearch.Ptrsize) + 3*4 + 5*4 + int32(pcln.Npcdata)*4 + int32(pcln.Nfuncdata)*int32(Thearch.Ptrsize)
if pcln.Nfuncdata > 0 && (end&int32(Thearch.Ptrsize-1) != 0) {
end += 4
}
Symgrow(Ctxt, ftab, int64(end))
// entry uintptr
off = int32(setaddr(Ctxt, ftab, int64(off), Ctxt.Cursym))
// name int32
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(ftabaddstring(ftab, Ctxt.Cursym.Name))))
// args int32
// TODO: Move into funcinfo.
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(Ctxt.Cursym.Args)))
// frame int32
// This has been removed (it was never set quite correctly anyway).
// Nothing should use it.
// Leave an obviously incorrect value.
// TODO: Remove entirely.
off = int32(setuint32(Ctxt, ftab, int64(off), 0x1234567))
if pcln != &pclntab_zpcln {
renumberfiles(Ctxt, pcln.File, &pcln.Pcfile)
if false {
// Sanity check the new numbering
for pciterinit(Ctxt, &it, &pcln.Pcfile); it.done == 0; pciternext(&it) {
if it.value < 1 || it.value > Ctxt.Nhistfile {
Diag("bad file number in pcfile: %d not in range [1, %d]\n", it.value, Ctxt.Nhistfile)
errorexit()
}
}
}
}
// pcdata
off = addpctab(ftab, off, &pcln.Pcsp)
off = addpctab(ftab, off, &pcln.Pcfile)
off = addpctab(ftab, off, &pcln.Pcline)
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(pcln.Npcdata)))
off = int32(setuint32(Ctxt, ftab, int64(off), uint32(pcln.Nfuncdata)))
for i = 0; i < int32(pcln.Npcdata); i++ {
off = addpctab(ftab, off, &pcln.Pcdata[i])
}
// funcdata, must be pointer-aligned and we're only int32-aligned.
// Missing funcdata will be 0 (nil pointer).
if pcln.Nfuncdata > 0 {
if off&int32(Thearch.Ptrsize-1) != 0 {
off += 4
}
for i = 0; i < int32(pcln.Nfuncdata); i++ {
if pcln.Funcdata[i] == nil {
setuintxx(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), uint64(pcln.Funcdataoff[i]), int64(Thearch.Ptrsize))
} else {
// TODO: Dedup.
funcdata_bytes += pcln.Funcdata[i].Size
setaddrplus(Ctxt, ftab, int64(off)+int64(Thearch.Ptrsize)*int64(i), pcln.Funcdata[i], pcln.Funcdataoff[i])
}
}
off += int32(pcln.Nfuncdata) * int32(Thearch.Ptrsize)
}
if off != end {
Diag("bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)", funcstart, off, end, pcln.Npcdata, pcln.Nfuncdata, Thearch.Ptrsize)
errorexit()
}
nfunc++
}
pclntabLastFunc = last
// Final entry of table is just end pc.
setaddrplus(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), last, last.Size)
// Start file table.
start := int32(len(ftab.P))
start += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1)
pclntabFiletabOffset = start
setuint32(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint32(start))
Symgrow(Ctxt, ftab, int64(start)+(int64(Ctxt.Nhistfile)+1)*4)
setuint32(Ctxt, ftab, int64(start), uint32(Ctxt.Nhistfile))
for s := Ctxt.Filesyms; s != nil; s = s.Next {
setuint32(Ctxt, ftab, int64(start)+s.Value*4, uint32(ftabaddstring(ftab, s.Name)))
}
ftab.Size = int64(len(ftab.P))
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f pclntab=%d bytes, funcdata total %d bytes\n", obj.Cputime(), int64(ftab.Size), int64(funcdata_bytes))
}
}
作者:SpiderOa
项目:g
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
* the per-compilation unit part of the DIE tree, while simultaneously
* emitting the debug_line section. When the final tree contains
* forward references, it will write the debug_info section in 2
* passes.
*
*/
func dwarfgeneratedebugsyms(ctxt *Link) {
if *FlagW { // disable dwarf
return
}
if *FlagS && HEADTYPE != obj.Hdarwin {
return
}
if HEADTYPE == obj.Hplan9 {
return
}
if Linkmode == LinkExternal {
if !Iself && HEADTYPE != obj.Hdarwin {
return
}
}
if ctxt.Debugvlog != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f dwarf\n", obj.Cputime())
}
// Forctxt.Diagnostic messages.
newattr(&dwtypes, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len("dwtypes")), "dwtypes")
// Some types that must exist to define other ones.
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "<unspecified>", 0)
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_NULLTYPE, "void", 0)
newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BARE_PTRTYPE, "unsafe.Pointer", 0)
die := newdie(ctxt, &dwtypes, dwarf.DW_ABRV_BASETYPE, "uintptr", 0) // needed for array size
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(SysArch.PtrSize), 0)
newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, obj.KindUintptr, 0)
// Prototypes needed for type synthesis.
prototypedies = map[string]*dwarf.DWDie{
"type.runtime.stringStructDWARF": nil,
"type.runtime.slice": nil,
"type.runtime.hmap": nil,
"type.runtime.bmap": nil,
"type.runtime.sudog": nil,
"type.runtime.waitq": nil,
"type.runtime.hchan": nil,
}
// Needed by the prettyprinter code for interface inspection.
defgotype(ctxt, lookup_or_diag(ctxt, "type.runtime._type"))
defgotype(ctxt, lookup_or_diag(ctxt, "type.runtime.interfacetype"))
defgotype(ctxt, lookup_or_diag(ctxt, "type.runtime.itab"))
genasmsym(ctxt, defdwsymb)
syms := writeabbrev(ctxt, nil)
syms, funcs := writelines(ctxt, syms)
syms = writeframes(ctxt, syms)
synthesizestringtypes(ctxt, dwtypes.Child)
synthesizeslicetypes(ctxt, dwtypes.Child)
synthesizemaptypes(ctxt, dwtypes.Child)
synthesizechantypes(ctxt, dwtypes.Child)
reversetree(&dwroot.Child)
reversetree(&dwtypes.Child)
reversetree(&dwglobals.Child)
movetomodule(&dwtypes)
movetomodule(&dwglobals)
// Need to reorder symbols so SDWARFINFO is after all SDWARFSECT
// (but we need to generate dies before writepub)
infosyms := writeinfo(ctxt, nil, funcs)
syms = writepub(ctxt, ".debug_pubnames", ispubname, syms)
syms = writepub(ctxt, ".debug_pubtypes", ispubtype, syms)
syms = writearanges(ctxt, syms)
syms = writegdbscript(ctxt, syms)
syms = append(syms, infosyms...)
dwarfp = syms
}
作者:hurkg
项目:g
func asmb(ctxt *ld.Link) {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f asmb\n", obj.Cputime())
}
if ld.Iself {
ld.Asmbelfsetup(ctxt)
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
ld.Cseek(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
/* output symbol table */
ld.Symsize = 0
ld.Lcsize = 0
symo := uint32(0)
if !*ld.FlagS {
if !ld.Iself {
ctxt.Diag("unsupported executable format")
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f sym\n", obj.Cputime())
}
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
ld.Cseek(int64(symo))
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym(ctxt)
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f dwarf\n", obj.Cputime())
}
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc(ctxt)
}
}
ctxt.Cursym = nil
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f header\n", obj.Cputime())
}
ld.Cseek(0)
switch ld.HEADTYPE {
default:
ctxt.Diag("unsupported operating system")
case obj.Hlinux:
ld.Asmbelf(ctxt, int64(symo))
}
ld.Cflush()
if *ld.FlagC {
fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
fmt.Printf("symsize=%d\n", ld.Symsize)
fmt.Printf("lcsize=%d\n", ld.Lcsize)
fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
}
}
作者:Greento
项目:g
// deadcode marks all reachable symbols.
//
// The basis of the dead code elimination is a flood fill of symbols,
// following their relocations, beginning at INITENTRY.
//
// This flood fill is wrapped in logic for pruning unused methods.
// All methods are mentioned by relocations on their receiver's *rtype.
// These relocations are specially defined as R_METHODOFF by the compiler
// so we can detect and manipulated them here.
//
// There are three ways a method of a reachable type can be invoked:
//
// 1. direct call
// 2. through a reachable interface type
// 3. reflect.Value.Call, .Method, or reflect.Method.Func
//
// The first case is handled by the flood fill, a directly called method
// is marked as reachable.
//
// The second case is handled by decomposing all reachable interface
// types into method signatures. Each encountered method is compared
// against the interface method signatures, if it matches it is marked
// as reachable. This is extremely conservative, but easy and correct.
//
// The third case is handled by looking to see if any of:
// - reflect.Value.Call is reachable
// - reflect.Value.Method is reachable
// - reflect.Type.Method or MethodByName is called.
// If any of these happen, all bets are off and all exported methods
// of reachable types are marked reachable.
//
// Any unreached text symbols are removed from ctxt.Textp.
func deadcode(ctxt *Link) {
if Debug['v'] != 0 {
fmt.Fprintf(ctxt.Bso, "%5.2f deadcode\n", obj.Cputime())
}
d := &deadcodepass{
ctxt: ctxt,
ifaceMethod: make(map[methodsig]bool),
}
// First, flood fill any symbols directly reachable in the call
// graph from INITENTRY. Ignore all methods not directly called.
d.init()
d.flood()
callSym := Linkrlookup(ctxt, "reflect.Value.Call", 0)
methSym := Linkrlookup(ctxt, "reflect.Value.Method", 0)
reflectSeen := false
if DynlinkingGo() {
// Exported methods may satisfy interfaces we don't know
// about yet when dynamically linking.
reflectSeen = true
}
for {
if !reflectSeen {
if d.reflectMethod || (callSym != nil && callSym.Attr.Reachable()) || (methSym != nil && methSym.Attr.Reachable()) {
// Methods might be called via reflection. Give up on
// static analysis, mark all exported methods of
// all reachable types as reachable.
reflectSeen = true
}
}
// Mark all methods that could satisfy a discovered
// interface as reachable. We recheck old marked interfaces
// as new types (with new methods) may have been discovered
// in the last pass.
var rem []methodref
for _, m := range d.markableMethods {
if (reflectSeen && m.isExported()) || d.ifaceMethod[m.m] {
d.markMethod(m)
} else {
rem = append(rem, m)
}
}
d.markableMethods = rem
if len(d.markQueue) == 0 {
// No new work was discovered. Done.
break
}
d.flood()
}
// Remove all remaining unreached R_METHODOFF relocations.
for _, m := range d.markableMethods {
for _, r := range m.r {
d.cleanupReloc(r)
}
}
if Buildmode != BuildmodeShared {
// Keep a typelink or itablink if the symbol it points at is being kept.
// (When BuildmodeShared, always keep typelinks and itablinks.)
for _, s := range ctxt.Allsym {
if strings.HasPrefix(s.Name, "go.typelink.") ||
//.........这里部分代码省略.........
作者:xslonepiec
项目:goio
func dodata() {
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
}
Bflush(&Bso)
var last *LSym
datap = nil
for s := Ctxt.Allsym; s != nil; s = s.Allsym {
if !s.Reachable || s.Special != 0 {
continue
}
if STEXT < s.Type && s.Type < SXREF {
if s.Onlist != 0 {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Onlist = 1
if last == nil {
datap = s
} else {
last.Next = s
}
s.Next = nil
last = s
}
}
for s := datap; s != nil; s = s.Next {
if int64(len(s.P)) > s.Size {
Diag("%s: initialize bounds (%d < %d)", s.Name, int64(s.Size), len(s.P))
}
}
/*
* now that we have the datap list, but before we start
* to assign addresses, record all the necessary
* dynamic relocations. these will grow the relocation
* symbol, which is itself data.
*
* on darwin, we need the symbol table numbers for dynreloc.
*/
if HEADTYPE == Hdarwin {
machosymorder()
}
dynreloc()
/* some symbols may no longer belong in datap (Mach-O) */
var l **LSym
var s *LSym
for l = &datap; ; {
s = *l
if s == nil {
break
}
if s.Type <= STEXT || SXREF <= s.Type {
*l = s.Next
} else {
l = &s.Next
}
}
*l = nil
datap = listsort(datap, datcmp, listnextp)
/*
* allocate sections. list is sorted by type,
* so we can just walk it for each piece we want to emit.
* segdata is processed before segtext, because we need
* to see all symbols in the .data and .bss sections in order
* to generate garbage collection information.
*/
/* begin segdata */
/* skip symbols belonging to segtext */
s = datap
for ; s != nil && s.Type < SELFSECT; s = s.Next {
}
/* writable ELF sections */
datsize := int64(0)
var sect *Section
for ; s != nil && s.Type < SELFGOT; s = s.Next {
sect = addsection(&Segdata, s.Name, 06)
sect.Align = symalign(s)
datsize = Rnd(datsize, int64(sect.Align))
sect.Vaddr = uint64(datsize)
s.Sect = sect
s.Type = SDATA
s.Value = int64(uint64(datsize) - sect.Vaddr)
growdatsize(&datsize, s)
sect.Length = uint64(datsize) - sect.Vaddr
}
/* .got (and .toc on ppc64) */
//.........这里部分代码省略.........
作者:bibbyflyawa
项目:g
//.........这里部分代码省略.........
}
switch s.Type & obj.SMASK {
case obj.SCONST,
obj.SRODATA,
obj.SSYMTAB,
obj.SPCLNTAB,
obj.SINITARR,
obj.SDATA,
obj.SNOPTRDATA,
obj.SELFROSECT,
obj.SMACHOGOT,
obj.STYPE,
obj.SSTRING,
obj.SGOSTRING,
obj.SGOFUNC,
obj.SWINDOWS:
if !s.Reachable {
continue
}
put(s, s.Name, 'D', Symaddr(s), s.Size, int(s.Version), s.Gotype)
case obj.SBSS, obj.SNOPTRBSS:
if !s.Reachable {
continue
}
if len(s.P) > 0 {
Diag("%s should not be bss (size=%d type=%d special=%d)", s.Name, int(len(s.P)), s.Type, s.Special)
}
put(s, s.Name, 'B', Symaddr(s), s.Size, int(s.Version), s.Gotype)
case obj.SFILE:
put(nil, s.Name, 'f', s.Value, 0, int(s.Version), nil)
case obj.SHOSTOBJ:
if HEADTYPE == obj.Hwindows || Iself {
put(s, s.Name, 'U', s.Value, 0, int(s.Version), nil)
}
case obj.SDYNIMPORT:
if !s.Reachable {
continue
}
put(s, s.Extname, 'U', 0, 0, int(s.Version), nil)
case obj.STLSBSS:
if Linkmode == LinkExternal && HEADTYPE != obj.Hopenbsd {
var type_ int
if goos == "android" {
type_ = 'B'
} else {
type_ = 't'
}
put(s, s.Name, type_, Symaddr(s), s.Size, int(s.Version), s.Gotype)
}
}
}
var a *Auto
var off int32
for s := Ctxt.Textp; s != nil; s = s.Next {
put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), s.Gotype)
// NOTE(ality): acid can't produce a stack trace without .frame symbols
put(nil, ".frame", 'm', int64(s.Locals)+int64(Thearch.Ptrsize), 0, 0, nil)
for a = s.Autom; a != nil; a = a.Link {
// Emit a or p according to actual offset, even if label is wrong.
// This avoids negative offsets, which cannot be encoded.
if a.Name != obj.A_AUTO && a.Name != obj.A_PARAM {
continue
}
// compute offset relative to FP
if a.Name == obj.A_PARAM {
off = a.Aoffset
} else {
off = a.Aoffset - int32(Thearch.Ptrsize)
}
// FP
if off >= 0 {
put(nil, a.Asym.Name, 'p', int64(off), 0, 0, a.Gotype)
continue
}
// SP
if off <= int32(-Thearch.Ptrsize) {
put(nil, a.Asym.Name, 'a', -(int64(off) + int64(Thearch.Ptrsize)), 0, 0, a.Gotype)
continue
}
}
}
// Otherwise, off is addressing the saved program counter.
// Something underhanded is going on. Say nothing.
if Debug['v'] != 0 || Debug['n'] != 0 {
fmt.Fprintf(&Bso, "%5.2f symsize = %d\n", obj.Cputime(), uint32(Symsize))
}
Bso.Flush()
}
作者:Mokole
项目:g
func asmb() {
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f asmb\n", obj.Cputime())
}
ld.Bso.Flush()
if ld.Iself {
ld.Asmbelfsetup()
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f datblk\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
ld.Cseek(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
/* output symbol table */
ld.Symsize = 0
ld.Lcsize = 0
symo := uint32(0)
if ld.Debug['s'] == 0 {
// TODO: rationalize
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f sym\n", obj.Cputime())
}
ld.Bso.Flush()
switch ld.HEADTYPE {
default:
if ld.Iself {
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
}
case obj.Hplan9:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
}
ld.Cseek(int64(symo))
switch ld.HEADTYPE {
default:
if ld.Iself {
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym()
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc()
}
}
case obj.Hplan9:
ld.Asmplan9sym()
ld.Cflush()
sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
if sym != nil {
ld.Lcsize = int32(len(sym.P))
for i := 0; int32(i) < ld.Lcsize; i++ {
ld.Cput(sym.P[i])
}
ld.Cflush()
}
}
}
ld.Ctxt.Cursym = nil
if ld.Debug['v'] != 0 {
fmt.Fprintf(ld.Bso, "%5.2f header\n", obj.Cputime())
}
ld.Bso.Flush()
ld.Cseek(0)
switch ld.HEADTYPE {
//.........这里部分代码省略.........