diff options
Diffstat (limited to 'src/cmd/oldlink/internal/sym/reloc.go')
-rw-r--r-- | src/cmd/oldlink/internal/sym/reloc.go | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/cmd/oldlink/internal/sym/reloc.go b/src/cmd/oldlink/internal/sym/reloc.go new file mode 100644 index 0000000000..4809db8c80 --- /dev/null +++ b/src/cmd/oldlink/internal/sym/reloc.go @@ -0,0 +1,128 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sym + +import ( + "cmd/internal/objabi" + "cmd/internal/sys" + "debug/elf" +) + +// Reloc is a relocation. +// +// The typical Reloc rewrites part of a symbol at offset Off to address Sym. +// A Reloc is stored in a slice on the Symbol it rewrites. +// +// Relocations are generated by the compiler as the type +// cmd/internal/obj.Reloc, which is encoded into the object file wire +// format and decoded by the linker into this type. A separate type is +// used to hold linker-specific state about the relocation. +// +// Some relocations are created by cmd/link. +type Reloc struct { + Off int32 // offset to rewrite + Siz uint8 // number of bytes to rewrite, 1, 2, or 4 + Done bool // set to true when relocation is complete + Type objabi.RelocType // the relocation type + Add int64 // addend + Sym *Symbol // symbol the relocation addresses + *relocExt // extra fields (see below), may be nil, call InitExt before use +} + +// relocExt contains extra fields in Reloc that are used only in +// certain cases. +type relocExt struct { + Xadd int64 // addend passed to external linker + Xsym *Symbol // symbol passed to external linker + Variant RelocVariant // variation on Type, currently used only on PPC64 and S390X +} + +func (r *Reloc) InitExt() { + if r.relocExt == nil { + r.relocExt = new(relocExt) + } +} + +// RelocVariant is a linker-internal variation on a relocation. +type RelocVariant uint8 + +const ( + RV_NONE RelocVariant = iota + RV_POWER_LO + RV_POWER_HI + RV_POWER_HA + RV_POWER_DS + + // RV_390_DBL is a s390x-specific relocation variant that indicates that + // the value to be placed into the relocatable field should first be + // divided by 2. + RV_390_DBL + + RV_CHECK_OVERFLOW RelocVariant = 1 << 7 + RV_TYPE_MASK RelocVariant = RV_CHECK_OVERFLOW - 1 +) + +func RelocName(arch *sys.Arch, r objabi.RelocType) string { + // We didn't have some relocation types at Go1.4. + // Uncomment code when we include those in bootstrap code. + + switch { + case r >= objabi.MachoRelocOffset: // Mach-O + // nr := (r - objabi.MachoRelocOffset)>>1 + // switch ctxt.Arch.Family { + // case sys.AMD64: + // return macho.RelocTypeX86_64(nr).String() + // case sys.ARM: + // return macho.RelocTypeARM(nr).String() + // case sys.ARM64: + // return macho.RelocTypeARM64(nr).String() + // case sys.I386: + // return macho.RelocTypeGeneric(nr).String() + // default: + // panic("unreachable") + // } + case r >= objabi.ElfRelocOffset: // ELF + nr := r - objabi.ElfRelocOffset + switch arch.Family { + case sys.AMD64: + return elf.R_X86_64(nr).String() + case sys.ARM: + return elf.R_ARM(nr).String() + case sys.ARM64: + return elf.R_AARCH64(nr).String() + case sys.I386: + return elf.R_386(nr).String() + case sys.MIPS, sys.MIPS64: + return elf.R_MIPS(nr).String() + case sys.PPC64: + return elf.R_PPC64(nr).String() + case sys.S390X: + return elf.R_390(nr).String() + default: + panic("unreachable") + } + } + + return r.String() +} + +// RelocByOff implements sort.Interface for sorting relocations by offset. +type RelocByOff []Reloc + +func (x RelocByOff) Len() int { return len(x) } + +func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +func (x RelocByOff) Less(i, j int) bool { + a := &x[i] + b := &x[j] + if a.Off < b.Off { + return true + } + if a.Off > b.Off { + return false + } + return false +} |