Home | History | Annotate | Download | only in sym
      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 sym
      6 
      7 import (
      8 	"cmd/internal/objabi"
      9 	"cmd/internal/sys"
     10 	"debug/elf"
     11 )
     12 
     13 // Reloc is a relocation.
     14 //
     15 // The typical Reloc rewrites part of a symbol at offset Off to address Sym.
     16 // A Reloc is stored in a slice on the Symbol it rewrites.
     17 //
     18 // Relocations are generated by the compiler as the type
     19 // cmd/internal/obj.Reloc, which is encoded into the object file wire
     20 // format and decoded by the linker into this type. A separate type is
     21 // used to hold linker-specific state about the relocation.
     22 //
     23 // Some relocations are created by cmd/link.
     24 type Reloc struct {
     25 	Off     int32            // offset to rewrite
     26 	Siz     uint8            // number of bytes to rewrite, 1, 2, or 4
     27 	Done    bool             // set to true when relocation is complete
     28 	Variant RelocVariant     // variation on Type
     29 	Type    objabi.RelocType // the relocation type
     30 	Add     int64            // addend
     31 	Xadd    int64            // addend passed to external linker
     32 	Sym     *Symbol          // symbol the relocation addresses
     33 	Xsym    *Symbol          // symbol passed to external linker
     34 }
     35 
     36 // RelocVariant is a linker-internal variation on a relocation.
     37 type RelocVariant uint8
     38 
     39 const (
     40 	RV_NONE RelocVariant = iota
     41 	RV_POWER_LO
     42 	RV_POWER_HI
     43 	RV_POWER_HA
     44 	RV_POWER_DS
     45 
     46 	// RV_390_DBL is a s390x-specific relocation variant that indicates that
     47 	// the value to be placed into the relocatable field should first be
     48 	// divided by 2.
     49 	RV_390_DBL
     50 
     51 	RV_CHECK_OVERFLOW RelocVariant = 1 << 7
     52 	RV_TYPE_MASK      RelocVariant = RV_CHECK_OVERFLOW - 1
     53 )
     54 
     55 func RelocName(arch *sys.Arch, r objabi.RelocType) string {
     56 	// We didn't have some relocation types at Go1.4.
     57 	// Uncomment code when we include those in bootstrap code.
     58 
     59 	switch {
     60 	case r >= 512: // Mach-O
     61 		// nr := (r - 512)>>1
     62 		// switch ctxt.Arch.Family {
     63 		// case sys.AMD64:
     64 		// 	return macho.RelocTypeX86_64(nr).String()
     65 		// case sys.ARM:
     66 		// 	return macho.RelocTypeARM(nr).String()
     67 		// case sys.ARM64:
     68 		// 	return macho.RelocTypeARM64(nr).String()
     69 		// case sys.I386:
     70 		// 	return macho.RelocTypeGeneric(nr).String()
     71 		// default:
     72 		// 	panic("unreachable")
     73 		// }
     74 	case r >= 256: // ELF
     75 		nr := r - 256
     76 		switch arch.Family {
     77 		case sys.AMD64:
     78 			return elf.R_X86_64(nr).String()
     79 		case sys.ARM:
     80 			return elf.R_ARM(nr).String()
     81 		case sys.ARM64:
     82 			return elf.R_AARCH64(nr).String()
     83 		case sys.I386:
     84 			return elf.R_386(nr).String()
     85 		case sys.MIPS, sys.MIPS64:
     86 			// return elf.R_MIPS(nr).String()
     87 		case sys.PPC64:
     88 			// return elf.R_PPC64(nr).String()
     89 		case sys.S390X:
     90 			// return elf.R_390(nr).String()
     91 		default:
     92 			panic("unreachable")
     93 		}
     94 	}
     95 
     96 	return r.String()
     97 }
     98 
     99 // RelocByOff implements sort.Interface for sorting relocations by offset.
    100 type RelocByOff []Reloc
    101 
    102 func (x RelocByOff) Len() int { return len(x) }
    103 
    104 func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    105 
    106 func (x RelocByOff) Less(i, j int) bool {
    107 	a := &x[i]
    108 	b := &x[j]
    109 	if a.Off < b.Off {
    110 		return true
    111 	}
    112 	if a.Off > b.Off {
    113 		return false
    114 	}
    115 	return false
    116 }
    117