]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/loadelf/ldelf.go
cmd/vet: honor analyzer flags when running vet outside $GOROOT/src
[gostls13.git] / src / cmd / link / internal / loadelf / ldelf.go
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package loadelf implements an ELF file reader.
6 package loadelf
7
8 import (
9         "bytes"
10         "cmd/internal/bio"
11         "cmd/internal/objabi"
12         "cmd/internal/sys"
13         "cmd/link/internal/loader"
14         "cmd/link/internal/sym"
15         "debug/elf"
16         "encoding/binary"
17         "fmt"
18         "io"
19         "log"
20         "sort"
21         "strings"
22 )
23
24 /*
25 Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
26 http://code.swtch.com/plan9port/src/tip/src/libmach/
27
28         Copyright © 2004 Russ Cox.
29         Portions Copyright © 2008-2010 Google Inc.
30         Portions Copyright © 2010 The Go Authors.
31
32 Permission is hereby granted, free of charge, to any person obtaining a copy
33 of this software and associated documentation files (the "Software"), to deal
34 in the Software without restriction, including without limitation the rights
35 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
36 copies of the Software, and to permit persons to whom the Software is
37 furnished to do so, subject to the following conditions:
38
39 The above copyright notice and this permission notice shall be included in
40 all copies or substantial portions of the Software.
41
42 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
45 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
47 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
48 THE SOFTWARE.
49 */
50 const (
51         ElfClassNone = 0
52         ElfClass32   = 1
53         ElfClass64   = 2
54 )
55
56 const (
57         ElfDataNone = 0
58         ElfDataLsb  = 1
59         ElfDataMsb  = 2
60 )
61
62 const (
63         ElfTypeNone         = 0
64         ElfTypeRelocatable  = 1
65         ElfTypeExecutable   = 2
66         ElfTypeSharedObject = 3
67         ElfTypeCore         = 4
68 )
69
70 const (
71         ElfMachNone        = 0
72         ElfMach32100       = 1
73         ElfMachSparc       = 2
74         ElfMach386         = 3
75         ElfMach68000       = 4
76         ElfMach88000       = 5
77         ElfMach486         = 6
78         ElfMach860         = 7
79         ElfMachMips        = 8
80         ElfMachS370        = 9
81         ElfMachMipsLe      = 10
82         ElfMachParisc      = 15
83         ElfMachVpp500      = 17
84         ElfMachSparc32Plus = 18
85         ElfMach960         = 19
86         ElfMachPower       = 20
87         ElfMachPower64     = 21
88         ElfMachS390        = 22
89         ElfMachV800        = 36
90         ElfMachFr20        = 37
91         ElfMachRh32        = 38
92         ElfMachRce         = 39
93         ElfMachArm         = 40
94         ElfMachAlpha       = 41
95         ElfMachSH          = 42
96         ElfMachSparc9      = 43
97         ElfMachAmd64       = 62
98         ElfMachArm64       = 183
99 )
100
101 const (
102         ElfAbiNone     = 0
103         ElfAbiSystemV  = 0
104         ElfAbiHPUX     = 1
105         ElfAbiNetBSD   = 2
106         ElfAbiLinux    = 3
107         ElfAbiSolaris  = 6
108         ElfAbiAix      = 7
109         ElfAbiIrix     = 8
110         ElfAbiFreeBSD  = 9
111         ElfAbiTru64    = 10
112         ElfAbiModesto  = 11
113         ElfAbiOpenBSD  = 12
114         ElfAbiARM      = 97
115         ElfAbiEmbedded = 255
116 )
117
118 const (
119         ElfSectNone      = 0
120         ElfSectProgbits  = 1
121         ElfSectSymtab    = 2
122         ElfSectStrtab    = 3
123         ElfSectRela      = 4
124         ElfSectHash      = 5
125         ElfSectDynamic   = 6
126         ElfSectNote      = 7
127         ElfSectNobits    = 8
128         ElfSectRel       = 9
129         ElfSectShlib     = 10
130         ElfSectDynsym    = 11
131         ElfSectFlagWrite = 0x1
132         ElfSectFlagAlloc = 0x2
133         ElfSectFlagExec  = 0x4
134 )
135
136 const (
137         ElfSymBindLocal  = 0
138         ElfSymBindGlobal = 1
139         ElfSymBindWeak   = 2
140 )
141
142 const (
143         ElfSymTypeNone    = 0
144         ElfSymTypeObject  = 1
145         ElfSymTypeFunc    = 2
146         ElfSymTypeSection = 3
147         ElfSymTypeFile    = 4
148         ElfSymTypeCommon  = 5
149         ElfSymTypeTLS     = 6
150 )
151
152 const (
153         ElfSymShnNone   = 0
154         ElfSymShnAbs    = 0xFFF1
155         ElfSymShnCommon = 0xFFF2
156 )
157
158 const (
159         ElfProgNone      = 0
160         ElfProgLoad      = 1
161         ElfProgDynamic   = 2
162         ElfProgInterp    = 3
163         ElfProgNote      = 4
164         ElfProgShlib     = 5
165         ElfProgPhdr      = 6
166         ElfProgFlagExec  = 0x1
167         ElfProgFlagWrite = 0x2
168         ElfProgFlagRead  = 0x4
169 )
170
171 const (
172         ElfNotePrStatus     = 1
173         ElfNotePrFpreg      = 2
174         ElfNotePrPsinfo     = 3
175         ElfNotePrTaskstruct = 4
176         ElfNotePrAuxv       = 6
177         ElfNotePrXfpreg     = 0x46e62b7f
178 )
179
180 // TODO(crawshaw): de-duplicate with cmd/link/internal/ld/elf.go.
181 const (
182         ELF64SYMSIZE = 24
183         ELF32SYMSIZE = 16
184
185         SHT_ARM_ATTRIBUTES = 0x70000003
186 )
187
188 type ElfHdrBytes struct {
189         Ident     [16]uint8
190         Type      [2]uint8
191         Machine   [2]uint8
192         Version   [4]uint8
193         Entry     [4]uint8
194         Phoff     [4]uint8
195         Shoff     [4]uint8
196         Flags     [4]uint8
197         Ehsize    [2]uint8
198         Phentsize [2]uint8
199         Phnum     [2]uint8
200         Shentsize [2]uint8
201         Shnum     [2]uint8
202         Shstrndx  [2]uint8
203 }
204
205 type ElfSectBytes struct {
206         Name    [4]uint8
207         Type    [4]uint8
208         Flags   [4]uint8
209         Addr    [4]uint8
210         Off     [4]uint8
211         Size    [4]uint8
212         Link    [4]uint8
213         Info    [4]uint8
214         Align   [4]uint8
215         Entsize [4]uint8
216 }
217
218 type ElfProgBytes struct {
219 }
220
221 type ElfSymBytes struct {
222         Name  [4]uint8
223         Value [4]uint8
224         Size  [4]uint8
225         Info  uint8
226         Other uint8
227         Shndx [2]uint8
228 }
229
230 type ElfHdrBytes64 struct {
231         Ident     [16]uint8
232         Type      [2]uint8
233         Machine   [2]uint8
234         Version   [4]uint8
235         Entry     [8]uint8
236         Phoff     [8]uint8
237         Shoff     [8]uint8
238         Flags     [4]uint8
239         Ehsize    [2]uint8
240         Phentsize [2]uint8
241         Phnum     [2]uint8
242         Shentsize [2]uint8
243         Shnum     [2]uint8
244         Shstrndx  [2]uint8
245 }
246
247 type ElfSectBytes64 struct {
248         Name    [4]uint8
249         Type    [4]uint8
250         Flags   [8]uint8
251         Addr    [8]uint8
252         Off     [8]uint8
253         Size    [8]uint8
254         Link    [4]uint8
255         Info    [4]uint8
256         Align   [8]uint8
257         Entsize [8]uint8
258 }
259
260 type ElfProgBytes64 struct {
261 }
262
263 type ElfSymBytes64 struct {
264         Name  [4]uint8
265         Info  uint8
266         Other uint8
267         Shndx [2]uint8
268         Value [8]uint8
269         Size  [8]uint8
270 }
271
272 type ElfSect struct {
273         name    string
274         nameoff uint32
275         type_   uint32
276         flags   uint64
277         addr    uint64
278         off     uint64
279         size    uint64
280         link    uint32
281         info    uint32
282         align   uint64
283         entsize uint64
284         base    []byte
285         sym     *sym.Symbol
286 }
287
288 type ElfObj struct {
289         f         *bio.Reader
290         base      int64 // offset in f where ELF begins
291         length    int64 // length of ELF
292         is64      int
293         name      string
294         e         binary.ByteOrder
295         sect      []ElfSect
296         nsect     uint
297         nsymtab   int
298         symtab    *ElfSect
299         symstr    *ElfSect
300         type_     uint32
301         machine   uint32
302         version   uint32
303         entry     uint64
304         phoff     uint64
305         shoff     uint64
306         flags     uint32
307         ehsize    uint32
308         phentsize uint32
309         phnum     uint32
310         shentsize uint32
311         shnum     uint32
312         shstrndx  uint32
313 }
314
315 type ElfSym struct {
316         name  string
317         value uint64
318         size  uint64
319         bind  uint8
320         type_ uint8
321         other uint8
322         shndx uint16
323         sym   *sym.Symbol
324 }
325
326 var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
327
328 const (
329         TagFile               = 1
330         TagCPUName            = 4
331         TagCPURawName         = 5
332         TagCompatibility      = 32
333         TagNoDefaults         = 64
334         TagAlsoCompatibleWith = 65
335         TagABIVFPArgs         = 28
336 )
337
338 type elfAttribute struct {
339         tag  uint64
340         sval string
341         ival uint64
342 }
343
344 type elfAttributeList struct {
345         data []byte
346         err  error
347 }
348
349 func (a *elfAttributeList) string() string {
350         if a.err != nil {
351                 return ""
352         }
353         nul := bytes.IndexByte(a.data, 0)
354         if nul < 0 {
355                 a.err = io.EOF
356                 return ""
357         }
358         s := string(a.data[:nul])
359         a.data = a.data[nul+1:]
360         return s
361 }
362
363 func (a *elfAttributeList) uleb128() uint64 {
364         if a.err != nil {
365                 return 0
366         }
367         v, size := binary.Uvarint(a.data)
368         a.data = a.data[size:]
369         return v
370 }
371
372 // Read an elfAttribute from the list following the rules used on ARM systems.
373 func (a *elfAttributeList) armAttr() elfAttribute {
374         attr := elfAttribute{tag: a.uleb128()}
375         switch {
376         case attr.tag == TagCompatibility:
377                 attr.ival = a.uleb128()
378                 attr.sval = a.string()
379
380         case attr.tag == 64: // Tag_nodefaults has no argument
381
382         case attr.tag == 65: // Tag_also_compatible_with
383                 // Not really, but we don't actually care about this tag.
384                 attr.sval = a.string()
385
386         // Tag with string argument
387         case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0):
388                 attr.sval = a.string()
389
390         default: // Tag with integer argument
391                 attr.ival = a.uleb128()
392         }
393         return attr
394 }
395
396 func (a *elfAttributeList) done() bool {
397         if a.err != nil || len(a.data) == 0 {
398                 return true
399         }
400         return false
401 }
402
403 // Look for the attribute that indicates the object uses the hard-float ABI (a
404 // file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
405 // format used means that we have to parse all of the file-level attributes to
406 // find the one we are looking for. This format is slightly documented in "ELF
407 // for the ARM Architecture" but mostly this is derived from reading the source
408 // to gold and readelf.
409 func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags uint32, err error) {
410         found = false
411         if data[0] != 'A' {
412                 return false, 0, fmt.Errorf(".ARM.attributes has unexpected format %c\n", data[0])
413         }
414         data = data[1:]
415         for len(data) != 0 {
416                 sectionlength := e.Uint32(data)
417                 sectiondata := data[4:sectionlength]
418                 data = data[sectionlength:]
419
420                 nulIndex := bytes.IndexByte(sectiondata, 0)
421                 if nulIndex < 0 {
422                         return false, 0, fmt.Errorf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
423                 }
424                 name := string(sectiondata[:nulIndex])
425                 sectiondata = sectiondata[nulIndex+1:]
426
427                 if name != "aeabi" {
428                         continue
429                 }
430                 for len(sectiondata) != 0 {
431                         subsectiontag, sz := binary.Uvarint(sectiondata)
432                         subsectionsize := e.Uint32(sectiondata[sz:])
433                         subsectiondata := sectiondata[sz+4 : subsectionsize]
434                         sectiondata = sectiondata[subsectionsize:]
435
436                         if subsectiontag != TagFile {
437                                 continue
438                         }
439                         attrList := elfAttributeList{data: subsectiondata}
440                         for !attrList.done() {
441                                 attr := attrList.armAttr()
442                                 if attr.tag == TagABIVFPArgs && attr.ival == 1 {
443                                         found = true
444                                         ehdrFlags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
445                                 }
446                         }
447                         if attrList.err != nil {
448                                 return false, 0, fmt.Errorf("could not parse .ARM.attributes\n")
449                         }
450                 }
451         }
452         return found, ehdrFlags, nil
453 }
454
455 func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
456         newSym := func(name string, version int) *sym.Symbol {
457                 return l.Create(name, syms)
458         }
459         lookup := func(name string, version int) *sym.Symbol {
460                 return l.LookupOrCreate(name, version, syms)
461         }
462         return load(arch, syms.IncVersion(), newSym, lookup, f, pkg, length, pn, flags)
463 }
464
465 func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, flags uint32) ([]*sym.Symbol, uint32, error) {
466         return load(arch, syms.IncVersion(), syms.Newsym, syms.Lookup, f, pkg, length, pn, flags)
467 }
468
469 type lookupFunc func(string, int) *sym.Symbol
470
471 // load loads the ELF file pn from f.
472 // Symbols are written into syms, and a slice of the text symbols is returned.
473 //
474 // On ARM systems, Load will attempt to determine what ELF header flags to
475 // emit by scanning the attributes in the ELF file being loaded. The
476 // parameter initEhdrFlags contains the current header flags for the output
477 // object, and the returned ehdrFlags contains what this Load function computes.
478 // TODO: find a better place for this logic.
479 func load(arch *sys.Arch, localSymVersion int, newSym, lookup lookupFunc, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
480         errorf := func(str string, args ...interface{}) ([]*sym.Symbol, uint32, error) {
481                 return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
482         }
483
484         base := f.Offset()
485
486         var hdrbuf [64]uint8
487         if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
488                 return errorf("malformed elf file: %v", err)
489         }
490         hdr := new(ElfHdrBytes)
491         binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
492         if string(hdr.Ident[:4]) != "\x7FELF" {
493                 return errorf("malformed elf file, bad header")
494         }
495         var e binary.ByteOrder
496         switch hdr.Ident[5] {
497         case ElfDataLsb:
498                 e = binary.LittleEndian
499
500         case ElfDataMsb:
501                 e = binary.BigEndian
502
503         default:
504                 return errorf("malformed elf file, unknown header")
505         }
506
507         // read header
508         elfobj := new(ElfObj)
509
510         elfobj.e = e
511         elfobj.f = f
512         elfobj.base = base
513         elfobj.length = length
514         elfobj.name = pn
515
516         is64 := 0
517         if hdr.Ident[4] == ElfClass64 {
518                 is64 = 1
519                 hdr := new(ElfHdrBytes64)
520                 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
521                 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
522                 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
523                 elfobj.version = e.Uint32(hdr.Version[:])
524                 elfobj.phoff = e.Uint64(hdr.Phoff[:])
525                 elfobj.shoff = e.Uint64(hdr.Shoff[:])
526                 elfobj.flags = e.Uint32(hdr.Flags[:])
527                 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
528                 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
529                 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
530                 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
531                 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
532                 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
533         } else {
534                 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
535                 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
536                 elfobj.version = e.Uint32(hdr.Version[:])
537                 elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
538                 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
539                 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
540                 elfobj.flags = e.Uint32(hdr.Flags[:])
541                 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
542                 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
543                 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
544                 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
545                 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
546                 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
547         }
548
549         elfobj.is64 = is64
550
551         if v := uint32(hdr.Ident[6]); v != elfobj.version {
552                 return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
553         }
554
555         if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
556                 return errorf("elf but not elf relocatable object")
557         }
558
559         switch arch.Family {
560         default:
561                 return errorf("elf %s unimplemented", arch.Name)
562
563         case sys.MIPS:
564                 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
565                         return errorf("elf object but not mips")
566                 }
567
568         case sys.MIPS64:
569                 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
570                         return errorf("elf object but not mips64")
571                 }
572
573         case sys.ARM:
574                 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
575                         return errorf("elf object but not arm")
576                 }
577
578         case sys.AMD64:
579                 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
580                         return errorf("elf object but not amd64")
581                 }
582
583         case sys.ARM64:
584                 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
585                         return errorf("elf object but not arm64")
586                 }
587
588         case sys.I386:
589                 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
590                         return errorf("elf object but not 386")
591                 }
592
593         case sys.PPC64:
594                 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
595                         return errorf("elf object but not ppc64")
596                 }
597
598         case sys.S390X:
599                 if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
600                         return errorf("elf object but not s390x")
601                 }
602         }
603
604         // load section list into memory.
605         elfobj.sect = make([]ElfSect, elfobj.shnum)
606
607         elfobj.nsect = uint(elfobj.shnum)
608         for i := 0; uint(i) < elfobj.nsect; i++ {
609                 f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
610                 sect := &elfobj.sect[i]
611                 if is64 != 0 {
612                         var b ElfSectBytes64
613
614                         if err := binary.Read(f, e, &b); err != nil {
615                                 return errorf("malformed elf file: %v", err)
616                         }
617
618                         sect.nameoff = e.Uint32(b.Name[:])
619                         sect.type_ = e.Uint32(b.Type[:])
620                         sect.flags = e.Uint64(b.Flags[:])
621                         sect.addr = e.Uint64(b.Addr[:])
622                         sect.off = e.Uint64(b.Off[:])
623                         sect.size = e.Uint64(b.Size[:])
624                         sect.link = e.Uint32(b.Link[:])
625                         sect.info = e.Uint32(b.Info[:])
626                         sect.align = e.Uint64(b.Align[:])
627                         sect.entsize = e.Uint64(b.Entsize[:])
628                 } else {
629                         var b ElfSectBytes
630
631                         if err := binary.Read(f, e, &b); err != nil {
632                                 return errorf("malformed elf file: %v", err)
633                         }
634
635                         sect.nameoff = e.Uint32(b.Name[:])
636                         sect.type_ = e.Uint32(b.Type[:])
637                         sect.flags = uint64(e.Uint32(b.Flags[:]))
638                         sect.addr = uint64(e.Uint32(b.Addr[:]))
639                         sect.off = uint64(e.Uint32(b.Off[:]))
640                         sect.size = uint64(e.Uint32(b.Size[:]))
641                         sect.link = e.Uint32(b.Link[:])
642                         sect.info = e.Uint32(b.Info[:])
643                         sect.align = uint64(e.Uint32(b.Align[:]))
644                         sect.entsize = uint64(e.Uint32(b.Entsize[:]))
645                 }
646         }
647
648         // read section string table and translate names
649         if elfobj.shstrndx >= uint32(elfobj.nsect) {
650                 return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
651         }
652
653         sect := &elfobj.sect[elfobj.shstrndx]
654         if err := elfmap(elfobj, sect); err != nil {
655                 return errorf("malformed elf file: %v", err)
656         }
657         for i := 0; uint(i) < elfobj.nsect; i++ {
658                 if elfobj.sect[i].nameoff != 0 {
659                         elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
660                 }
661         }
662
663         // load string table for symbols into memory.
664         elfobj.symtab = section(elfobj, ".symtab")
665
666         if elfobj.symtab == nil {
667                 // our work is done here - no symbols means nothing can refer to this file
668                 return
669         }
670
671         if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
672                 return errorf("elf object has symbol table with invalid string table link")
673         }
674
675         elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
676         if is64 != 0 {
677                 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
678         } else {
679                 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
680         }
681
682         if err := elfmap(elfobj, elfobj.symtab); err != nil {
683                 return errorf("malformed elf file: %v", err)
684         }
685         if err := elfmap(elfobj, elfobj.symstr); err != nil {
686                 return errorf("malformed elf file: %v", err)
687         }
688
689         // load text and data segments into memory.
690         // they are not as small as the section lists, but we'll need
691         // the memory anyway for the symbol images, so we might
692         // as well use one large chunk.
693
694         // create symbols for elfmapped sections
695         sectsymNames := make(map[string]bool)
696         counter := 0
697         for i := 0; uint(i) < elfobj.nsect; i++ {
698                 sect = &elfobj.sect[i]
699                 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
700                         if err := elfmap(elfobj, sect); err != nil {
701                                 return errorf("%s: malformed elf file: %v", pn, err)
702                         }
703                         // We assume the soft-float ABI unless we see a tag indicating otherwise.
704                         if initEhdrFlags == 0x5000002 {
705                                 ehdrFlags = 0x5000202
706                         } else {
707                                 ehdrFlags = initEhdrFlags
708                         }
709                         found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
710                         if err != nil {
711                                 // TODO(dfc) should this return an error?
712                                 log.Printf("%s: %v", pn, err)
713                         }
714                         if found {
715                                 ehdrFlags = newEhdrFlags
716                         }
717                 }
718                 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
719                         continue
720                 }
721                 if sect.type_ != ElfSectNobits {
722                         if err := elfmap(elfobj, sect); err != nil {
723                                 return errorf("%s: malformed elf file: %v", pn, err)
724                         }
725                 }
726
727                 name := fmt.Sprintf("%s(%s)", pkg, sect.name)
728                 for sectsymNames[name] {
729                         counter++
730                         name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
731                 }
732                 sectsymNames[name] = true
733
734                 s := lookup(name, localSymVersion)
735
736                 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
737                 default:
738                         return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
739
740                 case ElfSectFlagAlloc:
741                         s.Type = sym.SRODATA
742
743                 case ElfSectFlagAlloc + ElfSectFlagWrite:
744                         if sect.type_ == ElfSectNobits {
745                                 s.Type = sym.SNOPTRBSS
746                         } else {
747                                 s.Type = sym.SNOPTRDATA
748                         }
749
750                 case ElfSectFlagAlloc + ElfSectFlagExec:
751                         s.Type = sym.STEXT
752                 }
753
754                 if sect.name == ".got" || sect.name == ".toc" {
755                         s.Type = sym.SELFGOT
756                 }
757                 if sect.type_ == ElfSectProgbits {
758                         s.P = sect.base
759                         s.P = s.P[:sect.size]
760                 }
761
762                 s.Size = int64(sect.size)
763                 s.Align = int32(sect.align)
764                 sect.sym = s
765         }
766
767         // enter sub-symbols into symbol table.
768         // symbol 0 is the null symbol.
769         symbols := make([]*sym.Symbol, elfobj.nsymtab)
770
771         for i := 1; i < elfobj.nsymtab; i++ {
772                 var elfsym ElfSym
773                 if err := readelfsym(newSym, lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
774                         return errorf("%s: malformed elf file: %v", pn, err)
775                 }
776                 symbols[i] = elfsym.sym
777                 if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
778                         continue
779                 }
780                 if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
781                         s := elfsym.sym
782                         if uint64(s.Size) < elfsym.size {
783                                 s.Size = int64(elfsym.size)
784                         }
785                         if s.Type == 0 || s.Type == sym.SXREF {
786                                 s.Type = sym.SNOPTRBSS
787                         }
788                         continue
789                 }
790
791                 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
792                         continue
793                 }
794
795                 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
796                 if elfsym.sym == nil {
797                         continue
798                 }
799                 sect = &elfobj.sect[elfsym.shndx]
800                 if sect.sym == nil {
801                         if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
802                                 continue
803                         }
804
805                         if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
806                                 // This reportedly happens with clang 3.7 on ARM.
807                                 // See issue 13139.
808                                 continue
809                         }
810
811                         if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
812                                 // "$d" is a marker, not a real symbol.
813                                 // This happens with gcc on ARM64.
814                                 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
815                                 continue
816                         }
817
818                         if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
819                                 continue
820                         }
821                         return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
822                 }
823
824                 s := elfsym.sym
825                 if s.Outer != nil {
826                         if s.Attr.DuplicateOK() {
827                                 continue
828                         }
829                         return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name)
830                 }
831
832                 s.Sub = sect.sym.Sub
833                 sect.sym.Sub = s
834                 s.Type = sect.sym.Type
835                 s.Attr |= sym.AttrSubSymbol
836                 if !s.Attr.CgoExportDynamic() {
837                         s.SetDynimplib("") // satisfy dynimport
838                 }
839                 s.Value = int64(elfsym.value)
840                 s.Size = int64(elfsym.size)
841                 s.Outer = sect.sym
842                 if sect.sym.Type == sym.STEXT {
843                         if s.Attr.External() && !s.Attr.DuplicateOK() {
844                                 return errorf("%v: duplicate symbol definition", s)
845                         }
846                         s.Attr |= sym.AttrExternal
847                 }
848
849                 if elfobj.machine == ElfMachPower64 {
850                         flag := int(elfsym.other) >> 5
851                         if 2 <= flag && flag <= 6 {
852                                 s.SetLocalentry(1 << uint(flag-2))
853                         } else if flag == 7 {
854                                 return errorf("%v: invalid sym.other 0x%x", s, elfsym.other)
855                         }
856                 }
857         }
858
859         // Sort outer lists by address, adding to textp.
860         // This keeps textp in increasing address order.
861         for i := uint(0); i < elfobj.nsect; i++ {
862                 s := elfobj.sect[i].sym
863                 if s == nil {
864                         continue
865                 }
866                 if s.Sub != nil {
867                         s.Sub = sym.SortSub(s.Sub)
868                 }
869                 if s.Type == sym.STEXT {
870                         if s.Attr.OnList() {
871                                 return errorf("symbol %s listed multiple times", s.Name)
872                         }
873                         s.Attr |= sym.AttrOnList
874                         textp = append(textp, s)
875                         for s = s.Sub; s != nil; s = s.Sub {
876                                 if s.Attr.OnList() {
877                                         return errorf("symbol %s listed multiple times", s.Name)
878                                 }
879                                 s.Attr |= sym.AttrOnList
880                                 textp = append(textp, s)
881                         }
882                 }
883         }
884
885         // load relocations
886         for i := uint(0); i < elfobj.nsect; i++ {
887                 rsect := &elfobj.sect[i]
888                 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
889                         continue
890                 }
891                 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
892                         continue
893                 }
894                 sect = &elfobj.sect[rsect.info]
895                 if err := elfmap(elfobj, rsect); err != nil {
896                         return errorf("malformed elf file: %v", err)
897                 }
898                 rela := 0
899                 if rsect.type_ == ElfSectRela {
900                         rela = 1
901                 }
902                 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
903                 r := make([]sym.Reloc, n)
904                 p := rsect.base
905                 for j := 0; j < n; j++ {
906                         var add uint64
907                         rp := &r[j]
908                         var info uint64
909                         if is64 != 0 {
910                                 // 64-bit rel/rela
911                                 rp.Off = int32(e.Uint64(p))
912
913                                 p = p[8:]
914                                 info = e.Uint64(p)
915                                 p = p[8:]
916                                 if rela != 0 {
917                                         add = e.Uint64(p)
918                                         p = p[8:]
919                                 }
920                         } else {
921                                 // 32-bit rel/rela
922                                 rp.Off = int32(e.Uint32(p))
923
924                                 p = p[4:]
925                                 info = uint64(e.Uint32(p))
926                                 info = info>>8<<32 | info&0xff // convert to 64-bit info
927                                 p = p[4:]
928                                 if rela != 0 {
929                                         add = uint64(e.Uint32(p))
930                                         p = p[4:]
931                                 }
932                         }
933
934                         if info&0xffffffff == 0 { // skip R_*_NONE relocation
935                                 j--
936                                 n--
937                                 continue
938                         }
939
940                         if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
941                                 rp.Sym = nil
942                         } else {
943                                 var elfsym ElfSym
944                                 if err := readelfsym(newSym, lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
945                                         return errorf("malformed elf file: %v", err)
946                                 }
947                                 elfsym.sym = symbols[info>>32]
948                                 if elfsym.sym == nil {
949                                         return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", sect.sym.Name, j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
950                                 }
951
952                                 rp.Sym = elfsym.sym
953                         }
954
955                         rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
956                         rp.Siz, err = relSize(arch, pn, uint32(info))
957                         if err != nil {
958                                 return nil, 0, err
959                         }
960                         if rela != 0 {
961                                 rp.Add = int64(add)
962                         } else {
963                                 // load addend from image
964                                 if rp.Siz == 4 {
965                                         rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
966                                 } else if rp.Siz == 8 {
967                                         rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
968                                 } else {
969                                         return errorf("invalid rela size %d", rp.Siz)
970                                 }
971                         }
972
973                         if rp.Siz == 2 {
974                                 rp.Add = int64(int16(rp.Add))
975                         }
976                         if rp.Siz == 4 {
977                                 rp.Add = int64(int32(rp.Add))
978                         }
979                 }
980
981                 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
982                 sort.Sort(sym.RelocByOff(r[:n]))
983                 // just in case
984
985                 s := sect.sym
986                 s.R = r
987                 s.R = s.R[:n]
988         }
989
990         return textp, ehdrFlags, nil
991 }
992
993 func section(elfobj *ElfObj, name string) *ElfSect {
994         for i := 0; uint(i) < elfobj.nsect; i++ {
995                 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
996                         return &elfobj.sect[i]
997                 }
998         }
999         return nil
1000 }
1001
1002 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
1003         if sect.base != nil {
1004                 return nil
1005         }
1006
1007         if sect.off+sect.size > uint64(elfobj.length) {
1008                 err = fmt.Errorf("elf section past end of file")
1009                 return err
1010         }
1011
1012         sect.base = make([]byte, sect.size)
1013         elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
1014         if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
1015                 return fmt.Errorf("short read: %v", err)
1016         }
1017
1018         return nil
1019 }
1020
1021 func readelfsym(newSym, lookup lookupFunc, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
1022         if i >= elfobj.nsymtab || i < 0 {
1023                 err = fmt.Errorf("invalid elf symbol index")
1024                 return err
1025         }
1026
1027         if i == 0 {
1028                 return fmt.Errorf("readym: read null symbol!")
1029         }
1030
1031         if elfobj.is64 != 0 {
1032                 b := new(ElfSymBytes64)
1033                 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
1034                 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1035                 elfsym.value = elfobj.e.Uint64(b.Value[:])
1036                 elfsym.size = elfobj.e.Uint64(b.Size[:])
1037                 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1038                 elfsym.bind = b.Info >> 4
1039                 elfsym.type_ = b.Info & 0xf
1040                 elfsym.other = b.Other
1041         } else {
1042                 b := new(ElfSymBytes)
1043                 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
1044                 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1045                 elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
1046                 elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
1047                 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1048                 elfsym.bind = b.Info >> 4
1049                 elfsym.type_ = b.Info & 0xf
1050                 elfsym.other = b.Other
1051         }
1052
1053         var s *sym.Symbol
1054         if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
1055                 elfsym.name = ".got"
1056         }
1057         if elfsym.name == ".TOC." {
1058                 // Magic symbol on ppc64.  Will be set to this object
1059                 // file's .got+0x8000.
1060                 elfsym.bind = ElfSymBindLocal
1061         }
1062
1063         switch elfsym.type_ {
1064         case ElfSymTypeSection:
1065                 s = elfobj.sect[elfsym.shndx].sym
1066
1067         case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
1068                 switch elfsym.bind {
1069                 case ElfSymBindGlobal:
1070                         if needSym != 0 {
1071                                 s = lookup(elfsym.name, 0)
1072
1073                                 // for global scoped hidden symbols we should insert it into
1074                                 // symbol hash table, but mark them as hidden.
1075                                 // __i686.get_pc_thunk.bx is allowed to be duplicated, to
1076                                 // workaround that we set dupok.
1077                                 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without
1078                                 // set dupok generally. See https://golang.org/cl/5823055
1079                                 // comment #5 for details.
1080                                 if s != nil && elfsym.other == 2 {
1081                                         s.Attr |= sym.AttrDuplicateOK | sym.AttrVisibilityHidden
1082                                 }
1083                         }
1084
1085                 case ElfSymBindLocal:
1086                         if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
1087                                 // binutils for arm and arm64 generate these mapping
1088                                 // symbols, ignore these
1089                                 break
1090                         }
1091
1092                         if elfsym.name == ".TOC." {
1093                                 // We need to be able to look this up,
1094                                 // so put it in the hash table.
1095                                 if needSym != 0 {
1096                                         s = lookup(elfsym.name, localSymVersion)
1097                                         s.Attr |= sym.AttrVisibilityHidden
1098                                 }
1099
1100                                 break
1101                         }
1102
1103                         if needSym != 0 {
1104                                 // local names and hidden global names are unique
1105                                 // and should only be referenced by their index, not name, so we
1106                                 // don't bother to add them into the hash table
1107                                 // FIXME: pass empty string here for name? This would
1108                                 // reduce mem use, but also (possibly) make it harder
1109                                 // to debug problems.
1110                                 s = newSym(elfsym.name, localSymVersion)
1111
1112                                 s.Attr |= sym.AttrVisibilityHidden
1113                         }
1114
1115                 case ElfSymBindWeak:
1116                         if needSym != 0 {
1117                                 s = lookup(elfsym.name, 0)
1118                                 if elfsym.other == 2 {
1119                                         s.Attr |= sym.AttrVisibilityHidden
1120                                 }
1121
1122                                 // Allow weak symbols to be duplicated when already defined.
1123                                 if s.Outer != nil {
1124                                         s.Attr |= sym.AttrDuplicateOK
1125                                 }
1126                         }
1127
1128                 default:
1129                         err = fmt.Errorf("%s: invalid symbol binding %d", elfsym.name, elfsym.bind)
1130                         return err
1131                 }
1132         }
1133
1134         // TODO(mwhudson): the test of VisibilityHidden here probably doesn't make
1135         // sense and should be removed when someone has thought about it properly.
1136         if s != nil && s.Type == 0 && !s.Attr.VisibilityHidden() && elfsym.type_ != ElfSymTypeSection {
1137                 s.Type = sym.SXREF
1138         }
1139         elfsym.sym = s
1140
1141         return nil
1142 }
1143
1144 func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
1145         // TODO(mdempsky): Replace this with a struct-valued switch statement
1146         // once golang.org/issue/15164 is fixed or found to not impair cmd/link
1147         // performance.
1148
1149         const (
1150                 AMD64 = uint32(sys.AMD64)
1151                 ARM   = uint32(sys.ARM)
1152                 ARM64 = uint32(sys.ARM64)
1153                 I386  = uint32(sys.I386)
1154                 PPC64 = uint32(sys.PPC64)
1155                 S390X = uint32(sys.S390X)
1156         )
1157
1158         switch uint32(arch.Family) | elftype<<16 {
1159         default:
1160                 return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
1161
1162         case S390X | uint32(elf.R_390_8)<<16:
1163                 return 1, nil
1164
1165         case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
1166                 PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
1167                 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
1168                 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
1169                 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
1170                 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
1171                 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
1172                 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
1173                 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
1174                 S390X | uint32(elf.R_390_16)<<16,
1175                 S390X | uint32(elf.R_390_GOT16)<<16,
1176                 S390X | uint32(elf.R_390_PC16)<<16,
1177                 S390X | uint32(elf.R_390_PC16DBL)<<16,
1178                 S390X | uint32(elf.R_390_PLT16DBL)<<16:
1179                 return 2, nil
1180
1181         case ARM | uint32(elf.R_ARM_ABS32)<<16,
1182                 ARM | uint32(elf.R_ARM_GOT32)<<16,
1183                 ARM | uint32(elf.R_ARM_PLT32)<<16,
1184                 ARM | uint32(elf.R_ARM_GOTOFF)<<16,
1185                 ARM | uint32(elf.R_ARM_GOTPC)<<16,
1186                 ARM | uint32(elf.R_ARM_THM_PC22)<<16,
1187                 ARM | uint32(elf.R_ARM_REL32)<<16,
1188                 ARM | uint32(elf.R_ARM_CALL)<<16,
1189                 ARM | uint32(elf.R_ARM_V4BX)<<16,
1190                 ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
1191                 ARM | uint32(elf.R_ARM_PC24)<<16,
1192                 ARM | uint32(elf.R_ARM_JUMP24)<<16,
1193                 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
1194                 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
1195                 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
1196                 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
1197                 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
1198                 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
1199                 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
1200                 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
1201                 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
1202                 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
1203                 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
1204                 AMD64 | uint32(elf.R_X86_64_PC32)<<16,
1205                 AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
1206                 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
1207                 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
1208                 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
1209                 I386 | uint32(elf.R_386_32)<<16,
1210                 I386 | uint32(elf.R_386_PC32)<<16,
1211                 I386 | uint32(elf.R_386_GOT32)<<16,
1212                 I386 | uint32(elf.R_386_PLT32)<<16,
1213                 I386 | uint32(elf.R_386_GOTOFF)<<16,
1214                 I386 | uint32(elf.R_386_GOTPC)<<16,
1215                 I386 | uint32(elf.R_386_GOT32X)<<16,
1216                 PPC64 | uint32(elf.R_PPC64_REL24)<<16,
1217                 PPC64 | uint32(elf.R_PPC_REL32)<<16,
1218                 S390X | uint32(elf.R_390_32)<<16,
1219                 S390X | uint32(elf.R_390_PC32)<<16,
1220                 S390X | uint32(elf.R_390_GOT32)<<16,
1221                 S390X | uint32(elf.R_390_PLT32)<<16,
1222                 S390X | uint32(elf.R_390_PC32DBL)<<16,
1223                 S390X | uint32(elf.R_390_PLT32DBL)<<16,
1224                 S390X | uint32(elf.R_390_GOTPCDBL)<<16,
1225                 S390X | uint32(elf.R_390_GOTENT)<<16:
1226                 return 4, nil
1227
1228         case AMD64 | uint32(elf.R_X86_64_64)<<16,
1229                 AMD64 | uint32(elf.R_X86_64_PC64)<<16,
1230                 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
1231                 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
1232                 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
1233                 S390X | uint32(elf.R_390_GLOB_DAT)<<16,
1234                 S390X | uint32(elf.R_390_RELATIVE)<<16,
1235                 S390X | uint32(elf.R_390_GOTOFF)<<16,
1236                 S390X | uint32(elf.R_390_GOTPC)<<16,
1237                 S390X | uint32(elf.R_390_64)<<16,
1238                 S390X | uint32(elf.R_390_PC64)<<16,
1239                 S390X | uint32(elf.R_390_GOT64)<<16,
1240                 S390X | uint32(elf.R_390_PLT64)<<16:
1241                 return 8, nil
1242         }
1243 }
1244
1245 func cstring(x []byte) string {
1246         i := bytes.IndexByte(x, '\x00')
1247         if i >= 0 {
1248                 x = x[:i]
1249         }
1250         return string(x)
1251 }