X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/55e3d2f687f4ed9653982dbda92c6a055b0a8350..fb24a05017baddaa8cdc205852b134120bcc54ad:/src/ld/MachOReaderRelocatable.hpp diff --git a/src/ld/MachOReaderRelocatable.hpp b/src/ld/MachOReaderRelocatable.hpp index e576313..e6a182c 100644 --- a/src/ld/MachOReaderRelocatable.hpp +++ b/src/ld/MachOReaderRelocatable.hpp @@ -288,6 +288,7 @@ public: virtual uint32_t getOrdinal() const { return fOrdinal; } virtual void setOrdinal(uint32_t value) { fOrdinal = value; } virtual const void* getSectionRecord() const = 0; + virtual unsigned int getSectionIndex() const = 0; virtual bool isAlias() const { return false; } virtual uint8_t getLSDAReferenceKind() const { return 0; } virtual uint8_t getPersonalityReferenceKind() const { return 0; } @@ -397,21 +398,36 @@ public: else if ( rightAlias ) { return false; } - else { - // they must be tentative defintions - switch ( left->getDefinitionKind() ) { - case ObjectFile::Atom::kTentativeDefinition: - // sort tentative definitions by name - return ( strcmp(left->getName(), right->getName()) < 0 ); - case ObjectFile::Atom::kAbsoluteSymbol: - // sort absolute symbols with same address by name - return ( strcmp(left->getName(), right->getName()) < 0 ); - default: - // hack for rdar://problem/5102873 - if ( !left->isZeroFill() || !right->isZeroFill() ) - warning("atom sorting error for %s and %s in %s", left->getDisplayName(), right->getDisplayName(), left->getFile()->getPath()); - break; - } + // one might be a section start or end label + switch ( left->getContentType() ) { + case ObjectFile::Atom::kSectionStart: + return true; + case ObjectFile::Atom::kSectionEnd: + return false; + default: + break; + } + switch ( right->getContentType() ) { + case ObjectFile::Atom::kSectionStart: + return false; + case ObjectFile::Atom::kSectionEnd: + return true; + default: + break; + } + // they could be tentative defintions + switch ( left->getDefinitionKind() ) { + case ObjectFile::Atom::kTentativeDefinition: + // sort tentative definitions by name + return ( strcmp(left->getName(), right->getName()) < 0 ); + case ObjectFile::Atom::kAbsoluteSymbol: + // sort absolute symbols with same address by name + return ( strcmp(left->getName(), right->getName()) < 0 ); + default: + // hack for rdar://problem/5102873 + if ( !left->isZeroFill() || !right->isZeroFill() ) + warning("atom sorting error for %s and %s in %s", left->getDisplayName(), right->getDisplayName(), left->getFile()->getPath()); + break; } } return false; @@ -439,7 +455,7 @@ public: virtual ObjectFile::Atom::ContentType getContentType() const { return fType; } virtual SymbolTableInclusion getSymbolTableInclusion() const { return fSymbolTableInclusion; } virtual bool dontDeadStrip() const; - virtual bool isZeroFill() const { return ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL); } + virtual bool isZeroFill() const; virtual bool isThumb() const { return ((fSymbol->n_desc() & N_ARM_THUMB_DEF) != 0); } virtual uint64_t getSize() const { return fSize; } virtual std::vector& getReferences() const { return (std::vector&)(fReferences); } @@ -458,6 +474,7 @@ public: virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; } virtual uint64_t getObjectAddress() const { return fAddress; } virtual const void* getSectionRecord() const { return (const void*)fSection; } + virtual unsigned int getSectionIndex() const { return 1 + (fSection - fOwner.fSectionsStart); } virtual uint8_t getLSDAReferenceKind() const; virtual uint8_t getPersonalityReferenceKind() const; virtual uint32_t getCompactUnwindEncoding(uint64_t ehAtomAddress); @@ -590,6 +607,7 @@ SymbolAtom::SymbolAtom(Reader& owner, const macho_nlist

* symbol, const fAlignment.modulus = 0; } + template bool SymbolAtom::dontDeadStrip() const { @@ -643,6 +661,12 @@ ObjectFile::Atom& SymbolAtom::getFollowOnAtom() const return *((ObjectFile::Atom*)NULL); } +template +bool SymbolAtom::isZeroFill() const +{ + return ( ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL) && fOwner.fOptions.fOptimizeZeroFill ); +} + class Beyond { @@ -717,6 +741,7 @@ public: virtual const ObjectFile::ReaderOptions& getOptions() const { return fAliasOf.getOptions(); } virtual uint64_t getObjectAddress() const { return fAliasOf.getObjectAddress(); } virtual const void* getSectionRecord() const { return fAliasOf.getSectionRecord(); } + virtual unsigned int getSectionIndex() const { return fAliasOf.getSectionIndex(); } virtual bool isAlias() const { return true; } protected: @@ -778,7 +803,7 @@ public: virtual const char* getDisplayName() const { return getName(); } virtual ObjectFile::Atom::Scope getScope() const { return fScope; } virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ObjectFile::Atom::kTentativeDefinition; } - virtual bool isZeroFill() const { return true; } + virtual bool isZeroFill() const { return fOwner.fOptions.fOptimizeZeroFill; } virtual bool isThumb() const { return false; } virtual SymbolTableInclusion getSymbolTableInclusion() const { return ((fSymbol->n_desc() & REFERENCED_DYNAMICALLY) != 0) ? ObjectFile::Atom::kSymbolTableInAndNeverStrip : ObjectFile::Atom::kSymbolTableIn; } @@ -800,6 +825,7 @@ public: virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; } virtual uint64_t getObjectAddress() const { return ULLONG_MAX; } virtual const void* getSectionRecord() const { return NULL; } + virtual unsigned int getSectionIndex() const { return 0; } protected: typedef typename A::P P; @@ -916,6 +942,7 @@ public: virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; } virtual uint64_t getObjectAddress() const { return fAddress; } virtual const void* getSectionRecord() const { return (const void*)fSection; } + virtual unsigned int getSectionIndex() const { return fSectionIndex; } BaseAtom* redirectTo() { return fRedirect; } bool isWeakImportStub() { return fWeakImportStub; } void resolveName(); @@ -952,6 +979,7 @@ protected: ObjectFile::Atom::Scope fScope; ObjectFile::Atom::DefinitionKind fKind; ObjectFile::Atom::ContentType fType; + unsigned int fSectionIndex; }; template @@ -959,7 +987,7 @@ AnonymousAtom::AnonymousAtom(Reader& owner, const macho_section

* sectio : fOwner(owner), fSynthesizedName(NULL), fDisplayName(NULL), fSection(section), fAddress(addr), fSize(size), fSegment(NULL), fDontDeadStrip(true), fWeakImportStub(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn), fScope(ObjectFile::Atom::scopeTranslationUnit), fKind(ObjectFile::Atom::kRegularDefinition), - fType(ObjectFile::Atom::kUnclassifiedType) + fType(ObjectFile::Atom::kUnclassifiedType), fSectionIndex(1 + (section - owner.fSectionsStart)) { fSegment = new Segment(fSection); fRedirect = this; @@ -1030,6 +1058,33 @@ AnonymousAtom::AnonymousAtom(Reader& owner, const macho_section

* sectio if ( !fOwner.fOptions.fNoEHLabels ) fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn; } + else if ( section == owner.fUTF16Section ) { + if ( fOwner.fOptions.fForFinalLinkedImage ) { + fDontDeadStrip = false; + fScope = ObjectFile::Atom::scopeLinkageUnit; + fKind = ObjectFile::Atom::kWeakDefinition; + char* name = new char[16+5*size]; + strcpy(name, "utf16-string="); + char* s = &name[13]; + const uint16_t* words = (uint16_t*)((char*)(owner.fHeader) + section->offset() + addr - section->addr()); + unsigned int wordCount = size/2; + // note, the compiler sometimes puts trailing zeros on the end of the data + if ( E::get32(words[wordCount-1]) == 0 ) + --wordCount; + bool needSeperator = false; + for(unsigned int i=0; i < wordCount; ++i) { + if ( needSeperator ) + strcpy(s++, "."); + sprintf(s, "%04X", E::get32(words[i])); + s += 4; + needSeperator = true; + } + fSynthesizedName = name; + } + else { + asprintf((char**)&fSynthesizedName, "lutf16-0x%X", addr); + } + } break; case S_CSTRING_LITERALS: { @@ -1156,6 +1211,7 @@ AnonymousAtom::AnonymousAtom(Reader& owner, const macho_section

* sectio // add direct reference to target later, because its atom may not be constructed yet fOwner.fLocalNonLazys.push_back(this); fScope = ObjectFile::Atom::scopeTranslationUnit; + fType = ObjectFile::Atom::kNonLazyPointer; return; } else if ( (sym->n_value() < nonLazyPtrValue) && ((closestSym == NULL) || (sym->n_value() > closestSym->n_value())) ) { @@ -1175,21 +1231,26 @@ AnonymousAtom::AnonymousAtom(Reader& owner, const macho_section

* sectio } fScope = ObjectFile::Atom::scopeTranslationUnit; fOwner.fLocalNonLazys.push_back(this); + fType = ObjectFile::Atom::kNonLazyPointer; return; } const macho_nlist

* targetSymbol = &fOwner.fSymbols[symbolIndex]; const char* name = &fOwner.fStrings[targetSymbol->n_strx()]; char* str = new char[strlen(name)+16]; strcpy(str, name); - if ( type == S_LAZY_SYMBOL_POINTERS ) + if ( type == S_LAZY_SYMBOL_POINTERS ) { strcat(str, "$lazy_ptr"); - else + fType = ObjectFile::Atom::kLazyPointer; + } + else { strcat(str, "$non_lazy_ptr"); + fType = ObjectFile::Atom::kNonLazyPointer; + } fSynthesizedName = str; if ( type == S_NON_LAZY_SYMBOL_POINTERS ) fKind = ObjectFile::Atom::kWeakDefinition; - + if ( (targetSymbol->n_type() & N_EXT) == 0 ) { // target is translation unit scoped, so add direct reference to target //fOwner.makeReference(A::kPointer, addr, targetSymbol->n_value()); @@ -1204,7 +1265,7 @@ AnonymousAtom::AnonymousAtom(Reader& owner, const macho_section

* sectio } break; default: - throwf("section type %d not supported with address=0x%08X", type, addr); + throwf("section type %d not supported with address=0x%08llX", type, (uint64_t)addr); } //fprintf(stderr, "AnonymousAtom(%p) %s \n", this, this->getDisplayName()); } @@ -1267,6 +1328,9 @@ void AnonymousAtom::resolveName() if ( (superStr != NULL) && (strncmp(superStr, "cstring=", 8) == 0) ) { asprintf((char**)&fSynthesizedName, "cfstring=%s", &superStr[8]); } + else if ( (superStr != NULL) && (strncmp(superStr, "utf16-string=", 13) == 0) ) { + asprintf((char**)&fSynthesizedName, "cfstring-utf16=%s", &superStr[13]); + } else { // compiled with -fwritable-strings or a non-ASCII string fKind = ObjectFile::Atom::kRegularDefinition; // these are not coalescable @@ -1324,7 +1388,7 @@ ObjectFile::Atom::Scope AnonymousAtom::getScope() const template bool AnonymousAtom::isZeroFill() const { - return ( (fSection->flags() & SECTION_TYPE) == S_ZEROFILL ); + return ( ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL) && fOwner.fOptions.fOptimizeZeroFill ); } @@ -1434,6 +1498,7 @@ public: virtual uint64_t getObjectAddress() const { return fSymbol->n_value(); } virtual void setSectionOffset(uint64_t offset) { /* don't let fSectionOffset be altered*/ } virtual const void* getSectionRecord() const { return NULL; } + virtual unsigned int getSectionIndex() const { return 0; } protected: typedef typename A::P P; @@ -1472,6 +1537,110 @@ AbsoluteAtom::AbsoluteAtom(Reader& owner, const macho_nlist

* symbol) } +// +// An SectionBoundaryAtom represent the start or end of a section +// +template +class SectionBoundaryAtom : public BaseAtom +{ +public: + virtual ObjectFile::Reader* getFile() const { return &fOwner; } + virtual bool getTranslationUnitSource(const char** dir, const char** name) const + { return fOwner.getTranslationUnitSource(dir, name); } + virtual const char* getName() const { return fSymbolName; } + virtual const char* getDisplayName() const { return fDisplayName; } + virtual ObjectFile::Atom::Scope getScope() const { return ObjectFile::Atom::scopeLinkageUnit; } + virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ObjectFile::Atom::kWeakDefinition; } + virtual ObjectFile::Atom::ContentType getContentType() const { return fStart ? ObjectFile::Atom::kSectionStart : ObjectFile::Atom::kSectionEnd; } + virtual bool isZeroFill() const { return false; } + virtual bool isThumb() const { return false; } + virtual SymbolTableInclusion getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; } + virtual bool dontDeadStrip() const { return false; } + virtual uint64_t getSize() const { return 0; } + virtual std::vector& getReferences() const { return fgNoReferences; } + virtual bool mustRemainInSection() const { return true; } + virtual const char* getSectionName() const { return fSectionName; } + virtual ObjectFile::Segment& getSegment() const { return *fSegment; } + virtual ObjectFile::Atom& getFollowOnAtom() const { return *(ObjectFile::Atom*)NULL; } + virtual std::vector* getLineInfo() const { return NULL; } + virtual ObjectFile::Alignment getAlignment() const { return ObjectFile::Alignment(0); } + virtual void copyRawContent(uint8_t buffer[]) const { } + virtual void setScope(ObjectFile::Atom::Scope newScope) { } + virtual void setSize(uint64_t size) { } + virtual void addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; } + virtual void sortReferences() { } + virtual void addLineInfo(const ObjectFile::LineInfo& info) { throw "ld: can't add line info to tentative definition"; } + virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; } + virtual uint64_t getObjectAddress() const { return 0; } + virtual const void* getSectionRecord() const { return NULL; } + virtual unsigned int getSectionIndex() const { return 0; } + +protected: + typedef typename A::P P; + typedef typename A::P::E E; + typedef typename A::P::uint_t pint_t; + typedef typename A::ReferenceKinds Kinds; + friend class Reader; + + + class Segment : public ObjectFile::Segment + { + public: + Segment(const char* name, bool r, bool w, bool x): + fName(name), fReadable(r), fWritable(w), fExecutable(x) {} + + virtual const char* getName() const { return fName; } + virtual bool isContentReadable() const { return fReadable; } + virtual bool isContentWritable() const { return fWritable; } + virtual bool isContentExecutable() const { return fExecutable; } + private: + const char* fName; + bool fReadable; + bool fWritable; + bool fExecutable; + }; + + SectionBoundaryAtom(Reader&, bool start, const char* symbolName, const char* segSectName); + virtual ~SectionBoundaryAtom() {} + + Reader& fOwner; + class Segment* fSegment; + const char* fSymbolName; + const char* fSectionName; + const char* fDisplayName; + bool fStart; + static std::vector fgNoReferences; +}; + +template +std::vector SectionBoundaryAtom::fgNoReferences; + +// examples: +// section$start$__DATA$__my +// section$end$__DATA$__my +template +SectionBoundaryAtom::SectionBoundaryAtom(Reader& owner, bool start, const char* symbolName, const char* segSectName) + : fOwner(owner), fSymbolName(symbolName), fSectionName(NULL), fStart(start) +{ + const char* segSectDividor = strrchr(segSectName, '$'); + if ( segSectDividor == NULL ) + throwf("malformed section reference name: %s", symbolName); + fSectionName = segSectDividor + 1; + int segNameLen = segSectDividor - segSectName; + if ( segNameLen > 16 ) + throwf("malformed section reference name: %s", symbolName); + char segName[18]; + strlcpy(segName, segSectName, segNameLen+1); + if ( strcmp(segName, "__TEXT") == 0 ) + fSegment = new Segment("__TEXT", true, false, true); + else if ( strcmp(segName, "__DATA") == 0 ) + fSegment = new Segment("__DATA", true, true, false); + else + fSegment = new Segment(strdup(segName), true, true, false); + + asprintf((char**)&fDisplayName, "%s of section '%s' in segment '%s'", (start ? "start" : "end"), fSectionName, segName); +} + /// @@ -1664,6 +1833,7 @@ private: friend class AnonymousAtom; friend class TentativeAtom; friend class AbsoluteAtom; + friend class SectionBoundaryAtom; friend class SymbolAtom; typedef std::map AddrToAtomMap; @@ -1676,6 +1846,7 @@ private: static bool skip_form(const uint8_t ** offset, const uint8_t * end, uint64_t form, uint8_t addr_size, bool dwarf64); static const char* assureFullPath(const char* path); AtomAndOffset findAtomAndOffset(pint_t addr); + AtomAndOffset findAtomAndOffsetForSection(pint_t addr, unsigned int sectionIndex); AtomAndOffset findAtomAndOffset(pint_t baseAddr, pint_t realAddr); Reference* makeReference(Kinds kind, pint_t atAddr, pint_t toAddr); Reference* makeReference(Kinds kind, pint_t atAddr, pint_t fromAddr, pint_t toAddr); @@ -1717,6 +1888,7 @@ private: ObjectFile::Reader::DebugInfoKind fDebugInfo; bool fHasUUID; const macho_section

* fehFrameSection; + const macho_section

* fUTF16Section; std::set fLSDAAtoms; const macho_section

* fDwarfDebugInfoSect; const macho_section

* fDwarfDebugAbbrevSect; @@ -1744,7 +1916,7 @@ template Reader::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options, uint32_t ordinalBase) : fPath(strdup(path)), fModTime(modTime), fOrdinalBase(ordinalBase), fOptions(options), fHeader((const macho_header

*)fileContent), fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fSegment(NULL), fIndirectTable(NULL), - fDebugInfo(kDebugInfoNone), fHasUUID(false), fehFrameSection(NULL), + fDebugInfo(kDebugInfoNone), fHasUUID(false), fehFrameSection(NULL), fUTF16Section(NULL), fDwarfDebugInfoSect(NULL), fDwarfDebugAbbrevSect(NULL), fDwarfDebugLineSect(NULL), fDwarfTranslationUnitDir(NULL), fDwarfTranslationUnitFile(NULL), fAppleObjc(false), fHasDTraceProbes(false), fHaveIndirectSymbols(false), fReplacementClasses(false), fHasLongBranchStubs(false), @@ -1850,6 +2022,30 @@ Reader::Reader(const uint8_t* fileContent, const char* path, time_t modTime, } } } + else if ( (strcmp(sect->sectname(), "__ustring") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) ) { + // if there is a __ustring section parse it into AnonymousAtoms based on labels + fUTF16Section = sect; + std::vector utf16Addreses; + for (int i=fSymbolCount-1; i >= 0 ; --i) { + const macho_nlist

& sym = fSymbols[i]; + if ( (sym.n_type() & N_STAB) == 0 ) { + uint8_t type = (sym.n_type() & N_TYPE); + if ( type == N_SECT ) { + if ( &fSectionsStart[sym.n_sect()-1] == fUTF16Section ) { + utf16Addreses.push_back(sym.n_value()); + } + } + } + } + utf16Addreses.push_back(fUTF16Section->addr()+fUTF16Section->size()); + std::sort(utf16Addreses.begin(), utf16Addreses.end()); + for(int i=utf16Addreses.size()-2; i >=0 ; --i) { + pint_t size = utf16Addreses[i+1] - utf16Addreses[i]; + AnonymousAtom* strAtom = new AnonymousAtom(*this, fUTF16Section, utf16Addreses[i], size); + fAtoms.push_back(strAtom); + fAddrToAtom[utf16Addreses[i]] = strAtom; + } + } } @@ -1879,6 +2075,9 @@ Reader::Reader(const uint8_t* fileContent, const char* path, time_t modTime, else if ( section == fehFrameSection ) { // ignore labels in __eh_frame section } + else if ( section == fUTF16Section ) { + // ignore labels in __ustring section + } else { // ignore labels for atoms in other sections switch ( section->flags() & SECTION_TYPE ) { @@ -1947,6 +2146,13 @@ Reader::Reader(const uint8_t* fileContent, const char* path, time_t modTime, else if ( (type == N_UNDF) && (sym.n_value() != 0) ) { fAtoms.push_back(new TentativeAtom(*this, &sym)); } + else if ( (type == N_UNDF) && (sym.n_value() == 0) ) { + const char* symName = &fStrings[sym.n_strx()]; + if ( strncmp(symName, "section$start$", 14) == 0) + fAtoms.push_back(new SectionBoundaryAtom(*this, true, symName, &symName[14])); + else if ( strncmp(symName, "section$end$", 12) == 0) + fAtoms.push_back(new SectionBoundaryAtom(*this, false, symName, &symName[12])); + } else if ( type == N_ABS ) { const char* symName = &fStrings[sym.n_strx()]; if ( strncmp(symName, ".objc_class_name_", 17) == 0 ) { @@ -2089,8 +2295,9 @@ Reader::Reader(const uint8_t* fileContent, const char* path, time_t modTime, for(pint_t sectOffset=0; sectOffset < sect->size(); sectOffset += stringLen) { stringAddr = sect->addr() + sectOffset; stringLen = strlen((char*)(fHeader) + sect->offset() + sectOffset) + 1; - // add if not already an atom at that address - if ( fAddrToAtom.find(stringAddr) == fAddrToAtom.end() ) { + // add if not already a non-zero length atom at that address + typename AddrToAtomMap::iterator pos = fAddrToAtom.find(stringAddr); + if ( (pos == fAddrToAtom.end()) || (pos->second->getSize() == 0) ) { BaseAtom* newAtom = new AnonymousAtom(*this, sect, stringAddr, stringLen); if ( stringLen == 1 ) { // because of padding it may look like there are lots of empty strings, keep track of all @@ -3464,8 +3671,11 @@ Reference* Reader::makeReferenceToSymbol(Kinds kind, pint_t atAd // x86_64 uses external relocations everywhere, so external relocations do not imply by-name references // instead check scope of target const char* symbolName = &fStrings[toSymbol->n_strx()]; - if ( ((toSymbol->n_type() & N_TYPE) == N_SECT) && (((toSymbol->n_type() & N_EXT) == 0) || (symbolName[0] == 'L')) ) - return new Reference(kind, findAtomAndOffset(atAddr), findAtomAndOffset(toSymbol->n_value(), toSymbol->n_value()+toOffset)); + if ( ((toSymbol->n_type() & N_TYPE) == N_SECT) && (((toSymbol->n_type() & N_EXT) == 0) || (symbolName[0] == 'L')) ) { + AtomAndOffset targetAO = findAtomAndOffsetForSection(toSymbol->n_value(), toSymbol->n_sect()); + targetAO.offset = toOffset; + return new Reference(kind, findAtomAndOffset(atAddr), targetAO); + } else return new Reference(kind, findAtomAndOffset(atAddr), symbolName, toOffset); } @@ -3492,6 +3702,29 @@ BaseAtom* Reader::makeReferenceToEH(const char* ehName, pint_t ehAtomAdd return NULL; } +template +AtomAndOffset Reader::findAtomAndOffsetForSection(pint_t addr, unsigned int expectedSectionIndex) +{ + AtomAndOffset ao = findAtomAndOffset(addr); + if ( ao.atom != NULL ) { + if ( ((BaseAtom*)(ao.atom))->getSectionIndex() == expectedSectionIndex ) + return ao; + } + // The atom found is not in the section expected. + // This probably means there was a label at the end of the section. + // Do a slow sequential lookup + for (std::vector::iterator it=fAtoms.begin(); it != fAtoms.end(); ++it) { + BaseAtom* atom = *it; + if ( atom->getSectionIndex() == expectedSectionIndex ) { + pint_t objAddr = atom->getObjectAddress(); + if ( (objAddr == addr) || ((objAddr < addr) && (objAddr+atom->getSize() > addr)) ) { + return AtomAndOffset(atom, addr-atom->getObjectAddress()); + } + } + } + // no atom found that matched section, fall back to one orginally found + return ao; +} template AtomAndOffset Reader::findAtomAndOffset(pint_t addr) @@ -4123,7 +4356,7 @@ bool Reader::addRelocReference_powerpc(const macho_section* se makeByNameReference(A::kPointer, srcAddr, targetName, pointerValue); } else { - makeReference(A::kPointer, srcAddr, pointerValue); + new Reference(A::kPointer, findAtomAndOffset(srcAddr), findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum())); } } break; @@ -4411,9 +4644,8 @@ bool Reader::addRelocReference(const macho_section* sect, const mac makeByNameReference(kind, srcAddr, targetName, pointerValue); } else { - // if this is a branch to a stub, we need to see if the stub is for a weak imported symbol - ObjectFile::Atom* atom = findAtomAndOffset(pointerValue).atom; - const char* targetName = atom->getName(); + AtomAndOffset targetAO = findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum()); + const char* targetName = targetAO.atom->getName(); if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) { makeByNameReference(x86::kDtraceProbeSite, srcAddr, targetName, 0); addDtraceExtraInfos(srcAddr, &targetName[16]); @@ -4422,11 +4654,12 @@ bool Reader::addRelocReference(const macho_section* sect, const mac makeByNameReference(x86::kDtraceIsEnabledSite, srcAddr, targetName, 0); addDtraceExtraInfos(srcAddr, &targetName[20]); } - else if ( reloc->r_pcrel() && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn) - && ((AnonymousAtom*)atom)->isWeakImportStub() ) - makeReference(x86::kPCRel32WeakImport, srcAddr, pointerValue); + // if this is a reference to a stub, we need to see if the stub is for a weak imported symbol + else if ( reloc->r_pcrel() && (targetAO.atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn) + && ((AnonymousAtom*)targetAO.atom)->isWeakImportStub() ) + new Reference(x86::kPCRel32WeakImport, findAtomAndOffset(srcAddr), targetAO); else if ( reloc->r_symbolnum() != R_ABS ) - makeReference(kind, srcAddr, pointerValue); + new Reference(kind, findAtomAndOffset(srcAddr), targetAO); else { // find absolute symbol that corresponds to pointerValue AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(pointerValue); @@ -4986,7 +5219,7 @@ bool Reader::addRelocReference(const macho_section* sect, } else { AtomAndOffset at = findAtomAndOffset(srcAddr); - AtomAndOffset to = findAtomAndOffset(pointerValue); + AtomAndOffset to = findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum()); if ( to.atom->isThumb() ) to.offset &= -2; new Reference(kind, at, to); @@ -4994,7 +5227,7 @@ bool Reader::addRelocReference(const macho_section* sect, break; case ARM_THUMB_32BIT_BRANCH: - // work around for + // ignore old unnecessary relocs break; default: @@ -5598,6 +5831,16 @@ const char* Reference::getDescription() const fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset ); return temp; } + case arm::kPointerDiff12: + { + // by-name references have quoted names + const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : ""; + const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : ""; + sprintf(temp, "offset 0x%04X, 12-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)", + fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset, + fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset ); + return temp; + } case arm::kReadOnlyPointer: sprintf(temp, "offset 0x%04X, read-only pointer to ", fFixUpOffsetInSrc); break;