archiveVersion = 1;
classes = {
};
- objectVersion = 42;
+ objectVersion = 46;
objects = {
/* Begin PBXAggregateTarget section */
F9023C3006D5A227001BBF46 /* Project object */ = {
isa = PBXProject;
attributes = {
+ LastUpgradeCheck = 0600;
ORGANIZATIONNAME = "Apple Inc.";
};
buildConfigurationList = F933D92309291AC90083EAC8 /* Build configuration list for PBXProject "ld64" */;
- compatibilityVersion = "Xcode 2.4";
+ compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
F933D92409291AC90083EAC8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
- ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
GCC_DYNAMIC_NO_PIC = NO;
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ ONLY_ACTIVE_ARCH = YES;
};
name = Debug;
};
F933D92509291AC90083EAC8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
- ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
GCC_DYNAMIC_NO_PIC = NO;
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
};
F9849FF810B5DE8E009E9878 /* Release-assert */ = {
isa = XCBuildConfiguration;
buildSettings = {
- ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
- ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
GCC_DYNAMIC_NO_PIC = NO;
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
};
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_MODEL_TUNING = G5;
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
+ COMBINE_HIDPI_IMAGES = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
// hack until arm64 headers are worked out
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#define CPU_SUBTYPE_ARM64_ALL 0
-#define CPU_SUBTYPE_ARM64_V8 1
+#ifndef CPU_TYPE_ARM64
+ #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
+#endif
+#ifndef CPU_SUBTYPE_ARM64_ALL
+ #define CPU_SUBTYPE_ARM64_ALL 0
+#endif
+#ifndef CPU_SUBTYPE_ARM64_V8
+ #define CPU_SUBTYPE_ARM64_V8 1
+#endif
+
#define ARM64_RELOC_UNSIGNED 0 // for pointers
#define ARM64_RELOC_SUBTRACTOR 1 // must be followed by a ARM64_RELOC_UNSIGNED
#define UNWIND_ARM64_DWARF_SECTION_OFFSET 0x00FFFFFF
+#define UNW_ARM_D31 287
+
#ifndef LC_SOURCE_VERSION
#define LC_SOURCE_VERSION 0x2A
#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8)
#endif
+#define UNWIND_ARM_MODE_MASK 0x0F000000
+#define UNWIND_ARM_MODE_FRAME 0x01000000
+#define UNWIND_ARM_MODE_FRAME_D 0x02000000
+#define UNWIND_ARM_MODE_DWARF 0x04000000
+
+#define UNWIND_ARM_FRAME_STACK_ADJUST_MASK 0x00C00000
+
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R4 0x00000001
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R5 0x00000002
+#define UNWIND_ARM_FRAME_FIRST_PUSH_R6 0x00000004
+
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R8 0x00000008
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R9 0x00000010
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R10 0x00000020
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R11 0x00000040
+#define UNWIND_ARM_FRAME_SECOND_PUSH_R12 0x00000080
+
+#define UNWIND_ARM_FRAME_D_REG_COUNT_MASK 0x00000F00
+
+#define UNWIND_ARM_DWARF_SECTION_OFFSET 0x00FFFFFF
struct ArchInfo {
const char* archName;
#define SUPPORT_ARCH_arm_any 1
#endif
#if SUPPORT_ARCH_arm64
- { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "", false, false },
+ { "arm64", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, "arm64-", "aarch64-", false, false },
#endif
#if SUPPORT_ARCH_arm64v8
- { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8, "arm64v8-", "", true, false },
+ { "arm64v8", CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_V8, "arm64v8-", "aarch64-", true, false },
#endif
{ NULL, 0, 0, NULL, NULL, false, false }
};
fi
if [ -z "${RC_SUPPORTED_ARCHS}" ]; then
- RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m arm64"
+ RC_SUPPORTED_ARCHS="i386 x86_64 x86_64h armv6 armv7 armv7s armv7m armv7k arm64"
fi
for ANARCH in ${RC_SUPPORTED_ARCHS}
objOpts.forceDwarfConversion= (_options.outputKind() == Options::kDyld);
objOpts.neverConvertDwarf = !_options.needsUnwindInfoSection();
objOpts.verboseOptimizationHints = _options.verboseOptimizationHints();
+ objOpts.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
objOpts.subType = _options.subArchitecture();
ld::relocatable::File* objResult = mach_o::relocatable::parse(p, len, info.path, info.modTime, info.ordinal, objOpts);
if ( objResult != NULL ) {
ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
if ( dylibReader != NULL ) {
if ( ! dylibReader->installPathVersionSpecific() ) {
- dylibReader->forEachAtom(handler);
dylibReader->setImplicitlyLinked();
this->addDylib(dylibReader, info);
}
ld::dylib::File* dylibReader = dynamic_cast<ld::dylib::File*>(reader);
ld::archive::File* archiveReader = dynamic_cast<ld::archive::File*>(reader);
if ( dylibReader != NULL ) {
- dylibReader->forEachAtom(handler);
dylibReader->setImplicitlyLinked();
this->addDylib(dylibReader, info);
}
fArchitectureName = "unknown architecture";
}
+bool Options::armUsesZeroCostExceptions() const
+{
+ return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
+}
+
void Options::parseArch(const char* arch)
{
if ( arch == NULL )
}
break;
case CPU_TYPE_ARM:
- fAddCompactUnwindEncoding = false;
- fRemoveDwarfUnwindIfCompactExists = false;
+ if ( armUsesZeroCostExceptions() ) {
+ switch ( fOutputKind ) {
+ case Options::kObjectFile:
+ case Options::kStaticExecutable:
+ case Options::kPreload:
+ case Options::kKextBundle:
+ fAddCompactUnwindEncoding = false;
+ break;
+ case Options::kDyld:
+ case Options::kDynamicLibrary:
+ case Options::kDynamicBundle:
+ case Options::kDynamicExecutable:
+ fAddCompactUnwindEncoding = true;
+ break;
+ }
+ }
+ else {
+ fAddCompactUnwindEncoding = false;
+ fRemoveDwarfUnwindIfCompactExists = false;
+ }
break;
case 0:
// if -arch is missing, assume we don't want compact unwind info
// <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
// <rdar://problem/15974532> make armv7[s] use 16KB pages in user land code for iOS 8 or later
if ( fSegmentAlignment == 4096 ) {
- if ( (fArchitecture == CPU_TYPE_ARM64)
- || ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) &&
- ((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
- switch ( fOutputKind ) {
- case Options::kDynamicExecutable:
- case Options::kDynamicLibrary:
- case Options::kDynamicBundle:
- case Options::kDyld:
+ switch ( fOutputKind ) {
+ case Options::kDynamicExecutable:
+ case Options::kDynamicLibrary:
+ case Options::kDynamicBundle:
+ case Options::kDyld:
+ if ( (fArchitecture == CPU_TYPE_ARM64)
+ || ((fArchitecture == CPU_TYPE_ARM) && (fIOSVersionMin >= ld::iOS_8_0) &&
+ ((fSubArchitecture == CPU_SUBTYPE_ARM_V7S) || (fSubArchitecture == CPU_SUBTYPE_ARM_V7))) ) {
fSegmentAlignment = 4096*4;
- break;
- case Options::kStaticExecutable:
- case Options::kKextBundle:
- case Options::kObjectFile:
- case Options::kPreload:
- break;
- }
+ }
+ break;
+ case Options::kStaticExecutable:
+ case Options::kKextBundle:
+ // <rdar://problem/14676611> 16KB segments for arm64 kexts
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fIOSVersionMin >= ld::iOS_9_0) ) {
+ fSegmentAlignment = 4096*4;
+ }
+ break;
+ case Options::kObjectFile:
+ case Options::kPreload:
+ break;
}
}
+
+
// <rdar://problem/13624134> linker should not convert dwarf unwind if .o file has compact unwind section
switch ( fOutputKind ) {
case Options::kDynamicExecutable:
break;
}
+ // Make sure -image_base matches alignment
+ uint64_t alignedBaseAddress = (fBaseAddress+fSegmentAlignment-1) & (-fSegmentAlignment);
+ if ( alignedBaseAddress != fBaseAddress ) {
+ warning("base address 0x%llX is not properly aligned. Changing it to 0x%llX", fBaseAddress, alignedBaseAddress);
+ fBaseAddress = alignedBaseAddress;
+ }
+
}
void Options::checkIllegalOptionCombinations()
linkerOptions() const { return fLinkerOptions; }
FileInfo findFramework(const char* frameworkName) const;
FileInfo findLibrary(const char* rootName, bool dylibsOnly=false) const;
+ bool armUsesZeroCostExceptions() const;
const std::vector<SectionRename>& sectionRenames() const { return fSectionRenames; }
const std::vector<SegmentRename>& segmentRenames() const { return fSegmentRenames; }
bool moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const;
}
}
-static void userReadableSwiftVersion(uint8_t value, char versionString[64])
+static void userReadableSwiftVersion(uint8_t value, char versionString[32])
{
switch (value) {
case 1:
strcpy(versionString, "1.0");
break;
- case 2:
- strcpy(versionString, "1.1");
- break;
default:
- sprintf(versionString, "unknown ABI version 0x%02X", value);
+ sprintf(versionString, "0x%02X", value);
}
}
_internal.swiftVersion = file.swiftVersion();
}
else if ( file.swiftVersion() != _internal.swiftVersion ) {
- char fileVersion[64];
- char otherVersion[64];
+ char fileVersion[32];
+ char otherVersion[32];
userReadableSwiftVersion(file.swiftVersion(), fileVersion);
userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
if ( file.swiftVersion() > _internal.swiftVersion ) {
if ( (_options.iOSVersionMin() != iOSVersionUnset) && (_options.iOSVersionMin() < iOS_8_0) ) {
// <rdar://problem/17598404> only warn about linking against embedded dylib if it is built for iOS 8 or later
if ( dylibFile->iOSMinVersion() >= iOS_8_0 )
- throwf("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
+ warning("embedded dylibs/frameworks are only supported on iOS 8.0 and later (%s)", depInstallName);
}
}
if ( _options.sharedRegionEligible() ) {
optOpt.needsUnwindInfoSection = _options.needsUnwindInfoSection();
optOpt.keepDwarfUnwind = _options.keepDwarfUnwind();
optOpt.verboseOptimizationHints = _options.verboseOptimizationHints();
+ optOpt.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
optOpt.arch = _options.architecture();
optOpt.mcpu = _options.mcpuLTO();
optOpt.llvmOptions = &_options.llvmOptions();
enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100,
iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000,
- iOS_Future=0x10000000};
+ iOS_9_0=0x00090000, iOS_Future=0x10000000};
namespace relocatable {
//
const Registers_arm64&, const typename CFI_Parser<A>::PrologInfo& prolog,
char warningBuffer[1024]);
+ // arm specific variants
+ static bool isReturnAddressRegister(int regNum, const Registers_arm&);
+ static pint_t getCFA(A& addressSpace, const typename CFI_Parser<A>::PrologInfo& prolog, const Registers_arm&);
+ static compact_unwind_encoding_t encodeToUseDwarf(const Registers_arm&);
+ static compact_unwind_encoding_t createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+ const Registers_arm&, const typename CFI_Parser<A>::PrologInfo& prolog,
+ char warningBuffer[1024]);
+
};
}
+
+
+//
+// arm specific functions
+//
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::encodeToUseDwarf(const Registers_arm&)
+{
+ return UNWIND_ARM_MODE_DWARF;
+}
+
+
+template <typename A, typename R>
+compact_unwind_encoding_t DwarfInstructions<A,R>::createCompactEncodingFromProlog(A& addressSpace, pint_t funcAddr,
+ const Registers_arm& r, const typename CFI_Parser<A>::PrologInfo& prolog,
+ char warningBuffer[1024])
+{
+ warningBuffer[0] = '\0';
+ return UNWIND_ARM_MODE_DWARF;
+}
+
+
} // namespace libunwind
objOpts.forceDwarfConversion = false;
objOpts.neverConvertDwarf = false;
objOpts.verboseOptimizationHints = options.verboseOptimizationHints;
+ objOpts.armUsesZeroCostExceptions = options.armUsesZeroCostExceptions;
objOpts.subType = 0;
switch ( severity ) {
#if LTO_API_VERSION >= 10
case LTO_DS_REMARK:
- fprintf(stderr, "ld: LTO remark: %s\n", message);
- break;
#endif
case LTO_DS_NOTE:
case LTO_DS_WARNING:
bool needsUnwindInfoSection;
bool keepDwarfUnwind;
bool verboseOptimizationHints;
+ bool armUsesZeroCostExceptions;
cpu_type_t arch;
const char* mcpu;
const std::vector<const char*>* llvmOptions;
virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
const ld::IndirectBindingTable& ind) const;
+ virtual bool ignoreLabel(const char* label) const;
};
template <typename A>
virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
const ld::IndirectBindingTable& ind) const;
+ virtual bool ignoreLabel(const char* label) const;
};
template <typename A>
virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
const ld::IndirectBindingTable& ind) const;
+ virtual bool ignoreLabel(const char* label) const;
};
bool forceDwarfConversion() { return _forceDwarfConversion; }
bool verboseOptimizationHints() { return _verboseOptimizationHints; }
bool neverConvertDwarf() { return _neverConvertDwarf; }
+ bool armUsesZeroCostExceptions() { return _armUsesZeroCostExceptions; }
macho_data_in_code_entry<P>* dataInCodeStart() { return _dataInCodeStart; }
macho_data_in_code_entry<P>* dataInCodeEnd() { return _dataInCodeEnd; }
bool _forceDwarfConversion;
bool _neverConvertDwarf;
bool _verboseOptimizationHints;
+ bool _armUsesZeroCostExceptions;
unsigned int _stubsSectionNum;
const macho_section<P>* _stubsMachOSection;
std::vector<const char*> _dtraceProviderInfo;
// respond to -t option
if ( opts.logAllFiles )
printf("%s\n", _path);
+
+ _armUsesZeroCostExceptions = opts.armUsesZeroCostExceptions;
// parse start of mach-o file
if ( ! parseLoadCommands() )
template <>
uint32_t CFISection<arm>::cfiCount(Parser<arm>& parser)
{
+ if ( parser.armUsesZeroCostExceptions() ) {
+ // create ObjectAddressSpace object for use by libunwind
+ OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
+ return libunwind::CFI_Parser<OAS>::getCFICount(oas,
+ this->_machOSection->addr(), this->_machOSection->size());
+ }
return 0;
}
libunwind::CFI_Atom_Info<CFISection<arm>::OAS>::CFI_Atom_Info cfiArray[],
uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
{
- // arm does not use zero cost exceptions
- assert(count == 0);
+ if ( !parser.armUsesZeroCostExceptions() ) {
+ // most arm do not use zero cost exceptions
+ assert(count == 0);
+ return;
+ }
+ // create ObjectAddressSpace object for use by libunwind
+ OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
+
+ // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
+ const char* msg;
+ msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_arm>::parseCFIs(
+ oas, this->_machOSection->addr(), this->_machOSection->size(),
+ cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
+ cfiArray, count, (void*)&parser, warnFunc);
+ if ( msg != NULL )
+ throwf("malformed __eh_frame section: %s", msg);
}
}
#endif
+template <>
+void CFISection<arm>::addCiePersonalityFixups(class Parser<arm>& parser, const CFI_Atom_Info* cieInfo)
+{
+ uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
+ if ( (personalityEncoding == 0x9B) || (personalityEncoding == 0x90) ) {
+ uint32_t offsetInCFI = cieInfo->u.cieInfo.personality.offsetInCFI;
+ uint32_t nlpAddr = cieInfo->u.cieInfo.personality.targetAddress;
+ Atom<arm>* cieAtom = this->findAtomByAddress(cieInfo->address);
+ Atom<arm>* nlpAtom = parser.findAtomByAddress(nlpAddr);
+ assert(nlpAtom->contentType() == ld::Atom::typeNonLazyPointer);
+ Parser<arm>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
+
+ parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, nlpAtom);
+ parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, cieAtom);
+ parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, offsetInCFI);
+ parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
+ }
+ else if ( personalityEncoding != 0 ) {
+ throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding);
+ }
+}
+
+
template <typename A>
void CFISection<A>::addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo)
}
#endif
+#if SUPPORT_ARCH_arm_any
+template <>
+const char* CUSection<arm>::personalityName(class Parser<arm>& parser, const macho_relocation_info<arm::P>* reloc)
+{
+ if ( reloc->r_extern() ) {
+ assert((reloc->r_type() == ARM_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
+ const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
+ return parser.nameFromSymbol(sym);
+ }
+ else {
+ // support __LD, __compact_unwind personality entries which are pointer to personality non-lazy pointer
+ const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
+ pint_t nlPointerAddr = *content;
+ Section<arm>* nlSection = parser.sectionForAddress(nlPointerAddr);
+ if ( nlSection->type() == ld::Section::typeCode ) {
+ // personality function is defined in this .o file, so this is a direct reference to it
+ // atoms may not be constructed yet, so scan symbol table for labels
+ const char* name = parser.scanSymbolTableForAddress(nlPointerAddr);
+ return name;
+ }
+ else {
+ uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(nlPointerAddr, nlSection->machoSection());
+ const macho_nlist<P>& nlSymbol = parser.symbolFromIndex(symIndex);
+ return parser.nameFromSymbol(nlSymbol);
+ }
+ }
+}
+#endif
+
template <typename A>
const char* CUSection<A>::personalityName(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
template <>
bool CUSection<arm>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
{
- return false;
+ return ((enc & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_DWARF);
}
#endif
return count;
}
+template <typename A>
+bool Literal4Section<A>::ignoreLabel(const char* label) const
+{
+ return (label[0] == 'L') || (label[0] == 'l');
+}
template <typename A>
unsigned long Literal4Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
}
+template <typename A>
+bool Literal8Section<A>::ignoreLabel(const char* label) const
+{
+ return (label[0] == 'L') || (label[0] == 'l');
+}
+
template <typename A>
unsigned long Literal8Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
{
return false;
}
+template <typename A>
+bool Literal16Section<A>::ignoreLabel(const char* label) const
+{
+ return (label[0] == 'L') || (label[0] == 'l');
+}
template <typename A>
unsigned long Literal16Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
return ld::Atom::scopeLinkageUnit;
}
-
template <typename A>
const uint8_t* CFStringSection<A>::targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
ContentType* ct, unsigned int* count)
bool forceDwarfConversion;
bool neverConvertDwarf;
bool verboseOptimizationHints;
+ bool armUsesZeroCostExceptions;
uint32_t subType;
};
return ((enc & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF);
}
+template <>
+bool UnwindInfoAtom<arm>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
+{
+ return ((enc & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_DWARF);
+}
+
+
template <typename A>
void UnwindInfoAtom<A>::compressDuplicates(const std::vector<UnwindEntry>& entries, std::vector<UnwindEntry>& uniqueEntries)
{
_fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndianLow24of32));
}
+template <>
+void UnwindInfoAtom<arm>::addCompressedAddressOffsetFixup(uint32_t offset, const ld::Atom* func, const ld::Atom* fromFunc)
+{
+ if ( fromFunc->isThumb() ) {
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, func));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fromFunc));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, 1));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndianLow24of32));
+ }
+ else {
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, func));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of3, ld::Fixup::kindSubtractTargetAddress, fromFunc));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndianLow24of32));
+ }
+}
+
template <>
void UnwindInfoAtom<x86>::addCompressedEncodingFixup(uint32_t offset, const ld::Atom* fde)
{
_fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
}
+template <>
+void UnwindInfoAtom<arm>::addCompressedEncodingFixup(uint32_t offset, const ld::Atom* fde)
+{
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetSectionOffset, fde));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
+}
+
template <>
void UnwindInfoAtom<x86>::addRegularAddressFixup(uint32_t offset, const ld::Atom* func)
{
_fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
}
+template <>
+void UnwindInfoAtom<arm>::addRegularAddressFixup(uint32_t offset, const ld::Atom* func)
+{
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetImageOffset, func));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
+}
+
template <>
void UnwindInfoAtom<x86>::addRegularFDEOffsetFixup(uint32_t offset, const ld::Atom* fde)
{
_fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
}
+template <>
+void UnwindInfoAtom<arm>::addRegularFDEOffsetFixup(uint32_t offset, const ld::Atom* fde)
+{
+ _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k1of2, ld::Fixup::kindSetTargetSectionOffset, fde));
+ _fixups.push_back(ld::Fixup(offset+4, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndianLow24of32));
+}
+
template <>
void UnwindInfoAtom<x86>::addImageOffsetFixup(uint32_t offset, const ld::Atom* targ)
{
_fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
}
+template <>
+void UnwindInfoAtom<arm>::addImageOffsetFixup(uint32_t offset, const ld::Atom* targ)
+{
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of2, ld::Fixup::kindSetTargetImageOffset, targ));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of2, ld::Fixup::kindStoreLittleEndian32));
+}
+
template <>
void UnwindInfoAtom<x86>::addImageOffsetFixupPlusAddend(uint32_t offset, const ld::Atom* targ, uint32_t addend)
{
_fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndian32));
}
+template <>
+void UnwindInfoAtom<arm>::addImageOffsetFixupPlusAddend(uint32_t offset, const ld::Atom* targ, uint32_t addend)
+{
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k1of3, ld::Fixup::kindSetTargetImageOffset, targ));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, addend));
+ _fixups.push_back(ld::Fixup(offset, ld::Fixup::k3of3, ld::Fixup::kindStoreLittleEndian32));
+}
+
case CPU_TYPE_ARM64:
state.addAtom(*new UnwindInfoAtom<arm64>(entries, ehFrameSize));
break;
+#endif
+#if SUPPORT_ARCH_arm_any
+ case CPU_TYPE_ARM:
+ if ( opts.armUsesZeroCostExceptions() )
+ state.addAtom(*new UnwindInfoAtom<arm>(entries, ehFrameSize));
+ break;
#endif
default:
assert(0 && "no compact unwind for arch");
template <> ld::Fixup::Kind CompactUnwindAtom<arm64>::_s_pointerKind = ld::Fixup::kindStoreLittleEndian64;
template <> ld::Fixup::Kind CompactUnwindAtom<arm64>::_s_pointerStoreKind = ld::Fixup::kindStoreTargetAddressLittleEndian64;
#endif
+template <> ld::Fixup::Kind CompactUnwindAtom<arm>::_s_pointerKind = ld::Fixup::kindStoreLittleEndian32;
+template <> ld::Fixup::Kind CompactUnwindAtom<arm>::_s_pointerStoreKind = ld::Fixup::kindStoreTargetAddressLittleEndian32;
template <typename A>
CompactUnwindAtom<A>::CompactUnwindAtom(ld::Internal& state,const ld::Atom* funcAtom, uint32_t startOffset,
state.addAtom(*new CompactUnwindAtom<arm64>(state, atom, startOffset, endOffset-startOffset, cui));
break;
#endif
+ case CPU_TYPE_ARM:
+ state.addAtom(*new CompactUnwindAtom<arm>(state, atom, startOffset, endOffset-startOffset, cui));
+ break;
}
}
objOpts.keepDwarfUnwind = false;
objOpts.forceDwarfConversion = false;
objOpts.verboseOptimizationHints = true;
+ objOpts.armUsesZeroCostExceptions = true;
objOpts.subType = sPreferredSubArch;
#if 1
if ( ! foundFatSlice ) {
}
#endif
+template <>
+bool UnwindPrinter<arm>::validFile(const uint8_t* fileContent)
+{
+ const macho_header<P>* header = (const macho_header<P>*)fileContent;
+ if ( header->magic() != MH_MAGIC )
+ return false;
+ if ( header->cputype() != CPU_TYPE_ARM )
+ return false;
+ switch (header->filetype()) {
+ case MH_EXECUTE:
+ case MH_DYLIB:
+ case MH_BUNDLE:
+ case MH_DYLINKER:
+ case MH_OBJECT:
+ return true;
+ }
+ return false;
+}
+
template <typename A>
UnwindPrinter<A>::UnwindPrinter(const uint8_t* fileContent, uint32_t fileLength, const char* path, bool showFunctionNames)
: fHeader(NULL), fLength(fileLength), fUnwindSection(NULL),
}
#endif
+template <>
+void UnwindPrinter<arm>::decode(uint32_t encoding, const uint8_t* funcStart, char* str)
+{
+ *str = '\0';
+ switch ( encoding & UNWIND_ARM_MODE_MASK ) {
+ case UNWIND_ARM_MODE_DWARF:
+ sprintf(str, "dwarf offset 0x%08X, ", encoding & UNWIND_ARM_DWARF_SECTION_OFFSET);
+ break;
+ case UNWIND_ARM_MODE_FRAME:
+ case UNWIND_ARM_MODE_FRAME_D:
+ switch ( encoding & UNWIND_ARM_FRAME_STACK_ADJUST_MASK ) {
+ case 0x00000000:
+ strcpy(str, "std frame: ");
+ break;
+ case 0x00400000:
+ strcat(str, "std frame(sp adj 4): ");
+ break;
+ case 0x00800000:
+ strcat(str, "std frame(sp adj 8): ");
+ break;
+ case 0x00C00000:
+ strcat(str, "std frame(sp adj 12): ");
+ break;
+ }
+ if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R4 )
+ strcat(str, "r4 ");
+ if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R5 )
+ strcat(str, "r5 ");
+ if ( encoding & UNWIND_ARM_FRAME_FIRST_PUSH_R6 )
+ strcat(str, "r6 ");
+
+ if ( encoding & 0x000000F8)
+ strcat(str, " / ");
+ if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R8 )
+ strcat(str, "r8 ");
+ if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R9 )
+ strcat(str, "r9 ");
+ if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R10 )
+ strcat(str, "r10 ");
+ if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R11 )
+ strcat(str, "r11 ");
+ if ( encoding & UNWIND_ARM_FRAME_SECOND_PUSH_R12 )
+ strcat(str, "r12 ");
+
+ if ( (encoding & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_FRAME_D ) {
+ switch ( encoding & UNWIND_ARM_FRAME_D_REG_COUNT_MASK ) {
+ case 0x00000000:
+ strcat(str, " / d8 ");
+ break;
+ case 0x00000100:
+ strcat(str, " / d8,d10 ");
+ break;
+ case 0x00000200:
+ strcat(str, " / d8,d10,d12 ");
+ break;
+ case 0x00000300:
+ strcat(str, " / d8,d10,d12,d14 ");
+ break;
+ case 0x00000400:
+ strcat(str, " / d12,d14 / d8,d9,d10 ");
+ break;
+ case 0x00000500:
+ strcat(str, " / d14 / d8,d9,d10,d11,d12");
+ break;
+ case 0x00000600:
+ strcat(str, " / d8,d9,d10,d11,d12,d13,d14 ");
+ break;
+ case 0x00000700:
+ strcat(str, " / d8,d9,d10,d11,d12,d13,d14 ");
+ break;
+ default:
+ strcat(str, " / unknown D register usage ");
+ break;
+ }
+ }
+
+ break;
+ default:
+ if ( encoding == 0 )
+ strcpy(str, "no unwind information");
+ else
+ strcpy(str, "unsupported compact unwind");
+ break;
+ }
+}
template <>
}
#endif
+template <>
+const char* UnwindPrinter<arm>::personalityName(const macho_relocation_info<arm::P>* reloc)
+{
+ //assert(reloc->r_extern() && "reloc not extern on personality column in __compact_unwind section");
+ //assert((reloc->r_type() == GENERIC_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
+ const macho_nlist<P>& sym = fSymbols[reloc->r_symbolnum()];
+ return &fStrings[sym.n_strx()];
+}
template <typename A>
bool UnwindPrinter<A>::hasExernReloc(uint64_t sectionOffset, const char** personalityStr, pint_t* addr)
throw "in universal file, arm64 slice does not contain arm64 mach-o";
break;
#endif
+ case CPU_TYPE_ARM:
+ if ( UnwindPrinter<arm>::validFile(p + offset) )
+ UnwindPrinter<arm>::make(p + offset, size, path, showFunctionNames);
+ else
+ throw "in universal file, arm slice does not contain arm mach-o";
+ break;
default:
throwf("in universal file, unknown architecture slice 0x%x\n", cputype);
}
UnwindPrinter<arm64>::make(p, length, path, showFunctionNames);
}
#endif
+ else if ( UnwindPrinter<arm>::validFile(p) && onlyArchs.count(CPU_TYPE_ARM) ) {
+ UnwindPrinter<arm>::make(p, length, path, showFunctionNames);
+ }
else {
throw "not a known file type";
}
else if ( strcmp(arch, "arm64") == 0 )
onlyArchs.insert(CPU_TYPE_ARM64);
#endif
+ else if ( strcmp(arch, "armv7k") == 0 )
+ onlyArchs.insert(CPU_TYPE_ARM);
else
throwf("unknown architecture %s", arch);
}