作者:duhaibo040
项目:go-
func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
start := obj.Boffset(f)
ctxt.IncVersion()
var buf [8]uint8
obj.Bread(f, buf[:])
if string(buf[:]) != startmagic {
log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
}
c := obj.Bgetc(f)
if c != 1 {
log.Fatalf("%s: invalid file version number %d", pn, c)
}
var lib string
for {
lib = rdstring(f)
if lib == "" {
break
}
addlib(ctxt, pkg, pn, lib)
}
ctxt.CurRefs = []*LSym{nil} // zeroth ref is nil
for {
c, err := f.Peek(1)
if err != nil {
log.Fatalf("%s: peeking: %v", pn, err)
}
if c[0] == 0xff {
obj.Bgetc(f)
break
}
readref(ctxt, f, pkg, pn)
}
dataLength := rdint64(f)
data := make([]byte, dataLength)
obj.Bread(f, data)
for {
c, err := f.Peek(1)
if err != nil {
log.Fatalf("%s: peeking: %v", pn, err)
}
if c[0] == 0xff {
break
}
readsym(ctxt, f, &data, pkg, pn)
}
buf = [8]uint8{}
obj.Bread(f, buf[:])
if string(buf[:]) != endmagic {
log.Fatalf("%s: invalid file end", pn)
}
if obj.Boffset(f) != start+length {
log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(obj.Boffset(f)), int64(start+length))
}
}
作者:RealHacke
项目:g
// hostArchive reads an archive file holding host objects and links in
// required objects. The general format is the same as a Go archive
// file, but it has an armap listing symbols and the objects that
// define them. This is used for the compiler support library
// libgcc.a.
func hostArchive(name string) {
f, err := obj.Bopenr(name)
if err != nil {
if os.IsNotExist(err) {
// It's OK if we don't have a libgcc file at all.
return
}
Exitf("cannot open file %s: %v", name, err)
}
defer obj.Bterm(f)
magbuf := make([]byte, len(ARMAG))
if obj.Bread(f, magbuf) != len(magbuf) {
Exitf("file %s too short", name)
}
var arhdr ArHdr
l := nextar(f, obj.Boffset(f), &arhdr)
if l <= 0 {
Exitf("%s missing armap", name)
}
var armap archiveMap
if arhdr.name == "/" || arhdr.name == "/SYM64/" {
armap = readArmap(name, f, arhdr)
} else {
Exitf("%s missing armap", name)
}
loaded := make(map[uint64]bool)
any := true
for any {
var load []uint64
for s := Ctxt.Allsym; s != nil; s = s.Allsym {
for _, r := range s.R {
if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF {
if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
load = append(load, off)
loaded[off] = true
}
}
}
}
for _, off := range load {
l := nextar(f, int64(off), &arhdr)
if l <= 0 {
Exitf("%s missing archive entry at offset %d", name, off)
}
pname := fmt.Sprintf("%s(%s)", name, arhdr.name)
l = atolwhex(arhdr.size)
h := ldobj(f, "libgcc", l, pname, name, ArchiveObj)
obj.Bseek(f, h.off, 0)
h.ld(f, h.pkg, h.length, h.pn)
}
any = len(load) > 0
}
}
作者:4a
项目:g
// rdsymName reads a symbol name, replacing all "". with pkg.
func rdsymName(f *obj.Biobuf, pkg string) string {
n := rdint(f)
if n == 0 {
rdint64(f)
return ""
}
if len(rdBuf) < n {
rdBuf = make([]byte, n, 2*n)
}
origName := rdBuf[:n]
obj.Bread(f, origName)
adjName := rdBuf[n:n]
for {
i := bytes.Index(origName, emptyPkg)
if i == -1 {
adjName = append(adjName, origName...)
break
}
adjName = append(adjName, origName[:i]...)
adjName = append(adjName, pkg...)
adjName = append(adjName, '.')
origName = origName[i+len(emptyPkg):]
}
name := string(adjName)
if len(adjName) > len(rdBuf) {
rdBuf = adjName // save the larger buffer for reuse
}
return name
}
作者:bibbyflyawa
项目:g
/*
* look for the next file in an archive.
* adapted from libmach.
*/
func nextar(bp *obj.Biobuf, off int64, a *ArHdr) int64 {
if off&1 != 0 {
off++
}
obj.Bseek(bp, off, 0)
buf := make([]byte, SAR_HDR)
if n := obj.Bread(bp, buf); n < len(buf) {
if n >= 0 {
return 0
}
return -1
}
a.name = artrim(buf[0:16])
a.date = artrim(buf[16:28])
a.uid = artrim(buf[28:34])
a.gid = artrim(buf[34:40])
a.mode = artrim(buf[40:48])
a.size = artrim(buf[48:58])
a.fmag = artrim(buf[58:60])
arsize := atolwhex(a.size)
if arsize&1 != 0 {
arsize++
}
return int64(arsize) + SAR_HDR
}
作者:4a
项目:g
func rdstring(f *obj.Biobuf) string {
n := rdint(f)
if len(rdBuf) < n {
rdBuf = make([]byte, n)
}
obj.Bread(f, rdBuf[:n])
return string(rdBuf[:n])
}
作者:4a
项目:g
func macholoadsym(m *LdMachoObj, symtab *LdMachoSymtab) int {
if symtab.sym != nil {
return 0
}
strbuf := make([]byte, symtab.strsize)
if obj.Bseek(m.f, m.base+int64(symtab.stroff), 0) < 0 || obj.Bread(m.f, strbuf) != len(strbuf) {
return -1
}
symsize := 12
if m.is64 {
symsize = 16
}
n := int(symtab.nsym * uint32(symsize))
symbuf := make([]byte, n)
if obj.Bseek(m.f, m.base+int64(symtab.symoff), 0) < 0 || obj.Bread(m.f, symbuf) != len(symbuf) {
return -1
}
sym := make([]LdMachoSym, symtab.nsym)
p := symbuf
var s *LdMachoSym
var v uint32
for i := 0; uint32(i) < symtab.nsym; i++ {
s = &sym[i]
v = m.e.Uint32(p)
if v >= symtab.strsize {
return -1
}
s.name = cstring(strbuf[v:])
s.type_ = uint8(p[4])
s.sectnum = uint8(p[5])
s.desc = m.e.Uint16(p[6:])
if m.is64 {
s.value = m.e.Uint64(p[8:])
} else {
s.value = uint64(m.e.Uint32(p[8:]))
}
p = p[symsize:]
}
symtab.str = strbuf
symtab.sym = sym
return 0
}
作者:josharia
项目:go.ss
func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
start := obj.Boffset(f)
ctxt.Version++
var buf [8]uint8
obj.Bread(f, buf[:])
if string(buf[:]) != startmagic {
log.Fatalf("%s: invalid file start %x %x %x %x %x %x %x %x", pn, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7])
}
c := obj.Bgetc(f)
if c != 1 {
log.Fatalf("%s: invalid file version number %d", pn, c)
}
var lib string
for {
lib = rdstring(f)
if lib == "" {
break
}
addlib(ctxt, pkg, pn, lib)
}
for {
c, err := f.Peek(1)
if err != nil {
log.Fatalf("%s: peeking: %v", pn, err)
}
if c[0] == 0xff {
break
}
readsym(ctxt, f, pkg, pn)
}
buf = [8]uint8{}
obj.Bread(f, buf[:])
if string(buf[:]) != endmagic {
log.Fatalf("%s: invalid file end", pn)
}
if obj.Boffset(f) != start+length {
log.Fatalf("%s: unexpected end at %d, want %d", pn, int64(obj.Boffset(f)), int64(start+length))
}
}
作者:danny800
项目:g
// readArmap reads the archive symbol map.
func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap {
is64 := arhdr.name == "/SYM64/"
wordSize := 4
if is64 {
wordSize = 8
}
l := atolwhex(arhdr.size)
contents := make([]byte, l)
if obj.Bread(f, contents) != int(l) {
Exitf("short read from %s", filename)
}
var c uint64
if is64 {
c = binary.BigEndian.Uint64(contents)
} else {
c = uint64(binary.BigEndian.Uint32(contents))
}
contents = contents[wordSize:]
ret := make(archiveMap)
names := contents[c*uint64(wordSize):]
for i := uint64(0); i < c; i++ {
n := 0
for names[n] != 0 {
n++
}
name := string(names[:n])
names = names[n+1:]
// For Mach-O and PE/386 files we strip a leading
// underscore from the symbol name.
if goos == "darwin" || (goos == "windows" && goarch == "386") {
if name[0] == '_' && len(name) > 1 {
name = name[1:]
}
}
var off uint64
if is64 {
off = binary.BigEndian.Uint64(contents)
} else {
off = uint64(binary.BigEndian.Uint32(contents))
}
contents = contents[wordSize:]
ret[name] = off
}
return ret
}
作者:4a
项目:g
func macholoaddsym(m *LdMachoObj, d *LdMachoDysymtab) int {
n := int(d.nindirectsyms)
p := make([]byte, n*4)
if obj.Bseek(m.f, m.base+int64(d.indirectsymoff), 0) < 0 || obj.Bread(m.f, p) != len(p) {
return -1
}
d.indir = make([]uint32, n)
for i := 0; i < n; i++ {
d.indir[i] = m.e.Uint32(p[4*i:])
}
return 0
}
作者:4a
项目:g
func pemap(peobj *PeObj, sect *PeSect) int {
if sect.base != nil {
return 0
}
sect.base = make([]byte, sect.sh.SizeOfRawData)
if sect.sh.PointerToRawData == 0 { // .bss doesn't have data in object file
return 0
}
if obj.Bseek(peobj.f, int64(peobj.base)+int64(sect.sh.PointerToRawData), 0) < 0 || obj.Bread(peobj.f, sect.base) != len(sect.base) {
return -1
}
return 0
}
作者:4a
项目:g
func rddata(f *obj.Biobuf) []byte {
var p []byte
n := rdint(f)
if n > rddataBufMax {
p = make([]byte, n)
} else {
if len(rddataBuf) < n {
rddataBuf = make([]byte, rddataBufMax)
}
p = rddataBuf[:n:n]
rddataBuf = rddataBuf[n:]
}
obj.Bread(f, p)
return p
}
作者:4a
项目:g
func macholoadrel(m *LdMachoObj, sect *LdMachoSect) int {
if sect.rel != nil || sect.nreloc == 0 {
return 0
}
rel := make([]LdMachoRel, sect.nreloc)
n := int(sect.nreloc * 8)
buf := make([]byte, n)
if obj.Bseek(m.f, m.base+int64(sect.reloff), 0) < 0 || obj.Bread(m.f, buf) != n {
return -1
}
var p []byte
var r *LdMachoRel
var v uint32
for i := 0; uint32(i) < sect.nreloc; i++ {
r = &rel[i]
p = buf[i*8:]
r.addr = m.e.Uint32(p)
// TODO(rsc): Wrong interpretation for big-endian bitfields?
if r.addr&0x80000000 != 0 {
// scatterbrained relocation
r.scattered = 1
v = r.addr >> 24
r.addr &= 0xFFFFFF
r.type_ = uint8(v & 0xF)
v >>= 4
r.length = 1 << (v & 3)
v >>= 2
r.pcrel = uint8(v & 1)
r.value = m.e.Uint32(p[4:])
} else {
v = m.e.Uint32(p[4:])
r.symnum = v & 0xFFFFFF
v >>= 24
r.pcrel = uint8(v & 1)
v >>= 1
r.length = 1 << (v & 3)
v >>= 2
r.extrn = uint8(v & 1)
v >>= 1
r.type_ = uint8(v)
}
}
sect.rel = rel
return 0
}
作者:arnold
项目:g
func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
if sect.base != nil {
return nil
}
if sect.off+sect.size > uint64(elfobj.length) {
err = fmt.Errorf("elf section past end of file")
return err
}
sect.base = make([]byte, sect.size)
err = fmt.Errorf("short read")
if obj.Bseek(elfobj.f, int64(uint64(elfobj.base)+sect.off), 0) < 0 || obj.Bread(elfobj.f, sect.base) != len(sect.base) {
return err
}
return nil
}
作者:jacobs
项目:g
func (p *importer) string() string {
if p.debugFormat {
p.marker('s')
}
if n := int(p.rawInt64()); n > 0 {
if cap(p.buf) < n {
p.buf = make([]byte, n)
} else {
p.buf = p.buf[:n]
}
r := obj.Bread(p.in, p.buf)
p.read += r
if r != n {
Fatalf("read error: read %d bytes of %d", r, n)
}
return string(p.buf)
}
return ""
}
作者:josharia
项目:go.ss
func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym {
n := int(rdint(f))
if n == 0 {
rdint(f)
return nil
}
if len(symbuf) < n {
symbuf = make([]byte, n)
}
obj.Bread(f, symbuf[:n])
p := string(symbuf[:n])
v := int(rdint(f))
if v != 0 {
v = ctxt.Version
}
s := Linklookup(ctxt, expandpkg(p, pkg), v)
if v == 0 && s.Name[0] == '$' && s.Type == 0 {
if strings.HasPrefix(s.Name, "$f32.") {
x, _ := strconv.ParseUint(s.Name[5:], 16, 32)
i32 := int32(x)
s.Type = obj.SRODATA
s.Local = true
Adduint32(ctxt, s, uint32(i32))
s.Reachable = false
} else if strings.HasPrefix(s.Name, "$f64.") || strings.HasPrefix(s.Name, "$i64.") {
x, _ := strconv.ParseUint(s.Name[5:], 16, 64)
i64 := int64(x)
s.Type = obj.SRODATA
s.Local = true
Adduint64(ctxt, s, uint64(i64))
s.Reachable = false
}
}
if v == 0 && strings.HasPrefix(s.Name, "runtime.gcbits.") {
s.Local = true
}
return s
}
作者:srei
项目:g
func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) {
var p0, p1 int
if Debug['g'] != 0 {
return
}
if int64(int(length)) != length {
fmt.Fprintf(os.Stderr, "%s: too much pkg data in %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
errorexit()
}
return
}
// In a __.PKGDEF, we only care about the package name.
// Don't read all the export data.
if length > 1000 && whence == Pkgdef {
length = 1000
}
bdata := make([]byte, length)
if int64(obj.Bread(f, bdata)) != length {
fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
errorexit()
}
return
}
data := string(bdata)
// first \n$$ marks beginning of exports - skip rest of line
p0 = strings.Index(data, "\n$$")
if p0 < 0 {
if Debug['u'] != 0 && whence != ArchiveObj {
Exitf("cannot find export data in %s", filename)
}
return
}
// \n$$B marks the beginning of binary export data - don't skip over the B
p0 += 3
for p0 < len(data) && data[p0] != '\n' && data[p0] != 'B' {
p0++
}
// second marks end of exports / beginning of local data
p1 = strings.Index(data[p0:], "\n$$\n")
if p1 < 0 && whence == Pkgdef {
p1 = len(data) - p0
}
if p1 < 0 {
fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
if Debug['u'] != 0 {
errorexit()
}
return
}
p1 += p0
for p0 < p1 && data[p0] != 'B' && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
p0++
}
// don't check this section if we have binary (B) export data
// TODO fix this eventually
if p0 < p1 && data[p0] != 'B' {
if !strings.HasPrefix(data[p0:], "package ") {
fmt.Fprintf(os.Stderr, "%s: bad package section in %s - %.20s\n", os.Args[0], filename, data[p0:])
if Debug['u'] != 0 {
errorexit()
}
return
}
p0 += 8
for p0 < p1 && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
p0++
}
pname := p0
for p0 < p1 && data[p0] != ' ' && data[p0] != '\t' && data[p0] != '\n' {
p0++
}
if Debug['u'] != 0 && whence != ArchiveObj && (p0+6 > p1 || !strings.HasPrefix(data[p0:], " safe\n")) {
Exitf("load of unsafe package %s", filename)
}
name := data[pname:p0]
for p0 < p1 && data[p0] != '\n' {
p0++
}
if p0 < p1 {
p0++
}
if pkg == "main" && name != "main" {
Exitf("%s: not package main (package %s)", filename, name)
}
}
// __.PKGDEF has no cgo section - those are in the C compiler-generated object files.
//.........这里部分代码省略.........
作者:bibbyflyawa
项目:g
func objfile(lib *Library) {
pkg := pathtoprefix(lib.Pkg)
if Debug['v'] > 1 {
fmt.Fprintf(&Bso, "%5.2f ldobj: %s (%s)\n", obj.Cputime(), lib.File, pkg)
}
Bso.Flush()
var err error
var f *obj.Biobuf
f, err = obj.Bopenr(lib.File)
if err != nil {
Exitf("cannot open file %s: %v", lib.File, err)
}
magbuf := make([]byte, len(ARMAG))
if obj.Bread(f, magbuf) != len(magbuf) || !strings.HasPrefix(string(magbuf), ARMAG) {
/* load it as a regular file */
l := obj.Bseek(f, 0, 2)
obj.Bseek(f, 0, 0)
ldobj(f, pkg, l, lib.File, lib.File, FileObj)
obj.Bterm(f)
return
}
/* skip over optional __.GOSYMDEF and process __.PKGDEF */
off := obj.Boffset(f)
var arhdr ArHdr
l := nextar(f, off, &arhdr)
var pname string
if l <= 0 {
Diag("%s: short read on archive file symbol header", lib.File)
goto out
}
if strings.HasPrefix(arhdr.name, symname) {
off += l
l = nextar(f, off, &arhdr)
if l <= 0 {
Diag("%s: short read on archive file symbol header", lib.File)
goto out
}
}
if !strings.HasPrefix(arhdr.name, pkgname) {
Diag("%s: cannot find package header", lib.File)
goto out
}
if Buildmode == BuildmodeShared {
before := obj.Boffset(f)
pkgdefBytes := make([]byte, atolwhex(arhdr.size))
obj.Bread(f, pkgdefBytes)
hash := sha1.Sum(pkgdefBytes)
lib.hash = hash[:]
obj.Bseek(f, before, 0)
}
off += l
if Debug['u'] != 0 {
ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
}
/*
* load all the object files from the archive now.
* this gives us sequential file access and keeps us
* from needing to come back later to pick up more
* objects. it breaks the usual C archive model, but
* this is Go, not C. the common case in Go is that
* we need to load all the objects, and then we throw away
* the individual symbols that are unused.
*
* loading every object will also make it possible to
* load foreign objects not referenced by __.GOSYMDEF.
*/
for {
l = nextar(f, off, &arhdr)
if l == 0 {
break
}
if l < 0 {
Exitf("%s: malformed archive", lib.File)
}
off += l
pname = fmt.Sprintf("%s(%s)", lib.File, arhdr.name)
l = atolwhex(arhdr.size)
ldobj(f, pkg, l, pname, lib.File, ArchiveObj)
}
out:
obj.Bterm(f)
}
作者:josharia
项目:go.ss
func rdstring(f *obj.Biobuf) string {
n := rdint(f)
p := make([]byte, n)
obj.Bread(f, p)
return string(p)
}
作者:arnold
项目:g
func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
}
Ctxt.Version++
base := int32(obj.Boffset(f))
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 *LSym
var sect *ElfSect
var sym ElfSym
var symbols []*LSym
if obj.Bread(f, hdrbuf[:]) != len(hdrbuf) {
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 = int64(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 {
Diag("%s: elf but not elf relocatable object", pn)
return
}
//.........这里部分代码省略.........
作者:josharia
项目:go.ss
func rddata(f *obj.Biobuf) []byte {
n := rdint(f)
p := make([]byte, n)
obj.Bread(f, p)
return p
}