func toUTF16(data []byte) ([]uint16, error) { if len(data) < 2 { return []uint16{}, nil } if len(data)%2 > 0 { // TODO: if this is UTF-16 BE then this is likely encoded wrong data = append(data, 0) } var bo binary.ByteOrder if data[0] == 0xFF && data[1] == 0xFE { // UTF-16 LE bo = binary.LittleEndian } else if data[0] == 0xFE && data[1] == 0xFF { // UTF-16 BE bo = binary.BigEndian } else { return []uint16{}, nil } s := make([]uint16, 0, len(data)/2) for i := 2; i < len(data); i += 2 { s = append(s, bo.Uint16(data[i:i+2])) } return s, nil }
func decodeUTF16(b []byte, bo binary.ByteOrder) string { s := make([]uint16, 0, len(b)/2) for i := 0; i < len(b); i += 2 { s = append(s, bo.Uint16(b[i:i+2])) } return string(utf16.Decode(s)) }
func (b *Buffer) ReadUint16(order binary.ByteOrder) (uint16, error) { if b.readPos >= len(b.Buf)-2 { return 0, io.EOF } u := order.Uint16(b.Buf[b.readPos:]) b.readPos += 2 return u, nil }
func parseUtf16(strBytes []byte, bo binary.ByteOrder) (string, error) { shorts := make([]uint16, 0, len(strBytes)/2) for i := 0; i < len(strBytes); i += 2 { short := bo.Uint16(strBytes[i : i+2]) shorts = append(shorts, short) } return string(utf16.Decode(shorts)), nil }
func makeGuid(b []byte, order binary.ByteOrder) Guid { g := Guid{ DataA: order.Uint32(b[:4]), DataB: order.Uint16(b[4:6]), DataC: order.Uint16(b[6:8]), DataD: [8]byte{}, } copy(g.DataD[:], b[8:]) return g }
func UTF16ToUTF8String(b []byte, o binary.ByteOrder) dna.String { utf := make([]uint16, (len(b)+(2-1))/2) for i := 0; i+(2-1) < len(b); i += 2 { utf[i/2] = o.Uint16(b[i:]) } if len(b)/2 < len(utf) { utf[len(utf)-1] = utf8.RuneError } return dna.String(string(utf16.Decode(utf))) }
// Uint16 reads two bytes from the provided reader using a buffer from the // free list, converts it to a number using the provided byte order, and returns // the resulting uint16. func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, error) { buf := l.Borrow()[:2] if _, err := io.ReadFull(r, buf); err != nil { l.Return(buf) return 0, err } rv := byteOrder.Uint16(buf) l.Return(buf) return rv, nil }
func newParamListItemFromBytes(bin binary.ByteOrder, b []byte) (*paramListItem, error) { sz := bin.Uint16(b[2:]) if len(b) < int(sz+4) { return nil, io.EOF } return ¶mListItem{ pid: paramID(bin.Uint16(b[0:])), value: b[4 : 4+sz], }, nil }
func parseOptions(data []byte, byteOrder binary.ByteOrder) (*RawOptions, error) { if len(data) == 0 { return nil, nil } var options *RawOptions curData := data for { // // Read code + length // if len(curData) < 4 { return nil, io.ErrUnexpectedEOF } optionCode := OptionCode(byteOrder.Uint16(curData[:2])) optionLen := byteOrder.Uint16(curData[2:4]) if optionCode == OPTION_CODE_END_OF_OPT { break } curData = curData[4:] // // read value // if len(curData) < int(optionLen) { return nil, io.ErrUnexpectedEOF } optionValue := curData[:optionLen] // // check if this is new option // if options == nil { v := make(RawOptions) options = &v } optionValueArray, ok := (*options)[optionCode] if !ok { optionValueArray = make([]OptionValue, 0) (*options)[optionCode] = optionValueArray } (*options)[optionCode] = append(optionValueArray, optionValue) boundary := alignUint16(optionLen) curData = curData[boundary:] } return options, nil }
func newIPv6Address(byteOrder binary.ByteOrder, data []byte) IPv6Address { return IPv6Address{ byteOrder.Uint16(data[0:2]), byteOrder.Uint16(data[2:4]), byteOrder.Uint16(data[4:6]), byteOrder.Uint16(data[6:8]), byteOrder.Uint16(data[8:10]), byteOrder.Uint16(data[10:12]), byteOrder.Uint16(data[12:14]), byteOrder.Uint16(data[14:16]), } }
func initConnResponseTRead(in io.Reader, end binary.ByteOrder) *initConnResponseT { var buf [256]byte; var response initConnResponseT; in.Read(&buf); if buf[0] == failed { response.status = failed; response.reasonLength = buf[1]; response.reason = make([]byte, response.reasonLength); var i uint8; for i = 0; i < response.reasonLength; i++ { response.reason[i] = buf[i+2]; } end.Uint16(buf[i+1:i+3]); end.Uint16(buf[i+3:i+5]); } return &response; }
func newSimpleProtocol(n int, byteOrder binary.ByteOrder) *simpleProtocol { protocol := &simpleProtocol{ n: n, bo: byteOrder, } switch n { case 1: protocol.encodeHead = func(buffer []byte) { buffer[0] = byte(len(buffer) - n) } protocol.decodeHead = func(buffer []byte) int { return int(buffer[0]) } case 2: protocol.encodeHead = func(buffer []byte) { byteOrder.PutUint16(buffer, uint16(len(buffer)-n)) } protocol.decodeHead = func(buffer []byte) int { return int(byteOrder.Uint16(buffer)) } case 4: protocol.encodeHead = func(buffer []byte) { byteOrder.PutUint32(buffer, uint32(len(buffer)-n)) } protocol.decodeHead = func(buffer []byte) int { return int(byteOrder.Uint32(buffer)) } case 8: protocol.encodeHead = func(buffer []byte) { byteOrder.PutUint64(buffer, uint64(len(buffer)-n)) } protocol.decodeHead = func(buffer []byte) int { return int(byteOrder.Uint64(buffer)) } default: panic("unsupported packet head size") } return protocol }
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { bytesPerPixel := c.PixelFormat.BPP / 8 pixelBytes := make([]uint8, bytesPerPixel) var byteOrder binary.ByteOrder = binary.LittleEndian if c.PixelFormat.BigEndian { byteOrder = binary.BigEndian } colors := make([]Color, int(rect.Height)*int(rect.Width)) for y := uint16(0); y < rect.Height; y++ { for x := uint16(0); x < rect.Width; x++ { if _, err := io.ReadFull(r, pixelBytes); err != nil { return nil, err } var rawPixel uint32 if c.PixelFormat.BPP == 8 { rawPixel = uint32(pixelBytes[0]) } else if c.PixelFormat.BPP == 16 { rawPixel = uint32(byteOrder.Uint16(pixelBytes)) } else if c.PixelFormat.BPP == 32 { rawPixel = byteOrder.Uint32(pixelBytes) } color := &colors[int(y)*int(rect.Width)+int(x)] if c.PixelFormat.TrueColor { color.R = uint16((rawPixel >> c.PixelFormat.RedShift) & uint32(c.PixelFormat.RedMax)) color.G = uint16((rawPixel >> c.PixelFormat.GreenShift) & uint32(c.PixelFormat.GreenMax)) color.B = uint16((rawPixel >> c.PixelFormat.BlueShift) & uint32(c.PixelFormat.BlueMax)) } else { *color = c.ColorMap[rawPixel] } } } return &RawEncoding{colors}, nil }
// decodeNumeric decodes a simple stream of numeric or character data func decodeNumeric(de dataElement, bo binary.ByteOrder) (interface{}, error) { var b [8]byte var bs []byte if int(de.nBytes) > len(b) { bs = make([]byte, de.nBytes) } else { bs = b[:de.nBytes] } _, err := de.r.ReadAt(bs, 0) if err != nil { return nil, err } switch de.dataType { case miINT8: val := make([]int8, de.nBytes) for i, x := range bs { val[i] = int8(x) } return val, nil case miUINT8: val := make([]uint8, de.nBytes) copy(val, bs) return val, nil case miINT16: val := make([]int16, de.nBytes/2) for i := range bs { val[i] = int16(bo.Uint16(bs[2*i:])) } return val, nil case miUINT16: val := make([]uint16, de.nBytes/2) for i := range bs { val[i] = bo.Uint16(bs[2*i:]) } return val, nil case miINT32: val := make([]int32, de.nBytes/4) for i := range bs { val[i] = int32(bo.Uint32(bs[4*i:])) } return val, nil case miUINT32: val := make([]uint32, de.nBytes/4) for i := range bs { val[i] = bo.Uint32(bs[4*i:]) } return val, nil case miINT64: val := make([]int64, de.nBytes/8) for i := range bs { val[i] = int64(bo.Uint64(bs[8*i:])) } return val, nil case miUINT64: val := make([]uint64, de.nBytes/8) for i := range bs { val[i] = bo.Uint64(bs[8*i:]) } return val, nil case miSINGLE: val := make([]float32, de.nBytes/4) for i := range bs { val[i] = math.Float32frombits(bo.Uint32(bs[4*i:])) } return val, nil case miDOUBLE: val := make([]float64, de.nBytes/8) for i := range bs { val[i] = math.Float64frombits(bo.Uint64(bs[8*i:])) } return val, nil case miUTF8: return string(bs), nil case miUTF16: x := make([]uint16, de.nBytes/2) for i := range bs { x[i] = bo.Uint16(bs[2*i:]) } return string(utf16.Decode(x)), nil case miUTF32: runes := make([]rune, de.nBytes/4) for i := range runes { runes[i] = rune(bo.Uint32(bs[4*i:])) } return string(runes), nil } return nil, nil }
func (s *Stream) readSectionHeaderBlockBody(headerData []byte) (header *SectionHeaderBlock, err error) { // // read byte-order magic, version and section length // bodyData, err := s.read(16) if err != nil { return nil, err } // // read byte-order magic // var byteOrder binary.ByteOrder if bodyData[0] == 0x1A && bodyData[1] == 0x2B && bodyData[2] == 0x3C && bodyData[3] == 0x4D { byteOrder = binary.BigEndian } else if bodyData[3] == 0x1A && bodyData[2] == 0x2B && bodyData[1] == 0x3C && bodyData[0] == 0x4D { byteOrder = binary.LittleEndian } else { return nil, errors.New("invalid byte order mark") } // // read other fields // versionMajor := byteOrder.Uint16(bodyData[4:6]) versionMinor := byteOrder.Uint16(bodyData[6:8]) sectionLength := int64(byteOrder.Uint64(bodyData[8:16])) // // Read options // totalLength := byteOrder.Uint32(headerData[4:8]) optsLen := totalLength - 28 rawOpts, err := s.readOptions(optsLen, byteOrder) if err != nil { return nil, err } opts, err := parseSectionHeaderOptions(rawOpts) if err != nil { return nil, err } // // Read last block total length // _, err = s.readExactly(4) if err != nil { return nil, err } retval := &SectionHeaderBlock{ totalLength: totalLength, ByteOrder: byteOrder, VersionMajor: versionMajor, VersionMinor: versionMinor, SectionLength: sectionLength, RawOptions: rawOpts, Options: opts, } s.sectionHeader = retval return retval, nil }
// Convert raw image data into a 2d array of 64-bit labels func (d *Data) convertTo64bit(geom dvid.Geometry, data []uint8, bytesPerVoxel, stride int) ([]byte, error) { nx := int(geom.Size().Value(0)) ny := int(geom.Size().Value(1)) numBytes := nx * ny * 8 data64 := make([]byte, numBytes, numBytes) var byteOrder binary.ByteOrder if geom.DataShape().ShapeDimensions() == 2 { byteOrder = binary.BigEndian // This is the default for PNG } else { byteOrder = binary.LittleEndian } switch bytesPerVoxel { case 1: dstI := 0 for y := 0; y < ny; y++ { srcI := y * stride for x := 0; x < nx; x++ { binary.LittleEndian.PutUint64(data64[dstI:dstI+8], uint64(data[srcI])) srcI++ dstI += 8 } } case 2: dstI := 0 for y := 0; y < ny; y++ { srcI := y * stride for x := 0; x < nx; x++ { value := byteOrder.Uint16(data[srcI : srcI+2]) binary.LittleEndian.PutUint64(data64[dstI:dstI+8], uint64(value)) srcI += 2 dstI += 8 } } case 4: dstI := 0 for y := 0; y < ny; y++ { srcI := y * stride for x := 0; x < nx; x++ { value := byteOrder.Uint32(data[srcI : srcI+4]) binary.LittleEndian.PutUint64(data64[dstI:dstI+8], uint64(value)) srcI += 4 dstI += 8 } } case 8: dstI := 0 for y := 0; y < ny; y++ { srcI := y * stride for x := 0; x < nx; x++ { value := byteOrder.Uint64(data[srcI : srcI+8]) binary.LittleEndian.PutUint64(data64[dstI:dstI+8], uint64(value)) srcI += 8 dstI += 8 } } default: return nil, fmt.Errorf("could not convert to 64-bit label given %d bytes/voxel", bytesPerVoxel) } return data64, nil }
func getUint16(b []byte, byteOrder binary.ByteOrder) (uint16, int) { return byteOrder.Uint16(b), 2 }
func getInt16(b []byte, byteOrder binary.ByteOrder) (int16, int) { return int16(byteOrder.Uint16(b)), 2 }
func reprSShort(in []byte, bo binary.ByteOrder) string { return fmt.Sprintf("%d", int16(bo.Uint16(in))) }
func rvalSShort(in []byte, bo binary.ByteOrder) reflect.Value { return reflect.ValueOf(int16(bo.Uint16(in))) }
func newSchemeFromBytes(bin binary.ByteOrder, b []byte) encapsulationScheme { return encapsulationScheme{ scheme: binary.BigEndian.Uint16(b[0:]), // seems to always be BigEndian (?) options: bin.Uint16(b[2:]), } }
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 } switch SysArch.Family { default: Errorf(nil, "%s: elf %s unimplemented", pn, SysArch.Name) return case sys.MIPS64: if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 { Errorf(nil, "%s: elf object but not mips64", pn) return } case sys.ARM: if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { Errorf(nil, "%s: elf object but not arm", pn) return } case sys.AMD64: if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { Errorf(nil, "%s: elf object but not amd64", pn) return } case sys.ARM64: if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { Errorf(nil, "%s: elf object but not arm64", pn) return } case sys.I386: if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { Errorf(nil, "%s: elf object but not 386", pn) return } case sys.PPC64: if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { Errorf(nil, "%s: elf object but not ppc64", pn) return } case sys.S390X: if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 { Errorf(nil, "%s: elf object but not s390x", pn) return } } // load section list into memory. elfobj.sect = make([]ElfSect, elfobj.shnum) elfobj.nsect = uint(elfobj.shnum) for i := 0; uint(i) < elfobj.nsect; i++ { if f.Seek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { goto bad } sect = &elfobj.sect[i] if is64 != 0 { var b ElfSectBytes64 if err = binary.Read(f, e, &b); err != nil { goto bad } sect.nameoff = e.Uint32(b.Name[:]) sect.type_ = e.Uint32(b.Type[:]) sect.flags = e.Uint64(b.Flags[:]) sect.addr = e.Uint64(b.Addr[:]) sect.off = e.Uint64(b.Off[:]) sect.size = e.Uint64(b.Size[:]) sect.link = e.Uint32(b.Link[:]) sect.info = e.Uint32(b.Info[:]) sect.align = e.Uint64(b.Align[:]) sect.entsize = e.Uint64(b.Entsize[:]) } else { var b ElfSectBytes if err = binary.Read(f, e, &b); err != nil { goto bad } sect.nameoff = e.Uint32(b.Name[:]) sect.type_ = e.Uint32(b.Type[:]) sect.flags = uint64(e.Uint32(b.Flags[:])) sect.addr = uint64(e.Uint32(b.Addr[:])) sect.off = uint64(e.Uint32(b.Off[:])) sect.size = uint64(e.Uint32(b.Size[:])) sect.link = e.Uint32(b.Link[:]) sect.info = e.Uint32(b.Info[:]) sect.align = uint64(e.Uint32(b.Align[:])) sect.entsize = uint64(e.Uint32(b.Entsize[:])) } } // read section string table and translate names if elfobj.shstrndx >= uint32(elfobj.nsect) { err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) goto bad } sect = &elfobj.sect[elfobj.shstrndx] if err = elfmap(elfobj, sect); err != nil { goto bad } for i := 0; uint(i) < elfobj.nsect; i++ { if elfobj.sect[i].nameoff != 0 { elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) } } // load string table for symbols into memory. elfobj.symtab = section(elfobj, ".symtab") if elfobj.symtab == nil { // our work is done here - no symbols means nothing can refer to this file return } if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { Errorf(nil, "%s: elf object has symbol table with invalid string table link", pn) return } elfobj.symstr = &elfobj.sect[elfobj.symtab.link] if is64 != 0 { elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE) } else { elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE) } if err = elfmap(elfobj, elfobj.symtab); err != nil { goto bad } if err = elfmap(elfobj, elfobj.symstr); err != nil { goto bad } // load text and data segments into memory. // they are not as small as the section lists, but we'll need // the memory anyway for the symbol images, so we might // as well use one large chunk. // create symbols for elfmapped sections for i := 0; uint(i) < elfobj.nsect; i++ { sect = &elfobj.sect[i] if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" { if err = elfmap(elfobj, sect); err != nil { goto bad } parseArmAttributes(ctxt, e, sect.base[:sect.size]) } if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 { continue } if sect.type_ != ElfSectNobits { if err = elfmap(elfobj, sect); err != nil { goto bad } } name = fmt.Sprintf("%s(%s)", pkg, sect.name) s = ctxt.Syms.Lookup(name, localSymVersion) switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) { default: err = fmt.Errorf("unexpected flags for ELF section %s", sect.name) goto bad case ElfSectFlagAlloc: s.Type = obj.SRODATA case ElfSectFlagAlloc + ElfSectFlagWrite: if sect.type_ == ElfSectNobits { s.Type = obj.SNOPTRBSS } else { s.Type = obj.SNOPTRDATA } case ElfSectFlagAlloc + ElfSectFlagExec: s.Type = obj.STEXT } if sect.name == ".got" || sect.name == ".toc" { s.Type = obj.SELFGOT } if sect.type_ == ElfSectProgbits { s.P = sect.base s.P = s.P[:sect.size] } s.Size = int64(sect.size) s.Align = int32(sect.align) sect.sym = s } // enter sub-symbols into symbol table. // symbol 0 is the null symbol. symbols = make([]*Symbol, elfobj.nsymtab) for i := 1; i < elfobj.nsymtab; i++ { if err = readelfsym(ctxt, elfobj, i, &sym, 1, localSymVersion); err != nil { goto bad } symbols[i] = sym.sym if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { continue } if sym.shndx == ElfSymShnCommon { s = sym.sym if uint64(s.Size) < sym.size { s.Size = int64(sym.size) } if s.Type == 0 || s.Type == obj.SXREF { s.Type = obj.SNOPTRBSS } continue } if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { continue } // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols if sym.sym == nil { continue } sect = &elfobj.sect[sym.shndx] if sect.sym == nil { if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this continue } if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" { // This reportedly happens with clang 3.7 on ARM. // See issue 13139. continue } if strings.HasPrefix(sym.name, ".LASF") { // gcc on s390x does this continue } Errorf(sym.sym, "%s: sym#%d: ignoring symbol in section %d (type %d)", pn, i, sym.shndx, sym.type_) continue } s = sym.sym if s.Outer != nil { if s.Attr.DuplicateOK() { continue } Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) } s.Sub = sect.sym.Sub sect.sym.Sub = s s.Type = sect.sym.Type | s.Type&^obj.SMASK | obj.SSUB if !s.Attr.CgoExportDynamic() { s.Dynimplib = "" // satisfy dynimport } s.Value = int64(sym.value) s.Size = int64(sym.size) s.Outer = sect.sym if sect.sym.Type == obj.STEXT { if s.Attr.External() && !s.Attr.DuplicateOK() { Errorf(s, "%s: duplicate symbol definition", pn) } s.Attr |= AttrExternal } if elfobj.machine == ElfMachPower64 { flag = int(sym.other) >> 5 if 2 <= flag && flag <= 6 { s.Localentry = 1 << uint(flag-2) } else if flag == 7 { Errorf(s, "%s: invalid sym.other 0x%x", pn, sym.other) } } } // Sort outer lists by address, adding to textp. // This keeps textp in increasing address order. for i := 0; uint(i) < elfobj.nsect; i++ { s = elfobj.sect[i].sym if s == nil { continue } if s.Sub != nil { s.Sub = listsort(s.Sub) } if s.Type == obj.STEXT { if s.Attr.OnList() { log.Fatalf("symbol %s listed multiple times", s.Name) } s.Attr |= AttrOnList ctxt.Textp = append(ctxt.Textp, s) for s = s.Sub; s != nil; s = s.Sub { if s.Attr.OnList() { log.Fatalf("symbol %s listed multiple times", s.Name) } s.Attr |= AttrOnList ctxt.Textp = append(ctxt.Textp, s) } } } // load relocations for i := 0; uint(i) < elfobj.nsect; i++ { rsect = &elfobj.sect[i] if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { continue } if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { continue } sect = &elfobj.sect[rsect.info] if err = elfmap(elfobj, rsect); err != nil { goto bad } rela = 0 if rsect.type_ == ElfSectRela { rela = 1 } n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) r = make([]Reloc, n) p = rsect.base for j = 0; j < n; j++ { add = 0 rp = &r[j] if is64 != 0 { // 64-bit rel/rela rp.Off = int32(e.Uint64(p)) p = p[8:] info = e.Uint64(p) p = p[8:] if rela != 0 { add = e.Uint64(p) p = p[8:] } } else { // 32-bit rel/rela rp.Off = int32(e.Uint32(p)) p = p[4:] info = uint64(e.Uint32(p)) info = info>>8<<32 | info&0xff // convert to 64-bit info p = p[4:] if rela != 0 { add = uint64(e.Uint32(p)) p = p[4:] } } if info&0xffffffff == 0 { // skip R_*_NONE relocation j-- n-- continue } if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol rp.Sym = nil } else { if err = readelfsym(ctxt, elfobj, int(info>>32), &sym, 0, 0); err != nil { goto bad } sym.sym = symbols[info>>32] if sym.sym == nil { err = fmt.Errorf("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_) goto bad } rp.Sym = sym.sym } rp.Type = 256 + obj.RelocType(info) rp.Siz = relSize(ctxt, pn, uint32(info)) if rela != 0 { rp.Add = int64(add) } else { // load addend from image if rp.Siz == 4 { rp.Add = int64(e.Uint32(sect.base[rp.Off:])) } else if rp.Siz == 8 { rp.Add = int64(e.Uint64(sect.base[rp.Off:])) } else { Errorf(nil, "invalid rela size %d", rp.Siz) } } if rp.Siz == 2 { rp.Add = int64(int16(rp.Add)) } if rp.Siz == 4 { rp.Add = int64(int32(rp.Add)) } } //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); sort.Sort(rbyoff(r[:n])) // just in case s = sect.sym s.R = r s.R = s.R[:n] } return bad: Errorf(nil, "%s: malformed elf file: %v", pn, err) }
// Copy 'data' into program memory starting at address 'addr'. 'byteOrder' // determines whether the 16-bit words in 'data' are stored in big-endian or // little-endian form. func (em *Emulator) LoadProgramBytes(data []uint8, addr uint16, byteOrder binary.ByteOrder) { for i := 0; i+1 < len(data); i += 2 { em.ProgMem[addr] = byteOrder.Uint16(data[i:]) addr++ } }
func ldelf(f *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(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 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 } switch Thearch.Thechar { default: Diag("%s: elf %s unimplemented", pn, Thestring) return case '5': if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 { Diag("%s: elf object but not arm", pn) return } case '6': if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not amd64", pn) return } case '7': if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not arm64", pn) return } case '8': if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 { Diag("%s: elf object but not 386", pn) return } case '9': if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 { Diag("%s: elf object but not ppc64", pn) return } } // load section list into memory. elfobj.sect = make([]ElfSect, elfobj.shnum) elfobj.nsect = uint(elfobj.shnum) for i := 0; uint(i) < elfobj.nsect; i++ { if Bseek(f, int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 { goto bad } sect = &elfobj.sect[i] if is64 != 0 { var b ElfSectBytes64 if err = binary.Read(f, e, &b); err != nil { goto bad } sect.nameoff = uint32(e.Uint32(b.Name[:])) sect.type_ = e.Uint32(b.Type[:]) sect.flags = e.Uint64(b.Flags[:]) sect.addr = e.Uint64(b.Addr[:]) sect.off = e.Uint64(b.Off[:]) sect.size = e.Uint64(b.Size[:]) sect.link = e.Uint32(b.Link[:]) sect.info = e.Uint32(b.Info[:]) sect.align = e.Uint64(b.Align[:]) sect.entsize = e.Uint64(b.Entsize[:]) } else { var b ElfSectBytes if err = binary.Read(f, e, &b); err != nil { goto bad } sect.nameoff = uint32(e.Uint32(b.Name[:])) sect.type_ = e.Uint32(b.Type[:]) sect.flags = uint64(e.Uint32(b.Flags[:])) sect.addr = uint64(e.Uint32(b.Addr[:])) sect.off = uint64(e.Uint32(b.Off[:])) sect.size = uint64(e.Uint32(b.Size[:])) sect.link = e.Uint32(b.Link[:]) sect.info = e.Uint32(b.Info[:]) sect.align = uint64(e.Uint32(b.Align[:])) sect.entsize = uint64(e.Uint32(b.Entsize[:])) } } // read section string table and translate names if elfobj.shstrndx >= uint32(elfobj.nsect) { err = fmt.Errorf("shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect) goto bad } sect = &elfobj.sect[elfobj.shstrndx] if err = elfmap(elfobj, sect); err != nil { goto bad } for i := 0; uint(i) < elfobj.nsect; i++ { if elfobj.sect[i].nameoff != 0 { elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:]) } } // load string table for symbols into memory. elfobj.symtab = section(elfobj, ".symtab") if elfobj.symtab == nil { // our work is done here - no symbols means nothing can refer to this file return } if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) { Diag("%s: elf object has symbol table with invalid string table link", pn) return } elfobj.symstr = &elfobj.sect[elfobj.symtab.link] if is64 != 0 { elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE) } else { elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE) } if err = elfmap(elfobj, elfobj.symtab); err != nil { goto bad } if err = elfmap(elfobj, elfobj.symstr); err != nil { goto bad } // load text and data segments into memory. // they are not as small as the section lists, but we'll need // the memory anyway for the symbol images, so we might // as well use one large chunk. // create symbols for elfmapped sections for i := 0; uint(i) < elfobj.nsect; i++ { sect = &elfobj.sect[i] if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 { continue } if sect.type_ != ElfSectNobits { if err = elfmap(elfobj, sect); err != nil { goto bad } } name = fmt.Sprintf("%s(%s)", pkg, sect.name) s = Linklookup(Ctxt, name, Ctxt.Version) switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) { default: err = fmt.Errorf("unexpected flags for ELF section %s", sect.name) goto bad case ElfSectFlagAlloc: s.Type = SRODATA case ElfSectFlagAlloc + ElfSectFlagWrite: if sect.type_ == ElfSectNobits { s.Type = SNOPTRBSS } else { s.Type = SNOPTRDATA } case ElfSectFlagAlloc + ElfSectFlagExec: s.Type = STEXT } if sect.name == ".got" || sect.name == ".toc" { s.Type = SELFGOT } if sect.type_ == ElfSectProgbits { s.P = sect.base s.P = s.P[:sect.size] } s.Size = int64(sect.size) s.Align = int32(sect.align) sect.sym = s } // enter sub-symbols into symbol table. // symbol 0 is the null symbol. symbols = make([]*LSym, elfobj.nsymtab) if symbols == nil { Diag("out of memory") Errorexit() } for i := 1; i < elfobj.nsymtab; i++ { if err = readelfsym(elfobj, i, &sym, 1); err != nil { goto bad } symbols[i] = sym.sym if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone { continue } if sym.shndx == ElfSymShnCommon { s = sym.sym if uint64(s.Size) < sym.size { s.Size = int64(sym.size) } if s.Type == 0 || s.Type == SXREF { s.Type = SNOPTRBSS } continue } if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 { continue } // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols if sym.sym == nil { continue } sect = &elfobj.sect[sym.shndx:][0] if sect.sym == nil { if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this continue } Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_) continue } s = sym.sym if s.Outer != nil { if s.Dupok != 0 { continue } Diag("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name) Errorexit() } s.Sub = sect.sym.Sub sect.sym.Sub = s s.Type = sect.sym.Type | s.Type&^SMASK | SSUB if s.Cgoexport&CgoExportDynamic == 0 { s.Dynimplib = "" // satisfy dynimport } s.Value = int64(sym.value) s.Size = int64(sym.size) s.Outer = sect.sym if sect.sym.Type == STEXT { if s.External != 0 && s.Dupok == 0 { Diag("%s: duplicate definition of %s", pn, s.Name) } s.External = 1 } if elfobj.machine == ElfMachPower64 { flag = int(sym.other) >> 5 if 2 <= flag && flag <= 6 { s.Localentry = 1 << uint(flag-2) } else if flag == 7 { Diag("%s: invalid sym.other 0x%x for %s", pn, sym.other, s.Name) } } } // Sort outer lists by address, adding to textp. // This keeps textp in increasing address order. for i := 0; uint(i) < elfobj.nsect; i++ { s = elfobj.sect[i].sym if s == nil { continue } if s.Sub != nil { s.Sub = listsort(s.Sub, valuecmp, listsubp) } if s.Type == STEXT { if s.Onlist != 0 { log.Fatalf("symbol %s listed multiple times", s.Name) } s.Onlist = 1 if Ctxt.Etextp != nil { Ctxt.Etextp.Next = s } else { Ctxt.Textp = s } Ctxt.Etextp = s for s = s.Sub; s != nil; s = s.Sub { if s.Onlist != 0 { log.Fatalf("symbol %s listed multiple times", s.Name) } s.Onlist = 1 Ctxt.Etextp.Next = s Ctxt.Etextp = s } } } // load relocations for i := 0; uint(i) < elfobj.nsect; i++ { rsect = &elfobj.sect[i] if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel { continue } if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil { continue } sect = &elfobj.sect[rsect.info] if err = elfmap(elfobj, rsect); err != nil { goto bad } rela = 0 if rsect.type_ == ElfSectRela { rela = 1 } n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela)) r = make([]Reloc, n) p = rsect.base for j = 0; j < n; j++ { add = 0 rp = &r[j] if is64 != 0 { // 64-bit rel/rela rp.Off = int32(e.Uint64(p)) p = p[8:] info = e.Uint64(p) p = p[8:] if rela != 0 { add = e.Uint64(p) p = p[8:] } } else { // 32-bit rel/rela rp.Off = int32(e.Uint32(p)) p = p[4:] info = uint64(e.Uint32(p)) info = info>>8<<32 | info&0xff // convert to 64-bit info p = p[4:] if rela != 0 { add = uint64(e.Uint32(p)) p = p[4:] } } if info&0xffffffff == 0 { // skip R_*_NONE relocation j-- n-- continue } if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol rp.Sym = nil } else { if err = readelfsym(elfobj, int(info>>32), &sym, 0); err != nil { goto bad } sym.sym = symbols[info>>32] if sym.sym == nil { err = fmt.Errorf("%s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_) goto bad } rp.Sym = sym.sym } rp.Type = int32(reltype(pn, int(uint32(info)), &rp.Siz)) if rela != 0 { rp.Add = int64(add) } else { // load addend from image if rp.Siz == 4 { rp.Add = int64(e.Uint32(sect.base[rp.Off:])) } else if rp.Siz == 8 { rp.Add = int64(e.Uint64(sect.base[rp.Off:])) } else { Diag("invalid rela size %d", rp.Siz) } } if rp.Siz == 2 { rp.Add = int64(int16(rp.Add)) } if rp.Siz == 4 { rp.Add = int64(int32(rp.Add)) } } //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add); sort.Sort(rbyoff(r[:n])) // just in case s = sect.sym s.R = r s.R = s.R[:n] } return bad: Diag("%s: malformed elf file: %v", pn, err) }
func unmarshalVal(data []byte, bo binary.ByteOrder, ft FieldType, v reflect.Value) error { // Do the quick and simple thing. if v.Type() == ft.ReflectType() { v.Set(ft.Valuer()(data, bo)) return nil } typ := v.Type() switch typ.Kind() { case reflect.Ptr: switch typ { case bigRatType: // If the types were the same, it should have been caught above. return ErrUnsuppConversion{ft, typ} default: newV := reflect.New(typ.Elem()) if err := unmarshalVal(data, bo, ft, newV.Elem()); err != nil { return err } v.Set(newV) } case reflect.String: var s string switch ft.ReflectType().Kind() { case reflect.Uint8: s = string(data) default: return ErrUnsuppConversion{ft, typ} } v.SetString(s) case reflect.Uint16: // We can up convert an uint8/byte to a uint16. if ft.ReflectType().Kind() == reflect.Uint8 { v.SetUint(uint64(data[0])) } else { return ErrUnsuppConversion{ft, typ} } case reflect.Int16: // We can up convert an int8 to an int16. if ft.ReflectType().Kind() == reflect.Int8 { v.SetInt(int64(int8(data[0]))) } else { return ErrUnsuppConversion{ft, typ} } case reflect.Uint32: var u32 uint32 switch ft.ReflectType().Kind() { case reflect.Uint16: // We can up convert an uint16 to an uint32. u32 = uint32(bo.Uint16(data)) case reflect.Uint8: // We can up convert an uint8 to an uint32. u32 = uint32(data[0]) default: return ErrUnsuppConversion{ft, typ} } v.SetUint(uint64(u32)) case reflect.Int32: var i32 int32 switch ft.ReflectType().Kind() { case reflect.Int16: // We can up convert an int16 to an int32. i32 = int32(int16(bo.Uint16(data))) case reflect.Int8: // We can up convert an int8 to an int32. i32 = int32(int8(data[0])) default: return ErrUnsuppConversion{ft, typ} } v.SetInt(int64(i32)) case reflect.Uint64: var u64 uint64 switch ft.ReflectType().Kind() { case reflect.Uint32: u64 = uint64(bo.Uint32(data)) case reflect.Uint16: u64 = uint64(bo.Uint16(data)) case reflect.Uint8: u64 = uint64(data[0]) default: return ErrUnsuppConversion{ft, typ} } v.SetUint(u64) case reflect.Int64: var i64 int64 switch ft.ReflectType().Kind() { case reflect.Int32: i64 = int64(int32(bo.Uint32(data))) case reflect.Int16: i64 = int64(int16(bo.Uint16(data))) case reflect.Int8: i64 = int64(int8(data[0])) default: return ErrUnsuppConversion{ft, typ} } v.SetInt(i64) case reflect.Uint8, reflect.Int8, reflect.Float32, reflect.Float64: // If this was not handled at the top, we do not support // converting other types to these types. return ErrUnsuppConversion{ft, typ} } return nil }