From d4f9d05fde4b2cfd202a5852ec1ec3e960ef53ed Mon Sep 17 00:00:00 2001 From: David Fang Date: Thu, 8 Aug 2013 20:14:40 +0000 Subject: [PATCH] initial draft of PPCMachObjectWriter.cpp this records relocation entries in the mach-o object file for PIC code generation. tested on powerpc-darwin8, validated against darwin otool -rvV git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188004 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachOFormat.h | 19 + lib/Object/MachOObjectFile.cpp | 7 +- .../PowerPC/MCTargetDesc/CMakeLists.txt | 1 + .../PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 24 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 4 + .../MCTargetDesc/PPCMachObjectWriter.cpp | 385 ++++++++++++++++++ test/CodeGen/PowerPC/hello-reloc.s | 84 ++++ 7 files changed, 502 insertions(+), 22 deletions(-) create mode 100644 lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp create mode 100644 test/CodeGen/PowerPC/hello-reloc.s diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index 96ee8a766b8..2bbad0ac931 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -425,6 +425,25 @@ namespace macho { }; + /// PPC relocation types from + enum RelocationInfoTypePPC { + RIT_PPC_BR14 = RIT_Pair +1, + RIT_PPC_BR24, + RIT_PPC_HI16, + RIT_PPC_LO16, + RIT_PPC_HA16, + RIT_PPC_LO14, + RIT_PPC_SECTDIFF, + RIT_PPC_PB_LA_PTR, + RIT_PPC_HI16_SECTDIFF, + RIT_PPC_LO16_SECTDIFF, + RIT_PPC_HA16_SECTDIFF, + RIT_PPC_JBSR, + RIT_PPC_LO14_SECTDIFF, + RIT_PPC_LOCAL_SECTDIFF, + RIT_PPC_TLV + }; + } // end namespace macho } // end namespace object diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 5d0399ebd4f..9d6f53dca77 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -1059,7 +1059,8 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, break; } // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm) { + } else if (Arch == Triple::x86 || Arch == Triple::arm || + Arch == Triple::ppc) { // Generic relocation types... switch (Type) { case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info @@ -1084,7 +1085,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, } } - if (Arch == Triple::x86) { + if (Arch == Triple::x86 || Arch == Triple::ppc) { // All X86 relocations that need special printing were already // handled in the generic code. switch (Type) { @@ -1177,7 +1178,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { // On arches that use the generic relocations, GENERIC_RELOC_PAIR // is always hidden. - if (Arch == Triple::x86 || Arch == Triple::arm) { + if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { if (Type == macho::RIT_Pair) Result = true; } else if (Arch == Triple::x86_64) { // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows diff --git a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt index 45be4713b6d..3efa5ecf909 100644 --- a/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt @@ -5,6 +5,7 @@ add_llvm_library(LLVMPowerPCDesc PPCMCCodeEmitter.cpp PPCMCExpr.cpp PPCPredicates.cpp + PPCMachObjectWriter.cpp PPCELFObjectWriter.cpp ) diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp index b2a8701b68b..dd619548d00 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -69,19 +69,6 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { } namespace { -class PPCMachObjectWriter : public MCMachObjectTargetWriter { -public: - PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, - uint32_t CPUSubtype) - : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} - - void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, const MCAsmLayout &Layout, - const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue) { - llvm_unreachable("Relocation emission for MachO/PPC unimplemented!"); - } -}; class PPCAsmBackend : public MCAsmBackend { const Target &TheTarget; @@ -174,12 +161,11 @@ namespace { MCObjectWriter *createObjectWriter(raw_ostream &OS) const { bool is64 = getPointerSize() == 8; - return createMachObjectWriter(new PPCMachObjectWriter( - /*Is64Bit=*/is64, - (is64 ? object::mach::CTM_PowerPC64 : - object::mach::CTM_PowerPC), - object::mach::CSPPC_ALL), - OS, /*IsLittleEndian=*/false); + return createPPCMachObjectWriter( + OS, + /*Is64Bit=*/is64, + (is64 ? object::mach::CTM_PowerPC64 : object::mach::CTM_PowerPC), + object::mach::CSPPC_ALL); } virtual bool doesSectionRequireSymbols(const MCSection &Section) const { diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h index 9f2913252f1..16c3cb4179c 100644 --- a/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h @@ -46,6 +46,10 @@ MCAsmBackend *createPPCAsmBackend(const Target &T, StringRef TT, StringRef CPU); MCObjectWriter *createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI); +/// createPPCELFObjectWriter - Construct a PPC Mach-O object writer. +MCObjectWriter *createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype); } // End llvm namespace // Generated files will use "namespace PPC". To avoid symbol clash, diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp new file mode 100644 index 00000000000..c907b2ba6ed --- /dev/null +++ b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp @@ -0,0 +1,385 @@ +//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/PPCMCTargetDesc.h" +#include "MCTargetDesc/PPCFixupKinds.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Object/MachOFormat.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace llvm::object; + +namespace { +class PPCMachObjectWriter : public MCMachObjectTargetWriter { + bool RecordScatteredRelocation(MachObjectWriter *Writer, + const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue); + + void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, + MCValue Target, uint64_t &FixedValue); + +public: + PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) + : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, + /*UseAggressiveSymbolFolding=*/Is64Bit) {} + + void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm, + const MCAsmLayout &Layout, const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + if (Writer->is64Bit()) { + report_fatal_error("Relocation emission for MachO/PPC64 unimplemented."); + } else + RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + FixedValue); + } +}; +} + +/// computes the log2 of the size of the relocation, +/// used for relocation_info::r_length. +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: + report_fatal_error("log2size(FixupKind): Unhandled fixup kind!"); + case FK_PCRel_1: + case FK_Data_1: + return 0; + case FK_PCRel_2: + case FK_Data_2: + return 1; + case FK_PCRel_4: + case PPC::fixup_ppc_brcond14: + case PPC::fixup_ppc_half16: + case PPC::fixup_ppc_br24: + case FK_Data_4: + return 2; + case FK_PCRel_8: + case FK_Data_8: + return 3; + } + return 0; +} + +/// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum. +/// Outline based on PPCELFObjectWriter::getRelocTypeInner(). +static unsigned getRelocType(const MCValue &Target, + const MCFixupKind FixupKind, // from + // Fixup.getKind() + const bool IsPCRel) { + const MCSymbolRefExpr::VariantKind Modifier = + Target.isAbsolute() ? MCSymbolRefExpr::VK_None + : Target.getSymA()->getKind(); + // determine the type of the relocation + unsigned Type = macho::RIT_Vanilla; + if (IsPCRel) { // relative to PC + switch ((unsigned)FixupKind) { + default: + report_fatal_error("Unimplemented fixup kind (relative)"); + case PPC::fixup_ppc_br24: + Type = macho::RIT_PPC_BR24; // R_PPC_REL24 + break; + case PPC::fixup_ppc_brcond14: + Type = macho::RIT_PPC_BR14; + break; + case PPC::fixup_ppc_half16: + switch (Modifier) { + default: + llvm_unreachable("Unsupported modifier for half16 fixup"); + case MCSymbolRefExpr::VK_PPC_HA: + Type = macho::RIT_PPC_HA16; + break; + case MCSymbolRefExpr::VK_PPC_LO: + Type = macho::RIT_PPC_LO16; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = macho::RIT_PPC_HI16; + break; + } + break; + } + } else { + switch ((unsigned)FixupKind) { + default: + report_fatal_error("Unimplemented fixup kind (absolute)!"); + case PPC::fixup_ppc_half16: + switch (Modifier) { + default: + llvm_unreachable("Unsupported modifier for half16 fixup"); + case MCSymbolRefExpr::VK_PPC_HA: + Type = macho::RIT_PPC_HA16_SECTDIFF; + break; + case MCSymbolRefExpr::VK_PPC_LO: + Type = macho::RIT_PPC_LO16_SECTDIFF; + break; + case MCSymbolRefExpr::VK_PPC_HI: + Type = macho::RIT_PPC_HI16_SECTDIFF; + break; + } + break; + case FK_Data_4: + break; + case FK_Data_2: + break; + } + } + return Type; +} + +static void makeRelocationInfo(macho::RelocationEntry &MRE, + const uint32_t FixupOffset, const uint32_t Index, + const unsigned IsPCRel, const unsigned Log2Size, + const unsigned IsExtern, const unsigned Type) { + MRE.Word0 = FixupOffset; + // The bitfield offsets that work (as determined by trial-and-error) + // are different than what is documented in the mach-o manuals. + // Is this an endianness issue w/ PPC? + MRE.Word1 = ((Index << 8) | // was << 0 + (IsPCRel << 7) | // was << 24 + (Log2Size << 5) | // was << 25 + (IsExtern << 4) | // was << 27 + (Type << 0)); // was << 28 +} + +static void +makeScatteredRelocationInfo(macho::RelocationEntry &MRE, const uint32_t Addr, + const unsigned Type, const unsigned Log2Size, + const unsigned IsPCRel, const uint32_t Value2) { + // For notes on bitfield positions and endianness, see: + // https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry + MRE.Word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) | (IsPCRel << 30) | + macho::RF_Scattered); + MRE.Word1 = Value2; +} + +/// Compute fixup offset (address). +static uint32_t getFixupOffset(const MCAsmLayout &Layout, + const MCFragment *Fragment, + const MCFixup &Fixup) { + uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); + // On Mach-O, ppc_fixup_half16 relocations must refer to the + // start of the instruction, not the second halfword, as ELF does + if (Fixup.getKind() == PPC::fixup_ppc_half16) + FixupOffset &= ~uint32_t(3); + return FixupOffset; +} + +/// \return false if falling back to using non-scattered relocation, +/// otherwise true for normal scattered relocation. +/// based on X86MachObjectWriter::RecordScatteredRelocation +/// and ARMMachObjectWriter::RecordScatteredRelocation +bool PPCMachObjectWriter::RecordScatteredRelocation( + MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + unsigned Log2Size, uint64_t &FixedValue) { + // caller already computes these, can we just pass and reuse? + const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup); + const MCFixupKind FK = Fixup.getKind(); + const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK); + const unsigned Type = getRelocType(Target, FK, IsPCRel); + + // Is this a local or SECTDIFF relocation entry? + // SECTDIFF relocation entries have symbol subtractions, + // and require two entries, the first for the add-symbol value, + // the second for the subtract-symbol value. + + // See . + const MCSymbol *A = &Target.getSymA()->getSymbol(); + MCSymbolData *A_SD = &Asm.getSymbolData(*A); + + if (!A_SD->getFragment()) + report_fatal_error("symbol '" + A->getName() + + "' can not be undefined in a subtraction expression"); + + uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); + uint64_t SecAddr = + Writer->getSectionAddress(A_SD->getFragment()->getParent()); + FixedValue += SecAddr; + uint32_t Value2 = 0; + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); + + if (!B_SD->getFragment()) + report_fatal_error("symbol '" + B->getSymbol().getName() + + "' can not be undefined in a subtraction expression"); + + // FIXME: is Type correct? see include/llvm/Object/MachOFormat.h + Value2 = Writer->getSymbolAddress(B_SD, Layout); + FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); + } + // FIXME: does FixedValue get used?? + + // Relocations are written out in reverse order, so the PAIR comes first. + if (Type == macho::RIT_PPC_SECTDIFF || Type == macho::RIT_PPC_HI16_SECTDIFF || + Type == macho::RIT_PPC_LO16_SECTDIFF || + Type == macho::RIT_PPC_HA16_SECTDIFF || + Type == macho::RIT_PPC_LO14_SECTDIFF || + Type == macho::RIT_PPC_LOCAL_SECTDIFF) { + // X86 had this piece, but ARM does not + // If the offset is too large to fit in a scattered relocation, + // we're hosed. It's an unfortunate limitation of the MachO format. + if (FixupOffset > 0xffffff) { + char Buffer[32]; + format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer)); + Asm.getContext().FatalError(Fixup.getLoc(), + Twine("Section too large, can't encode " + "r_address (") + + Buffer + ") into 24 bits of scattered " + "relocation entry."); + llvm_unreachable("fatal error returned?!"); + } + + // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()? + // see PPCMCExpr::EvaluateAsRelocatableImpl() + uint32_t other_half = 0; + switch (Type) { + case macho::RIT_PPC_LO16_SECTDIFF: + other_half = (FixedValue >> 16) & 0xffff; + // applyFixupOffset longer extracts the high part because it now assumes + // this was already done. + // It looks like this is not true for the FixedValue needed with Mach-O + // relocs. + // So we need to adjust FixedValue again here. + FixedValue &= 0xffff; + break; + case macho::RIT_PPC_HA16_SECTDIFF: + other_half = FixedValue & 0xffff; + FixedValue = + ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff; + break; + case macho::RIT_PPC_HI16_SECTDIFF: + other_half = FixedValue & 0xffff; + FixedValue = (FixedValue >> 16) & 0xffff; + break; + default: + llvm_unreachable("Invalid PPC scattered relocation type."); + break; + } + + macho::RelocationEntry MRE; + makeScatteredRelocationInfo(MRE, other_half, macho::RIT_Pair, Log2Size, + IsPCRel, Value2); + Writer->addRelocation(Fragment->getParent(), MRE); + } else { + // If the offset is more than 24-bits, it won't fit in a scattered + // relocation offset field, so we fall back to using a non-scattered + // relocation. This is a bit risky, as if the offset reaches out of + // the block and the linker is doing scattered loading on this + // symbol, things can go badly. + // + // Required for 'as' compatibility. + if (FixupOffset > 0xffffff) + return false; + } + macho::RelocationEntry MRE; + makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value); + Writer->addRelocation(Fragment->getParent(), MRE); + return true; +} + +// see PPCELFObjectWriter for a general outline of cases +void PPCMachObjectWriter::RecordPPCRelocation( + MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + uint64_t &FixedValue) { + const MCFixupKind FK = Fixup.getKind(); // unsigned + const unsigned Log2Size = getFixupKindLog2Size(FK); + const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK); + const unsigned RelocType = getRelocType(Target, FK, IsPCRel); + + // If this is a difference or a defined symbol plus an offset, then we need a + // scattered relocation entry. Differences always require scattered + // relocations. + if (Target.getSymB() && + // Q: are branch targets ever scattered? + RelocType != macho::RIT_PPC_BR24 && RelocType != macho::RIT_PPC_BR14) { + RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, + Log2Size, FixedValue); + return; + } + + // this doesn't seem right for RIT_PPC_BR24 + // Get the symbol data, if any. + MCSymbolData *SD = 0; + if (Target.getSymA()) + SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); + + // See . + const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup); + unsigned Index = 0; + unsigned IsExtern = 0; + unsigned Type = RelocType; + + if (Target.isAbsolute()) { // constant + // SymbolNum of 0 indicates the absolute section. + // + // FIXME: Currently, these are never generated (see code below). I cannot + // find a case where they are actually emitted. + report_fatal_error("FIXME: relocations to absolute targets " + "not yet implemented"); + // the above line stolen from ARM, not sure + } else { + // Resolve constant variables. + if (SD->getSymbol().isVariable()) { + int64_t Res; + if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( + Res, Layout, Writer->getSectionAddressMap())) { + FixedValue = Res; + return; + } + } + + // Check whether we need an external or internal relocation. + if (Writer->doesSymbolRequireExternRelocation(SD)) { + IsExtern = 1; + Index = SD->getIndex(); + // For external relocations, make sure to offset the fixup value to + // compensate for the addend of the symbol address, if it was + // undefined. This occurs with weak definitions, for example. + if (!SD->Symbol->isUndefined()) + FixedValue -= Layout.getSymbolOffset(SD); + } else { + // The index is the section ordinal (1-based). + const MCSectionData &SymSD = + Asm.getSectionData(SD->getSymbol().getSection()); + Index = SymSD.getOrdinal() + 1; + FixedValue += Writer->getSectionAddress(&SymSD); + } + if (IsPCRel) + FixedValue -= Writer->getSectionAddress(Fragment->getParent()); + } + + // struct relocation_info (8 bytes) + macho::RelocationEntry MRE; + makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, IsExtern, + Type); + Writer->addRelocation(Fragment->getParent(), MRE); +} + +MCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit, + uint32_t CPUType, + uint32_t CPUSubtype) { + return createMachObjectWriter( + new PPCMachObjectWriter(Is64Bit, CPUType, CPUSubtype), OS, + /*IsLittleEndian=*/false); +} diff --git a/test/CodeGen/PowerPC/hello-reloc.s b/test/CodeGen/PowerPC/hello-reloc.s new file mode 100644 index 00000000000..9bbfb381789 --- /dev/null +++ b/test/CodeGen/PowerPC/hello-reloc.s @@ -0,0 +1,84 @@ +; This tests for the basic implementation of PPCMachObjectWriter.cpp, +; which is responsible for writing mach-o relocation entries for (PIC) +; PowerPC objects. +; NOTE: Darwin PPC asm syntax is not yet supported by PPCAsmParser, +; so this test case uses ELF PPC asm syntax to produce a mach-o object. +; Once PPCAsmParser supports darwin asm syntax, this test case should +; be updated accordingly. + +; RUN: llvm-mc -filetype=obj -relocation-model=pic -mcpu=g4 -triple=powerpc-apple-darwin8 %s -o - | llvm-readobj -relocations | FileCheck -check-prefix=DARWIN-G4-DUMP %s + +; .machine ppc7400 + .section __TEXT,__textcoal_nt,coalesced,pure_instructions + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .section __TEXT,__text,regular,pure_instructions + .globl _main + .align 4 +_main: ; @main +; BB#0: ; %entry + mflr 0 + stw 31, -4(1) + stw 0, 8(1) + stwu 1, -80(1) + bl L0$pb +L0$pb: + mr 31, 1 + li 5, 0 + mflr 2 + stw 3, 68(31) + stw 5, 72(31) + stw 4, 64(31) + addis 2, 2, (L_.str-L0$pb)@ha + la 3, (L_.str-L0$pb)@l(2) + bl L_puts$stub + li 3, 0 + addi 1, 1, 80 + lwz 0, 8(1) + lwz 31, -4(1) + mtlr 0 + blr + + .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 + .align 4 +L_puts$stub: + .indirect_symbol _puts + mflr 0 + bcl 20, 31, L_puts$stub$tmp +L_puts$stub$tmp: + mflr 11 + addis 11, 11, (L_puts$lazy_ptr-L_puts$stub$tmp)@ha + mtlr 0 + lwzu 12, (L_puts$lazy_ptr-L_puts$stub$tmp)@l(11) + mtctr 12 + bctr + .section __DATA,__la_symbol_ptr,lazy_symbol_pointers +L_puts$lazy_ptr: + .indirect_symbol _puts + .long dyld_stub_binding_helper + +.subsections_via_symbols + .section __TEXT,__cstring,cstring_literals +L_.str: ; @.str + .asciz "Hello, world!" + +; DARWIN-G4-DUMP:Format: Mach-O 32-bit ppc +; DARWIN-G4-DUMP:Arch: powerpc +; DARWIN-G4-DUMP:AddressSize: 32bit +; DARWIN-G4-DUMP:Relocations [ +; DARWIN-G4-DUMP: Section __text { +; DARWIN-G4-DUMP: 0x34 1 2 0 PPC_RELOC_BR24 0 - +; DARWIN-G4-DUMP: 0x30 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _main +; DARWIN-G4-DUMP: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _main +; DARWIN-G4-DUMP: 0x2C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _main +; DARWIN-G4-DUMP: 0x60 0 2 n/a PPC_RELOC_PAIR 1 _main +; DARWIN-G4-DUMP: } +; DARWIN-G4-DUMP: Section __picsymbolstub1 { +; DARWIN-G4-DUMP: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _main +; DARWIN-G4-DUMP: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _main +; DARWIN-G4-DUMP: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _main +; DARWIN-G4-DUMP: 0x18 0 2 n/a PPC_RELOC_PAIR 1 _main +; DARWIN-G4-DUMP: } +; DARWIN-G4-DUMP: Section __la_symbol_ptr { +; DARWIN-G4-DUMP: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper +; DARWIN-G4-DUMP: } +; DARWIN-G4-DUMP:] -- 2.34.1