]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/loadelf/ldelf.go
[dev.link] cmd/internal/obj: emit only '/' in DWARF file names
[gostls13.git] / src / cmd / link / internal / loadelf / ldelf.go
1 // Copyright 2019 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     loader.Sym
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   loader.Sym
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 // Load loads the ELF file pn from f.
456 // Symbols are installed into the loader, and a slice of the text symbols is returned.
457 //
458 // On ARM systems, Load will attempt to determine what ELF header flags to
459 // emit by scanning the attributes in the ELF file being loaded. The
460 // parameter initEhdrFlags contains the current header flags for the output
461 // object, and the returned ehdrFlags contains what this Load function computes.
462 // TODO: find a better place for this logic.
463 func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []loader.Sym, ehdrFlags uint32, err error) {
464         newSym := func(name string, version int) loader.Sym {
465                 return l.CreateExtSym(name)
466         }
467         lookup := func(name string, version int) loader.Sym {
468                 return l.LookupOrCreateSym(name, version)
469         }
470         errorf := func(str string, args ...interface{}) ([]loader.Sym, uint32, error) {
471                 return nil, 0, fmt.Errorf("loadelf: %s: %v", pn, fmt.Sprintf(str, args...))
472         }
473
474         base := f.Offset()
475
476         var hdrbuf [64]uint8
477         if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
478                 return errorf("malformed elf file: %v", err)
479         }
480         hdr := new(ElfHdrBytes)
481         binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
482         if string(hdr.Ident[:4]) != "\x7FELF" {
483                 return errorf("malformed elf file, bad header")
484         }
485         var e binary.ByteOrder
486         switch hdr.Ident[5] {
487         case ElfDataLsb:
488                 e = binary.LittleEndian
489
490         case ElfDataMsb:
491                 e = binary.BigEndian
492
493         default:
494                 return errorf("malformed elf file, unknown header")
495         }
496
497         // read header
498         elfobj := new(ElfObj)
499
500         elfobj.e = e
501         elfobj.f = f
502         elfobj.base = base
503         elfobj.length = length
504         elfobj.name = pn
505
506         is64 := 0
507         if hdr.Ident[4] == ElfClass64 {
508                 is64 = 1
509                 hdr := new(ElfHdrBytes64)
510                 binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
511                 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
512                 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
513                 elfobj.version = e.Uint32(hdr.Version[:])
514                 elfobj.phoff = e.Uint64(hdr.Phoff[:])
515                 elfobj.shoff = e.Uint64(hdr.Shoff[:])
516                 elfobj.flags = e.Uint32(hdr.Flags[:])
517                 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
518                 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
519                 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
520                 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
521                 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
522                 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
523         } else {
524                 elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
525                 elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
526                 elfobj.version = e.Uint32(hdr.Version[:])
527                 elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
528                 elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
529                 elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
530                 elfobj.flags = e.Uint32(hdr.Flags[:])
531                 elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
532                 elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
533                 elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
534                 elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
535                 elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
536                 elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
537         }
538
539         elfobj.is64 = is64
540
541         if v := uint32(hdr.Ident[6]); v != elfobj.version {
542                 return errorf("malformed elf version: got %d, want %d", v, elfobj.version)
543         }
544
545         if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
546                 return errorf("elf but not elf relocatable object")
547         }
548
549         switch arch.Family {
550         default:
551                 return errorf("elf %s unimplemented", arch.Name)
552
553         case sys.MIPS:
554                 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
555                         return errorf("elf object but not mips")
556                 }
557
558         case sys.MIPS64:
559                 if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
560                         return errorf("elf object but not mips64")
561                 }
562
563         case sys.ARM:
564                 if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
565                         return errorf("elf object but not arm")
566                 }
567
568         case sys.AMD64:
569                 if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
570                         return errorf("elf object but not amd64")
571                 }
572
573         case sys.ARM64:
574                 if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
575                         return errorf("elf object but not arm64")
576                 }
577
578         case sys.I386:
579                 if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
580                         return errorf("elf object but not 386")
581                 }
582
583         case sys.PPC64:
584                 if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
585                         return errorf("elf object but not ppc64")
586                 }
587
588         case sys.S390X:
589                 if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
590                         return errorf("elf object but not s390x")
591                 }
592         }
593
594         // load section list into memory.
595         elfobj.sect = make([]ElfSect, elfobj.shnum)
596
597         elfobj.nsect = uint(elfobj.shnum)
598         for i := 0; uint(i) < elfobj.nsect; i++ {
599                 f.MustSeek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0)
600                 sect := &elfobj.sect[i]
601                 if is64 != 0 {
602                         var b ElfSectBytes64
603
604                         if err := binary.Read(f, e, &b); err != nil {
605                                 return errorf("malformed elf file: %v", err)
606                         }
607
608                         sect.nameoff = e.Uint32(b.Name[:])
609                         sect.type_ = e.Uint32(b.Type[:])
610                         sect.flags = e.Uint64(b.Flags[:])
611                         sect.addr = e.Uint64(b.Addr[:])
612                         sect.off = e.Uint64(b.Off[:])
613                         sect.size = e.Uint64(b.Size[:])
614                         sect.link = e.Uint32(b.Link[:])
615                         sect.info = e.Uint32(b.Info[:])
616                         sect.align = e.Uint64(b.Align[:])
617                         sect.entsize = e.Uint64(b.Entsize[:])
618                 } else {
619                         var b ElfSectBytes
620
621                         if err := binary.Read(f, e, &b); err != nil {
622                                 return errorf("malformed elf file: %v", err)
623                         }
624
625                         sect.nameoff = e.Uint32(b.Name[:])
626                         sect.type_ = e.Uint32(b.Type[:])
627                         sect.flags = uint64(e.Uint32(b.Flags[:]))
628                         sect.addr = uint64(e.Uint32(b.Addr[:]))
629                         sect.off = uint64(e.Uint32(b.Off[:]))
630                         sect.size = uint64(e.Uint32(b.Size[:]))
631                         sect.link = e.Uint32(b.Link[:])
632                         sect.info = e.Uint32(b.Info[:])
633                         sect.align = uint64(e.Uint32(b.Align[:]))
634                         sect.entsize = uint64(e.Uint32(b.Entsize[:]))
635                 }
636         }
637
638         // read section string table and translate names
639         if elfobj.shstrndx >= uint32(elfobj.nsect) {
640                 return errorf("malformed elf file: shstrndx out of range %d >= %d", elfobj.shstrndx, elfobj.nsect)
641         }
642
643         sect := &elfobj.sect[elfobj.shstrndx]
644         if err := elfmap(elfobj, sect); err != nil {
645                 return errorf("malformed elf file: %v", err)
646         }
647         for i := 0; uint(i) < elfobj.nsect; i++ {
648                 if elfobj.sect[i].nameoff != 0 {
649                         elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
650                 }
651         }
652
653         // load string table for symbols into memory.
654         elfobj.symtab = section(elfobj, ".symtab")
655
656         if elfobj.symtab == nil {
657                 // our work is done here - no symbols means nothing can refer to this file
658                 return
659         }
660
661         if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
662                 return errorf("elf object has symbol table with invalid string table link")
663         }
664
665         elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
666         if is64 != 0 {
667                 elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
668         } else {
669                 elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
670         }
671
672         if err := elfmap(elfobj, elfobj.symtab); err != nil {
673                 return errorf("malformed elf file: %v", err)
674         }
675         if err := elfmap(elfobj, elfobj.symstr); err != nil {
676                 return errorf("malformed elf file: %v", err)
677         }
678
679         // load text and data segments into memory.
680         // they are not as small as the section lists, but we'll need
681         // the memory anyway for the symbol images, so we might
682         // as well use one large chunk.
683
684         // create symbols for elfmapped sections
685         sectsymNames := make(map[string]bool)
686         counter := 0
687         for i := 0; uint(i) < elfobj.nsect; i++ {
688                 sect = &elfobj.sect[i]
689                 if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
690                         if err := elfmap(elfobj, sect); err != nil {
691                                 return errorf("%s: malformed elf file: %v", pn, err)
692                         }
693                         // We assume the soft-float ABI unless we see a tag indicating otherwise.
694                         if initEhdrFlags == 0x5000002 {
695                                 ehdrFlags = 0x5000202
696                         } else {
697                                 ehdrFlags = initEhdrFlags
698                         }
699                         found, newEhdrFlags, err := parseArmAttributes(e, sect.base[:sect.size])
700                         if err != nil {
701                                 // TODO(dfc) should this return an error?
702                                 log.Printf("%s: %v", pn, err)
703                         }
704                         if found {
705                                 ehdrFlags = newEhdrFlags
706                         }
707                 }
708                 if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
709                         continue
710                 }
711                 if sect.type_ != ElfSectNobits {
712                         if err := elfmap(elfobj, sect); err != nil {
713                                 return errorf("%s: malformed elf file: %v", pn, err)
714                         }
715                 }
716
717                 name := fmt.Sprintf("%s(%s)", pkg, sect.name)
718                 for sectsymNames[name] {
719                         counter++
720                         name = fmt.Sprintf("%s(%s%d)", pkg, sect.name, counter)
721                 }
722                 sectsymNames[name] = true
723
724                 sb, _ := l.MakeSymbolUpdater(lookup(name, localSymVersion))
725
726                 switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
727                 default:
728                         return errorf("%s: unexpected flags for ELF section %s", pn, sect.name)
729
730                 case ElfSectFlagAlloc:
731                         sb.SetType(sym.SRODATA)
732
733                 case ElfSectFlagAlloc + ElfSectFlagWrite:
734                         if sect.type_ == ElfSectNobits {
735                                 sb.SetType(sym.SNOPTRBSS)
736                         } else {
737                                 sb.SetType(sym.SNOPTRDATA)
738                         }
739
740                 case ElfSectFlagAlloc + ElfSectFlagExec:
741                         sb.SetType(sym.STEXT)
742                 }
743
744                 if sect.name == ".got" || sect.name == ".toc" {
745                         sb.SetType(sym.SELFGOT)
746                 }
747                 if sect.type_ == ElfSectProgbits {
748                         sb.SetData(sect.base[:sect.size])
749                 }
750
751                 sb.SetSize(int64(sect.size))
752                 sb.SetAlign(int32(sect.align))
753
754                 sect.sym = sb.Sym()
755         }
756
757         // enter sub-symbols into symbol table.
758         // symbol 0 is the null symbol.
759         symbols := make([]loader.Sym, elfobj.nsymtab)
760
761         for i := 1; i < elfobj.nsymtab; i++ {
762                 var elfsym ElfSym
763                 if err := readelfsym(newSym, lookup, l, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
764                         return errorf("%s: malformed elf file: %v", pn, err)
765                 }
766                 symbols[i] = elfsym.sym
767                 if elfsym.type_ != ElfSymTypeFunc && elfsym.type_ != ElfSymTypeObject && elfsym.type_ != ElfSymTypeNone && elfsym.type_ != ElfSymTypeCommon {
768                         continue
769                 }
770                 if elfsym.shndx == ElfSymShnCommon || elfsym.type_ == ElfSymTypeCommon {
771                         sb, ns := l.MakeSymbolUpdater(elfsym.sym)
772                         if uint64(sb.Size()) < elfsym.size {
773                                 sb.SetSize(int64(elfsym.size))
774                         }
775                         if sb.Type() == 0 || sb.Type() == sym.SXREF {
776                                 sb.SetType(sym.SNOPTRBSS)
777                         }
778                         symbols[i] = ns
779                         elfsym.sym = ns
780                         continue
781                 }
782
783                 if uint(elfsym.shndx) >= elfobj.nsect || elfsym.shndx == 0 {
784                         continue
785                 }
786
787                 // even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
788                 if elfsym.sym == 0 {
789                         continue
790                 }
791                 sect = &elfobj.sect[elfsym.shndx]
792                 if sect.sym == 0 {
793                         if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
794                                 continue
795                         }
796
797                         if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
798                                 // This reportedly happens with clang 3.7 on ARM.
799                                 // See issue 13139.
800                                 continue
801                         }
802
803                         if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
804                                 // "$d" is a marker, not a real symbol.
805                                 // This happens with gcc on ARM64.
806                                 // See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
807                                 continue
808                         }
809
810                         if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
811                                 continue
812                         }
813                         return errorf("%v: sym#%d: ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.shndx, elfsym.type_)
814                 }
815
816                 s := elfsym.sym
817                 if l.OuterSym(s) != 0 {
818                         if l.AttrDuplicateOK(s) {
819                                 continue
820                         }
821                         return errorf("duplicate symbol reference: %s in both %s and %s",
822                                 l.SymName(s), l.SymName(l.OuterSym(s)), l.SymName(sect.sym))
823                 }
824
825                 sectsb, _ := l.MakeSymbolUpdater(sect.sym)
826                 sb, _ := l.MakeSymbolUpdater(s)
827
828                 sb.SetType(sectsb.Type())
829                 sectsb.PrependSub(s)
830                 if !l.AttrCgoExportDynamic(s) {
831                         sb.SetDynimplib("") // satisfy dynimport
832                 }
833                 sb.SetValue(int64(elfsym.value))
834                 sb.SetSize(int64(elfsym.size))
835                 if sectsb.Type() == sym.STEXT {
836                         if l.AttrExternal(s) && !l.AttrDuplicateOK(s) {
837                                 return errorf("%s: duplicate symbol definition", sb.Name())
838                         }
839                         l.SetAttrExternal(s, true)
840                 }
841
842                 if elfobj.machine == ElfMachPower64 {
843                         flag := int(elfsym.other) >> 5
844                         if 2 <= flag && flag <= 6 {
845                                 l.SetSymLocalentry(s, 1<<uint(flag-2))
846                         } else if flag == 7 {
847                                 return errorf("%s: invalid sym.other 0x%x", sb.Name(), elfsym.other)
848                         }
849                 }
850         }
851
852         // Sort outer lists by address, adding to textp.
853         // This keeps textp in increasing address order.
854         for i := uint(0); i < elfobj.nsect; i++ {
855                 s := elfobj.sect[i].sym
856                 if s == 0 {
857                         continue
858                 }
859                 sb, _ := l.MakeSymbolUpdater(s)
860                 s = sb.Sym()
861                 if l.SubSym(s) != 0 {
862                         sb.SortSub()
863                 }
864                 if sb.Type() == sym.STEXT {
865                         if l.AttrOnList(s) {
866                                 return errorf("symbol %s listed multiple times",
867                                         l.SymName(s))
868                         }
869                         l.SetAttrOnList(s, true)
870                         textp = append(textp, s)
871                         for ss := l.SubSym(s); ss != 0; ss = l.SubSym(ss) {
872                                 if l.AttrOnList(ss) {
873                                         return errorf("symbol %s listed multiple times",
874                                                 l.SymName(ss))
875                                 }
876                                 l.SetAttrOnList(ss, true)
877                                 textp = append(textp, ss)
878                         }
879                 }
880         }
881
882         // load relocations
883         for i := uint(0); i < elfobj.nsect; i++ {
884                 rsect := &elfobj.sect[i]
885                 if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
886                         continue
887                 }
888                 if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
889                         continue
890                 }
891                 sect = &elfobj.sect[rsect.info]
892                 if err := elfmap(elfobj, rsect); err != nil {
893                         return errorf("malformed elf file: %v", err)
894                 }
895                 rela := 0
896                 if rsect.type_ == ElfSectRela {
897                         rela = 1
898                 }
899                 n := int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
900                 r := make([]loader.Reloc, n)
901                 p := rsect.base
902                 for j := 0; j < n; j++ {
903                         var add uint64
904                         rp := &r[j]
905                         var info uint64
906                         if is64 != 0 {
907                                 // 64-bit rel/rela
908                                 rp.Off = int32(e.Uint64(p))
909
910                                 p = p[8:]
911                                 info = e.Uint64(p)
912                                 p = p[8:]
913                                 if rela != 0 {
914                                         add = e.Uint64(p)
915                                         p = p[8:]
916                                 }
917                         } else {
918                                 // 32-bit rel/rela
919                                 rp.Off = int32(e.Uint32(p))
920
921                                 p = p[4:]
922                                 info = uint64(e.Uint32(p))
923                                 info = info>>8<<32 | info&0xff // convert to 64-bit info
924                                 p = p[4:]
925                                 if rela != 0 {
926                                         add = uint64(e.Uint32(p))
927                                         p = p[4:]
928                                 }
929                         }
930
931                         if info&0xffffffff == 0 { // skip R_*_NONE relocation
932                                 j--
933                                 n--
934                                 continue
935                         }
936
937                         if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
938                                 rp.Sym = 0
939                         } else {
940                                 var elfsym ElfSym
941                                 if err := readelfsym(newSym, lookup, l, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
942                                         return errorf("malformed elf file: %v", err)
943                                 }
944                                 elfsym.sym = symbols[info>>32]
945                                 if elfsym.sym == 0 {
946                                         return errorf("malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", l.SymName(sect.sym), j, int(info>>32), elfsym.name, elfsym.shndx, elfsym.type_)
947                                 }
948
949                                 rp.Sym = elfsym.sym
950                         }
951
952                         rp.Type = objabi.ElfRelocOffset + objabi.RelocType(info)
953                         rp.Size, err = relSize(arch, pn, uint32(info))
954                         if err != nil {
955                                 return nil, 0, err
956                         }
957                         if rela != 0 {
958                                 rp.Add = int64(add)
959                         } else {
960                                 // load addend from image
961                                 if rp.Size == 4 {
962                                         rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
963                                 } else if rp.Size == 8 {
964                                         rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
965                                 } else {
966                                         return errorf("invalid rela size %d", rp.Size)
967                                 }
968                         }
969
970                         if rp.Size == 2 {
971                                 rp.Add = int64(int16(rp.Add))
972                         }
973                         if rp.Size == 4 {
974                                 rp.Add = int64(int32(rp.Add))
975                         }
976                 }
977
978                 //print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
979                 sort.Sort(loader.RelocByOff(r[:n]))
980                 // just in case
981
982                 sb, _ := l.MakeSymbolUpdater(sect.sym)
983                 r = r[:n]
984                 sb.SetRelocs(r)
985         }
986
987         return textp, ehdrFlags, nil
988 }
989
990 func section(elfobj *ElfObj, name string) *ElfSect {
991         for i := 0; uint(i) < elfobj.nsect; i++ {
992                 if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
993                         return &elfobj.sect[i]
994                 }
995         }
996         return nil
997 }
998
999 func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
1000         if sect.base != nil {
1001                 return nil
1002         }
1003
1004         if sect.off+sect.size > uint64(elfobj.length) {
1005                 err = fmt.Errorf("elf section past end of file")
1006                 return err
1007         }
1008
1009         sect.base = make([]byte, sect.size)
1010         elfobj.f.MustSeek(int64(uint64(elfobj.base)+sect.off), 0)
1011         if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
1012                 return fmt.Errorf("short read: %v", err)
1013         }
1014
1015         return nil
1016 }
1017
1018 func readelfsym(newSym, lookup func(string, int) loader.Sym, l *loader.Loader, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
1019         if i >= elfobj.nsymtab || i < 0 {
1020                 err = fmt.Errorf("invalid elf symbol index")
1021                 return err
1022         }
1023
1024         if i == 0 {
1025                 return fmt.Errorf("readym: read null symbol!")
1026         }
1027
1028         if elfobj.is64 != 0 {
1029                 b := new(ElfSymBytes64)
1030                 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
1031                 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1032                 elfsym.value = elfobj.e.Uint64(b.Value[:])
1033                 elfsym.size = elfobj.e.Uint64(b.Size[:])
1034                 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1035                 elfsym.bind = b.Info >> 4
1036                 elfsym.type_ = b.Info & 0xf
1037                 elfsym.other = b.Other
1038         } else {
1039                 b := new(ElfSymBytes)
1040                 binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
1041                 elfsym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
1042                 elfsym.value = uint64(elfobj.e.Uint32(b.Value[:]))
1043                 elfsym.size = uint64(elfobj.e.Uint32(b.Size[:]))
1044                 elfsym.shndx = elfobj.e.Uint16(b.Shndx[:])
1045                 elfsym.bind = b.Info >> 4
1046                 elfsym.type_ = b.Info & 0xf
1047                 elfsym.other = b.Other
1048         }
1049
1050         var s loader.Sym
1051
1052         if elfsym.name == "_GLOBAL_OFFSET_TABLE_" {
1053                 elfsym.name = ".got"
1054         }
1055         if elfsym.name == ".TOC." {
1056                 // Magic symbol on ppc64.  Will be set to this object
1057                 // file's .got+0x8000.
1058                 elfsym.bind = ElfSymBindLocal
1059         }
1060
1061         switch elfsym.type_ {
1062         case ElfSymTypeSection:
1063                 s = elfobj.sect[elfsym.shndx].sym
1064
1065         case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
1066                 switch elfsym.bind {
1067                 case ElfSymBindGlobal:
1068                         if needSym != 0 {
1069                                 s = lookup(elfsym.name, 0)
1070
1071                                 // for global scoped hidden symbols we should insert it into
1072                                 // symbol hash table, but mark them as hidden.
1073                                 // __i686.get_pc_thunk.bx is allowed to be duplicated, to
1074                                 // workaround that we set dupok.
1075                                 // TODO(minux): correctly handle __i686.get_pc_thunk.bx without
1076                                 // set dupok generally. See https://golang.org/cl/5823055
1077                                 // comment #5 for details.
1078                                 if s != 0 && elfsym.other == 2 {
1079                                         if !l.IsExternal(s) {
1080                                                 _, s = l.MakeSymbolUpdater(s)
1081                                         }
1082                                         l.SetAttrDuplicateOK(s, true)
1083                                         l.SetAttrVisibilityHidden(s, true)
1084                                 }
1085                         }
1086
1087                 case ElfSymBindLocal:
1088                         if (arch.Family == sys.ARM || arch.Family == sys.ARM64) && (strings.HasPrefix(elfsym.name, "$a") || strings.HasPrefix(elfsym.name, "$d") || strings.HasPrefix(elfsym.name, "$x")) {
1089                                 // binutils for arm and arm64 generate these mapping
1090                                 // symbols, ignore these
1091                                 break
1092                         }
1093
1094                         if elfsym.name == ".TOC." {
1095                                 // We need to be able to look this up,
1096                                 // so put it in the hash table.
1097                                 if needSym != 0 {
1098                                         s = lookup(elfsym.name, localSymVersion)
1099                                         l.SetAttrVisibilityHidden(s, true)
1100                                 }
1101                                 break
1102                         }
1103
1104                         if needSym != 0 {
1105                                 // local names and hidden global names are unique
1106                                 // and should only be referenced by their index, not name, so we
1107                                 // don't bother to add them into the hash table
1108                                 // FIXME: pass empty string here for name? This would
1109                                 // reduce mem use, but also (possibly) make it harder
1110                                 // to debug problems.
1111                                 s = newSym(elfsym.name, localSymVersion)
1112                                 l.SetAttrVisibilityHidden(s, true)
1113                         }
1114
1115                 case ElfSymBindWeak:
1116                         if needSym != 0 {
1117                                 s = lookup(elfsym.name, 0)
1118                                 if elfsym.other == 2 {
1119                                         l.SetAttrVisibilityHidden(s, true)
1120                                 }
1121
1122                                 // Allow weak symbols to be duplicated when already defined.
1123                                 if l.OuterSym(s) != 0 {
1124                                         l.SetAttrDuplicateOK(s, true)
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 != 0 && l.SymType(s) == 0 && !l.AttrVisibilityHidden(s) && elfsym.type_ != ElfSymTypeSection {
1137                 sb, _ := l.MakeSymbolUpdater(s)
1138                 sb.SetType(sym.SXREF)
1139         }
1140         elfsym.sym = s
1141
1142         return nil
1143 }
1144
1145 func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, error) {
1146         // TODO(mdempsky): Replace this with a struct-valued switch statement
1147         // once golang.org/issue/15164 is fixed or found to not impair cmd/link
1148         // performance.
1149
1150         const (
1151                 AMD64 = uint32(sys.AMD64)
1152                 ARM   = uint32(sys.ARM)
1153                 ARM64 = uint32(sys.ARM64)
1154                 I386  = uint32(sys.I386)
1155                 PPC64 = uint32(sys.PPC64)
1156                 S390X = uint32(sys.S390X)
1157         )
1158
1159         switch uint32(arch.Family) | elftype<<16 {
1160         default:
1161                 return 0, fmt.Errorf("%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
1162
1163         case S390X | uint32(elf.R_390_8)<<16:
1164                 return 1, nil
1165
1166         case PPC64 | uint32(elf.R_PPC64_TOC16)<<16,
1167                 PPC64 | uint32(elf.R_PPC64_TOC16_LO)<<16,
1168                 PPC64 | uint32(elf.R_PPC64_TOC16_HI)<<16,
1169                 PPC64 | uint32(elf.R_PPC64_TOC16_HA)<<16,
1170                 PPC64 | uint32(elf.R_PPC64_TOC16_DS)<<16,
1171                 PPC64 | uint32(elf.R_PPC64_TOC16_LO_DS)<<16,
1172                 PPC64 | uint32(elf.R_PPC64_REL16_LO)<<16,
1173                 PPC64 | uint32(elf.R_PPC64_REL16_HI)<<16,
1174                 PPC64 | uint32(elf.R_PPC64_REL16_HA)<<16,
1175                 S390X | uint32(elf.R_390_16)<<16,
1176                 S390X | uint32(elf.R_390_GOT16)<<16,
1177                 S390X | uint32(elf.R_390_PC16)<<16,
1178                 S390X | uint32(elf.R_390_PC16DBL)<<16,
1179                 S390X | uint32(elf.R_390_PLT16DBL)<<16:
1180                 return 2, nil
1181
1182         case ARM | uint32(elf.R_ARM_ABS32)<<16,
1183                 ARM | uint32(elf.R_ARM_GOT32)<<16,
1184                 ARM | uint32(elf.R_ARM_PLT32)<<16,
1185                 ARM | uint32(elf.R_ARM_GOTOFF)<<16,
1186                 ARM | uint32(elf.R_ARM_GOTPC)<<16,
1187                 ARM | uint32(elf.R_ARM_THM_PC22)<<16,
1188                 ARM | uint32(elf.R_ARM_REL32)<<16,
1189                 ARM | uint32(elf.R_ARM_CALL)<<16,
1190                 ARM | uint32(elf.R_ARM_V4BX)<<16,
1191                 ARM | uint32(elf.R_ARM_GOT_PREL)<<16,
1192                 ARM | uint32(elf.R_ARM_PC24)<<16,
1193                 ARM | uint32(elf.R_ARM_JUMP24)<<16,
1194                 ARM64 | uint32(elf.R_AARCH64_CALL26)<<16,
1195                 ARM64 | uint32(elf.R_AARCH64_ADR_GOT_PAGE)<<16,
1196                 ARM64 | uint32(elf.R_AARCH64_LD64_GOT_LO12_NC)<<16,
1197                 ARM64 | uint32(elf.R_AARCH64_ADR_PREL_PG_HI21)<<16,
1198                 ARM64 | uint32(elf.R_AARCH64_ADD_ABS_LO12_NC)<<16,
1199                 ARM64 | uint32(elf.R_AARCH64_LDST8_ABS_LO12_NC)<<16,
1200                 ARM64 | uint32(elf.R_AARCH64_LDST32_ABS_LO12_NC)<<16,
1201                 ARM64 | uint32(elf.R_AARCH64_LDST64_ABS_LO12_NC)<<16,
1202                 ARM64 | uint32(elf.R_AARCH64_LDST128_ABS_LO12_NC)<<16,
1203                 ARM64 | uint32(elf.R_AARCH64_PREL32)<<16,
1204                 ARM64 | uint32(elf.R_AARCH64_JUMP26)<<16,
1205                 AMD64 | uint32(elf.R_X86_64_PC32)<<16,
1206                 AMD64 | uint32(elf.R_X86_64_PLT32)<<16,
1207                 AMD64 | uint32(elf.R_X86_64_GOTPCREL)<<16,
1208                 AMD64 | uint32(elf.R_X86_64_GOTPCRELX)<<16,
1209                 AMD64 | uint32(elf.R_X86_64_REX_GOTPCRELX)<<16,
1210                 I386 | uint32(elf.R_386_32)<<16,
1211                 I386 | uint32(elf.R_386_PC32)<<16,
1212                 I386 | uint32(elf.R_386_GOT32)<<16,
1213                 I386 | uint32(elf.R_386_PLT32)<<16,
1214                 I386 | uint32(elf.R_386_GOTOFF)<<16,
1215                 I386 | uint32(elf.R_386_GOTPC)<<16,
1216                 I386 | uint32(elf.R_386_GOT32X)<<16,
1217                 PPC64 | uint32(elf.R_PPC64_REL24)<<16,
1218                 PPC64 | uint32(elf.R_PPC_REL32)<<16,
1219                 S390X | uint32(elf.R_390_32)<<16,
1220                 S390X | uint32(elf.R_390_PC32)<<16,
1221                 S390X | uint32(elf.R_390_GOT32)<<16,
1222                 S390X | uint32(elf.R_390_PLT32)<<16,
1223                 S390X | uint32(elf.R_390_PC32DBL)<<16,
1224                 S390X | uint32(elf.R_390_PLT32DBL)<<16,
1225                 S390X | uint32(elf.R_390_GOTPCDBL)<<16,
1226                 S390X | uint32(elf.R_390_GOTENT)<<16:
1227                 return 4, nil
1228
1229         case AMD64 | uint32(elf.R_X86_64_64)<<16,
1230                 AMD64 | uint32(elf.R_X86_64_PC64)<<16,
1231                 ARM64 | uint32(elf.R_AARCH64_ABS64)<<16,
1232                 ARM64 | uint32(elf.R_AARCH64_PREL64)<<16,
1233                 PPC64 | uint32(elf.R_PPC64_ADDR64)<<16,
1234                 S390X | uint32(elf.R_390_GLOB_DAT)<<16,
1235                 S390X | uint32(elf.R_390_RELATIVE)<<16,
1236                 S390X | uint32(elf.R_390_GOTOFF)<<16,
1237                 S390X | uint32(elf.R_390_GOTPC)<<16,
1238                 S390X | uint32(elf.R_390_64)<<16,
1239                 S390X | uint32(elf.R_390_PC64)<<16,
1240                 S390X | uint32(elf.R_390_GOT64)<<16,
1241                 S390X | uint32(elf.R_390_PLT64)<<16:
1242                 return 8, nil
1243         }
1244 }
1245
1246 func cstring(x []byte) string {
1247         i := bytes.IndexByte(x, '\x00')
1248         if i >= 0 {
1249                 x = x[:i]
1250         }
1251         return string(x)
1252 }