}
func machoreloc1(r *ld.Reloc, sectoff int64) int {
- return -1
+ var v uint32
+
+ rs := r.Xsym
+
+ // ld64 has a bug handling MACHO_ARM64_RELOC_UNSIGNED with !extern relocation.
+ // see cmd/internal/ld/data.go for details. The workarond is that don't use !extern
+ // UNSIGNED relocation at all.
+ if rs.Type == ld.SHOSTOBJ || r.Type == ld.R_CALLARM64 || r.Type == ld.R_ADDRARM64 || r.Type == ld.R_ADDR {
+ if rs.Dynid < 0 {
+ ld.Diag("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.(*ld.Section)).Extnum)
+ if v == 0 {
+ ld.Diag("reloc %d to symbol %s in non-macho section %s type=%d", r.Type, rs.Name, (rs.Sect.(*ld.Section)).Name, rs.Type)
+ return -1
+ }
+ }
+
+ switch r.Type {
+ default:
+ return -1
+
+ case ld.R_ADDR:
+ v |= ld.MACHO_ARM64_RELOC_UNSIGNED << 28
+
+ case ld.R_CALLARM64:
+ if r.Xadd != 0 {
+ ld.Diag("ld64 doesn't allow BR26 reloc with non-zero addend: %s+%d", rs.Name, r.Xadd)
+ }
+
+ v |= 1 << 24 // pc-relative bit
+ v |= ld.MACHO_ARM64_RELOC_BRANCH26 << 28
+
+ case ld.R_ADDRARM64:
+ r.Siz = 4
+ // Two relocation entries: MACHO_ARM64_RELOC_PAGEOFF12 MACHO_ARM64_RELOC_PAGE21
+ // if r.Xadd is non-zero, add two MACHO_ARM64_RELOC_ADDEND.
+ if r.Xadd != 0 {
+ ld.Thearch.Lput(uint32(sectoff + 4))
+ ld.Thearch.Lput((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
+ }
+ ld.Thearch.Lput(uint32(sectoff + 4))
+ ld.Thearch.Lput(v | (ld.MACHO_ARM64_RELOC_PAGEOFF12 << 28) | (2 << 25))
+ if r.Xadd != 0 {
+ ld.Thearch.Lput(uint32(sectoff))
+ ld.Thearch.Lput((ld.MACHO_ARM64_RELOC_ADDEND << 28) | (2 << 25) | uint32(r.Xadd&0xffffff))
+ }
+ v |= 1 << 24 // pc-relative bit
+ v |= ld.MACHO_ARM64_RELOC_PAGE21 << 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
}
func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
case ld.R_ADDRARM64:
r.Done = 0
- // the first instruction is always at the lower address, this is endian neutral;
- // but note that o0 and o1 should still use the target endian.
- o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
- o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
-
- // when laid out, the instruction order must always be o1, o2.
- if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
- *val = int64(o0)<<32 | int64(o1)
- } else {
- *val = int64(o1)<<32 | int64(o0)
- }
-
// set up addend for eventual relocation via outer symbol.
rs := r.Sym
r.Xadd = r.Add
}
r.Xsym = rs
+ // the first instruction is always at the lower address, this is endian neutral;
+ // but note that o0 and o1 should still use the target endian.
+ o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
+ o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
+
+ // Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
+ // will make the linking fail because it thinks the code is not PIC even though
+ // the BR26 relocation should be fully resolved at link time.
+ // That is the reason why the next if block is disabled. When the bug in ld64
+ // is fixed, we can enable this block and also enable duff's device in cmd/7g.
+ if false && ld.HEADTYPE == ld.Hdarwin {
+ // Mach-O wants the addend to be encoded in the instruction
+ // Note that although Mach-O supports ARM64_RELOC_ADDEND, it
+ // can only encode 24-bit of signed addend, but the instructions
+ // supports 33-bit of signed addend, so we always encode the
+ // addend in place.
+ o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
+ o1 |= uint32(r.Xadd&0xfff) << 10
+ r.Xadd = 0
+ }
+
+ // when laid out, the instruction order must always be o1, o2.
+ if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+ *val = int64(o0)<<32 | int64(o1)
+ } else {
+ *val = int64(o1)<<32 | int64(o0)
+ }
+
return 0
case ld.R_CALLARM64:
ld.Addstring(s, "")
}
ld.Elfwritedynent(ld.Linklookup(ld.Ctxt, ".dynamic", 0), ld.DT_NEEDED, uint64(ld.Addstring(s, lib)))
+ } else if ld.HEADTYPE == ld.Hdarwin {
+ ld.Machoadddynlib(lib)
} else {
ld.Diag("adddynlib: unsupported binary format")
}
ld.Cseek(int64(ld.Segdata.Fileoff))
ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+ machlink := uint32(0)
+ if ld.HEADTYPE == ld.Hdarwin {
+ if ld.Debug['v'] != 0 {
+ fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+ }
+
+ if ld.Debug['w'] == 0 { // TODO(minux): enable DWARF Support
+ dwarfoff := uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Length), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)))
+ ld.Cseek(int64(dwarfoff))
+
+ ld.Segdwarf.Fileoff = uint64(ld.Cpos())
+ ld.Dwarfemitdebugsections()
+ ld.Segdwarf.Filelen = uint64(ld.Cpos()) - ld.Segdwarf.Fileoff
+ }
+
+ machlink = uint32(ld.Domacholink())
+ }
+
/* output symbol table */
ld.Symsize = 0
case ld.Hplan9:
symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+
+ case ld.Hdarwin:
+ symo = uint32(ld.Rnd(int64(uint64(ld.HEADR)+ld.Segtext.Filelen), int64(ld.INITRND)) + ld.Rnd(int64(ld.Segdata.Filelen), int64(ld.INITRND)) + int64(machlink))
}
ld.Cseek(int64(symo))
ld.Cflush()
}
+
+ case ld.Hdarwin:
+ if ld.Linkmode == ld.LinkExternal {
+ ld.Machoemitreloc()
+ }
}
}
ld.Hopenbsd,
ld.Hnacl:
ld.Asmbelf(int64(symo))
+
+ case ld.Hdarwin:
+ ld.Asmbmacho()
}
ld.Cflush()
MACHO_CPU_ARM = 12
MACHO_SUBCPU_ARM = 0
MACHO_SUBCPU_ARMV7 = 9
+ MACHO_CPU_ARM64 = 1<<24 | 12
+ MACHO_SUBCPU_ARM64_ALL = 0
MACHO32SYMSIZE = 12
MACHO64SYMSIZE = 16
MACHO_X86_64_RELOC_UNSIGNED = 0
MACHO_X86_64_RELOC_SIGNED_4 = 8
MACHO_ARM_RELOC_VANILLA = 0
MACHO_ARM_RELOC_BR24 = 5
+ MACHO_ARM64_RELOC_UNSIGNED = 0
+ MACHO_ARM64_RELOC_BRANCH26 = 2
+ MACHO_ARM64_RELOC_PAGE21 = 3
+ MACHO_ARM64_RELOC_PAGEOFF12 = 4
+ MACHO_ARM64_RELOC_ADDEND = 10
MACHO_GENERIC_RELOC_VANILLA = 0
MACHO_FAKE_GOTPCREL = 100
)
func Machoinit() {
switch Thearch.Thechar {
// 64-bit architectures
- case '6', '9':
+ case '6', '7', '9':
macho64 = true
// 32-bit architectures
func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
- msect := newMachoSect(mseg, buf, segname)
+ var msect *MachoSect
+ if Thearch.Thechar == '7' && sect.Rwx&1 == 0 {
+ // darwin/arm64 forbids absolute relocs in __TEXT, so if
+ // the section is not executable, put it in __DATA segment.
+ msect = newMachoSect(mseg, buf, "__DATA")
+ } else {
+ msect = newMachoSect(mseg, buf, segname)
+ }
+
if sect.Rellen > 0 {
msect.reloc = uint32(sect.Reloff)
msect.nreloc = uint32(sect.Rellen / 8)
mh.cpu = MACHO_CPU_AMD64
mh.subcpu = MACHO_SUBCPU_X86
+ case '7':
+ mh.cpu = MACHO_CPU_ARM64
+ mh.subcpu = MACHO_SUBCPU_ARM64_ALL
+
case '8':
mh.cpu = MACHO_CPU_386
mh.subcpu = MACHO_SUBCPU_X86
ml.data[2+15] = uint32(Entryvalue()) /* start pc */
case '6':
- ml := newMachoLoad(5, 42+2) /* unix thread */
- ml.data[0] = 4 /* thread type */
- ml.data[1] = 42 /* word count */
- ml.data[2+32] = uint32(Entryvalue()) /* start pc */
- ml.data[2+32+1] = uint32(Entryvalue() >> 16 >> 16) // hide >>32 for 8l
+ ml := newMachoLoad(5, 42+2) /* unix thread */
+ ml.data[0] = 4 /* thread type */
+ ml.data[1] = 42 /* word count */
+ ml.data[2+32] = uint32(Entryvalue()) /* start pc */
+ ml.data[2+32+1] = uint32(Entryvalue() >> 32)
+
+ case '7':
+ ml := newMachoLoad(5, 68+2) /* unix thread */
+ ml.data[0] = 6 /* thread type */
+ ml.data[1] = 68 /* word count */
+ ml.data[2+64] = uint32(Entryvalue()) /* start pc */
+ ml.data[2+64+1] = uint32(Entryvalue() >> 32)
case '8':
ml := newMachoLoad(5, 16+2) /* unix thread */