作者:achand
项目:g
// Convert the direct jump relocation r to refer to a trampoline if the target is too far
func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
switch r.Type {
case obj.R_CALLARM:
// r.Add is the instruction
// low 24-bit encodes the target address
t := (ld.Symaddr(r.Sym) + int64(signext24(r.Add&0xffffff)*4) - (s.Value + int64(r.Off))) / 4
if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
// direct call too far, need to insert trampoline.
// look up existing trampolines first. if we found one within the range
// of direct call, we can reuse it. otherwise create a new one.
offset := (signext24(r.Add&0xffffff) + 2) * 4
var tramp *ld.Symbol
for i := 0; ; i++ {
name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i)
tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
if tramp.Type == obj.SDYNIMPORT {
// don't reuse trampoline defined in other module
continue
}
if tramp.Value == 0 {
// either the trampoline does not exist -- we need to create one,
// or found one the address which is not assigned -- this will be
// laid down immediately after the current function. use this one.
break
}
t = (ld.Symaddr(tramp) - 8 - (s.Value + int64(r.Off))) / 4
if t >= -0x800000 && t < 0x7fffff {
// found an existing trampoline that is not too far
// we can just use it
break
}
}
if tramp.Type == 0 {
// trampoline does not exist, create one
ctxt.AddTramp(tramp)
if ctxt.DynlinkingGo() {
if immrot(uint32(offset)) == 0 {
ld.Errorf(s, "odd offset in dynlink direct call: %v+%d", r.Sym, offset)
}
gentrampdyn(tramp, r.Sym, int64(offset))
} else if ld.Buildmode == ld.BuildmodeCArchive || ld.Buildmode == ld.BuildmodeCShared || ld.Buildmode == ld.BuildmodePIE {
gentramppic(tramp, r.Sym, int64(offset))
} else {
gentramp(tramp, r.Sym, int64(offset))
}
}
// modify reloc to point to tramp, which will be resolved later
r.Sym = tramp
r.Add = r.Add&0xff000000 | 0xfffffe // clear the offset embedded in the instruction
r.Done = 0
}
default:
ld.Errorf(s, "trampoline called with non-jump reloc: %v", r.Type)
}
}
作者:achand
项目:g
func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
var v uint32
rs := r.Xsym
if rs.Type == obj.SHOSTOBJ {
if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type)
return -1
}
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
v = uint32(rs.Sect.Extnum)
if v == 0 {
ld.Errorf(s, "reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
switch r.Type {
default:
return -1
case obj.R_ADDR:
v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28
case obj.R_CALL,
obj.R_PCREL:
v |= 1 << 24 // pc-relative bit
v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28
}
switch r.Siz {
default:
return -1
case 1:
v |= 0 << 25
case 2:
v |= 1 << 25
case 4:
v |= 2 << 25
case 8:
v |= 3 << 25
}
ld.Thearch.Lput(uint32(sectoff))
ld.Thearch.Lput(v)
return 0
}
作者:kuangchanglan
项目:g
func archrelocaddr(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
var o1, o2 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = uint32(*val >> 32)
o2 = uint32(*val)
} else {
o1 = uint32(*val)
o2 = uint32(*val >> 32)
}
// We are spreading a 31-bit address across two instructions, putting the
// high (adjusted) part in the low 16 bits of the first instruction and the
// low part in the low 16 bits of the second instruction, or, in the DS case,
// bits 15-2 (inclusive) of the address into bits 15-2 of the second
// instruction (it is an error in this case if the low 2 bits of the address
// are non-zero).
t := ld.Symaddr(r.Sym) + r.Add
if t < 0 || t >= 1<<31 {
ld.Errorf(s, "relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
}
if t&0x8000 != 0 {
t += 0x10000
}
switch r.Type {
case obj.R_ADDRPOWER:
o1 |= (uint32(t) >> 16) & 0xffff
o2 |= uint32(t) & 0xffff
case obj.R_ADDRPOWER_DS:
o1 |= (uint32(t) >> 16) & 0xffff
if t&3 != 0 {
ld.Errorf(s, "bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
}
o2 |= uint32(t) & 0xfffc
default:
return -1
}
if ctxt.Arch.ByteOrder == binary.BigEndian {
*val = int64(o1)<<32 | int64(o2)
} else {
*val = int64(o2)<<32 | int64(o1)
}
return 0
}
作者:achand
项目:g
func pereloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) bool {
var v uint32
rs := r.Xsym
if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d to non-coff symbol %s type=%d", r.Type, rs.Name, rs.Type)
return false
}
ld.Thearch.Lput(uint32(sectoff))
ld.Thearch.Lput(uint32(rs.Dynid))
switch r.Type {
default:
return false
case obj.R_ADDR:
if r.Siz == 8 {
v = ld.IMAGE_REL_AMD64_ADDR64
} else {
v = ld.IMAGE_REL_AMD64_ADDR32
}
case obj.R_CALL,
obj.R_PCREL:
v = ld.IMAGE_REL_AMD64_REL32
}
ld.Thearch.Wput(uint16(v))
return true
}
作者:achand
项目:g
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
switch r.Variant & ld.RV_TYPE_MASK {
default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
return t
case ld.RV_NONE:
return t
case ld.RV_390_DBL:
if (t & 1) != 0 {
ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
}
return t >> 1
}
}
作者:achand
项目:g
func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
if s.Plt >= 0 {
return
}
ld.Adddynsym(ctxt, s)
if ld.Iself {
plt := ctxt.Syms.Lookup(".plt", 0)
got := ctxt.Syms.Lookup(".got.plt", 0)
rel := ctxt.Syms.Lookup(".rel.plt", 0)
if plt.Size == 0 {
elfsetupplt(ctxt)
}
// jmpq *got+size
ld.Adduint8(ctxt, plt, 0xff)
ld.Adduint8(ctxt, plt, 0x25)
ld.Addaddrplus(ctxt, plt, got, got.Size)
// add to got: pointer to current pos in plt
ld.Addaddrplus(ctxt, got, plt, plt.Size)
// pushl $x
ld.Adduint8(ctxt, plt, 0x68)
ld.Adduint32(ctxt, plt, uint32(rel.Size))
// jmp .plt
ld.Adduint8(ctxt, plt, 0xe9)
ld.Adduint32(ctxt, plt, uint32(-(plt.Size + 4)))
// rel
ld.Addaddrplus(ctxt, rel, got, got.Size-4)
ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_386_JMP_SLOT))
s.Plt = int32(plt.Size - 16)
} else if ld.Headtype == obj.Hdarwin {
// Same laziness as in 6l.
plt := ctxt.Syms.Lookup(".plt", 0)
addgotsym(ctxt, s)
ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.plt", 0), uint32(s.Dynid))
// jmpq *got+size(IP)
s.Plt = int32(plt.Size)
ld.Adduint8(ctxt, plt, 0xff)
ld.Adduint8(ctxt, plt, 0x25)
ld.Addaddrplus(ctxt, plt, ctxt.Syms.Lookup(".got", 0), int64(s.Got))
} else {
ld.Errorf(s, "addpltsym: unsupported binary format")
}
}
作者:kuangchanglan
项目:g
// Convert the direct jump relocation r to refer to a trampoline if the target is too far
func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
switch r.Type {
case obj.R_CALLARM:
// r.Add is the instruction
// low 24-bit encodes the target address
t := (ld.Symaddr(r.Sym) + int64(signext24(r.Add&0xffffff)*4) - (s.Value + int64(r.Off))) / 4
if t > 0x7fffff || t < -0x800000 || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
// direct call too far, need to insert trampoline
offset := (signext24(r.Add&0xffffff) + 2) * 4
var tramp *ld.Symbol
for i := 0; ; i++ {
name := r.Sym.Name + fmt.Sprintf("%+d-tramp%d", offset, i)
tramp = ctxt.Syms.Lookup(name, int(r.Sym.Version))
if tramp.Value == 0 {
// either the trampoline does not exist -- we need to create one,
// or found one the address which is not assigned -- this will be
// laid down immediately after the current function. use this one.
break
}
t = (ld.Symaddr(tramp) - 8 - (s.Value + int64(r.Off))) / 4
if t >= -0x800000 && t < 0x7fffff {
// found an existing trampoline that is not too far
// we can just use it
break
}
}
if tramp.Type == 0 {
// trampoline does not exist, create one
ctxt.AddTramp(tramp)
tramp.Size = 12 // 3 instructions
tramp.P = make([]byte, tramp.Size)
t = ld.Symaddr(r.Sym) + int64(offset)
o1 := uint32(0xe5900000 | 11<<12 | 15<<16) // MOVW (R15), R11 // R15 is actual pc + 8
o2 := uint32(0xe12fff10 | 11) // JMP (R11)
o3 := uint32(t) // WORD $target
ld.SysArch.ByteOrder.PutUint32(tramp.P, o1)
ld.SysArch.ByteOrder.PutUint32(tramp.P[4:], o2)
ld.SysArch.ByteOrder.PutUint32(tramp.P[8:], o3)
}
// modify reloc to point to tramp, which will be resolved later
r.Sym = tramp
r.Add = r.Add&0xff000000 | 0xfffffe // clear the offset embedded in the instruction
r.Done = 0
}
default:
ld.Errorf(s, "trampoline called with non-jump reloc: %v", r.Type)
}
}
作者:kuangchanglan
项目:g
func addgotsyminternal(ctxt *ld.Link, s *ld.Symbol) {
if s.Got >= 0 {
return
}
got := ctxt.Syms.Lookup(".got", 0)
s.Got = int32(got.Size)
ld.Addaddrplus(ctxt, got, s, 0)
if ld.Iself {
} else {
ld.Errorf(s, "addgotsyminternal: unsupported binary format")
}
}
作者:kuangchanglan
项目:g
// Return the value of .TOC. for symbol s
func symtoc(ctxt *ld.Link, s *ld.Symbol) int64 {
var toc *ld.Symbol
if s.Outer != nil {
toc = ctxt.Syms.ROLookup(".TOC.", int(s.Outer.Version))
} else {
toc = ctxt.Syms.ROLookup(".TOC.", int(s.Version))
}
if toc == nil {
ld.Errorf(s, "TOC-relative relocation in object without .TOC.")
return 0
}
return toc.Value
}
作者:kuangchanglan
项目:g
func addgotsym(ctxt *ld.Link, s *ld.Symbol) {
if s.Got >= 0 {
return
}
ld.Adddynsym(ctxt, s)
got := ctxt.Syms.Lookup(".got", 0)
s.Got = int32(got.Size)
ld.Adduint32(ctxt, got, 0)
if ld.Iself {
rel := ctxt.Syms.Lookup(".rel", 0)
ld.Addaddrplus(ctxt, rel, got, int64(s.Got))
ld.Adduint32(ctxt, rel, ld.ELF32_R_INFO(uint32(s.Dynid), ld.R_ARM_GLOB_DAT))
} else {
ld.Errorf(s, "addgotsym: unsupported binary format")
}
}
作者:kuangchanglan
项目:g
func addpltsym(ctxt *ld.Link, s *ld.Symbol) {
if s.Plt >= 0 {
return
}
ld.Adddynsym(ctxt, s)
if ld.Iself {
plt := ctxt.Syms.Lookup(".plt", 0)
rela := ctxt.Syms.Lookup(".rela.plt", 0)
if plt.Size == 0 {
elfsetupplt(ctxt)
}
// Create the glink resolver if necessary
glink := ensureglinkresolver(ctxt)
// Write symbol resolver stub (just a branch to the
// glink resolver stub)
r := ld.Addrel(glink)
r.Sym = glink
r.Off = int32(glink.Size)
r.Siz = 4
r.Type = obj.R_CALLPOWER
ld.Adduint32(ctxt, glink, 0x48000000) // b .glink
// In the ppc64 ABI, the dynamic linker is responsible
// for writing the entire PLT. We just need to
// reserve 8 bytes for each PLT entry and generate a
// JMP_SLOT dynamic relocation for it.
//
// TODO(austin): ABI v1 is different
s.Plt = int32(plt.Size)
plt.Size += 8
ld.Addaddrplus(ctxt, rela, plt, int64(s.Plt))
ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_PPC64_JMP_SLOT))
ld.Adduint64(ctxt, rela, 0)
} else {
ld.Errorf(s, "addpltsym: unsupported binary format")
}
}
作者:achand
项目:g
func addgotsym(ctxt *ld.Link, s *ld.Symbol) {
if s.Got >= 0 {
return
}
ld.Adddynsym(ctxt, s)
got := ctxt.Syms.Lookup(".got", 0)
s.Got = int32(got.Size)
ld.Adduint64(ctxt, got, 0)
if ld.Iself {
rela := ctxt.Syms.Lookup(".rela", 0)
ld.Addaddrplus(ctxt, rela, got, int64(s.Got))
ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_X86_64_GLOB_DAT))
ld.Adduint64(ctxt, rela, 0)
} else if ld.Headtype == obj.Hdarwin {
ld.Adduint32(ctxt, ctxt.Syms.Lookup(".linkedit.got", 0), uint32(s.Dynid))
} else {
ld.Errorf(s, "addgotsym: unsupported binary format")
}
}
作者:achand
项目:g
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
if ld.Linkmode == ld.LinkExternal {
switch r.Type {
default:
return -1
case obj.R_ADDRMIPS,
obj.R_ADDRMIPSU:
r.Done = 0
// set up addend for eventual relocation via outer symbol.
rs := r.Sym
r.Xadd = r.Add
for rs.Outer != nil {
r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
rs = rs.Outer
}
if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name)
}
r.Xsym = rs
return 0
case obj.R_ADDRMIPSTLS,
obj.R_CALLMIPS,
obj.R_JMPMIPS:
r.Done = 0
r.Xsym = r.Sym
r.Xadd = r.Add
return 0
}
}
switch r.Type {
case obj.R_CONST:
*val = r.Add
return 0
case obj.R_GOTOFF:
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
return 0
case obj.R_ADDRMIPS,
obj.R_ADDRMIPSU:
t := ld.Symaddr(r.Sym) + r.Add
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
if r.Type == obj.R_ADDRMIPS {
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
} else {
*val = int64(o1&0xffff0000 | uint32((t+1<<15)>>16)&0xffff)
}
return 0
case obj.R_ADDRMIPSTLS:
// thread pointer is at 0x7000 offset from the start of TLS data area
t := ld.Symaddr(r.Sym) + r.Add - 0x7000
if t < -32768 || t >= 32678 {
ld.Errorf(s, "TLS offset out of range %d", t)
}
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
*val = int64(o1&0xffff0000 | uint32(t)&0xffff)
return 0
case obj.R_CALLMIPS,
obj.R_JMPMIPS:
// Low 26 bits = (S + A) >> 2
t := ld.Symaddr(r.Sym) + r.Add
o1 := ld.SysArch.ByteOrder.Uint32(s.P[r.Off:])
*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
return 0
}
return -1
}
作者:Harvey-O
项目:g
func asmb(ctxt *ld.Link) {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f asmb\n", obj.Cputime())
}
if ld.Iself {
ld.Asmbelfsetup()
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
ld.Cseek(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
/* output symbol table */
ld.Symsize = 0
ld.Lcsize = 0
symo := uint32(0)
if !*ld.FlagS {
if !ld.Iself {
ld.Errorf(nil, "unsupported executable format")
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f sym\n", obj.Cputime())
}
symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
ld.Cseek(int64(symo))
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f elfsym\n", obj.Cputime())
}
ld.Asmelfsym(ctxt)
ld.Cflush()
ld.Cwrite(ld.Elfstrdat)
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f dwarf\n", obj.Cputime())
}
if ld.Linkmode == ld.LinkExternal {
ld.Elfemitreloc(ctxt)
}
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f header\n", obj.Cputime())
}
ld.Cseek(0)
switch ld.Headtype {
default:
ld.Errorf(nil, "unsupported operating system")
case obj.Hlinux:
ld.Asmbelf(ctxt, int64(symo))
}
ld.Cflush()
if *ld.FlagC {
fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
fmt.Printf("symsize=%d\n", ld.Symsize)
fmt.Printf("lcsize=%d\n", ld.Lcsize)
fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
}
}
作者:kuangchanglan
项目:g
func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 {
switch r.Variant & ld.RV_TYPE_MASK {
default:
ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
fallthrough
case ld.RV_NONE:
return t
case ld.RV_POWER_LO:
if r.Variant&ld.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = ld.Be32(s.P[r.Off-2:])
} else {
o1 = ld.Le32(s.P[r.Off:])
}
switch o1 >> 26 {
case 24, // ori
26, // xori
28: // andi
if t>>16 != 0 {
goto overflow
}
default:
if int64(int16(t)) != t {
goto overflow
}
}
}
return int64(int16(t))
case ld.RV_POWER_HA:
t += 0x8000
fallthrough
// Fallthrough
case ld.RV_POWER_HI:
t >>= 16
if r.Variant&ld.RV_CHECK_OVERFLOW != 0 {
// Whether to check for signed or unsigned
// overflow depends on the instruction
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = ld.Be32(s.P[r.Off-2:])
} else {
o1 = ld.Le32(s.P[r.Off:])
}
switch o1 >> 26 {
case 25, // oris
27, // xoris
29: // andis
if t>>16 != 0 {
goto overflow
}
default:
if int64(int16(t)) != t {
goto overflow
}
}
}
return int64(int16(t))
case ld.RV_POWER_DS:
var o1 uint32
if ctxt.Arch.ByteOrder == binary.BigEndian {
o1 = uint32(ld.Be16(s.P[r.Off:]))
} else {
o1 = uint32(ld.Le16(s.P[r.Off:]))
}
if t&3 != 0 {
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
}
if (r.Variant&ld.RV_CHECK_OVERFLOW != 0) && int64(int16(t)) != t {
goto overflow
}
return int64(o1)&0x3 | int64(int16(t))
}
overflow:
ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
return t
}
作者:achand
项目:g
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
targ := r.Sym
switch r.Type {
default:
if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d", r.Type)
return false
}
// Handle relocations found in ELF object files.
case 256 + ld.R_390_12,
256 + ld.R_390_GOT12:
ld.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-256)
return false
case 256 + ld.R_390_8,
256 + ld.R_390_16,
256 + ld.R_390_32,
256 + ld.R_390_64:
if targ.Type == obj.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
}
r.Type = obj.R_ADDR
return true
case 256 + ld.R_390_PC16,
256 + ld.R_390_PC32,
256 + ld.R_390_PC64:
if targ.Type == obj.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name)
}
if targ.Type == 0 || targ.Type == obj.SXREF {
ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
}
r.Type = obj.R_PCREL
r.Add += int64(r.Siz)
return true
case 256 + ld.R_390_GOT16,
256 + ld.R_390_GOT32,
256 + ld.R_390_GOT64:
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
return true
case 256 + ld.R_390_PLT16DBL,
256 + ld.R_390_PLT32DBL:
r.Type = obj.R_PCREL
r.Variant = ld.RV_390_DBL
r.Add += int64(r.Siz)
if targ.Type == obj.SDYNIMPORT {
addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt)
}
return true
case 256 + ld.R_390_PLT32,
256 + ld.R_390_PLT64:
r.Type = obj.R_PCREL
r.Add += int64(r.Siz)
if targ.Type == obj.SDYNIMPORT {
addpltsym(ctxt, targ)
r.Sym = ctxt.Syms.Lookup(".plt", 0)
r.Add += int64(targ.Plt)
}
return true
case 256 + ld.R_390_COPY:
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
return false
case 256 + ld.R_390_GLOB_DAT:
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
return false
case 256 + ld.R_390_JMP_SLOT:
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
return false
case 256 + ld.R_390_RELATIVE:
ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-256)
return false
case 256 + ld.R_390_GOTOFF:
if targ.Type == obj.SDYNIMPORT {
ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
}
r.Type = obj.R_GOTOFF
return true
case 256 + ld.R_390_GOTPC:
r.Type = obj.R_PCREL
r.Sym = ctxt.Syms.Lookup(".got", 0)
r.Add += int64(r.Siz)
return true
case 256 + ld.R_390_PC16DBL,
256 + ld.R_390_PC32DBL:
r.Type = obj.R_PCREL
//.........这里部分代码省略.........
作者:kuangchanglan
项目:g
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
if ld.Linkmode == ld.LinkExternal {
switch r.Type {
default:
return -1
case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE:
r.Done = 0
// check Outer is nil, Type is TLSBSS?
r.Xadd = r.Add
r.Xsym = r.Sym
return 0
case obj.R_ADDRPOWER,
obj.R_ADDRPOWER_DS,
obj.R_ADDRPOWER_TOCREL,
obj.R_ADDRPOWER_TOCREL_DS,
obj.R_ADDRPOWER_GOT,
obj.R_ADDRPOWER_PCREL:
r.Done = 0
// set up addend for eventual relocation via outer symbol.
rs := r.Sym
r.Xadd = r.Add
for rs.Outer != nil {
r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
rs = rs.Outer
}
if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
ld.Errorf(s, "missing section for %s", rs.Name)
}
r.Xsym = rs
return 0
case obj.R_CALLPOWER:
r.Done = 0
r.Xsym = r.Sym
r.Xadd = r.Add
return 0
}
}
switch r.Type {
case obj.R_CONST:
*val = r.Add
return 0
case obj.R_GOTOFF:
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0))
return 0
case obj.R_ADDRPOWER, obj.R_ADDRPOWER_DS:
return archrelocaddr(ctxt, r, s, val)
case obj.R_CALLPOWER:
// Bits 6 through 29 = (S + A - P) >> 2
t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
if t&3 != 0 {
ld.Errorf(s, "relocation for %s+%d is not aligned: %d", r.Sym.Name, r.Off, t)
}
if int64(int32(t<<6)>>6) != t {
// TODO(austin) This can happen if text > 32M.
// Add a call trampoline to .text in that case.
ld.Errorf(s, "relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
}
*val |= int64(uint32(t) &^ 0xfc000003)
return 0
case obj.R_POWER_TOC: // S + A - .TOC.
*val = ld.Symaddr(r.Sym) + r.Add - symtoc(ctxt, s)
return 0
case obj.R_POWER_TLS_LE:
// The thread pointer points 0x7000 bytes after the start of the the
// thread local storage area as documented in section "3.7.2 TLS
// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
// Specification".
v := r.Sym.Value - 0x7000
if int64(int16(v)) != v {
ld.Errorf(s, "TLS offset out of range %d", v)
}
*val = (*val &^ 0xffff) | (v & 0xffff)
return 0
}
return -1
}
作者:kuangchanglan
项目:g
func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) bool {
targ := r.Sym
switch r.Type {
default:
if r.Type >= 256 {
ld.Errorf(s, "unexpected relocation type %d", r.Type)
return false
}
// Handle relocations found in ELF object files.
case 256 + ld.R_PPC64_REL24:
r.Type = obj.R_CALLPOWER
// This is a local call, so the caller isn't setting
// up r12 and r2 is the same for the caller and
// callee. Hence, we need to go to the local entry
// point. (If we don't do this, the callee will try
// to use r12 to compute r2.)
r.Add += int64(r.Sym.Localentry) * 4
if targ.Type == obj.SDYNIMPORT {
// Should have been handled in elfsetupplt
ld.Errorf(s, "unexpected R_PPC64_REL24 for dyn import")
}
return true
case 256 + ld.R_PPC_REL32:
r.Type = obj.R_PCREL
r.Add += 4
if targ.Type == obj.SDYNIMPORT {
ld.Errorf(s, "unexpected R_PPC_REL32 for dyn import")
}
return true
case 256 + ld.R_PPC64_ADDR64:
r.Type = obj.R_ADDR
if targ.Type == obj.SDYNIMPORT {
// These happen in .toc sections
ld.Adddynsym(ctxt, targ)
rela := ctxt.Syms.Lookup(".rela", 0)
ld.Addaddrplus(ctxt, rela, s, int64(r.Off))
ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(targ.Dynid), ld.R_PPC64_ADDR64))
ld.Adduint64(ctxt, rela, uint64(r.Add))
r.Type = 256 // ignore during relocsym
}
return true
case 256 + ld.R_PPC64_TOC16:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_LO | ld.RV_CHECK_OVERFLOW
return true
case 256 + ld.R_PPC64_TOC16_LO:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_LO
return true
case 256 + ld.R_PPC64_TOC16_HA:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW
return true
case 256 + ld.R_PPC64_TOC16_HI:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW
return true
case 256 + ld.R_PPC64_TOC16_DS:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_DS | ld.RV_CHECK_OVERFLOW
return true
case 256 + ld.R_PPC64_TOC16_LO_DS:
r.Type = obj.R_POWER_TOC
r.Variant = ld.RV_POWER_DS
return true
case 256 + ld.R_PPC64_REL16_LO:
r.Type = obj.R_PCREL
r.Variant = ld.RV_POWER_LO
r.Add += 2 // Compensate for relocation size of 2
return true
case 256 + ld.R_PPC64_REL16_HI:
r.Type = obj.R_PCREL
r.Variant = ld.RV_POWER_HI | ld.RV_CHECK_OVERFLOW
r.Add += 2
return true
case 256 + ld.R_PPC64_REL16_HA:
r.Type = obj.R_PCREL
r.Variant = ld.RV_POWER_HA | ld.RV_CHECK_OVERFLOW
r.Add += 2
return true
//.........这里部分代码省略.........
作者:kuangchanglan
项目:g
func machoreloc1(s *ld.Symbol, r *ld.Reloc, sectoff int64) int {
var v uint32
rs := r.Xsym
if r.Type == obj.R_PCREL {
if rs.Type == obj.SHOSTOBJ {
ld.Errorf(s, "pc-relative relocation of external symbol is not supported")
return -1
}
if r.Siz != 4 {
return -1
}
// emit a pair of "scattered" relocations that
// resolve to the difference of section addresses of
// the symbol and the instruction
// this value is added to the field being relocated
o1 := uint32(sectoff)
o1 |= 1 << 31 // scattered bit
o1 |= ld.MACHO_ARM_RELOC_SECTDIFF << 24
o1 |= 2 << 28 // size = 4
o2 := uint32(0)
o2 |= 1 << 31 // scattered bit
o2 |= ld.MACHO_ARM_RELOC_PAIR << 24
o2 |= 2 << 28 // size = 4
ld.Thearch.Lput(o1)
ld.Thearch.Lput(uint32(ld.Symaddr(rs)))
ld.Thearch.Lput(o2)
ld.Thearch.Lput(uint32(s.Value + int64(r.Off)))
return 0
}
if rs.Type == obj.SHOSTOBJ || r.Type == obj.R_CALLARM {
if rs.Dynid < 0 {
ld.Errorf(s, "reloc %d to non-macho symbol %s type=%d", r.Type, rs.Name, rs.Type)
return -1
}
v = uint32(rs.Dynid)
v |= 1 << 27 // external relocation
} else {
v = uint32(rs.Sect.Extnum)
if v == 0 {
ld.Errorf(s, "reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, rs.Sect.Name, rs.Type)
return -1
}
}
switch r.Type {
default:
return -1
case obj.R_ADDR:
v |= ld.MACHO_GENERIC_RELOC_VANILLA << 28
case obj.R_CALLARM:
v |= 1 << 24 // pc-relative bit
v |= ld.MACHO_ARM_RELOC_BR24 << 28
}
switch r.Siz {
default:
return -1
case 1:
v |= 0 << 25
case 2:
v |= 1 << 25
case 4:
v |= 2 << 25
case 8:
v |= 3 << 25
}
ld.Thearch.Lput(uint32(sectoff))
ld.Thearch.Lput(v)
return 0
}
作者:achand
项目:g
func asmb(ctxt *ld.Link) {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f asmb\n", obj.Cputime())
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f codeblk\n", obj.Cputime())
}
if ld.Iself {
ld.Asmbelfsetup()
}
sect := ld.Segtext.Sect
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
// 0xCC is INT $3 - breakpoint instruction
ld.CodeblkPad(ctxt, int64(sect.Vaddr), int64(sect.Length), []byte{0xCC})
for sect = sect.Next; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
}
if ld.Segrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f rodatblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
}
if ld.Segrelrodata.Filelen > 0 {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f relrodatblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segrelrodata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
}
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f datblk\n", obj.Cputime())
}
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
ld.Cseek(int64(ld.Segdwarf.Fileoff))
ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
machlink := int64(0)
if ld.Headtype == obj.Hdarwin {
machlink = ld.Domacholink(ctxt)
}
switch ld.Headtype {
default:
ld.Errorf(nil, "unknown header type %v", ld.Headtype)
fallthrough
case obj.Hplan9:
break
case obj.Hdarwin:
ld.Flag8 = true /* 64-bit addresses */
case obj.Hlinux,
obj.Hfreebsd,
obj.Hnetbsd,
obj.Hopenbsd,
obj.Hdragonfly,
obj.Hsolaris:
ld.Flag8 = true /* 64-bit addresses */
case obj.Hnacl,
obj.Hwindows,
obj.Hwindowsgui:
break
}
ld.Symsize = 0
ld.Spsize = 0
ld.Lcsize = 0
symo := int64(0)
if !*ld.FlagS {
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f sym\n", obj.Cputime())
}
switch ld.Headtype {
default:
case obj.Hplan9:
*ld.FlagS = true
symo = int64(ld.Segdata.Fileoff + ld.Segdata.Filelen)
case obj.Hdarwin:
symo = int64(ld.Segdwarf.Fileoff + uint64(ld.Rnd(int64(ld.Segdwarf.Filelen), int64(*ld.FlagRound))) + uint64(machlink))
case obj.Hlinux,
obj.Hfreebsd,
obj.Hnetbsd,
obj.Hopenbsd,
obj.Hdragonfly,
obj.Hsolaris,
//.........这里部分代码省略.........