1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
26 namespace ObjectFileMachO
{
28 class Reference
: public ObjectFile::Reference
31 Reference(macho_uintptr_t fixUpOffset
, Kind kind
, const char* targetName
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
);
32 Reference(macho_uintptr_t fixUpOffset
, Kind kind
, class Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
);
33 Reference(macho_uintptr_t fixUpOffset
, Kind kind
, class Atom
& target
, uint64_t offsetInTarget
, class Atom
& fromTarget
, uint64_t offsetInFromTarget
);
37 virtual bool isTargetUnbound() const;
38 virtual bool isFromTargetUnbound() const;
39 virtual bool isWeakReference() const;
40 virtual bool requiresRuntimeFixUp(bool slideable
) const;
41 virtual bool isLazyReference() const;
42 virtual Kind
getKind() const;
43 virtual uint64_t getFixUpOffset() const;
44 virtual const char* getTargetName() const;
45 virtual ObjectFile::Atom
& getTarget() const;
46 virtual uint64_t getTargetOffset() const;
47 virtual bool hasFromTarget() const;
48 virtual ObjectFile::Atom
& getFromTarget() const;
49 virtual const char* getFromTargetName() const;
50 virtual void setTarget(ObjectFile::Atom
&, uint64_t offset
);
51 virtual void setFromTarget(ObjectFile::Atom
&);
52 virtual void setFromTargetName(const char*);
53 virtual void setFromTargetOffset(uint64_t);
54 virtual const char* getDescription() const;
55 virtual uint64_t getFromTargetOffset() const;
60 ObjectFile::Atom
* fTarget
;
61 ObjectFile::Atom
* fFromTarget
;
62 const char* fTargetName
;
63 const char* fFromTargetName
;
64 macho_uintptr_t fTargetOffset
;
65 macho_uintptr_t fFromTargetOffset
;
66 macho_uintptr_t fFixUpOffsetInSrc
;
74 class Reader
: public ObjectFile::Reader
77 Reader(const char* path
);
78 Reader(const macho_header
* header
, const char* path
, const ObjectFile::ReaderOptions
& options
);
81 virtual const char* getPath();
82 virtual std::vector
<class ObjectFile::Atom
*>& getAtoms();
83 virtual std::vector
<class ObjectFile::Atom
*>* getJustInTimeAtomsFor(const char* name
);
84 virtual std::vector
<ObjectFile::StabsInfo
>* getStabsDebugInfo(); // stabs info not associated with an atom
89 void init(const macho_header
* header
, const char* path
);
90 void buildOffsetsSet(const macho_relocation_info
* reloc
, const macho_section
* sect
, std::set
<uint32_t>& offsets
, std::set
<uint32_t>& dontUse
);
91 void addRelocReference(const macho_section
* sect
, const macho_relocation_info
* reloc
);
92 Atom
* findAtomCoveringOffset(uint32_t offset
);
93 uint32_t findAtomIndex(const Atom
& atom
);
94 void addFixUp(uint32_t srcAddr
, uint32_t dstAddr
, Reference::Kind kind
, uint32_t picBaseAddr
);
95 class Segment
* makeSegmentFromSection(const macho_section
*);
96 macho_uintptr_t
commonsOffset();
97 void insertOffsetIfText(std::set
<uint32_t>& offsets
, uint32_t value
);
98 void insertOffsetIfNotText(std::set
<uint32_t>& offsets
, uint32_t value
);
99 const macho_section
* findSectionCoveringOffset(uint32_t offset
);
100 void addCallSiteReference(Atom
& src
, uint32_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint32_t picBaseOffset
, uint32_t offsetInTargetAtom
);
101 void deadStub(Atom
& target
);
104 const ObjectFile::ReaderOptions
& fOptions
;
105 const macho_header
* fHeader
;
106 const char* fStrings
;
107 const macho_nlist
* fSymbols
;
108 uint32_t fSymbolCount
;
109 const macho_segment_command
* fSegment
;
110 const uint32_t* fIndirectTable
;
111 std::vector
<class Atom
*> fAtoms
;
112 std::vector
<class Segment
*> fSegments
;
113 std::set
<class ObjectFile::Atom
*> fDeadAtoms
;
114 uint32_t fNonAtomStabsStartIndex
;
115 uint32_t fNonAtomStabsCount
;
116 std::vector
<uint32_t> fNonAtomExtras
;
119 class Segment
: public ObjectFile::Segment
122 virtual const char* getName() const;
123 virtual bool isContentReadable() const;
124 virtual bool isContentWritable() const;
125 virtual bool isContentExecutable() const;
127 Segment(const macho_section
*);
130 const macho_section
* fSection
;
133 class Atom
: public ObjectFile::Atom
136 virtual ObjectFile::Reader
* getFile() const;
137 virtual const char* getName() const;
138 virtual const char* getDisplayName() const;
139 virtual Scope
getScope() const;
140 virtual bool isTentativeDefinition() const;
141 virtual bool isWeakDefinition() const;
142 virtual bool isCoalesableByName() const;
143 virtual bool isCoalesableByValue() const;
144 virtual bool isZeroFill() const;
145 virtual bool dontDeadStrip() const;
146 virtual bool dontStripName() const; // referenced dynamically
147 virtual bool isImportProxy() const;
148 virtual uint64_t getSize() const;
149 virtual std::vector
<ObjectFile::Reference
*>& getReferences() const;
150 virtual bool mustRemainInSection() const;
151 virtual const char* getSectionName() const;
152 virtual Segment
& getSegment() const;
153 virtual bool requiresFollowOnAtom() const;
154 virtual ObjectFile::Atom
& getFollowOnAtom() const;
155 virtual std::vector
<ObjectFile::StabsInfo
>* getStabsDebugInfo() const;
156 virtual uint8_t getAlignment() const;
157 virtual WeakImportSetting
getImportWeakness() const { return ObjectFile::Atom::kWeakUnset
; }
158 virtual void copyRawContent(uint8_t buffer
[]) const;
159 virtual void writeContent(bool finalLinkedImage
, ObjectFile::ContentWriter
&) const;
160 virtual void setScope(Scope
);
161 virtual void setImportWeakness(bool weakImport
) { }
167 Atom(Reader
&, const macho_nlist
*);
168 Atom(Reader
&, uint32_t offset
);
171 const macho_section
* findSectionFromOffset(uint32_t offset
);
172 const macho_section
* getCommonsSection();
173 void setSize(macho_uintptr_t
);
174 void setFollowOnAtom(Atom
&);
175 static bool atomCompare(const Atom
* lhs
, const Atom
* rhs
);
176 Reference
* addDirectReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
);
177 Reference
* addByNameReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, const char* targetName
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
);
178 Reference
* addDifferenceReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, Atom
& fromTarget
, uint64_t offsetInFromTarget
);
179 Reference
* addReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
);
182 const macho_nlist
* fSymbol
;
183 macho_uintptr_t fOffset
;
184 macho_uintptr_t fSize
;
185 const macho_section
* fSection
;
187 const char* fSynthesizedName
;
188 std::vector
<class Reference
*> fReferences
;
189 ObjectFile::Atom::Scope fScope
;
190 uint32_t fStabsStartIndex
;
191 uint32_t fStabsCount
;
193 static macho_section fgCommonsSection
; // for us by tentative definitions
197 Reader
* MakeReader(const macho_header
* mh
, const char* path
, const ObjectFile::ReaderOptions
& options
)
199 return new Reader(mh
, path
, options
);
203 Reader::Reader(const macho_header
* header
, const char* path
, const ObjectFile::ReaderOptions
& options
)
204 : fPath(NULL
), fOptions(options
), fHeader(NULL
), fStrings(NULL
), fSymbols(NULL
), fSymbolCount(0), fSegment(NULL
)
209 Reader::Reader(const char* path
)
210 : fPath(NULL
), fOptions(*(new ObjectFile::ReaderOptions())), fHeader(NULL
), fStrings(NULL
), fSymbols(NULL
), fSymbolCount(0), fSegment(NULL
),
211 fIndirectTable(NULL
), fNonAtomStabsStartIndex(0), fNonAtomStabsCount(0)
213 struct stat stat_buf
;
215 int fd
= ::open(path
, O_RDONLY
, 0);
216 ::fstat(fd
, &stat_buf
);
217 void* p
= ::mmap(NULL
, stat_buf
.st_size
, PROT_READ
, MAP_FILE
, fd
, 0);
219 if ( ((macho_header
*)p
)->magic() == MH_MAGIC
) {
220 init((macho_header
*)p
, path
);
223 throw "add fat handling";
232 bool Atom::atomCompare(const Atom
* lhs
, const Atom
* rhs
)
234 return lhs
->fOffset
< rhs
->fOffset
;
239 void Reader::init(const macho_header
* header
, const char* path
)
242 #if defined(ARCH_PPC)
243 if ( (header
->magic() != MH_MAGIC
) || (header
->cputype() != CPU_TYPE_POWERPC
) )
244 throw "not a valid ppc mach-o file";
245 #elif defined(ARCH_I386)
246 if ( (header
->magic() != MH_MAGIC
) || (header
->cputype() != CPU_TYPE_I386
) )
247 throw "not a valid i386 mach-o file";
248 #elif defined(ARCH_PPC64)
249 if ( (header
->magic() != MH_MAGIC_64
) || (header
->cputype() != CPU_TYPE_POWERPC64
) )
250 throw "not a valid ppc64 mach-o file";
253 // cache intersting pointers
254 fPath
= strdup(path
);
256 const uint32_t cmd_count
= header
->ncmds();
257 const macho_load_command
* const cmds
= (macho_load_command
*)((char*)header
+ macho_header::size
);
258 const macho_load_command
* cmd
= cmds
;
259 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
260 switch (cmd
->cmd()) {
263 const macho_symtab_command
* symtab
= (macho_symtab_command
*)cmd
;
264 fSymbolCount
= symtab
->nsyms();
265 fSymbols
= (const macho_nlist
*)((char*)header
+ symtab
->symoff());
266 fStrings
= (char*)header
+ symtab
->stroff();
271 const macho_dysymtab_command
* dsymtab
= (struct macho_dysymtab_command
*)cmd
;
272 fIndirectTable
= (uint32_t*)((char*)fHeader
+ dsymtab
->indirectsymoff());
276 if ( cmd
->cmd() == macho_segment_command::command
) {
277 fSegment
= (macho_segment_command
*)cmd
;
281 cmd
= (const macho_load_command
*)(((char*)cmd
)+cmd
->cmdsize());
284 // add all atoms that have entries in symbol table
285 std::set
<uint32_t> symbolAtomOffsets
;
286 for (uint32_t i
=0; i
< fSymbolCount
; ++i
) {
287 const macho_nlist
& sym
= fSymbols
[i
];
288 if ( (sym
.n_type() & N_STAB
) == 0 ) {
289 uint8_t type
= (sym
.n_type() & N_TYPE
);
290 if ( (type
== N_SECT
) || ((type
== N_UNDF
) && (sym
.n_value() != 0)) ) {
291 // real definition or "tentative definition"
292 Atom
* newAtom
= new Atom(*this, &sym
);
293 fAtoms
.push_back(newAtom
);
294 symbolAtomOffsets
.insert(newAtom
->fOffset
);
299 // add all points referenced in relocations
300 const macho_section
* const sectionsStart
= (macho_section
*)((char*)fSegment
+ sizeof(macho_segment_command
));
301 const macho_section
* const sectionsEnd
= §ionsStart
[fSegment
->nsects()];
302 std::set
<uint32_t> cleavePoints
;
303 std::set
<uint32_t> dontCleavePoints
;
304 for (const macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
305 const macho_relocation_info
* relocs
= (macho_relocation_info
*)((char*)(fHeader
) + sect
->reloff());
306 const uint32_t relocCount
= sect
->nreloc();
307 for (uint32_t r
= 0; r
< relocCount
; ++r
) {
308 buildOffsetsSet(&relocs
[r
], sect
, cleavePoints
, dontCleavePoints
);
311 // add all stub functions and (non)lazy pointers
312 std::set
<uint32_t> deadStubOffsets
;
313 for (const macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
314 uint8_t type (sect
->flags() & SECTION_TYPE
);
318 const uint32_t stubSize
= sect
->reserved2();
319 // TVector glue sections are marked as S_SYMBOL_STUBS but are only 8 bytes
320 if ( stubSize
> 8 ) {
321 for(uint32_t sectOffset
=0; sectOffset
< sect
->size(); sectOffset
+= stubSize
) {
322 uint32_t stubAddr
= sect
->addr() + sectOffset
;
323 if ( cleavePoints
.count(stubAddr
) == 0 ) {
324 cleavePoints
.insert(stubAddr
);
325 deadStubOffsets
.insert(stubAddr
);
331 case S_NON_LAZY_SYMBOL_POINTERS
:
332 case S_LAZY_SYMBOL_POINTERS
:
333 for(uint32_t sectOffset
=0; sectOffset
< sect
->size(); sectOffset
+= sizeof(macho_uintptr_t
)) {
334 uint32_t pointerAddr
= sect
->addr() + sectOffset
;
335 cleavePoints
.insert(pointerAddr
);
339 // also make sure each section break is a cleave point
340 if ( sect
->size() != 0 )
341 cleavePoints
.insert(sect
->addr());
344 for (std::set
<uint32_t>::iterator it
=cleavePoints
.begin(); it
!= cleavePoints
.end(); it
++) {
345 uint32_t cleavePoint
= *it
;
346 //printf("cleave offset 0x%08X, don't cleave=%d, isSymbol=%d\n", cleavePoint, dontCleavePoints.count(cleavePoint), symbolAtomOffsets.count(cleavePoint));
347 // only create an atom if it is not a don't-cleave point and there is not already an atom at this offset
348 if ( (dontCleavePoints
.count(cleavePoint
) == 0) && (symbolAtomOffsets
.count(cleavePoint
) == 0) )
349 fAtoms
.push_back(new Atom(*this, cleavePoint
));
352 const uint32_t atomCount
= fAtoms
.size();
353 if ( atomCount
> 0 ) {
354 // sort the atoms so the occur in source file order
355 std::sort(fAtoms
.begin(), fAtoms
.end(), Atom::atomCompare
);
357 // tell each atom its size and follow on
358 const bool dontDeadStrip
= ((fHeader
->flags() & MH_SUBSECTIONS_VIA_SYMBOLS
) == 0);
359 Atom
* lastAtom
= fAtoms
[0];
360 for (uint32_t i
=1; i
< atomCount
; ++i
) {
361 Atom
* thisAtom
= fAtoms
[i
];
362 if ( lastAtom
->getSize() == 0 ) {
363 if ( lastAtom
->fSection
== thisAtom
->fSection
)
364 lastAtom
->setSize(thisAtom
->fOffset
- lastAtom
->fOffset
);
366 lastAtom
->setSize(lastAtom
->fSection
->addr() + lastAtom
->fSection
->size() - lastAtom
->fOffset
);
369 lastAtom
->setFollowOnAtom(*thisAtom
);
372 lastAtom
= fAtoms
[atomCount
-1];
373 if ( lastAtom
->getSize() == 0 )
374 lastAtom
->setSize(lastAtom
->fSection
->addr() + lastAtom
->fSection
->size() - lastAtom
->fOffset
);
376 // add relocation based references
377 for (const macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
378 const macho_relocation_info
* relocs
= (macho_relocation_info
*)((char*)(fHeader
) + sect
->reloff());
379 const uint32_t relocCount
= sect
->nreloc();
380 for (uint32_t r
= 0; r
< relocCount
; ++r
) {
381 addRelocReference(sect
, &relocs
[r
]);
385 // add dead stubs to list to delete
386 for (std::set
<uint32_t>::iterator it
=deadStubOffsets
.begin(); it
!= deadStubOffsets
.end(); it
++) {
387 Atom
* deadStub
= findAtomCoveringOffset(*it
);
388 this->deadStub(*deadStub
);
391 // remove dead stubs and lazy pointers
392 for (std::set
<ObjectFile::Atom
*>::iterator deadIt
=fDeadAtoms
.begin(); deadIt
!= fDeadAtoms
.end(); deadIt
++) {
393 for (std::vector
<Atom
*>::iterator it
=fAtoms
.begin(); it
!= fAtoms
.end(); it
++) {
394 if ( *deadIt
== *it
) {
403 // process stabs debugging info
404 if ( ! fOptions
.fStripDebugInfo
) {
405 // scan symbol table for stabs entries
406 fNonAtomStabsStartIndex
= 0xFFFFFFFF;
407 fNonAtomStabsCount
= 0;
408 uint32_t possibleStart
= 0;
410 const uint32_t atomCount
= fAtoms
.size();
411 enum { start
, inBeginEnd
, foundFirst
, inFunction
} state
= start
;
412 for (uint32_t symbolIndex
= 0; symbolIndex
< fSymbolCount
; ++symbolIndex
) {
413 const macho_nlist
* sym
= &fSymbols
[symbolIndex
];
414 uint8_t type
= sym
->n_type();
415 if ( (type
& N_STAB
) != 0 ) {
416 if ( fNonAtomStabsStartIndex
== 0xFFFFFFFF )
417 fNonAtomStabsStartIndex
= symbolIndex
;
420 if ( (type
== N_SLINE
) || (type
== N_SOL
) ) {
421 possibleStart
= symbolIndex
;
424 else if ( type
== N_BNSYM
) {
425 macho_uintptr_t targetAddr
= sym
->n_value();
426 atom
= this->findAtomCoveringOffset(targetAddr
);
427 if ( (atom
!= NULL
) || (atom
->fOffset
== targetAddr
) ) {
428 atom
->fStabsStartIndex
= symbolIndex
;
429 if ( fNonAtomStabsCount
== 0 )
430 fNonAtomStabsCount
= symbolIndex
- fNonAtomStabsStartIndex
;
433 fprintf(stderr
, "can't find atom for stabs 0x%02X at %08X in %s\n", type
, targetAddr
, path
);
438 else if ( (type
== N_STSYM
) || (type
== N_LCSYM
) ) {
439 macho_uintptr_t targetAddr
= sym
->n_value();
440 atom
= this->findAtomCoveringOffset(targetAddr
);
441 if ( (atom
!= NULL
) || (atom
->fOffset
== targetAddr
) ) {
442 atom
->fStabsStartIndex
= symbolIndex
;
443 atom
->fStabsCount
= 1;
444 if ( fNonAtomStabsCount
== 0 )
445 fNonAtomStabsCount
= symbolIndex
- fNonAtomStabsStartIndex
;
448 fprintf(stderr
, "can't find atom for stabs 0x%02X at %08X in %s\n", type
, targetAddr
, path
);
452 else if ( type
== N_GSYM
) {
453 // n_value field is NOT atom address ;-(
454 // need to find atom by name match
455 const char* symString
= &fStrings
[sym
->n_strx()];
456 const char* colon
= strchr(symString
, ':');
458 if ( colon
!= NULL
) {
459 int nameLen
= colon
- symString
;
460 for (uint32_t searchIndex
= 0; searchIndex
< atomCount
; ++searchIndex
) {
461 const char* atomName
= fAtoms
[searchIndex
]->getName();
462 if ( (atomName
!= NULL
) && (strncmp(&atomName
[1], symString
, nameLen
) == 0) ) {
463 atom
= fAtoms
[searchIndex
];
464 atom
->fStabsStartIndex
= symbolIndex
;
465 atom
->fStabsCount
= 1;
466 if ( fNonAtomStabsCount
== 0 )
467 fNonAtomStabsCount
= symbolIndex
- fNonAtomStabsStartIndex
;
474 fprintf(stderr
, "can't find atom for N_GSYM stabs %s in %s\n", symString
, path
);
478 else if ( type
== N_LSYM
) {
479 if ( fNonAtomStabsCount
!= 0 ) {
480 // built with -gfull and some type definition not at start of source
481 fNonAtomExtras
.push_back(symbolIndex
);
486 if ( type
== N_ENSYM
) {
489 atom
->fStabsCount
= symbolIndex
- atom
->fStabsStartIndex
+ 1;
493 if ( (type
== N_FUN
) && (sym
->n_sect() != 0) ) {
495 macho_uintptr_t targetAddr
= sym
->n_value();
496 atom
= this->findAtomCoveringOffset(targetAddr
);
497 if ( (atom
== NULL
) || (atom
->fOffset
!= targetAddr
) ) {
498 fprintf(stderr
, "can't find atom for stabs FUN index: %d at 0x%08llX in %s\n", symbolIndex
, (uint64_t)targetAddr
, path
);
502 atom
->fStabsStartIndex
= possibleStart
;
503 if ( fNonAtomStabsCount
== 0 )
504 fNonAtomStabsCount
= possibleStart
- fNonAtomStabsStartIndex
;
507 else if ( (type
== N_FUN
) && (sym
->n_sect() == 0) ) {
508 fprintf(stderr
, "end stab FUN found without start FUN, index=%d in %s\n", symbolIndex
, path
);
513 if ( (type
== N_FUN
) && (sym
->n_sect() == 0) ) {
516 atom
->fStabsCount
= symbolIndex
- atom
->fStabsStartIndex
+ 1;
527 void Reader::addRelocReference(const macho_section
* sect
, const macho_relocation_info
* reloc
)
533 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
534 uint32_t instruction
;
537 if ( (reloc
->r_address() & R_SCATTERED
) == 0 ) {
538 fixUpPtr
= (uint32_t*)((char*)(fHeader
) + sect
->offset() + reloc
->r_address());
539 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
540 const macho_relocation_info
* nextReloc
= &reloc
[1];
542 switch ( reloc
->r_type() ) {
543 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
546 if ( reloc
->r_extern() ) {
547 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
548 int32_t displacement
= (instruction
& 0x03FFFFFC);
549 if ( (displacement
& 0x02000000) != 0 )
550 displacement
|= 0xFC000000;
551 uint32_t offsetInTarget
= sect
->addr() + reloc
->r_address() + displacement
;
552 srcAddr
= sect
->addr() + reloc
->r_address();
553 src
= findAtomCoveringOffset(srcAddr
);
554 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
555 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
556 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupBranch24
, targetName
, offsetInTarget
, 0);
559 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
560 if ( (instruction
& 0x4C000000) == 0x48000000 ) {
561 int32_t displacement
= (instruction
& 0x03FFFFFC);
562 if ( (displacement
& 0x02000000) != 0 )
563 displacement
|= 0xFC000000;
564 srcAddr
= sect
->addr() + reloc
->r_address();
565 dstAddr
= srcAddr
+ displacement
;
566 src
= findAtomCoveringOffset(srcAddr
);
567 dst
= findAtomCoveringOffset(dstAddr
);
568 this->addCallSiteReference(*src
, srcAddr
- src
->fOffset
, Reference::ppcFixupBranch24
, *dst
, 0, dstAddr
- dst
->fOffset
);
575 if ( reloc
->r_extern() ) {
576 srcAddr
= sect
->addr() + reloc
->r_address();
577 src
= findAtomCoveringOffset(srcAddr
);
578 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
579 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
580 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupBranch14
, targetName
, 0, 0);
583 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
584 int32_t displacement
= (instruction
& 0x0000FFFC);
585 if ( (displacement
& 0x00008000) != 0 )
586 displacement
|= 0xFFFF0000;
587 srcAddr
= sect
->addr() + reloc
->r_address();
588 dstAddr
= srcAddr
+ displacement
;
589 src
= findAtomCoveringOffset(srcAddr
);
590 dst
= findAtomCoveringOffset(dstAddr
);
591 this->addCallSiteReference(*src
, srcAddr
- src
->fOffset
, Reference::ppcFixupBranch14
, *dst
, 0, dstAddr
- dst
->fOffset
);
596 // skip, processed by a previous look ahead
600 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
601 printf("PPC_RELOC_LO16 missing following pair\n");
604 srcAddr
= sect
->addr() + reloc
->r_address();
605 if ( reloc
->r_extern() ) {
606 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
607 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
608 src
= findAtomCoveringOffset(srcAddr
);
609 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
610 dstAddr
= (nextReloc
->r_address() << 16) | (instruction
& 0x0000FFFF);
611 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsLow16
, targetName
, dstAddr
, 0);
614 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
615 int16_t lowBits
= (instruction
& 0xFFFF);
616 dstAddr
= (nextReloc
->r_address() << 16) + (int32_t)lowBits
;
617 if ( (lowBits
& 0x8000) != 0 )
619 addFixUp(srcAddr
, dstAddr
, Reference::ppcFixupAbsLow16
, 0);
625 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
626 printf("PPC_RELOC_LO14 missing following pair\n");
629 srcAddr
= sect
->addr() + reloc
->r_address();
630 if ( reloc
->r_extern() ) {
631 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
632 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
633 src
= findAtomCoveringOffset(srcAddr
);
634 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
635 dstAddr
= (nextReloc
->r_address() << 16) | (instruction
& 0x0000FFFC);
636 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsLow14
, targetName
, dstAddr
, 0);
639 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
640 dstAddr
= (nextReloc
->r_address() << 16) | (instruction
& 0x0000FFFC);
641 addFixUp(srcAddr
, dstAddr
, Reference::ppcFixupAbsLow14
, 0);
647 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
648 printf("PPC_RELOC_HI16 missing following pair\n");
651 srcAddr
= sect
->addr() + reloc
->r_address();
652 if ( reloc
->r_extern() ) {
653 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
654 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
655 src
= findAtomCoveringOffset(srcAddr
);
656 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
657 dstAddr
= ((instruction
& 0x0000FFFF) << 16) | (nextReloc
->r_address() & 0x0000FFFF);
658 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsHigh16
, targetName
, dstAddr
, 0);
661 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
662 dstAddr
= ((instruction
& 0x0000FFFF) << 16) | (nextReloc
->r_address() & 0x0000FFFF);
663 addFixUp(srcAddr
, dstAddr
, Reference::ppcFixupAbsHigh16
, 0);
669 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
670 printf("PPC_RELOC_HA16 missing following pair\n");
673 srcAddr
= sect
->addr() + reloc
->r_address();
674 if ( reloc
->r_extern() ) {
675 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
676 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
677 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
678 int16_t lowBits
= (nextReloc
->r_address() & 0x0000FFFF);
679 dstAddr
= ((instruction
& 0x0000FFFF) << 16) + (int32_t)lowBits
;
680 src
= findAtomCoveringOffset(srcAddr
);
681 src
->addByNameReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsHigh16AddLow
, targetName
, dstAddr
, 0);
684 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
685 int16_t lowBits
= (nextReloc
->r_address() & 0x0000FFFF);
686 dstAddr
= ((instruction
& 0x0000FFFF) << 16) + (int32_t)lowBits
;
687 addFixUp(srcAddr
, dstAddr
, Reference::ppcFixupAbsHigh16AddLow
, 0);
691 case GENERIC_RELOC_VANILLA
:
693 srcAddr
= sect
->addr() + reloc
->r_address();
694 Atom
* srcAtom
= findAtomCoveringOffset(srcAddr
);
695 uint32_t offsetInSrcAtom
= srcAddr
- srcAtom
->fOffset
;
696 macho_uintptr_t pointerValue
= ENDIAN_SWAP_POINTER(*((macho_uintptr_t
*)fixUpPtr
));
697 if ( reloc
->r_extern() ) {
698 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
699 uint8_t type
= targetSymbol
->n_type() & N_TYPE
;
700 if ( type
== N_UNDF
) {
701 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
702 macho_uintptr_t addend
= pointerValue
;
703 // ppc lazy pointers have initial reference to dyld_stub_binding_helper
704 if ( (srcAtom
->fSection
->flags() & SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
) {
705 std::vector
<ObjectFile::Reference
*>& refs
= srcAtom
->getReferences();
706 if ( refs
.size() > 0 ) {
707 Reference
* ref
= (Reference
*)refs
[0];
708 #if defined(ARCH_PPC64)
709 // hack to work around bad crt1.o in Mac OS X 10.4
710 targetName
= "dyld_stub_binding_helper";
712 ref
->setFromTargetName(targetName
);
715 fprintf(stderr
, "lazy pointer (%s) should only have one reference - has %ld references\n", srcAtom
->getDisplayName(), refs
.size());
718 #if defined(ARCH_PPC64)
719 // hack to work around bad crt1.o in Mac OS X 10.4
720 else if ( (srcAtom
->fSection
->flags() & SECTION_TYPE
) == S_NON_LAZY_SYMBOL_POINTERS
) {
721 // ignore extra relocation
725 srcAtom
->addByNameReference(offsetInSrcAtom
, Reference::pointer
, targetName
, addend
, 0);
729 dstAddr
= targetSymbol
->n_value();
730 Atom
* dstAtom
= findAtomCoveringOffset(dstAddr
);
731 macho_uintptr_t addend
= pointerValue
;
732 // ppc lazy pointers have initial reference to dyld_stub_binding_helper
733 if ( (srcAtom
->fSection
->flags() & SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
) {
734 std::vector
<ObjectFile::Reference
*>& refs
= srcAtom
->getReferences();
735 if ( refs
.size() > 0 ) {
736 Reference
* ref
= (Reference
*)refs
[0];
737 ref
->setFromTarget(*dstAtom
);
738 ref
->setFromTargetOffset(dstAddr
- dstAtom
->fOffset
);
741 fprintf(stderr
, "lazy pointer (%s) should only have one reference - has %ld references\n", srcAtom
->getDisplayName(), refs
.size());
745 srcAtom
->addReference(offsetInSrcAtom
, Reference::pointer
, *dstAtom
, addend
, 0);
750 Atom
* dstAtom
= findAtomCoveringOffset(pointerValue
);
751 // lazy pointers have references to dyld_stub_binding_helper which need to be ignored
752 if ( (srcAtom
->fSection
->flags() & SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
) {
753 std::vector
<ObjectFile::Reference
*>& refs
= srcAtom
->getReferences();
754 if ( refs
.size() > 0 ) {
755 Reference
* ref
= (Reference
*)refs
[0];
756 ref
->setFromTarget(*dstAtom
);
757 ref
->setFromTargetOffset(pointerValue
- dstAtom
->fOffset
);
760 fprintf(stderr
, "lazy pointer (%s) should only have one reference - has %ld references\n", srcAtom
->getDisplayName(), refs
.size());
764 srcAtom
->addReference(offsetInSrcAtom
, Reference::pointer
, *dstAtom
, pointerValue
-dstAtom
->fOffset
, 0);
773 #if defined(ARCH_I386)
774 case GENERIC_RELOC_VANILLA
:
776 srcAddr
= sect
->addr() + reloc
->r_address();
777 src
= findAtomCoveringOffset(srcAddr
);
778 if ( reloc
->r_length() != 2 )
779 throw "bad vanilla relocation length";
780 Reference::Kind kind
;
781 macho_uintptr_t pointerValue
= ENDIAN_SWAP_POINTER(*((macho_uintptr_t
*)fixUpPtr
));
782 if ( reloc
->r_pcrel() ) {
783 kind
= Reference::x86FixupBranch32
;
784 pointerValue
+= srcAddr
+ sizeof(macho_uintptr_t
);
787 kind
= Reference::pointer
;
789 uint32_t offsetInSrcAtom
= srcAddr
- src
->fOffset
;
790 if ( reloc
->r_extern() ) {
791 const macho_nlist
* targetSymbol
= &fSymbols
[reloc
->r_symbolnum()];
792 uint8_t type
= targetSymbol
->n_type() & N_TYPE
;
793 if ( type
== N_UNDF
) {
794 const char* targetName
= &fStrings
[targetSymbol
->n_strx()];
795 macho_uintptr_t addend
= pointerValue
;
796 src
->addByNameReference(offsetInSrcAtom
, kind
, targetName
, addend
, 0);
799 dstAddr
= targetSymbol
->n_value();
800 dst
= findAtomCoveringOffset(dstAddr
);
801 macho_uintptr_t addend
= pointerValue
- dstAddr
;
802 src
->addReference(offsetInSrcAtom
, kind
, *dst
, addend
, 0);
806 dst
= findAtomCoveringOffset(pointerValue
);
807 // lazy pointers have references to dyld_stub_binding_helper which need to be ignored
808 if ( (src
->fSection
->flags() & SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
) {
809 std::vector
<ObjectFile::Reference
*>& refs
= src
->getReferences();
810 if ( refs
.size() == 1 ) {
811 Reference
* ref
= (Reference
*)refs
[0];
812 ref
->setFromTarget(*dst
);
813 ref
->setFromTargetOffset(pointerValue
- dst
->fOffset
);
816 fprintf(stderr
, "lazy pointer (%s) should only have one reference - has %ld references\n", src
->getDisplayName(), refs
.size());
819 else if ( ((uint8_t*)fixUpPtr
)[-1] == 0xE8 ) // special case call instruction
820 this->addCallSiteReference(*src
, offsetInSrcAtom
, kind
, *dst
, 0, pointerValue
- dst
->fOffset
);
822 src
->addReference(offsetInSrcAtom
, kind
, *dst
, 0, 0);
829 printf("unknown relocation type %d\n", reloc
->r_type());
833 const macho_scattered_relocation_info
* sreloc
= (macho_scattered_relocation_info
*)reloc
;
834 srcAddr
= sect
->addr() + sreloc
->r_address();
835 dstAddr
= sreloc
->r_value();
836 fixUpPtr
= (uint32_t*)((char*)(fHeader
) + sect
->offset() + sreloc
->r_address());
837 const macho_scattered_relocation_info
* nextSReloc
= &sreloc
[1];
838 const macho_relocation_info
* nextReloc
= &reloc
[1];
839 // file format allows pair to be scattered or not
840 bool nextRelocIsPair
= false;
841 uint32_t nextRelocAddress
= 0;
842 uint32_t nextRelocValue
= 0;
843 if ( (nextReloc
->r_address() & R_SCATTERED
) == 0 ) {
844 if ( nextReloc
->r_type() == PPC_RELOC_PAIR
) {
845 nextRelocIsPair
= true;
846 nextRelocAddress
= nextReloc
->r_address();
850 if ( nextSReloc
->r_type() == PPC_RELOC_PAIR
) {
851 nextRelocIsPair
= true;
852 nextRelocAddress
= nextSReloc
->r_address();
853 nextRelocValue
= nextSReloc
->r_value();
856 switch (sreloc
->r_type()) {
857 case GENERIC_RELOC_VANILLA
:
859 macho_uintptr_t betterDstAddr
= ENDIAN_SWAP_POINTER(*((macho_uintptr_t
*)fixUpPtr
));
860 //fprintf(stderr, "pointer reloc: srcAddr=0x%08X, dstAddr=0x%08X, pointer=0x%08lX\n", srcAddr, dstAddr, betterDstAddr);
861 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
862 Atom
* src
= findAtomCoveringOffset(srcAddr
);
863 Atom
* dst
= findAtomCoveringOffset(dstAddr
);
864 src
->addReference(srcAddr
- src
->fOffset
, Reference::pointer
, *dst
, betterDstAddr
- dst
->fOffset
, 0);
867 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
870 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
871 if ( (instruction
& 0x4C000000) == 0x48000000 ) {
872 int32_t displacement
= (instruction
& 0x03FFFFFC);
873 if ( (displacement
& 0x02000000) != 0 )
874 displacement
|= 0xFC000000;
875 srcAddr
= sect
->addr() + sreloc
->r_address();
876 dstAddr
= sreloc
->r_value();
877 src
= findAtomCoveringOffset(srcAddr
);
878 dst
= findAtomCoveringOffset(dstAddr
);
879 this->addCallSiteReference(*src
, srcAddr
- src
->fOffset
, Reference::ppcFixupBranch24
, *dst
, 0, srcAddr
+ displacement
- sreloc
->r_value());
883 case PPC_RELOC_LO16_SECTDIFF
:
885 if ( ! nextRelocIsPair
) {
886 printf("PPC_RELOC_LO16_SECTDIFF missing following PAIR\n");
889 src
= findAtomCoveringOffset(srcAddr
);
890 dst
= findAtomCoveringOffset(dstAddr
);
891 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
892 int16_t lowBits
= (instruction
& 0xFFFF);
893 int32_t displacement
= (nextRelocAddress
<< 16) + (int32_t)lowBits
;
894 if ( (lowBits
& 0x8000) != 0 )
895 displacement
+= 0x10000;
896 uint32_t picBaseOffset
= nextRelocValue
- src
->fOffset
;
897 int64_t dstOffset
= src
->fOffset
+ picBaseOffset
+ displacement
- dst
->fOffset
;
898 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupPicBaseLow16
, *dst
, dstOffset
, picBaseOffset
);
901 case PPC_RELOC_LO14_SECTDIFF
:
903 if ( ! nextRelocIsPair
) {
904 printf("PPC_RELOC_LO14_SECTDIFF missing following PAIR\n");
907 src
= findAtomCoveringOffset(srcAddr
);
908 dst
= findAtomCoveringOffset(dstAddr
);
909 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
910 int16_t lowBits
= (instruction
& 0xFFFC);
911 int32_t displacement
= (nextRelocAddress
<< 16) + (int32_t)lowBits
;
912 if ( (lowBits
& 0x8000) != 0 )
913 displacement
+= 0x10000;
914 uint32_t picBaseOffset
= nextRelocValue
- src
->fOffset
;
915 int64_t dstOffset
= src
->fOffset
+ picBaseOffset
+ displacement
- dst
->fOffset
;
916 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupPicBaseLow14
, *dst
, dstOffset
, picBaseOffset
);
919 case PPC_RELOC_HA16_SECTDIFF
:
921 if ( ! nextRelocIsPair
) {
922 printf("PPC_RELOC_LO14_SECTDIFF missing following PAIR\n");
925 src
= findAtomCoveringOffset(srcAddr
);
926 dst
= findAtomCoveringOffset(dstAddr
);
927 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
928 int16_t lowBits
= (nextRelocAddress
& 0x0000FFFF);
929 int32_t displacement
= ((instruction
& 0x0000FFFF) << 16) + (int32_t)lowBits
;
930 uint32_t picBaseOffset
= nextRelocValue
- src
->fOffset
;
931 int64_t dstOffset
= src
->fOffset
+ picBaseOffset
+ displacement
- dst
->fOffset
;
932 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupPicBaseHigh16
, *dst
, dstOffset
, picBaseOffset
);
937 if ( ! nextRelocIsPair
) {
938 printf("PPC_RELOC_LO14 missing following PAIR\n");
941 src
= findAtomCoveringOffset(srcAddr
);
942 dst
= findAtomCoveringOffset(dstAddr
);
943 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
944 int16_t lowBits
= (instruction
& 0xFFFC);
945 uint32_t betterDstAddr
= (nextRelocAddress
<< 16) + (int32_t)lowBits
;
946 if ( (lowBits
& 0x8000) != 0 )
947 betterDstAddr
+= 0x10000;
948 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsLow14
, *dst
, betterDstAddr
- dst
->fOffset
, 0);
953 if ( ! nextRelocIsPair
) {
954 printf("PPC_RELOC_LO16 missing following PAIR\n");
957 src
= findAtomCoveringOffset(srcAddr
);
958 dst
= findAtomCoveringOffset(dstAddr
);
959 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
960 int16_t lowBits
= (instruction
& 0xFFFF);
961 uint32_t betterDstAddr
= (nextRelocAddress
<< 16) + (int32_t)lowBits
;
962 if ( (lowBits
& 0x8000) != 0 )
963 betterDstAddr
+= 0x10000;
964 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsLow16
, *dst
, betterDstAddr
- dst
->fOffset
, 0);
969 if ( ! nextRelocIsPair
) {
970 printf("PPC_RELOC_HA16 missing following PAIR\n");
973 src
= findAtomCoveringOffset(srcAddr
);
974 dst
= findAtomCoveringOffset(dstAddr
);
975 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
976 int16_t lowBits
= (nextRelocAddress
& 0xFFFF);
977 uint32_t betterDstAddr
= ((instruction
& 0xFFFF) << 16) + (int32_t)lowBits
;
978 src
->addReference(srcAddr
- src
->fOffset
, Reference::ppcFixupAbsHigh16AddLow
, *dst
, betterDstAddr
- dst
->fOffset
, 0);
981 case PPC_RELOC_SECTDIFF
:
982 case PPC_RELOC_LOCAL_SECTDIFF
:
984 const macho_scattered_relocation_info
* nextReloc
= &sreloc
[1];
985 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
986 printf("PPC_RELOC_SECTDIFF missing following pair\n");
989 srcAddr
= sect
->addr() + sreloc
->r_address();
990 uint32_t toAddr
= sreloc
->r_value();
991 uint32_t fromAddr
= nextReloc
->r_value();
992 src
= findAtomCoveringOffset(srcAddr
);
993 Atom
* to
= findAtomCoveringOffset(toAddr
);
994 Atom
* from
= findAtomCoveringOffset(fromAddr
);
995 //macho_intptr_t pointerValue = *(macho_intptr_t*)fixUpPtr;
996 //uint64_t toOffset = to->fOffset;
997 //uint64_t fromOffset = from->fOffset;
998 //int64_t pointerValue64 = pointerValue;
999 //uint64_t addend = pointerValue64 - (toOffset - fromOffset);
1000 Reference::Kind kind
= Reference::pointer32Difference
;
1001 if ( sreloc
->r_length() == 3 )
1002 kind
= Reference::pointer64Difference
;
1003 src
->addDifferenceReference(srcAddr
- src
->fOffset
, kind
, *to
, toAddr
- to
->fOffset
, *from
, fromAddr
- from
->fOffset
);
1006 case PPC_RELOC_PAIR
:
1008 case PPC_RELOC_HI16_SECTDIFF
:
1009 printf("unexpected scattered relocation type PPC_RELOC_HI16_SECTDIFF\n");
1012 #if defined(ARCH_I386)
1013 case GENERIC_RELOC_SECTDIFF
:
1014 case GENERIC_RELOC_LOCAL_SECTDIFF
:
1016 if ( nextSReloc
->r_type() != GENERIC_RELOC_PAIR
) {
1017 printf("GENERIC_RELOC_SECTDIFF missing following pair\n");
1020 srcAddr
= sect
->addr() + sreloc
->r_address();
1021 uint32_t toAddr
= sreloc
->r_value();
1022 uint32_t fromAddr
= nextSReloc
->r_value();
1023 src
= findAtomCoveringOffset(srcAddr
);
1024 Atom
* to
= findAtomCoveringOffset(toAddr
);
1025 Atom
* from
= findAtomCoveringOffset(fromAddr
);
1026 Reference::Kind kind
= Reference::pointer32Difference
;
1027 if ( sreloc
->r_length() != 2 )
1028 throw "bad length for GENERIC_RELOC_SECTDIFF";
1029 src
->addDifferenceReference(srcAddr
- src
->fOffset
, kind
, *to
, toAddr
- to
->fOffset
, *from
, fromAddr
- from
->fOffset
);
1032 case GENERIC_RELOC_PAIR
:
1033 // do nothing, already used via a look ahead
1037 printf("unknown scattered relocation type %d\n", sreloc
->r_type());
1044 void Reader::addFixUp(uint32_t srcAddr
, uint32_t dstAddr
, Reference::Kind kind
, uint32_t picBaseAddr
)
1046 Atom
* src
= findAtomCoveringOffset(srcAddr
);
1047 Atom
* dst
= findAtomCoveringOffset(dstAddr
);
1048 src
->addReference(srcAddr
- src
->fOffset
, kind
, *dst
, dstAddr
- dst
->fOffset
, picBaseAddr
- src
->fOffset
);
1051 Atom
* Reader::findAtomCoveringOffset(uint32_t offset
)
1054 // binary search of sorted atoms
1055 Atom
** base
= &fAtoms
[0];
1056 for (uint32_t n
= fAtoms
.size(); n
> 0; n
/= 2) {
1057 Atom
** pivot
= &base
[n
/2];
1058 Atom
* pivotAtom
= *pivot
;
1059 if ( pivotAtom
->fOffset
<= offset
) {
1060 if ( offset
< (pivotAtom
->fOffset
+ pivotAtom
->fSize
) )
1063 // move base to symbol after pivot
1072 // possible that last atom is zero length
1073 Atom
* lastAtom
= fAtoms
.back();
1074 if ( (lastAtom
->fOffset
== offset
) && (lastAtom
->fSize
== 0) )
1077 const uint32_t atomCount
= fAtoms
.size();
1078 for (uint32_t i
=0; i
< atomCount
; ++i
) {
1079 Atom
* atom
= fAtoms
[i
];
1080 if ( (atom
->fOffset
<= offset
) && (offset
< (atom
->fOffset
+ atom
->fSize
)) )
1084 throwf("address 0x%08X is not in any atom", offset
);
1087 uint32_t Reader::findAtomIndex(const Atom
& atom
)
1089 const Atom
* target
= &atom
;
1090 const uint32_t atomCount
= fAtoms
.size();
1091 for (uint32_t i
=0; i
< atomCount
; ++i
) {
1092 Atom
* anAtom
= fAtoms
[i
];
1093 if ( anAtom
== target
)
1099 static void insertOffset(std::set
<uint32_t>& offsets
, uint32_t value
)
1101 //fprintf(stderr, "cleave point at 0x%08X\n", value);
1102 offsets
.insert(value
);
1105 void Reader::insertOffsetIfNotText(std::set
<uint32_t>& offsets
, uint32_t value
)
1107 const macho_section
* sect
= findSectionCoveringOffset(value
);
1108 if ( (sect
== NULL
) || (strcmp(sect
->segname(),"__TEXT") != 0) || (strncmp(sect
->sectname(),"__text", 6) != 0) ) {
1109 offsets
.insert(value
);
1113 void Reader::insertOffsetIfText(std::set
<uint32_t>& offsets
, uint32_t value
)
1115 const macho_section
* sect
= findSectionCoveringOffset(value
);
1116 if ( (sect
!= NULL
) && (strcmp(sect
->segname(),"__TEXT") == 0) && (strncmp(sect
->sectname(),"__text", 6) == 0) ) {
1117 //fprintf(stderr, "don't cleave point at 0x%08X\n", value);
1118 offsets
.insert(value
);
1122 const macho_section
* Reader::findSectionCoveringOffset(uint32_t offset
)
1124 const macho_section
* const sectionsStart
= (macho_section
*)((char*)fSegment
+ sizeof(macho_segment_command
));
1125 const macho_section
* const sectionsEnd
= §ionsStart
[fSegment
->nsects()];
1126 for (const macho_section
* sect
=sectionsStart
; sect
< sectionsEnd
; ++sect
) {
1127 if ( (sect
->addr() <= offset
) && (offset
< (sect
->addr() + sect
->size())) )
1134 void Reader::buildOffsetsSet(const macho_relocation_info
* reloc
, const macho_section
* sect
, std::set
<uint32_t>& cleavePoints
, std::set
<uint32_t>& dontCleavePoints
)
1136 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
1137 uint32_t targetAddr
;
1139 if ( (reloc
->r_address() & R_SCATTERED
) == 0 ) {
1140 uint32_t* fixUpPtr
= (uint32_t*)((char*)(fHeader
) + sect
->offset() + reloc
->r_address());
1141 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
1142 uint32_t instruction
;
1144 switch ( reloc
->r_type() ) {
1145 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
1146 case PPC_RELOC_BR14
:
1147 // do nothing. local branch should not cleave
1149 case PPC_RELOC_BR24
:
1151 if ( ! reloc
->r_extern() ) {
1152 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
1153 if ( (instruction
& 0x4C000000) == 0x48000000 ) {
1154 int32_t displacement
= (instruction
& 0x03FFFFFC);
1155 if ( (displacement
& 0x02000000) != 0 )
1156 displacement
|= 0xFC000000;
1157 //cleavePoints.insert(reloc->r_address() + displacement);
1158 insertOffset(cleavePoints
, sect
->addr() + reloc
->r_address() + displacement
);
1163 case PPC_RELOC_PAIR
:
1164 // skip, processed by a look ahead
1166 case PPC_RELOC_LO16
:
1168 const macho_relocation_info
* nextReloc
= &reloc
[1];
1169 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
1170 printf("PPC_RELOC_LO16 missing following pair\n");
1173 if ( ! reloc
->r_extern() ) {
1174 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
1175 targetAddr
= (nextReloc
->r_address() << 16) | (instruction
& 0x0000FFFF);
1176 //cleavePoints.insert(targetAddr);
1177 insertOffset(cleavePoints
, (targetAddr
));
1181 case PPC_RELOC_LO14
:
1183 const macho_relocation_info
* nextReloc
= &reloc
[1];
1184 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
1185 printf("PPC_RELOC_LO14 missing following pair\n");
1188 if ( ! reloc
->r_extern() ) {
1189 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
1190 targetAddr
= (nextReloc
->r_address() << 16) | (instruction
& 0x0000FFFC);
1191 //cleavePoints.insert(targetAddr);
1192 insertOffset(cleavePoints
, (targetAddr
));
1196 case PPC_RELOC_HI16
:
1198 const macho_relocation_info
* nextReloc
= &reloc
[1];
1199 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
1200 printf("PPC_RELOC_HI16 missing following pair\n");
1203 if ( ! reloc
->r_extern() ) {
1204 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
1205 targetAddr
= ((instruction
& 0x0000FFFF) << 16) | (nextReloc
->r_address() & 0x0000FFFF);
1206 //cleavePoints.insert(targetAddr);
1207 insertOffset(cleavePoints
, targetAddr
);
1211 case PPC_RELOC_HA16
:
1213 const macho_relocation_info
* nextReloc
= &reloc
[1];
1214 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
1215 printf("PPC_RELOC_HA16 missing following pair\n");
1218 if ( ! reloc
->r_extern() ) {
1219 instruction
= OSSwapBigToHostInt32(*fixUpPtr
);
1220 int16_t lowBits
= (nextReloc
->r_address() & 0x0000FFFF);
1221 targetAddr
= ((instruction
& 0x0000FFFF) << 16) + (int32_t)lowBits
;
1222 //cleavePoints.insert(targetAddr);
1223 insertOffset(cleavePoints
, targetAddr
);
1227 case PPC_RELOC_JBSR
:
1231 case GENERIC_RELOC_VANILLA
:
1233 #if defined(ARCH_PPC64)
1234 if ( reloc
->r_length() != 3 )
1235 throw "vanilla pointer relocation found that is not 8-bytes";
1236 #elif defined(ARCH_PPC) || defined(ARCH_I386)
1237 if ( reloc
->r_length() != 2 )
1238 throw "vanilla pointer relocation found that is not 4-bytes";
1240 //fprintf(stderr, "addr=0x%08X, pcrel=%d, len=%d, extern=%d, type=%d\n", reloc->r_address(), reloc->r_pcrel(), reloc->r_length(), reloc->r_extern(), reloc->r_type());
1241 if ( !reloc
->r_extern() ) {
1242 macho_uintptr_t pointerValue
= ENDIAN_SWAP_POINTER(*((macho_uintptr_t
*)fixUpPtr
));
1243 #if defined(ARCH_I386)
1244 // i386 stubs have internal relocs that should not cause a cleave
1245 if ( (sect
->flags() & SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
)
1248 if ( reloc
->r_pcrel() )
1249 pointerValue
+= reloc
->r_address() + sect
->addr() + sizeof(macho_uintptr_t
);
1250 // a pointer into code does not cleave the code (gcc always pointers to labels)
1251 insertOffsetIfNotText(cleavePoints
, pointerValue
);
1256 printf("unknown relocation type %d\n", reloc
->r_type());
1260 const macho_scattered_relocation_info
* sreloc
= (macho_scattered_relocation_info
*)reloc
;
1261 switch (sreloc
->r_type()) {
1262 case GENERIC_RELOC_VANILLA
:
1263 insertOffset(cleavePoints
, sreloc
->r_value());
1265 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
1266 case PPC_RELOC_BR24
:
1267 insertOffset(cleavePoints
, sreloc
->r_value());
1269 case PPC_RELOC_HA16
:
1270 case PPC_RELOC_HI16
:
1271 case PPC_RELOC_LO16
:
1272 case PPC_RELOC_LO14
:
1273 case PPC_RELOC_LO16_SECTDIFF
:
1274 case PPC_RELOC_LO14_SECTDIFF
:
1275 case PPC_RELOC_HA16_SECTDIFF
:
1276 case PPC_RELOC_HI16_SECTDIFF
:
1277 //cleavePoints.insert(sreloc->r_value());
1278 insertOffset(cleavePoints
, sreloc
->r_value());
1279 insertOffsetIfText(dontCleavePoints
, sreloc
->r_value());
1281 case PPC_RELOC_SECTDIFF
:
1282 case PPC_RELOC_LOCAL_SECTDIFF
:
1283 // these do not cleave up a .o file
1284 // a SECTDIFF in __TEXT probably means a jump table, and should prevent a cleave
1286 const macho_scattered_relocation_info
* nextReloc
= &sreloc
[1];
1287 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
) {
1288 printf("PPC_RELOC_SECTDIFF missing following pair\n");
1291 insertOffsetIfText(dontCleavePoints
, sreloc
->r_value());
1292 insertOffsetIfText(dontCleavePoints
, nextReloc
->r_value());
1295 case PPC_RELOC_PAIR
:
1296 // do nothing, already used via a look ahead
1299 #if defined(ARCH_I386)
1300 case GENERIC_RELOC_SECTDIFF
:
1301 case GENERIC_RELOC_LOCAL_SECTDIFF
:
1302 // these do not cleave up a .o file
1303 // a SECTDIFF in __TEXT probably means a jump table, and should prevent a cleave
1305 const macho_scattered_relocation_info
* nextReloc
= &sreloc
[1];
1306 if ( nextReloc
->r_type() != GENERIC_RELOC_PAIR
) {
1307 printf("GENERIC_RELOC_SECTDIFF missing following pair\n");
1310 insertOffsetIfText(dontCleavePoints
, sreloc
->r_value());
1311 insertOffsetIfText(dontCleavePoints
, nextReloc
->r_value());
1314 case GENERIC_RELOC_PAIR
:
1315 // do nothing, already used via a look ahead
1319 printf("unknown relocation type %d\n", sreloc
->r_type());
1326 Segment
* Reader::makeSegmentFromSection(const macho_section
* sect
)
1328 // make segment object if one does not already exist
1329 const uint32_t segmentCount
= fSegments
.size();
1330 for (uint32_t i
=0; i
< segmentCount
; ++i
) {
1331 Segment
* seg
= fSegments
[i
];
1332 if ( strcmp(sect
->segname(), seg
->getName()) == 0 )
1335 Segment
* seg
= new Segment(sect
);
1336 fSegments
.push_back(seg
);
1340 macho_uintptr_t
Reader::commonsOffset()
1342 return fSegment
->vmsize();
1345 const char* Reader::getPath()
1350 std::vector
<class ObjectFile::Atom
*>& Reader::getAtoms()
1352 return (std::vector
<class ObjectFile::Atom
*>&)(fAtoms
);
1355 std::vector
<class ObjectFile::Atom
*>* Reader::getJustInTimeAtomsFor(const char* name
)
1357 // object files have no just-in-time atoms
1362 std::vector
<ObjectFile::StabsInfo
>* Reader::getStabsDebugInfo()
1364 if ( fNonAtomStabsCount
== 0 )
1367 std::vector
<ObjectFile::StabsInfo
>* stabs
= new std::vector
<ObjectFile::StabsInfo
>();
1368 stabs
->reserve(fNonAtomStabsCount
);
1370 for (uint32_t i
=0; i
< fNonAtomStabsCount
; ++i
) {
1371 const macho_nlist
* sym
= &fSymbols
[fNonAtomStabsStartIndex
+i
];
1372 if ( (sym
->n_type() & N_STAB
) != 0 ) {
1373 ObjectFile::StabsInfo stab
;
1374 stab
.atomOffset
= sym
->n_value();
1375 stab
.string
= &fStrings
[sym
->n_strx()];
1376 stab
.type
= sym
->n_type();
1377 stab
.other
= sym
->n_sect();
1378 stab
.desc
= sym
->n_desc();
1379 // for N_SO n_value is offset of first atom, but our gdb ignores this, so we omit that calculation
1380 if ( stab
.type
== N_SO
)
1381 stab
.atomOffset
= 0;
1382 stabs
->push_back(stab
);
1386 // add any extra N_LSYM's not at start of symbol table
1387 for (std::vector
<uint32_t>::iterator it
=fNonAtomExtras
.begin(); it
!= fNonAtomExtras
.end(); ++it
) {
1388 const macho_nlist
* sym
= &fSymbols
[*it
];
1389 ObjectFile::StabsInfo stab
;
1390 stab
.atomOffset
= sym
->n_value();
1391 stab
.string
= &fStrings
[sym
->n_strx()];
1392 stab
.type
= sym
->n_type();
1393 stab
.other
= sym
->n_sect();
1394 stab
.desc
= sym
->n_desc();
1395 stabs
->push_back(stab
);
1401 void Reader::deadStub(Atom
& target
)
1404 fDeadAtoms
.insert(&target
);
1406 // remove lazy pointer
1407 const int stubNameLen
= strlen(target
.fSynthesizedName
);
1408 char lazyName
[stubNameLen
+8];
1409 strcpy(lazyName
, target
.fSynthesizedName
);
1410 strcpy(&lazyName
[stubNameLen
-5], "$lazy_ptr");
1411 const uint32_t atomCount
= fAtoms
.size();
1412 for (uint32_t i
=1; i
< atomCount
; ++i
) {
1413 Atom
* atom
= fAtoms
[i
];
1414 if ( (atom
->fSynthesizedName
!= NULL
) && (strcmp(atom
->fSynthesizedName
, lazyName
) == 0) ) {
1415 fDeadAtoms
.insert(atom
);
1422 void Reader::addCallSiteReference(Atom
& src
, uint32_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint32_t picBaseOffset
, uint32_t offsetInTargetAtom
)
1424 // the compiler some times produces stub to static functions and then calls the stubs
1425 // we need to skip the stub if a static function exists with the same name and remove the stub
1426 if ( target
.isLazyStub() ) {
1427 const macho_section
* section
= target
.fSection
;
1428 uint32_t index
= (target
.fOffset
- section
->addr()) / section
->reserved2();
1429 uint32_t indirectTableIndex
= section
->reserved1() + index
;
1430 uint32_t symbolIndex
= ENDIAN_READ32(fIndirectTable
[indirectTableIndex
]);
1431 if ( (symbolIndex
& INDIRECT_SYMBOL_LOCAL
) == 0 ) {
1432 const macho_nlist
* sym
= &fSymbols
[symbolIndex
];
1433 if ( (sym
->n_value() != 0) && ((sym
->n_type() & N_EXT
) == 0) ) {
1434 Atom
* betterTarget
= this->findAtomCoveringOffset(sym
->n_value());
1435 if ( (betterTarget
!= NULL
) && (betterTarget
->getScope() == ObjectFile::Atom::scopeTranslationUnit
) ) {
1436 // use direct reference to static function
1437 src
.addDirectReference(offsetInSrcAtom
, kind
, *betterTarget
, offsetInTargetAtom
, picBaseOffset
);
1439 // remove stub and lazy pointer
1440 this->deadStub(target
);
1447 // fall through to general case
1448 src
.addReference(offsetInSrcAtom
, kind
, target
, offsetInTargetAtom
, picBaseOffset
);
1452 Atom::Atom(Reader
& owner
, const macho_nlist
* symbol
)
1453 : fOwner(owner
), fSymbol(symbol
), fOffset(0), fSize(0), fSection(NULL
), fSegment(NULL
), fSynthesizedName(NULL
),
1454 fStabsStartIndex(0), fStabsCount(0)
1456 uint8_t type
= symbol
->n_type();
1457 if ( (type
& N_EXT
) == 0 )
1458 fScope
= ObjectFile::Atom::scopeTranslationUnit
;
1459 else if ( (type
& N_PEXT
) != 0 )
1460 fScope
= ObjectFile::Atom::scopeLinkageUnit
;
1462 fScope
= ObjectFile::Atom::scopeGlobal
;
1463 if ( (type
& N_TYPE
) == N_SECT
) {
1465 const macho_section
* sections
= (macho_section
*)((char*)fOwner
.fSegment
+ sizeof(macho_segment_command
));
1466 fSection
= §ions
[fSymbol
->n_sect()-1];
1467 fSegment
= owner
.makeSegmentFromSection(fSection
);
1468 fOffset
= fSymbol
->n_value();
1469 uint8_t type
= fSection
->flags() & SECTION_TYPE
;
1471 case S_LAZY_SYMBOL_POINTERS
:
1472 case S_NON_LAZY_SYMBOL_POINTERS
:
1474 // get target name out of indirect symbol table
1475 uint32_t index
= (fOffset
- fSection
->addr()) / sizeof(macho_uintptr_t
);
1476 index
+= fSection
->reserved1();
1477 uint32_t symbolIndex
= ENDIAN_READ32(fOwner
.fIndirectTable
[index
]);
1478 uint32_t strOffset
= fOwner
.fSymbols
[symbolIndex
].n_strx();
1479 const char* name
= &fOwner
.fStrings
[strOffset
];
1480 Reference
* ref
= this->addByNameReference(0, Reference::pointer
, name
, 0, 0);
1481 if ( type
== S_LAZY_SYMBOL_POINTERS
) {
1488 else if ( ((type
& N_TYPE
) == N_UNDF
) && (symbol
->n_value() != 0) ) {
1489 // tentative definition
1490 fSize
= symbol
->n_value();
1491 fSection
= getCommonsSection();
1492 fSegment
= owner
.makeSegmentFromSection(fSection
);
1493 fOffset
= owner
.commonsOffset();
1496 printf("unknown symbol type: %d\n", type
);
1500 Atom::Atom(Reader
& owner
, uint32_t offset
)
1501 : fOwner(owner
), fSymbol(NULL
), fOffset(offset
), fSize(0), fSection(NULL
), fSegment(NULL
), fSynthesizedName(NULL
),
1502 fStabsStartIndex(0), fStabsCount(0)
1504 fSection
= findSectionFromOffset(offset
);
1505 fScope
= ObjectFile::Atom::scopeLinkageUnit
;
1506 fSegment
= owner
.makeSegmentFromSection(fSection
);
1507 uint8_t type
= fSection
->flags() & SECTION_TYPE
;
1509 case S_SYMBOL_STUBS
:
1511 uint32_t index
= (offset
- fSection
->addr()) / fSection
->reserved2();
1512 index
+= fSection
->reserved1();
1513 uint32_t symbolIndex
= ENDIAN_READ32(fOwner
.fIndirectTable
[index
]);
1514 uint32_t strOffset
= fOwner
.fSymbols
[symbolIndex
].n_strx();
1515 const char* name
= &fOwner
.fStrings
[strOffset
];
1516 char* str
= new char[strlen(name
)+8];
1518 strcat(str
, "$stub");
1519 fSynthesizedName
= str
;
1522 case S_LAZY_SYMBOL_POINTERS
:
1523 case S_NON_LAZY_SYMBOL_POINTERS
:
1525 uint32_t index
= (offset
- fSection
->addr()) / sizeof(macho_uintptr_t
);
1526 index
+= fSection
->reserved1();
1527 uint32_t symbolIndex
= ENDIAN_READ32(fOwner
.fIndirectTable
[index
]);
1528 uint32_t strOffset
= fOwner
.fSymbols
[symbolIndex
].n_strx();
1529 const char* name
= &fOwner
.fStrings
[strOffset
];
1530 char* str
= new char[strlen(name
)+16];
1532 if ( type
== S_LAZY_SYMBOL_POINTERS
)
1533 strcat(str
, "$lazy_ptr");
1535 strcat(str
, "$non_lazy_ptr");
1536 fSynthesizedName
= str
;
1537 Reference
* ref
= this->addByNameReference(0, Reference::pointer
, name
, 0, 0);
1538 if ( type
== S_LAZY_SYMBOL_POINTERS
) {
1541 const macho_nlist
* sym
= &fOwner
.fSymbols
[symbolIndex
];
1542 if ( (sym
->n_type() & N_TYPE
) == N_UNDF
) {
1543 if ( (sym
->n_desc() & N_WEAK_REF
) != 0 )
1556 macho_section
Atom::fgCommonsSection
;
1559 bool Atom::isLazyStub()
1561 return ( (fSection
->flags() & SECTION_TYPE
) == S_SYMBOL_STUBS
);
1564 const macho_section
* Atom::getCommonsSection() {
1565 if ( strcmp(fgCommonsSection
.sectname(), "__common") != 0 ) {
1566 fgCommonsSection
.set_sectname("__common");
1567 fgCommonsSection
.set_segname("__DATA");
1568 fgCommonsSection
.set_flags(S_ZEROFILL
);
1570 return &fgCommonsSection
;
1573 ObjectFile::Reader
* Atom::getFile() const
1579 const char* Atom::getName() const
1581 if ( fSymbol
!= NULL
)
1582 return &fOwner
.fStrings
[fSymbol
->n_strx()];
1584 return fSynthesizedName
;
1587 const char* Atom::getDisplayName() const
1589 if ( fSymbol
!= NULL
)
1590 return &fOwner
.fStrings
[fSymbol
->n_strx()];
1592 if ( fSynthesizedName
!= NULL
)
1593 return fSynthesizedName
;
1595 static char temp
[32];
1596 sprintf(temp
, "atom #%u", fOwner
.findAtomIndex(*this));
1600 ObjectFile::Atom::Scope
Atom::getScope() const
1605 void Atom::setScope(ObjectFile::Atom::Scope newScope
)
1611 bool Atom::isWeakDefinition() const
1613 if ( isTentativeDefinition() )
1615 if ( fSymbol
!= NULL
)
1616 return ( (fSymbol
->n_desc() & N_WEAK_DEF
) != 0 );
1617 uint8_t type
= fSection
->flags() & SECTION_TYPE
;
1619 case S_SYMBOL_STUBS
:
1620 case S_LAZY_SYMBOL_POINTERS
:
1621 case S_NON_LAZY_SYMBOL_POINTERS
:
1627 bool Atom::isTentativeDefinition() const
1629 return (fSection
== &fgCommonsSection
);
1632 bool Atom::isCoalesableByName() const
1634 uint8_t type
= fSection
->flags() & SECTION_TYPE
;
1636 case S_SYMBOL_STUBS
:
1640 if ( isTentativeDefinition() )
1645 bool Atom::isCoalesableByValue() const
1647 uint8_t type
= fSection
->flags() & SECTION_TYPE
;
1649 case S_CSTRING_LITERALS
:
1650 case S_4BYTE_LITERALS
:
1651 case S_8BYTE_LITERALS
:
1657 bool Atom::isZeroFill() const
1659 return ((fSection
->flags() & SECTION_TYPE
) == S_ZEROFILL
);
1662 bool Atom::dontDeadStrip() const
1664 if ( fSymbol
!= NULL
)
1665 return ( (fSymbol
->n_desc() & N_NO_DEAD_STRIP
) != 0 );
1670 bool Atom::dontStripName() const
1672 if ( fSymbol
!= NULL
)
1673 return ( (fSymbol
->n_desc() & REFERENCED_DYNAMICALLY
) != 0 );
1677 bool Atom::isImportProxy() const
1683 uint64_t Atom::getSize() const
1690 std::vector
<ObjectFile::Reference
*>& Atom::getReferences() const
1692 return (std::vector
<ObjectFile::Reference
*>&)(fReferences
);
1695 bool Atom::mustRemainInSection() const
1700 const char* Atom::getSectionName() const
1702 if ( strlen(fSection
->sectname()) > 15 ) {
1703 static char temp
[18];
1704 strncpy(temp
, fSection
->sectname(), 16);
1708 return fSection
->sectname();
1711 Segment
& Atom::getSegment() const
1716 bool Atom::requiresFollowOnAtom() const
1718 // requires follow-on if built with old compiler and not the last atom
1719 if ( (fOwner
.fHeader
->flags() & MH_SUBSECTIONS_VIA_SYMBOLS
) == 0) {
1720 if ( fOwner
.findAtomIndex(*this) < (fOwner
.fAtoms
.size()-1) )
1726 ObjectFile::Atom
& Atom::getFollowOnAtom() const
1728 uint32_t myIndex
= fOwner
.findAtomIndex(*this);
1729 return *fOwner
.fAtoms
[myIndex
+1];
1732 std::vector
<ObjectFile::StabsInfo
>* Atom::getStabsDebugInfo() const
1734 if ( fStabsCount
== 0 )
1737 std::vector
<ObjectFile::StabsInfo
>* stabs
= new std::vector
<ObjectFile::StabsInfo
>();
1738 stabs
->reserve(fStabsCount
);
1740 for (uint32_t i
=0; i
< fStabsCount
; ++i
) {
1741 const macho_nlist
* sym
= &fOwner
.fSymbols
[fStabsStartIndex
+i
];
1742 if ( (sym
->n_type() & N_STAB
) != 0 ) {
1743 ObjectFile::StabsInfo stab
;
1744 stab
.atomOffset
= sym
->n_value();
1745 stab
.string
= &fOwner
.fStrings
[sym
->n_strx()];
1746 stab
.type
= sym
->n_type();
1747 stab
.other
= sym
->n_sect();
1748 stab
.desc
= sym
->n_desc();
1749 switch ( stab
.type
) {
1751 if ( stab
.other
== 0 )
1753 // end of function N_FUN has size (not address) so should not be adjusted
1762 // all these stab types need their value changed from an absolute address to the atom offset
1763 stab
.atomOffset
-= fOffset
;
1766 stabs
->push_back(stab
);
1773 uint8_t Atom::getAlignment() const
1775 // mach-o file format has no alignment information for atoms - just whole sections
1776 if ( fSection
!= NULL
) {
1777 if ( isTentativeDefinition() ) {
1778 // common symbols align to their size
1779 // that is, a 4-byte common aligns to 4-bytes
1780 // to be safe, odd size commons align to the next power-of-2 size
1781 uint8_t alignment
= (uint8_t)ceil(log2(this->getSize()));
1782 // limit alignment of extremely large commons to 2^15 bytes (8-page)
1783 if ( alignment
< 15 )
1789 // so we assume every atom requires the same alignment as the whole section
1790 return fSection
->align();
1798 void Atom::copyRawContent(uint8_t buffer
[]) const
1802 bzero(buffer
, fSize
);
1804 uint32_t fileOffset
= fSection
->offset() - fSection
->addr() + fOffset
;
1805 memcpy(buffer
, (char*)(fOwner
.fHeader
)+fileOffset
, fSize
);
1809 void Atom::writeContent(bool finalLinkedImage
, ObjectFile::ContentWriter
& writer
) const
1811 const uint32_t referencesCount
= fReferences
.size();
1813 // skip copy if no fix-ups
1814 if ( referencesCount
== 0 ) {
1815 uint32_t fileOffset
= fSection
->offset() - fSection
->addr() + fOffset
;
1816 writer
.write(0, (char*)(fOwner
.fHeader
)+fileOffset
, fSize
);
1821 uint8_t buffer
[this->getSize()];
1822 this->copyRawContent(buffer
);
1824 // apply any fix-ups
1825 for (uint32_t i
=0; i
< referencesCount
; ++i
) {
1826 Reference
* ref
= fReferences
[i
];
1827 uint32_t offset
= ref
->getFixUpOffset();
1828 uint32_t* instructionPtr
= (uint32_t*)&buffer
[offset
];
1829 ObjectFile::Atom
& target
= ref
->getTarget();
1830 if ( &target
== NULL
) {
1831 if ( finalLinkedImage
)
1832 throw "target not found";
1836 uint32_t instruction
;
1837 uint32_t newInstruction
;
1838 switch ( ref
->getKind() ) {
1839 case Reference::noFixUp
:
1841 case Reference::pointer
:
1843 //fprintf(stderr, "writeContent: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
1844 if ( ref
->isLazyReference() && finalLinkedImage
) {
1845 // lazy-symbol ==> pointer contains address of dyld_stub_binding_helper (stored in "from" target)
1846 *((macho_uintptr_t
*)instructionPtr
) = ENDIAN_SWAP_POINTER(ref
->getFromTarget().getAddress());
1848 else if ( target
.isImportProxy() ) {
1849 // external realocation ==> pointer contains addend
1850 *((macho_uintptr_t
*)instructionPtr
) = ENDIAN_SWAP_POINTER(ref
->getTargetOffset());
1853 // internal relocation
1854 if ( finalLinkedImage
|| (strcmp(target
.getSectionName(), "__common") != 0) ) {
1855 // pointer contains target address
1856 //printf("Atom::writeContent() target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
1857 *((macho_uintptr_t
*)instructionPtr
) = ENDIAN_SWAP_POINTER(target
.getAddress() + ref
->getTargetOffset());
1860 // pointer contains addend
1861 *((macho_uintptr_t
*)instructionPtr
) = ENDIAN_SWAP_POINTER(ref
->getTargetOffset());
1866 case Reference::ppcFixupBranch24
:
1868 //fprintf(stderr, "bl fixup to %s at 0x%08llX, ", target.getDisplayName(), target.getAddress());
1869 int64_t displacement
= (target
.getAddress() + ref
->getTargetOffset() ) - (this->getAddress() + offset
);
1870 if ( !finalLinkedImage
&& target
.isImportProxy() ) {
1871 // doing "ld -r" to an external symbol
1872 // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
1873 displacement
-= target
.getAddress();
1876 const int64_t bl_eightMegLimit
= 0x00FFFFFF;
1877 if ( (displacement
> bl_eightMegLimit
) || (displacement
< (-bl_eightMegLimit
)) ) {
1878 //fprintf(stderr, "bl out of range (%lld max is +/-16M) from %s in %s to %s in %s\n", displacement, this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
1879 throwf("bl out of range (%lld max is +/-16M) from %s in %s to %s in %s", displacement
, this->getDisplayName(), this->getFile()->getPath(), target
.getDisplayName(), target
.getFile()->getPath());
1882 instruction
= OSReadBigInt32(instructionPtr
, 0);
1883 newInstruction
= (instruction
& 0xFC000003) | ((uint32_t)displacement
& 0x03FFFFFC);
1884 //fprintf(stderr, "bl fixup: 0x%08X -> 0x%08X\n", instruction, newInstruction);
1885 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1888 case Reference::ppcFixupBranch14
:
1890 case Reference::ppcFixupPicBaseLow16
:
1892 uint64_t targetAddr
= target
.getAddress() + ref
->getTargetOffset();
1893 uint64_t picBaseAddr
= this->getAddress() + ref
->getFromTargetOffset();
1894 int64_t displacement
= targetAddr
- picBaseAddr
;
1895 const int64_t picbase_twoGigLimit
= 0x80000000;
1896 if ( (displacement
> picbase_twoGigLimit
) || (displacement
< (-picbase_twoGigLimit
)) )
1897 throw "32-bit pic-base out of range";
1898 uint16_t instructionLowHalf
= (displacement
& 0xFFFF);
1899 instruction
= OSReadBigInt32(instructionPtr
, 0);
1900 newInstruction
= (instruction
& 0xFFFF0000) | instructionLowHalf
;
1901 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1904 case Reference::ppcFixupPicBaseLow14
:
1906 uint64_t targetAddr
= target
.getAddress() + ref
->getTargetOffset();
1907 uint64_t picBaseAddr
= this->getAddress() + ref
->getFromTargetOffset();
1908 int64_t displacement
= targetAddr
- picBaseAddr
;
1909 const int64_t picbase_twoGigLimit
= 0x80000000;
1910 if ( (displacement
> picbase_twoGigLimit
) || (displacement
< (-picbase_twoGigLimit
)) )
1911 throw "32-bit pic-base out of range";
1912 uint16_t instructionLowHalf
= (displacement
& 0xFFFF);
1913 if ( (instructionLowHalf
& 0x3) != 0 )
1914 throw "bad address for lo14 instruction fix-up";
1915 instruction
= OSReadBigInt32(instructionPtr
, 0);
1916 newInstruction
= (instruction
& 0xFFFF0003) | instructionLowHalf
;
1917 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1920 case Reference::ppcFixupPicBaseHigh16
:
1922 uint64_t targetAddr
= target
.getAddress() + ref
->getTargetOffset();
1923 uint64_t picBaseAddr
= this->getAddress() + ref
->getFromTargetOffset();
1924 int64_t displacement
= targetAddr
- picBaseAddr
;
1925 const int64_t picbase_twoGigLimit
= 0x80000000;
1926 if ( (displacement
> picbase_twoGigLimit
) || (displacement
< (-picbase_twoGigLimit
)) )
1927 throw "32-bit pic-base out of range";
1928 uint16_t instructionLowHalf
= displacement
>> 16;
1929 if ( (displacement
& 0x00008000) != 0 )
1930 ++instructionLowHalf
;
1931 instruction
= OSReadBigInt32(instructionPtr
, 0);
1932 newInstruction
= (instruction
& 0xFFFF0000) | instructionLowHalf
;
1933 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1936 case Reference::ppcFixupAbsLow16
:
1938 int64_t addr
= target
.getAddress() + ref
->getTargetOffset();
1939 if ( !finalLinkedImage
&& target
.isImportProxy() )
1940 addr
-= target
.getAddress() ;
1941 uint16_t instructionLowHalf
= (addr
& 0xFFFF);
1942 instruction
= OSReadBigInt32(instructionPtr
, 0);
1943 newInstruction
= (instruction
& 0xFFFF0000) | instructionLowHalf
;
1944 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1947 case Reference::ppcFixupAbsLow14
:
1949 int64_t addr
= target
.getAddress() + ref
->getTargetOffset();
1950 if ( !finalLinkedImage
&& target
.isImportProxy() )
1951 addr
-= target
.getAddress() ;
1952 uint16_t instructionLowHalf
= (addr
& 0xFFFF);
1953 if ( (instructionLowHalf
& 0x3) != 0 )
1954 throw "bad address for lo14 instruction fix-up";
1955 instruction
= OSReadBigInt32(instructionPtr
, 0);
1956 newInstruction
= (instruction
& 0xFFFF0003) | instructionLowHalf
;
1957 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1960 case Reference::ppcFixupAbsHigh16
:
1962 int64_t addr
= target
.getAddress() + ref
->getTargetOffset();
1963 if ( !finalLinkedImage
&& target
.isImportProxy() )
1964 addr
-= target
.getAddress() ;
1965 uint16_t hi16
= (addr
>> 16);
1966 instruction
= OSReadBigInt32(instructionPtr
, 0);
1967 newInstruction
= (instruction
& 0xFFFF0000) | hi16
;
1968 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1971 case Reference::ppcFixupAbsHigh16AddLow
:
1973 int64_t addr
= target
.getAddress() + ref
->getTargetOffset();
1974 if ( !finalLinkedImage
&& target
.isImportProxy() )
1975 addr
-= target
.getAddress() ;
1976 if ( addr
& 0x00008000 )
1978 instruction
= OSReadBigInt32(instructionPtr
, 0);
1979 newInstruction
= (instruction
& 0xFFFF0000) | (addr
>> 16);
1980 OSWriteBigInt32(instructionPtr
, 0, newInstruction
);
1983 case Reference::pointer32Difference
:
1984 ENDIAN_WRITE32(*instructionPtr
, target
.getAddress() + ref
->getTargetOffset() - (ref
->getFromTarget().getAddress() + ref
->getFromTargetOffset()));
1986 case Reference::pointer64Difference
:
1987 *((uint64_t*)instructionPtr
) = ENDIAN_SWAP64(target
.getAddress() + ref
->getTargetOffset() - (ref
->getFromTarget().getAddress() + ref
->getFromTargetOffset()));
1989 case Reference::x86FixupBranch32
:
1991 int64_t displacement
= target
.getAddress() - (this->getAddress() + offset
);
1992 if ( target
.isImportProxy() ) {
1996 const int64_t bl_twoGigLimit
= 0x7FFFFFFF;
1997 if ( (displacement
> bl_twoGigLimit
) || (displacement
< (-bl_twoGigLimit
)) ) {
1998 //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
1999 throw "call out of range";
2002 OSWriteLittleInt32(instructionPtr
, 0, (int32_t)displacement
);
2009 writer
.write(0, buffer
, getSize());
2014 const macho_section
* Atom::findSectionFromOffset(uint32_t offset
)
2016 const macho_section
* const sectionsStart
= (const macho_section
*)( (char*)fOwner
.fSegment
+ sizeof(macho_segment_command
) );
2017 const macho_section
* const sectionsEnd
= §ionsStart
[fOwner
.fSegment
->nsects()];
2018 for (const macho_section
* s
= sectionsStart
; s
< sectionsEnd
; ++s
) {
2019 if ( (s
->addr() <= offset
) && (offset
< (s
->addr()+s
->size())) )
2022 throwf("address 0x%08X is not in any section", offset
);
2025 void Atom::setSize(macho_uintptr_t size
)
2031 void Atom::setFollowOnAtom(Atom
&)
2036 Reference
* Atom::addReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
)
2038 if ( (target
.getScope() != ObjectFile::Atom::scopeTranslationUnit
) && ((target
.fSymbol
!= NULL
) || (target
.fSynthesizedName
!= NULL
)) )
2039 return this->addByNameReference(offsetInSrcAtom
, kind
, target
.getName(), offsetInTarget
, offsetInFromTarget
);
2041 return this->addDirectReference(offsetInSrcAtom
, kind
, target
, offsetInTarget
, offsetInFromTarget
);
2045 Reference
* Atom::addDirectReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
)
2047 Reference
* ref
= new Reference(offsetInSrcAtom
, kind
, target
, offsetInTarget
, offsetInFromTarget
);
2048 // in rare cases, there may already be a by-name reference to the same atom. If so, replace with this direct reference
2049 for (std::vector
<Reference
*>::iterator it
=fReferences
.begin(); it
!= fReferences
.end(); it
++) {
2050 ObjectFile::Reference
* aRef
= *it
;
2051 if ( (aRef
->getFixUpOffset() == offsetInSrcAtom
) && (aRef
->getKind() == kind
) ) {
2057 // note: adding to start of list because mach-o relocs are in reverse offset order in the .o file
2058 fReferences
.insert(fReferences
.begin(), ref
);
2062 Reference
* Atom::addByNameReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, const char* targetName
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
)
2064 Reference
* ref
= new Reference(offsetInSrcAtom
, kind
, targetName
, offsetInTarget
, offsetInFromTarget
);
2065 // note: adding to start of list because mach-o relocs are in reverse offset order in the .o file
2066 fReferences
.insert(fReferences
.begin(), ref
);
2070 Reference
* Atom::addDifferenceReference(macho_uintptr_t offsetInSrcAtom
, Reference::Kind kind
, Atom
& target
, uint64_t offsetInTarget
, Atom
& fromTarget
, uint64_t offsetInFromTarget
)
2072 Reference
* ref
= new Reference(offsetInSrcAtom
, kind
, target
, offsetInTarget
, fromTarget
, offsetInFromTarget
);
2073 // note: adding to start of list because mach-o relocs are in reverse offset order in the .o file
2074 fReferences
.insert(fReferences
.begin(), ref
);
2079 Segment::Segment(const macho_section
* sect
)
2084 const char* Segment::getName() const
2086 return fSection
->segname();
2089 bool Segment::isContentReadable() const
2094 bool Segment::isContentWritable() const
2096 if ( strcmp(fSection
->segname(), "__DATA") == 0 )
2098 if ( strcmp(fSection
->segname(), "__OBJC") == 0 )
2103 bool Segment::isContentExecutable() const
2105 return ( strcmp(fSection
->segname(), "__TEXT") == 0 );
2109 Reference::Reference(macho_uintptr_t fixUpOffset
, Kind kind
, const char* targetName
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
)
2110 : fTarget(NULL
), fFromTarget(NULL
), fTargetName(targetName
), fFromTargetName(NULL
), fTargetOffset(offsetInTarget
), fFromTargetOffset(offsetInFromTarget
),
2111 fFixUpOffsetInSrc(fixUpOffset
), fKind(kind
), fLazy(false), fWeak(false)
2115 Reference::Reference(macho_uintptr_t fixUpOffset
, Kind kind
, class Atom
& target
, uint64_t offsetInTarget
, uint64_t offsetInFromTarget
)
2116 : fTarget(&target
), fFromTarget(NULL
), fTargetName(NULL
), fFromTargetName(NULL
), fTargetOffset(offsetInTarget
), fFromTargetOffset(offsetInFromTarget
),
2117 fFixUpOffsetInSrc(fixUpOffset
), fKind(kind
), fLazy(false), fWeak(false)
2121 Reference::Reference(macho_uintptr_t fixUpOffset
, Kind kind
, class Atom
& target
, uint64_t offsetInTarget
, class Atom
& fromTarget
, uint64_t offsetInFromTarget
)
2122 : fTarget(&target
), fFromTarget(&fromTarget
), fTargetName(NULL
), fFromTargetName(NULL
), fTargetOffset(offsetInTarget
), fFromTargetOffset(offsetInFromTarget
),
2123 fFixUpOffsetInSrc(fixUpOffset
), fKind(kind
), fLazy(false), fWeak(false)
2125 // assure no direct references to something that might be coalesced
2126 if ( (target
.isWeakDefinition() || target
.isCoalesableByName()) && (target
.getScope() != ObjectFile::Atom::scopeTranslationUnit
) && (target
.getName() != NULL
) ) {
2127 //fprintf(stderr, "change TO direct reference to by-name: from %s to %s in %p\n", fromTarget.getDisplayName(), target.getName(), this);
2128 fTargetName
= target
.getName();
2131 // Note: We should also allow by-name from references, but many other chunks of code assume from targets are always direct//
2132 // if ( (fromTarget.isWeakDefinition() || fromTarget.isCoalesableByName()) && (fromTarget.getScope() != ObjectFile::Atom::scopeTranslationUnit) && (fromTarget.getName() != NULL)) {
2133 // fprintf(stderr, "change FROM direct reference to by-name: from %s to %s in %p\n", fromTarget.getDisplayName(), target.getName(), this);
2134 // fFromTargetName = fromTarget.getName();
2135 // fFromTarget = NULL;
2141 Reference::~Reference()
2145 bool Reference::isTargetUnbound() const
2147 return ( fTarget
== NULL
);
2150 bool Reference::isFromTargetUnbound() const
2152 return ( fFromTarget
== NULL
);
2155 bool Reference::isWeakReference() const
2160 bool Reference::requiresRuntimeFixUp(bool slideable
) const
2162 // This static linker only supports pure code (no code fixups are runtime)
2163 #if defined(ARCH_PPC) || defined(ARCH_PPC64)
2164 // Only data can be fixed up, and the codegen assures only "pointers" need runtime fixups
2165 return ( (fKind
== Reference::pointer
) && (fTarget
->isImportProxy() || fTarget
->isWeakDefinition() || slideable
) );
2166 #elif defined(ARCH_I386)
2167 // For i386, Reference::pointer is used for both data pointers and instructions with 32-bit absolute operands
2168 if ( fKind
== Reference::pointer
) {
2169 if ( fTarget
->isImportProxy() )
2180 bool Reference::isLazyReference() const
2185 ObjectFile::Reference::Kind
Reference::getKind() const
2190 uint64_t Reference::getFixUpOffset() const
2192 return fFixUpOffsetInSrc
;
2195 const char* Reference::getTargetName() const
2197 if ( fTargetName
!= NULL
)
2199 return fTarget
->getName();
2202 ObjectFile::Atom
& Reference::getTarget() const
2207 void Reference::setTarget(ObjectFile::Atom
& target
, uint64_t offset
)
2210 fTargetOffset
= offset
;
2214 ObjectFile::Atom
& Reference::getFromTarget() const
2216 return *fFromTarget
;
2219 bool Reference::hasFromTarget() const
2221 return ( (fFromTarget
!= NULL
) || (fFromTargetName
!= NULL
) );
2224 const char* Reference::getFromTargetName() const
2226 if ( fFromTargetName
!= NULL
)
2227 return fFromTargetName
;
2228 return fFromTarget
->getName();
2231 void Reference::setFromTarget(ObjectFile::Atom
& target
)
2233 fFromTarget
= &target
;
2236 void Reference::setFromTargetName(const char* name
)
2238 fFromTargetName
= name
;
2241 void Reference::setFromTargetOffset(uint64_t offset
)
2243 fFromTargetOffset
= offset
;
2246 uint64_t Reference::getTargetOffset() const
2248 return fTargetOffset
;
2252 uint64_t Reference::getFromTargetOffset() const
2254 return fFromTargetOffset
;
2257 void Reference::setLazy(bool lazy
)
2262 void Reference::setWeak(bool weak
)
2267 const char* Reference::getDescription() const
2269 static char temp
[256];
2270 if ( fKind
== pointer32Difference
) {
2271 // by-name references have quoted names
2272 bool targetByName
= ( &(this->getTarget()) == NULL
);
2273 bool fromByName
= ( &(this->getFromTarget()) == NULL
);
2274 const char* targetQuotes
= targetByName
? "\"" : "";
2275 const char* fromQuotes
= fromByName
? "\"" : "";
2276 sprintf(temp
, "offset 0x%04llX, 32-bit pointer difference: (&%s%s%s + %lld) - (&%s%s%s + %lld)",
2277 this->getFixUpOffset(), targetQuotes
, this->getTargetName(), targetQuotes
, this->getTargetOffset(),
2278 fromQuotes
, this->getFromTargetName(), fromQuotes
, this->getFromTargetOffset() );
2280 else if ( fKind
== pointer64Difference
) {
2281 // by-name references have quoted names
2282 bool targetByName
= ( &(this->getTarget()) == NULL
);
2283 bool fromByName
= ( &(this->getFromTarget()) == NULL
);
2284 const char* targetQuotes
= targetByName
? "\"" : "";
2285 const char* fromQuotes
= fromByName
? "\"" : "";
2286 sprintf(temp
, "offset 0x%04llX, 64-bit pointer difference: (&%s%s%s + %lld) - (&%s%s%s + %lld)",
2287 this->getFixUpOffset(), targetQuotes
, this->getTargetName(), targetQuotes
, this->getTargetOffset(),
2288 fromQuotes
, this->getFromTargetName(), fromQuotes
, this->getFromTargetOffset() );
2293 sprintf(temp
, "reference to ");
2297 const char* weak
= "";
2300 const char* lazy
= "";
2303 sprintf(temp
, "offset 0x%04llX, %s%spointer to ", this->getFixUpOffset(), weak
, lazy
);
2306 case ppcFixupBranch14
:
2307 case ppcFixupBranch24
:
2308 sprintf(temp
, "offset 0x%04llX, bl pc-rel fixup to ", this->getFixUpOffset());
2310 case ppcFixupPicBaseLow16
:
2311 sprintf(temp
, "offset 0x%04llX, low 16 fixup from pic-base offset 0x%04llX to ", this->getFixUpOffset(), this->getFromTargetOffset());
2313 case ppcFixupPicBaseLow14
:
2314 sprintf(temp
, "offset 0x%04llX, low 14 fixup from pic-base offset 0x%04llX to ", this->getFixUpOffset(), this->getFromTargetOffset());
2316 case ppcFixupPicBaseHigh16
:
2317 sprintf(temp
, "offset 0x%04llX, high 16 fixup from pic-base offset 0x%04llX to ", this->getFixUpOffset(), this->getFromTargetOffset());
2319 case ppcFixupAbsLow16
:
2320 sprintf(temp
, "offset 0x%04llX, low 16 fixup to absolute address of ", this->getFixUpOffset());
2322 case ppcFixupAbsLow14
:
2323 sprintf(temp
, "offset 0x%04llX, low 14 fixup to absolute address of ", this->getFixUpOffset());
2325 case ppcFixupAbsHigh16
:
2326 sprintf(temp
, "offset 0x%04llX, high 16 fixup to absolute address of ", this->getFixUpOffset());
2328 case ppcFixupAbsHigh16AddLow
:
2329 sprintf(temp
, "offset 0x%04llX, high 16 fixup to absolute address of ", this->getFixUpOffset());
2331 case pointer32Difference
:
2332 case pointer64Difference
:
2335 case x86FixupBranch32
:
2336 sprintf(temp
, "offset 0x%04llX, pc-rel fixup to ", this->getFixUpOffset());
2339 // always quote by-name references
2340 if ( fTargetName
!= NULL
) {
2342 strcat(temp
, fTargetName
);
2345 else if ( fTarget
!= NULL
) {
2346 strcat(temp
, fTarget
->getDisplayName());
2349 strcat(temp
, "NULL target");
2351 if ( fTargetOffset
!= 0 )
2352 sprintf(&temp
[strlen(temp
)], " plus 0x%08llX", this->getTargetOffset());
2353 if ( (fKind
==pointer
) && fLazy
) {
2354 strcat(temp
, " initially bound to \"");
2355 if ( (fFromTarget
!= NULL
) || (fFromTargetName
!= NULL
) ) {
2356 strcat(temp
, this->getFromTargetName());
2358 if ( this->getFromTargetOffset() != 0 )
2359 sprintf(&temp
[strlen(temp
)], " plus 0x%08llX", this->getFromTargetOffset());
2362 strcat(temp
, "\" << missing >>");