_swiftVersion(0),
_cpuSubType(0),
_minOSVersion(0),
- _platform(0),
+ _platform(Options::kPlatformUnknown),
_canScatterAtoms(false),
- _srcKind(kSourceUnknown) {}
+ _objcHasCategoryClassPropertiesField(false),
+ _srcKind(kSourceUnknown) { }
virtual ~File();
// overrides of ld::File
virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
{ return false; }
virtual uint32_t minOSVersion() const { return _minOSVersion; }
- virtual uint32_t platformLoadCommand() const { return _platform; }
+ virtual uint32_t platform() const { return _platform; }
// overrides of ld::relocatable::File
virtual ObjcConstraint objCConstraint() const { return _objConstraint; }
+ virtual bool objcHasCategoryClassPropertiesField() const
+ { return _objcHasCategoryClassPropertiesField; }
virtual uint32_t cpuSubType() const { return _cpuSubType; }
virtual DebugInfoKind debugInfo() const { return _debugInfoKind; }
virtual const std::vector<ld::relocatable::File::Stab>* stabs() const { return &_stabs; }
virtual bool canScatterAtoms() const { return _canScatterAtoms; }
virtual const char* translationUnitSource() const;
virtual LinkerOptionsList* linkerOptions() const { return &_linkerOptions; }
+ virtual const ToolVersionList& toolVersions() const { return _toolVersions; }
virtual uint8_t swiftVersion() const { return _swiftVersion; }
virtual ld::Bitcode* getBitcode() const { return _bitcode.get(); }
virtual SourceKind sourceKind() const { return _srcKind; }
- const uint8_t* fileContent() { return _fileContent; }
+ virtual const uint8_t* fileContent() const { return _fileContent; }
private:
friend class Atom<A>;
friend class Section<A>;
uint8_t _swiftVersion;
uint32_t _cpuSubType;
uint32_t _minOSVersion;
- uint32_t _platform;
+ Options::Platform _platform;
bool _canScatterAtoms;
+ bool _objcHasCategoryClassPropertiesField;
std::vector<std::vector<const char*> > _linkerOptions;
std::unique_ptr<ld::Bitcode> _bitcode;
SourceKind _srcKind;
+ ToolVersionList _toolVersions;
};
TLVDefsSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s) :
SymboledSection<A>(parser, f, s) { }
+ typedef typename A::P::uint_t pint_t;
+
+ virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
+
private:
};
typedef typename A::P::uint_t pint_t;
typedef typename A::P P;
+ virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&);
virtual ld::Atom::ContentType contentType() { return ld::Atom::typeTLVPointer; }
virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "tlv_lazy_ptr"; }
}
#endif
+
template <typename A>
void Atom<A>::verifyAlignment(const macho_section<P>&) const
{
TargetDesc& target);
uint32_t tentativeDefinitionCount() { return _tentativeDefinitionCount; }
uint32_t absoluteSymbolCount() { return _absoluteSymbolCount; }
-
+
+ uint32_t fileLength() const { return _fileLength; }
bool hasStubsSection() { return (_stubsSectionNum != 0); }
unsigned int stubsSectionNum() { return _stubsSectionNum; }
void addDtraceExtraInfos(const SourceLocation& src, const char* provider);
bool verboseOptimizationHints() { return _verboseOptimizationHints; }
bool neverConvertDwarf() { return _neverConvertDwarf; }
bool armUsesZeroCostExceptions() { return _armUsesZeroCostExceptions; }
+ uint8_t maxDefaultCommonAlignment() { return _maxDefaultCommonAlignment; }
+
macho_data_in_code_entry<P>* dataInCodeStart() { return _dataInCodeStart; }
macho_data_in_code_entry<P>* dataInCodeEnd() { return _dataInCodeEnd; }
bool _ignoreMismatchPlatform;
bool _treateBitcodeAsData;
bool _usingBitcode;
+ uint8_t _maxDefaultCommonAlignment;
unsigned int _stubsSectionNum;
const macho_section<P>* _stubsMachOSection;
std::vector<const char*> _dtraceProviderInfo;
}
#endif
+
template <typename A>
bool Parser<A>::hasObjC2Categories(const uint8_t* fileContent)
{
uint32_t symbolCount = symtab->nsyms();
const macho_nlist<P>* symbols = (const macho_nlist<P>*)(fileContent + symtab->symoff());
const char* strings = (char*)fileContent + symtab->stroff();
- for (uint32_t i = 0; i < symbolCount; ++i) {
+ for (uint32_t j = 0; j < symbolCount; ++j) {
// ignore stabs and count only ext symbols
- if ( (symbols[i].n_type() & N_STAB) == 0 &&
- (symbols[i].n_type() & N_EXT) != 0 ) {
- const char* symName = &strings[symbols[i].n_strx()];
+ if ( (symbols[j].n_type() & N_STAB) == 0 &&
+ (symbols[j].n_type() & N_EXT) != 0 ) {
+ const char* symName = &strings[symbols[j].n_strx()];
syms.push_back(symName);
}
}
#define STACK_ALLOC_IF_SMALL(_type, _name, _actual_count, _maxCount) \
_type* _name = NULL; \
uint32_t _name##_count = 1; \
- if ( _actual_count > _maxCount ) \
+ uint32_t _name##_stack_count = _actual_count; \
+ if ( _actual_count > _maxCount ) { \
_name = (_type*)malloc(sizeof(_type) * _actual_count); \
+ _name##_stack_count = 1; \
+ } \
else \
_name##_count = _actual_count; \
- _type _name##_buffer[_name##_count]; \
+ _type _name##_buffer[_name##_stack_count]; \
if ( _name == NULL ) \
_name = _name##_buffer;
printf("%s\n", _path);
_armUsesZeroCostExceptions = opts.armUsesZeroCostExceptions;
+ _maxDefaultCommonAlignment = opts.maxDefaultCommonAlignment;
// parse start of mach-o file
if ( ! parseLoadCommands(opts.platform, opts.minOSVersion, opts.simulator, opts.ignoreMismatchPlatform) )
// create lists of address that already have compact unwind and thus don't need the dwarf parsed
unsigned cuLsdaCount = 0;
- pint_t cuStarts[countOfCUs];
+ STACK_ALLOC_IF_SMALL(pint_t, cuStarts, countOfCUs, 1024);
for (uint32_t i=0; i < countOfCUs; ++i) {
if ( CUSection<A>::encodingMeansUseDwarf(cuInfoArray[i].compactUnwindInfo) )
cuStarts[i] = -1;
#endif
if ( ignoreMismatchPlatform )
break;
- _file->_platform = cmd->cmd();
lcPlatform = Options::platformForLoadCommand(cmd->cmd());
+ _file->_platform = lcPlatform;
_file->_minOSVersion = ((macho_version_min_command<P>*)cmd)->version();
break;
- default:
- if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
- if ( segment != NULL )
- throw "more than one LC_SEGMENT found in object file";
- segment = (macho_segment_command<P>*)cmd;
+ case LC_BUILD_VERSION:
+ {
+ const macho_build_version_command<P>* buildVersCmd = (macho_build_version_command<P>*)cmd;
+ if ( ignoreMismatchPlatform )
+ break;
+ lcPlatform = (Options::Platform)buildVersCmd->platform();
+ _file->_platform = lcPlatform;
+ _file->_minOSVersion = buildVersCmd->minos();
+ const macho_build_tool_version<P>* entry = (macho_build_tool_version<P>*)((uint8_t*)cmd + sizeof(macho_build_version_command<P>));
+ for (uint32_t t=0; t < buildVersCmd->ntools(); ++t) {
+ _file->_toolVersions.push_back(std::make_pair(entry->tool(), entry->version()));
+ ++entry;
+ }
}
break;
+ case macho_segment_command<P>::CMD:
+ if ( segment != NULL )
+ throw "more than one LC_SEGMENT found in object file";
+ segment = (macho_segment_command<P>*)cmd;
+ break;
+ default:
+ // ignore unknown load commands
+ break;
}
cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
if ( cmd > cmdsEnd )
if ( lcPlatform == Options::kPlatformUnknown )
break;
// fall through if the Platform is not Unknown
+ case Options::kPlatform_bridgeOS:
case Options::kPlatformWatchOS:
- // WatchOS errors on cross-linking all the time.
- throwf("building for %s%s, but linking in object file built for %s,",
+ // Error when using bitcocde, warning otherwise.
+ if (_usingBitcode)
+ throwf("building for %s%s, but linking in object file built for %s,",
Options::platformName(platform), (simulator ? " simulator" : ""),
Options::platformName(lcPlatform));
+ else
+ warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. "
+ "Note: This will be an error in the future.",
+ Options::platformName(platform), (simulator ? " simulator" : ""), path(),
+ Options::platformName(lcPlatform));
break;
#if SUPPORT_APPLE_TV
case Options::kPlatform_tvOS:
throw "missing LC_SEGMENT";
_sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
_machOSectionsCount = segment->nsects();
-
+ if ( (sizeof(macho_segment_command<P>) + _machOSectionsCount * sizeof(macho_section<P>)) > segment->cmdsize() )
+ throw "too many sections for size of LC_SEGMENT command";
return true;
}
return Options::kPlatformOSX;
case LC_VERSION_MIN_IPHONEOS:
return Options::kPlatformiOS;
+ case LC_VERSION_MIN_WATCHOS:
+ return Options::kPlatformWatchOS;
+ #if SUPPORT_APPLE_TV
+ case LC_VERSION_MIN_TVOS:
+ return Options::kPlatform_tvOS;
+ #endif
+ case LC_BUILD_VERSION:
+ return (Options::Platform)((macho_build_version_command<P>*)cmd)->platform();
}
cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
if ( cmd > cmdsEnd )
for (uint32_t i=0; i < _machOSectionsCount; ++i) {
const macho_section<P>* sect = &_sectionsStart[i];
+ uint8_t sectionType = (sect->flags() & SECTION_TYPE);
+ if ( (sect->offset() + sect->size() > _fileLength) && (sectionType != S_ZEROFILL) && (sectionType != S_THREAD_LOCAL_ZEROFILL) )
+ throwf("section %s/%s extends beyond end of file,", sect->segname(), sect->sectname());
+
if ( (sect->flags() & S_ATTR_DEBUG) != 0 ) {
if ( strcmp(sect->segname(), "__DWARF") == 0 ) {
// note that .o file has dwarf
// #define OBJC_IMAGE_SUPPORTS_GC 2
// #define OBJC_IMAGE_GC_ONLY 4
// #define OBJC_IMAGE_IS_SIMULATED 32
+ // #define OBJC_IMAGE_HAS_CATEGORY_CLASS_PROPERTIES 64
//
const uint32_t* contents = (uint32_t*)(_file->fileContent()+sect->offset());
if ( (sect->size() >= 8) && (contents[0] == 0) ) {
else
_file->_objConstraint = ld::File::objcConstraintRetainRelease;
_file->_swiftVersion = ((flags >> 8) & 0xFF);
+ _file->_objcHasCategoryClassPropertiesField = (flags & 64);
if ( sect->size() > 8 ) {
warning("section %s/%s has unexpectedly large size %llu in %s",
sect->segname(), Section<A>::makeSectionName(sect), sect->size(), _file->path());
alignP2 = 63 - (uint8_t)__builtin_clzll(size);
if ( size != (1ULL << alignP2) )
++alignP2;
+ // <rdar://problem/24871389> limit default alignment of large commons
+ if ( alignP2 > parser.maxDefaultCommonAlignment() )
+ alignP2 = parser.maxDefaultCommonAlignment();
}
- // limit alignment of extremely large commons to 2^15 bytes (8-page)
- if ( alignP2 > 15 )
- alignP2 = 15;
Atom<A>* allocatedSpace = (Atom<A>*)p;
new (allocatedSpace) Atom<A>(*this, parser.nameFromSymbol(sym), (pint_t)ULLONG_MAX, size,
ld::Atom::definitionTentative, ld::Atom::combineByName,
break;
case S_LAZY_SYMBOL_POINTERS:
case S_NON_LAZY_SYMBOL_POINTERS:
+ case S_THREAD_LOCAL_VARIABLE_POINTERS:
elementSize = sizeof(pint_t);
break;
default:
- throw "section does not use inirect symbol table";
+ throw "section does not use indirect symbol table";
}
uint32_t indexInSection = (addr - sect->addr()) / elementSize;
uint32_t indexIntoIndirectTable = sect->reserved1() + indexInSection;
const uint8_t * debug_info;
const uint8_t * debug_abbrev;
const uint8_t * di;
+ const uint8_t * next_cu;
const uint8_t * da;
const uint8_t * end;
const uint8_t * enda;
if ( (_file->_dwarfDebugInfoSect == NULL) || (_file->_dwarfDebugAbbrevSect == NULL) )
return false;
- debug_info = (uint8_t*)_file->fileContent() + _file->_dwarfDebugInfoSect->offset();
- debug_abbrev = (uint8_t*)_file->fileContent() + _file->_dwarfDebugAbbrevSect->offset();
- di = debug_info;
-
if (_file->_dwarfDebugInfoSect->size() < 12)
- /* Too small to be a real debug_info section. */
- return false;
- sz = A::P::E::get32(*(uint32_t*)di);
- di += 4;
- dwarf64 = sz == 0xffffffff;
- if (dwarf64)
- sz = A::P::E::get64(*(uint64_t*)di), di += 8;
- else if (sz > 0xffffff00)
- /* Unknown dwarf format. */
- return false;
-
- /* Verify claimed size. */
- if (sz + (di - debug_info) > _file->_dwarfDebugInfoSect->size() || sz <= (dwarf64 ? 23 : 11))
- return false;
-
- vers = A::P::E::get16(*(uint16_t*)di);
- if (vers < 2 || vers > 4)
- /* DWARF version wrong for this code.
- Chances are we could continue anyway, but we don't know for sure. */
+ /* Too small to be a real debug_info section. */
return false;
- di += 2;
-
- /* Find the debug_abbrev section. */
- abbrev_base = dwarf64 ? A::P::E::get64(*(uint64_t*)di) : A::P::E::get32(*(uint32_t*)di);
- di += dwarf64 ? 8 : 4;
-
- if (abbrev_base > _file->_dwarfDebugAbbrevSect->size())
- return false;
- da = debug_abbrev + abbrev_base;
- enda = debug_abbrev + _file->_dwarfDebugAbbrevSect->size();
-
- address_size = *di++;
-
- /* Find the abbrev number we're looking for. */
- end = di + sz;
- abbrev = read_uleb128 (&di, end);
- if (abbrev == (uint64_t) -1)
- return false;
-
- /* Skip through the debug_abbrev section looking for that abbrev. */
- for (;;)
- {
- uint64_t this_abbrev = read_uleb128 (&da, enda);
- uint64_t attr;
-
- if (this_abbrev == abbrev)
- /* This is almost always taken. */
- break;
- skip_leb128 (&da, enda); /* Skip the tag. */
- if (da == enda)
- return false;
- da++; /* Skip the DW_CHILDREN_* value. */
-
- do {
- attr = read_uleb128 (&da, enda);
- skip_leb128 (&da, enda);
- } while (attr != 0 && attr != (uint64_t) -1);
- if (attr != 0)
- return false;
- }
-
- /* Check that the abbrev is one for a DW_TAG_compile_unit. */
- if (read_uleb128 (&da, enda) != DW_TAG_compile_unit)
- return false;
- if (da == enda)
- return false;
- da++; /* Skip the DW_CHILDREN_* value. */
-
- /* Now, go through the DIE looking for DW_AT_name,
- DW_AT_comp_dir, and DW_AT_stmt_list. */
- for (;;)
- {
- uint64_t attr = read_uleb128 (&da, enda);
- uint64_t form = read_uleb128 (&da, enda);
-
- if (attr == (uint64_t) -1)
- return false;
- else if (attr == 0)
- return true;
- if (form == DW_FORM_indirect)
- form = read_uleb128 (&di, end);
- switch (attr) {
- case DW_AT_name:
- *name = getDwarfString(form, di);
- break;
- case DW_AT_comp_dir:
- *comp_dir = getDwarfString(form, di);
- break;
- case DW_AT_stmt_list:
- *stmt_list = getDwarfOffset(form, di, dwarf64);
- break;
- default:
- if (! skip_form (&di, end, form, address_size, dwarf64))
- return false;
- }
- }
+ debug_info = (uint8_t*)_file->fileContent() + _file->_dwarfDebugInfoSect->offset();
+ debug_abbrev = (uint8_t*)_file->fileContent() + _file->_dwarfDebugAbbrevSect->offset();
+ next_cu = debug_info;
+
+ while ((uint64_t)(next_cu - debug_info) < _file->_dwarfDebugInfoSect->size()) {
+ di = next_cu;
+ sz = A::P::E::get32(*(uint32_t*)di);
+ di += 4;
+ dwarf64 = sz == 0xffffffff;
+ if (dwarf64)
+ sz = A::P::E::get64(*(uint64_t*)di), di += 8;
+ else if (sz > 0xffffff00)
+ /* Unknown dwarf format. */
+ return false;
+
+ /* Verify claimed size. */
+ if (sz + (di - debug_info) > _file->_dwarfDebugInfoSect->size() || sz <= (dwarf64 ? 23 : 11))
+ return false;
+
+ next_cu = di + sz;
+
+ vers = A::P::E::get16(*(uint16_t*)di);
+ if (vers < 2 || vers > 4)
+ /* DWARF version wrong for this code.
+ Chances are we could continue anyway, but we don't know for sure. */
+ return false;
+ di += 2;
+
+ /* Find the debug_abbrev section. */
+ abbrev_base = dwarf64 ? A::P::E::get64(*(uint64_t*)di) : A::P::E::get32(*(uint32_t*)di);
+ di += dwarf64 ? 8 : 4;
+
+ if (abbrev_base > _file->_dwarfDebugAbbrevSect->size())
+ return false;
+ da = debug_abbrev + abbrev_base;
+ enda = debug_abbrev + _file->_dwarfDebugAbbrevSect->size();
+
+ address_size = *di++;
+
+ /* Find the abbrev number we're looking for. */
+ end = di + sz;
+ abbrev = read_uleb128 (&di, end);
+ if (abbrev == (uint64_t) -1)
+ return false;
+
+ /* Skip through the debug_abbrev section looking for that abbrev. */
+ for (;;)
+ {
+ uint64_t this_abbrev = read_uleb128 (&da, enda);
+ uint64_t attr;
+
+ if (this_abbrev == abbrev)
+ /* This is almost always taken. */
+ break;
+ skip_leb128 (&da, enda); /* Skip the tag. */
+ if (da == enda)
+ return false;
+ da++; /* Skip the DW_CHILDREN_* value. */
+
+ do {
+ attr = read_uleb128 (&da, enda);
+ skip_leb128 (&da, enda);
+ } while (attr != 0 && attr != (uint64_t) -1);
+ if (attr != 0)
+ return false;
+ }
+
+ /* Check that the abbrev is one for a DW_TAG_compile_unit. */
+ if (read_uleb128 (&da, enda) != DW_TAG_compile_unit)
+ return false;
+ if (da == enda)
+ return false;
+ da++; /* Skip the DW_CHILDREN_* value. */
+
+ /* Now, go through the DIE looking for DW_AT_name,
+ DW_AT_comp_dir, and DW_AT_stmt_list. */
+ bool skip_to_next_cu = false;
+ while (!skip_to_next_cu) {
+
+ uint64_t attr = read_uleb128 (&da, enda);
+ uint64_t form = read_uleb128 (&da, enda);
+
+ if (attr == (uint64_t) -1)
+ return false;
+ else if (attr == 0)
+ return true;
+ if (form == DW_FORM_indirect)
+ form = read_uleb128 (&di, end);
+
+ switch (attr) {
+ case DW_AT_name:
+ *name = getDwarfString(form, di);
+ /* Swift object files may contain two CUs: One
+ describes the Swift code, one is created by the
+ clang importer. Skip over the CU created by the
+ clang importer as it may be empty. */
+ if (std::string(*name) == "<swift-imported-modules>")
+ skip_to_next_cu = true;
+ break;
+ case DW_AT_comp_dir:
+ *comp_dir = getDwarfString(form, di);
+ break;
+ case DW_AT_stmt_list:
+ *stmt_list = getDwarfOffset(form, di, dwarf64);
+ break;
+ default:
+ if (! skip_form (&di, end, form, address_size, dwarf64))
+ return false;
+ }
+ }
+ }
+ return false;
}
return true;
}
+
template <typename A>
bool CFISection<A>::needsRelocating()
{
libunwind::CFI_Atom_Info<CFISection<x86_64>::OAS>::CFI_Atom_Info cfiArray[],
uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
{
+ const uint32_t sectionSize = this->_machOSection->size();
// copy __eh_frame data to buffer
- memcpy(buffer, file().fileContent() + this->_machOSection->offset(), this->_machOSection->size());
+ memcpy(buffer, file().fileContent() + this->_machOSection->offset(), sectionSize);
// and apply relocations
const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + this->_machOSection->reloff());
fprintf(stderr, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc->r_address());
break;
}
+ if ( reloc->r_address() > sectionSize )
+ throwf("malformed __eh_frame relocation, offset (0x%08X) is beyond end of section,", reloc->r_address());
uint64_t* p64;
uint32_t* p32;
switch ( reloc->r_length() ) {
uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
{
// copy __eh_frame data to buffer
- memcpy(buffer, file().fileContent() + this->_machOSection->offset(), this->_machOSection->size());
+ const uint32_t sectionSize = this->_machOSection->size();
+ memcpy(buffer, file().fileContent() + this->_machOSection->offset(), sectionSize);
// and apply relocations
const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + this->_machOSection->reloff());
fprintf(stderr, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc->r_address());
break;
}
+ if ( reloc->r_address() > sectionSize )
+ throwf("malformed __eh_frame relocation, offset (0x%08X) is beyond end of section,", reloc->r_address());
switch ( reloc->r_length() ) {
case 3:
E::set64(*p64, value + addend64);
template <> bool CFISection<arm>::bigEndian() { return false; }
template <> bool CFISection<arm64>::bigEndian() { return false; }
-
template <>
void CFISection<x86_64>::addCiePersonalityFixups(class Parser<x86_64>& parser, const CFI_Atom_Info* cieInfo)
{
}
#endif
+
template <>
void CFISection<arm>::addCiePersonalityFixups(class Parser<arm>& 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)
}
#endif
+
template <typename A>
int CUSection<A>::infoSorter(const void* l, const void* r)
{
}
// scan relocs, extern relocs are needed for personality references (possibly for function/lsda refs??)
+ const uint32_t sectionSize = this->_machOSection->size();
const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(this->file().fileContent() + this->_machOSection->reloff());
const macho_relocation_info<P>* relocsEnd = &relocs[this->_machOSection->nreloc()];
for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
+ if ( reloc->r_address() & R_SCATTERED )
+ continue;
+ if ( reloc->r_address() > sectionSize )
+ throwf("malformed __compact_unwind relocation, offset (0x%08X) is beyond end of section,", reloc->r_address());
if ( reloc->r_extern() ) {
// only expect external relocs on some colummns
if ( (reloc->r_address() % sizeof(macho_compact_unwind_entry<P>)) == macho_compact_unwind_entry<P>::personalityFieldOffset() ) {
return ld::Atom::symbolTableInWithRandomAutoStripLabel;
}
+
template <typename A>
ld::Atom::SymbolTableInclusion ImplicitSizeSection<A>::symbolTableInclusion()
{
return ld::Atom::combineByNameAndReferences;
}
+template <>
+void TLVPointerSection<arm>::makeFixups(class Parser<arm>& parser, const struct Parser<arm>::CFI_CU_InfoArrays&)
+{
+ // add references for each thread local pointer atom based on indirect symbol table
+ const macho_section<P>* sect = this->machoSection();
+ const pint_t endAddr = sect->addr() + sect->size();
+ for (pint_t addr = sect->addr(); addr < endAddr; addr += sizeof(pint_t)) {
+ typename Parser<arm>::SourceLocation src;
+ typename Parser<arm>::TargetDesc target;
+ src.atom = this->findAtomByAddress(addr);
+ src.offsetInAtom = 0;
+ uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(addr, sect);
+ target.atom = NULL;
+ target.name = NULL;
+ target.weakImport = false;
+ target.addend = 0;
+ if ( symIndex == INDIRECT_SYMBOL_LOCAL ) {
+ throwf("unexpected INDIRECT_SYMBOL_LOCAL in section %s", this->sectionName());
+ }
+ else {
+ const macho_nlist<P>& sym = parser.symbolFromIndex(symIndex);
+ // use direct reference for local symbols
+ if ( ((sym.n_type() & N_TYPE) == N_SECT) && ((sym.n_type() & N_EXT) == 0) ) {
+ throwf("unexpected pointer to local symbol in section %s", this->sectionName());
+ }
+ else {
+ target.name = parser.nameFromSymbol(sym);
+ target.weakImport = parser.weakImportFromSymbol(sym);
+ assert(src.atom->combine() == ld::Atom::combineByNameAndReferences);
+ }
+ }
+ parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
+ }
+}
+
+template <typename A>
+void TLVPointerSection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&)
+{
+ assert(0 && "should not have thread-local-pointer sections in .o files");
+}
+
template <typename A>
const char* TLVPointerSection<A>::targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind, bool* isStatic)
bool Section<x86_64>::addRelocFixup(class Parser<x86_64>& parser, const macho_relocation_info<P>* reloc)
{
const macho_section<P>* sect = this->machoSection();
+ if ( sect == NULL ) {
+ warning("malformed mach-o, relocations not supported on section %s", this->sectionName());
+ return false;
+ }
uint64_t srcAddr = sect->addr() + reloc->r_address();
Parser<x86_64>::SourceLocation src;
Parser<x86_64>::TargetDesc target;
}
else {
parser.findTargetFromAddressAndSectionNum(contentValue, nextReloc->r_symbolnum(), toTarget);
- useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit);
+ useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit) || ((toTarget.atom->combine() == ld::Atom::combineByNameAndContent) || (toTarget.atom->combine() == ld::Atom::combineByNameAndReferences));
+ }
+ if ( useDirectBinding ) {
+ if ( (toTarget.atom->combine() == ld::Atom::combineByNameAndContent) || (toTarget.atom->combine() == ld::Atom::combineByNameAndReferences) )
+ parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, toTarget.atom);
+ else
+ parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom);
}
- if ( useDirectBinding )
- parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom);
else
parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.weakImport, toTarget.name);
parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindAddAddend, toTarget.addend);
}
#endif
+
template <typename A>
bool ObjC1ClassSection<A>::addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
{
}
#endif
+
template <typename A>
void Section<A>::addLOH(class Parser<A>& parser, int kind, int count, const uint64_t addrs[]) {
void Section<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&)
{
const macho_section<P>* sect = this->machoSection();
+ if ( sect->reloff() + (sect->nreloc() * sizeof(macho_relocation_info<P>)) > parser.fileLength() )
+ throwf("relocations for section %s/%s extends beyond end of file,", sect->segname(), Section<A>::makeSectionName(sect) );
const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + sect->reloff());
const uint32_t relocCount = sect->nreloc();
for (uint32_t r = 0; r < relocCount; ++r) {
Atom<A>* end = &_endAtoms[-1];
for(Atom<A>* p = _beginAtoms; p < end; ++p) {
Atom<A>* nextAtom = &p[1];
- if ( _altEntries.count(nextAtom) != 0 ) {
+ // <rdar://problem/22960070> support alt_entry aliases (alias process already added followOn, don't repeat)
+ if ( (_altEntries.count(nextAtom) != 0) && (p->_objAddress != nextAtom->_objAddress) ) {
typename Parser<A>::SourceLocation src(p, 0);
parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, nextAtom);
typename Parser<A>::SourceLocation src2(nextAtom, 0);
if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
*result = CPU_TYPE_ARM64;
- *subResult = CPU_SUBTYPE_ARM64_ALL;
+ *subResult = header->cpusubtype();
*platform = Parser<arm64>::findPlatform(header);
return true;
}