]> git.saurik.com Git - apple/ld64.git/blob - src/ld/MachOReaderRelocatable.hpp
ld64-97.17.tar.gz
[apple/ld64.git] / src / ld / MachOReaderRelocatable.hpp
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2005-2009 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
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
12 * file.
13 *
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.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #ifndef __OBJECT_FILE_MACH_O__
26 #define __OBJECT_FILE_MACH_O__
27
28 #include <stdint.h>
29 #include <math.h>
30 #include <unistd.h>
31 #include <sys/param.h>
32
33 #include <vector>
34 #include <set>
35 #include <algorithm>
36
37 #include "MachOFileAbstraction.hpp"
38 #include "Architectures.hpp"
39 #include "ObjectFile.h"
40 #include "dwarf2.h"
41 #include "debugline.h"
42
43 #include <libunwind/DwarfInstructions.hpp>
44 #include <libunwind/AddressSpace.hpp>
45 #include <libunwind/Registers.hpp>
46
47 //
48 //
49 // To implement architecture xxx, you must write template specializations for the following six methods:
50 // Reader<xxx>::validFile()
51 // Reader<xxx>::validSectionType()
52 // Reader<xxx>::addRelocReference()
53 // Reference<xxx>::getDescription()
54 //
55 //
56
57
58
59 extern __attribute__((noreturn)) void throwf(const char* format, ...);
60 extern void warning(const char* format, ...);
61
62 namespace mach_o {
63 namespace relocatable {
64
65
66
67 class ReferenceSorter
68 {
69 public:
70 bool operator()(const ObjectFile::Reference* left, const ObjectFile::Reference* right)
71 {
72 return ( left->getFixUpOffset() < right->getFixUpOffset() );
73 }
74 };
75
76
77 // forward reference
78 template <typename A> class Reader;
79
80 struct AtomAndOffset
81 {
82 AtomAndOffset(ObjectFile::Atom* a=NULL) : atom(a), offset(0) {}
83 AtomAndOffset(ObjectFile::Atom* a, uint32_t off) : atom(a), offset(off) {}
84 ObjectFile::Atom* atom;
85 uint32_t offset;
86 };
87
88
89 template <typename A>
90 class Reference : public ObjectFile::Reference
91 {
92 public:
93 typedef typename A::P P;
94 typedef typename A::P::uint_t pint_t;
95 typedef typename A::ReferenceKinds Kinds;
96
97 Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset& toTarget);
98 Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset& fromTarget, const AtomAndOffset& toTarget);
99 Reference(Kinds kind, const AtomAndOffset& at, const char* toName, uint32_t toOffset);
100
101 virtual ~Reference() {}
102
103
104 virtual ObjectFile::Reference::TargetBinding getTargetBinding() const;
105 virtual ObjectFile::Reference::TargetBinding getFromTargetBinding() const;
106 virtual uint8_t getKind() const { return (uint8_t)fKind; }
107 virtual uint64_t getFixUpOffset() const { return fFixUpOffsetInSrc; }
108 virtual const char* getTargetName() const { return (fToTarget.atom != NULL) ? fToTarget.atom->getName() : fToTargetName; }
109 virtual ObjectFile::Atom& getTarget() const { return *fToTarget.atom; }
110 virtual uint64_t getTargetOffset() const { return (int64_t)((int32_t)fToTarget.offset); }
111 virtual ObjectFile::Atom& getFromTarget() const { return *fFromTarget.atom; }
112 virtual const char* getFromTargetName() const { return (fFromTarget.atom != NULL) ? fFromTarget.atom->getName() : fFromTargetName; }
113 virtual void setTarget(ObjectFile::Atom& target, uint64_t offset) { fToTarget.atom = &target; fToTarget.offset = offset; }
114 virtual void setToTargetOffset(uint64_t offset) { fToTarget.offset = offset; }
115 virtual void setFromTarget(ObjectFile::Atom& target) { fFromTarget.atom = &target; }
116 virtual void setFromTargetName(const char* name) { fFromTargetName = name; }
117 virtual void setFromTargetOffset(uint64_t offset) { fFromTarget.offset = offset; }
118 virtual const char* getDescription() const;
119 virtual uint64_t getFromTargetOffset() const { return fFromTarget.offset; }
120 virtual bool isBranch() const;
121 virtual const char* getTargetDisplayName() const { return (fToTarget.atom != NULL) ? fToTarget.atom->getDisplayName() : fToTargetName; }
122 virtual const char* getFromTargetDisplayName() const { return (fFromTarget.atom != NULL) ? fFromTarget.atom->getDisplayName() : fFromTargetName; }
123
124 static bool fgForFinalLinkedImage;
125
126 private:
127 pint_t fFixUpOffsetInSrc;
128 AtomAndOffset fToTarget;
129 AtomAndOffset fFromTarget;
130 const char* fToTargetName;
131 const char* fFromTargetName;
132 Kinds fKind;
133
134 };
135
136
137 template <typename A> bool Reference<A>::fgForFinalLinkedImage = true;
138
139 template <typename A>
140 Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset& toTarget)
141 : fFixUpOffsetInSrc(at.offset), fToTarget(toTarget), fToTargetName(NULL), fFromTargetName(NULL),
142 fKind(kind)
143 {
144 // make reference a by-name unless:
145 // - the reference type is only used with direct references
146 // - the target is translation unit scoped
147 // - the target kind is not regular (is weak or tentative)
148 if ( (kind != A::kNoFixUp) && (kind != A::kFollowOn) && (kind != A::kGroupSubordinate)
149 && (toTarget.atom->getScope() != ObjectFile::Atom::scopeTranslationUnit)
150 && (toTarget.atom->getDefinitionKind() != ObjectFile::Atom::kRegularDefinition)
151 && (toTarget.atom != at.atom) ) {
152 fToTargetName = toTarget.atom->getName();
153 //fprintf(stderr, "Reference(): changing to by-name %p %s, target scope=%d, target section=%s\n", toTarget.atom, fToTargetName, toTarget.atom->getScope(), toTarget.atom->getSectionName());
154 fToTarget.atom = NULL;
155 }
156 ((class BaseAtom*)at.atom)->addReference(this);
157 //fprintf(stderr, "Reference(): %p fToTarget<%s, %08X>\n", this, (fToTarget.atom != NULL) ? fToTarget.atom->getDisplayName() : fToTargetName , fToTarget.offset);
158 }
159
160 template <typename A>
161 Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const AtomAndOffset& fromTarget, const AtomAndOffset& toTarget)
162 : fFixUpOffsetInSrc(at.offset), fToTarget(toTarget), fFromTarget(fromTarget),
163 fToTargetName(NULL), fFromTargetName(NULL), fKind(kind)
164 {
165 // make reference a by-name where needed
166 if ( (kind != A::kNoFixUp) && (kind != A::kFollowOn) && (kind != A::kGroupSubordinate)
167 && (toTarget.atom->getScope() != ObjectFile::Atom::scopeTranslationUnit)
168 && (toTarget.atom->getDefinitionKind() != ObjectFile::Atom::kRegularDefinition)
169 && (toTarget.atom != at.atom) ) {
170 fToTargetName = toTarget.atom->getName();
171 fToTarget.atom = NULL;
172 }
173 ((class BaseAtom*)at.atom)->addReference(this);
174 //fprintf(stderr, "Reference(): %p kind=%d, fToTarget<%s, %08X>, fromTarget<%s, %08X>\n", this, kind,
175 // this->getTargetName(), fToTarget.offset, this->getFromTargetName(), fromTarget.offset);
176 }
177
178 template <typename A>
179 Reference<A>::Reference(Kinds kind, const AtomAndOffset& at, const char* toName, uint32_t toOffset)
180 : fFixUpOffsetInSrc(at.offset),
181 fToTargetName(toName), fFromTargetName(NULL), fKind(kind)
182 {
183 fToTarget.offset = toOffset;
184 ((class BaseAtom*)at.atom)->addReference(this);
185 }
186
187 template <typename A>
188 ObjectFile::Reference::TargetBinding Reference<A>::getTargetBinding() const
189 {
190 if ( fgForFinalLinkedImage ) {
191 if ( (fKind == A::kDtraceProbe) || (fKind == A::kDtraceProbeSite) || (fKind == A::kDtraceIsEnabledSite) || (fKind == A::kDtraceTypeReference) )
192 return ObjectFile::Reference::kDontBind;
193 }
194 if ( fToTarget.atom == NULL )
195 return ObjectFile::Reference::kUnboundByName;
196 if ( fToTargetName == NULL )
197 return ObjectFile::Reference::kBoundDirectly;
198 else
199 return ObjectFile::Reference::kBoundByName;
200 }
201
202 template <typename A>
203 ObjectFile::Reference::TargetBinding Reference<A>::getFromTargetBinding() const
204 {
205 if ( fFromTarget.atom == NULL ) {
206 if ( fFromTargetName == NULL )
207 return ObjectFile::Reference::kDontBind;
208 else
209 return ObjectFile::Reference::kUnboundByName;
210 }
211 else {
212 if ( fFromTargetName == NULL )
213 return ObjectFile::Reference::kBoundDirectly;
214 else
215 return ObjectFile::Reference::kBoundByName;
216 }
217 }
218
219
220
221 template <typename A>
222 class Segment : public ObjectFile::Segment
223 {
224 public:
225 Segment(const macho_section<typename A::P>* sect);
226 virtual const char* getName() const { return fSection->segname(); }
227 virtual bool isContentReadable() const { return true; }
228 virtual bool isContentWritable() const { return fWritable; }
229 virtual bool isContentExecutable() const { return fExecutable; }
230 private:
231 const macho_section<typename A::P>* fSection;
232 bool fWritable;
233 bool fExecutable;
234 };
235
236 template <typename A>
237 Segment<A>::Segment(const macho_section<typename A::P>* sect)
238 : fSection(sect), fWritable(true), fExecutable(false)
239 {
240 if ( strcmp(fSection->segname(), "__TEXT") == 0 ) {
241 fWritable = false;
242 fExecutable = true;
243 }
244 else if ( strcmp(fSection->segname(), "__IMPORT") == 0 ) {
245 fWritable = true;
246 fExecutable = true;
247 }
248 }
249
250
251 class DataSegment : public ObjectFile::Segment
252 {
253 public:
254 virtual const char* getName() const { return "__DATA"; }
255 virtual bool isContentReadable() const { return true; }
256 virtual bool isContentWritable() const { return true; }
257 virtual bool isContentExecutable() const { return false; }
258
259 static DataSegment fgSingleton;
260 };
261
262 DataSegment DataSegment::fgSingleton;
263
264 class LinkEditSegment : public ObjectFile::Segment
265 {
266 public:
267 virtual const char* getName() const { return "__LINKEDIT"; }
268 virtual bool isContentReadable() const { return true; }
269 virtual bool isContentWritable() const { return false; }
270 virtual bool isContentExecutable() const { return false; }
271
272 static LinkEditSegment fgSingleton;
273 };
274
275 LinkEditSegment LinkEditSegment::fgSingleton;
276
277 class BaseAtom : public ObjectFile::Atom
278 {
279 public:
280 BaseAtom() : fStabsStartIndex(0), fStabsCount(0), fHasCompactUnwindInfo(false) {}
281
282 virtual void setSize(uint64_t size) = 0;
283 virtual void addReference(ObjectFile::Reference* ref) = 0;
284 virtual void sortReferences() = 0;
285 virtual void addLineInfo(const ObjectFile::LineInfo& info) = 0;
286 virtual const ObjectFile::ReaderOptions& getOptions() const = 0;
287 virtual uint64_t getObjectAddress() const = 0;
288 virtual uint32_t getOrdinal() const { return fOrdinal; }
289 virtual void setOrdinal(uint32_t value) { fOrdinal = value; }
290 virtual const void* getSectionRecord() const = 0;
291 virtual unsigned int getSectionIndex() const = 0;
292 virtual bool isAlias() const { return false; }
293 virtual uint8_t getLSDAReferenceKind() const { return 0; }
294 virtual uint8_t getPersonalityReferenceKind() const { return 0; }
295 virtual uint32_t getCompactUnwindEncoding(uint64_t ehAtomAddress) { return 0; }
296 virtual ObjectFile::UnwindInfo::iterator beginUnwind() { return fHasCompactUnwindInfo ? &fSingleUnwindInfo[0] : NULL; }
297 virtual ObjectFile::UnwindInfo::iterator endUnwind() { return fHasCompactUnwindInfo ? &fSingleUnwindInfo[1] : NULL; }
298 virtual ObjectFile::Reference* getLSDA();
299 virtual ObjectFile::Reference* getFDE();
300 virtual Atom* getPersonalityPointer();
301 virtual void setCompactUnwindEncoding(uint64_t ehAtomAddress);
302
303 uint32_t fStabsStartIndex;
304 uint32_t fStabsCount;
305 uint32_t fOrdinal;
306 ObjectFile::UnwindInfo fSingleUnwindInfo[1];
307 bool fHasCompactUnwindInfo;
308 };
309
310
311 ObjectFile::Reference* BaseAtom::getLSDA()
312 {
313 const uint8_t groupKind = this->getLSDAReferenceKind();
314 const std::vector<ObjectFile::Reference*>& refs = this->getReferences();
315 for (std::vector<ObjectFile::Reference*>::const_iterator it=refs.begin(); it != refs.end(); it++) {
316 ObjectFile::Reference* ref = *it;
317 if ( (ref->getKind() == groupKind) && (ref->getTarget().getContentType() == ObjectFile::Atom::kLSDAType) ) {
318 return ref;
319 }
320 }
321 return NULL;
322 }
323
324 ObjectFile::Reference* BaseAtom::getFDE()
325 {
326 const uint8_t groupKind = this->getLSDAReferenceKind();
327 const std::vector<ObjectFile::Reference*>& refs = this->getReferences();
328 for (std::vector<ObjectFile::Reference*>::const_iterator it=refs.begin(); it != refs.end(); it++) {
329 ObjectFile::Reference* ref = *it;
330 if ( (ref->getKind() == groupKind) && (ref->getTarget().getContentType() == ObjectFile::Atom::kCFIType) ) {
331 return ref;
332 }
333 }
334 return NULL;
335 }
336
337 ObjectFile::Atom* BaseAtom::getPersonalityPointer()
338 {
339 const uint8_t personalityKind = this->getPersonalityReferenceKind();
340 const std::vector<ObjectFile::Reference*>& refs = this->getReferences();
341 for (std::vector<ObjectFile::Reference*>::const_iterator it=refs.begin(); it != refs.end(); it++) {
342 ObjectFile::Reference* ref = *it;
343 if ( ref->getKind() == personalityKind ) {
344 if ( strcmp(ref->getTarget().getSectionName(), "__nl_symbol_ptr") == 0 )
345 return &ref->getTarget();
346 if ( strcmp(ref->getTarget().getSectionName(), "__pointers") == 0 )
347 return &ref->getTarget();
348 }
349 }
350 return NULL;
351 }
352
353
354 void BaseAtom::setCompactUnwindEncoding(uint64_t ehAtomAddress)
355 {
356 fSingleUnwindInfo[0].unwindInfo = this->getCompactUnwindEncoding(ehAtomAddress);
357 fHasCompactUnwindInfo = true;
358 }
359
360
361 class BaseAtomSorter
362 {
363 public:
364 bool operator()(const class BaseAtom* left, const class BaseAtom* right) {
365 if ( left == right )
366 return false;
367 uint64_t leftAddr = left->getObjectAddress();
368 uint64_t rightAddr = right->getObjectAddress();
369 if ( leftAddr < rightAddr ) {
370 return true;
371 }
372 else if ( leftAddr > rightAddr ) {
373 return false;
374 }
375 else {
376 // if they have same address, one might be the end of a section and the other the start of the next section
377 const void* leftSection = left->getSectionRecord();
378 const void* rightSection = right->getSectionRecord();
379 if ( leftSection != rightSection ) {
380 return ( leftSection < rightSection );
381 }
382 // if they have same address and section, one might be an alias
383 bool leftAlias = left->isAlias();
384 bool rightAlias = right->isAlias();
385 if ( leftAlias && rightAlias ) {
386 // sort multiple aliases for same address first by scope
387 ObjectFile::Atom::Scope leftScope = left->getScope();
388 ObjectFile::Atom::Scope rightScope = right->getScope();
389 if ( leftScope != rightScope ) {
390 return ( leftScope < rightScope );
391 }
392 // sort multiple aliases for same address then by name
393 return ( strcmp(left->getName(), right->getName()) < 0 );
394 }
395 else if ( leftAlias ) {
396 return true;
397 }
398 else if ( rightAlias ) {
399 return false;
400 }
401 // one might be a section start or end label
402 switch ( left->getContentType() ) {
403 case ObjectFile::Atom::kSectionStart:
404 return true;
405 case ObjectFile::Atom::kSectionEnd:
406 return false;
407 default:
408 break;
409 }
410 switch ( right->getContentType() ) {
411 case ObjectFile::Atom::kSectionStart:
412 return false;
413 case ObjectFile::Atom::kSectionEnd:
414 return true;
415 default:
416 break;
417 }
418 // they could be tentative defintions
419 switch ( left->getDefinitionKind() ) {
420 case ObjectFile::Atom::kTentativeDefinition:
421 // sort tentative definitions by name
422 return ( strcmp(left->getName(), right->getName()) < 0 );
423 case ObjectFile::Atom::kAbsoluteSymbol:
424 // sort absolute symbols with same address by name
425 return ( strcmp(left->getName(), right->getName()) < 0 );
426 default:
427 // hack for rdar://problem/5102873
428 if ( !left->isZeroFill() || !right->isZeroFill() )
429 warning("atom sorting error for %s and %s in %s", left->getDisplayName(), right->getDisplayName(), left->getFile()->getPath());
430 break;
431 }
432 }
433 return false;
434 }
435 };
436
437
438 //
439 // A SymbolAtom represents a chunk of a mach-o object file that has a symbol table entry
440 // pointing to it. A C function or global variable is represented by one of these atoms.
441 //
442 //
443 template <typename A>
444 class SymbolAtom : public BaseAtom
445 {
446 public:
447 virtual ObjectFile::Reader* getFile() const { return &fOwner; }
448 virtual bool getTranslationUnitSource(const char** dir, const char** name) const
449 { return fOwner.getTranslationUnitSource(dir, name); }
450 virtual const char* getName() const { return &fOwner.fStrings[fSymbol->n_strx()]; }
451 virtual const char* getDisplayName() const { return getName(); }
452 virtual ObjectFile::Atom::Scope getScope() const { return fScope; }
453 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ((fSymbol->n_desc() & N_WEAK_DEF) != 0)
454 ? ObjectFile::Atom::kWeakDefinition : ObjectFile::Atom::kRegularDefinition; }
455 virtual ObjectFile::Atom::ContentType getContentType() const { return fType; }
456 virtual SymbolTableInclusion getSymbolTableInclusion() const { return fSymbolTableInclusion; }
457 virtual bool dontDeadStrip() const;
458 virtual bool isZeroFill() const;
459 virtual bool isThumb() const { return ((fSymbol->n_desc() & N_ARM_THUMB_DEF) != 0); }
460 virtual uint64_t getSize() const { return fSize; }
461 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
462 virtual bool mustRemainInSection() const { return true; }
463 virtual const char* getSectionName() const;
464 virtual Segment<A>& getSegment() const { return *fSegment; }
465 virtual ObjectFile::Atom& getFollowOnAtom() const;
466 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return (std::vector<ObjectFile::LineInfo>*)&fLineInfo; }
467 virtual ObjectFile::Alignment getAlignment() const { return fAlignment; }
468 virtual void copyRawContent(uint8_t buffer[]) const;
469 virtual void setScope(ObjectFile::Atom::Scope newScope) { fScope = newScope; }
470 virtual void setSize(uint64_t size);
471 virtual void addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
472 virtual void sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
473 virtual void addLineInfo(const ObjectFile::LineInfo& info) { fLineInfo.push_back(info); }
474 virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; }
475 virtual uint64_t getObjectAddress() const { return fAddress; }
476 virtual const void* getSectionRecord() const { return (const void*)fSection; }
477 virtual unsigned int getSectionIndex() const { return 1 + (fSection - fOwner.fSectionsStart); }
478 virtual uint8_t getLSDAReferenceKind() const;
479 virtual uint8_t getPersonalityReferenceKind() const;
480 virtual uint32_t getCompactUnwindEncoding(uint64_t ehAtomAddress);
481
482 protected:
483 typedef typename A::P P;
484 typedef typename A::P::E E;
485 typedef typename A::P::uint_t pint_t;
486 typedef typename A::ReferenceKinds Kinds;
487 typedef typename std::vector<Reference<A>*> ReferenceVector;
488 typedef typename ReferenceVector::iterator ReferenceVectorIterator; // seems to help C++ parser
489 typedef typename ReferenceVector::const_iterator ReferenceVectorConstIterator; // seems to help C++ parser
490 friend class Reader<A>;
491
492 SymbolAtom(Reader<A>&, const macho_nlist<P>*, const macho_section<P>*);
493 virtual ~SymbolAtom() {}
494
495 Reader<A>& fOwner;
496 const macho_nlist<P>* fSymbol;
497 pint_t fAddress;
498 pint_t fSize;
499 const macho_section<P>* fSection;
500 Segment<A>* fSegment;
501 ReferenceVector fReferences;
502 std::vector<ObjectFile::LineInfo> fLineInfo;
503 ObjectFile::Atom::Scope fScope;
504 SymbolTableInclusion fSymbolTableInclusion;
505 ObjectFile::Atom::ContentType fType;
506 ObjectFile::Alignment fAlignment;
507 };
508
509
510 template <typename A>
511 SymbolAtom<A>::SymbolAtom(Reader<A>& owner, const macho_nlist<P>* symbol, const macho_section<P>* section)
512 : fOwner(owner), fSymbol(symbol), fAddress(0), fSize(0), fSection(section), fSegment(NULL), fType(ObjectFile::Atom::kUnclassifiedType), fAlignment(0)
513 {
514 fSingleUnwindInfo[0].startOffset = 0;
515 fSingleUnwindInfo[0].unwindInfo = 0;
516 uint8_t type = symbol->n_type();
517 if ( (type & N_EXT) == 0 )
518 fScope = ObjectFile::Atom::scopeTranslationUnit;
519 else if ( (type & N_PEXT) != 0 )
520 fScope = ObjectFile::Atom::scopeLinkageUnit;
521 else
522 fScope = ObjectFile::Atom::scopeGlobal;
523 if ( (type & N_TYPE) == N_SECT ) {
524 // real definition
525 fSegment = new Segment<A>(fSection);
526 fAddress = fSymbol->n_value();
527 pint_t sectionStartAddr = section->addr();
528 pint_t sectionEndAddr = section->addr()+section->size();
529 if ( (fAddress < sectionStartAddr) || (fAddress > (sectionEndAddr)) ) {
530 throwf("malformed .o file, symbol %s with address 0x%0llX is not with section %d (%s,%s) address range of 0x%0llX to 0x%0llX",
531 this->getName(), (uint64_t)fAddress, fSymbol->n_sect(), section->segname(), section->sectname(),
532 (uint64_t)sectionStartAddr, (uint64_t)(sectionEndAddr) );
533 }
534 }
535 else {
536 warning("unknown symbol type: %d", type);
537 }
538
539 //fprintf(stderr, "SymbolAtom(%p) %s fAddress=0x%X\n", this, this->getDisplayName(), (uint32_t)fAddress);
540 // support for .o files built with old ld64
541 if ( (fSymbol->n_desc() & N_WEAK_DEF) && (strcmp(fSection->sectname(),"__picsymbolstub1__TEXT") == 0) ) {
542 const char* name = this->getName();
543 const int nameLen = strlen(name);
544 if ( (nameLen > 6) && strcmp(&name[nameLen-5], "$stub") == 0 ) {
545 // switch symbol to point at name that does not have trailing $stub
546 char correctName[nameLen];
547 strncpy(correctName, name, nameLen-5);
548 correctName[nameLen-5] = '\0';
549 const macho_nlist<P>* symbolsStart = fOwner.fSymbols;
550 const macho_nlist<P>* symbolsEnd = &symbolsStart[fOwner.fSymbolCount];
551 for(const macho_nlist<P>* s = symbolsStart; s < symbolsEnd; ++s) {
552 if ( strcmp(&fOwner.fStrings[s->n_strx()], correctName) == 0 ) {
553 fSymbol = s;
554 break;
555 }
556 }
557 }
558 }
559 // support for labeled stubs
560 switch ( section->flags() & SECTION_TYPE ) {
561 case S_SYMBOL_STUBS:
562 setSize(section->reserved2());
563 break;
564 case S_LAZY_SYMBOL_POINTERS:
565 case S_NON_LAZY_SYMBOL_POINTERS:
566 setSize(sizeof(pint_t));
567 break;
568 case S_4BYTE_LITERALS:
569 setSize(4);
570 break;
571 case S_8BYTE_LITERALS:
572 setSize(8);
573 break;
574 case S_16BYTE_LITERALS:
575 setSize(16);
576 break;
577 case S_CSTRING_LITERALS:
578 setSize(strlen((char*)(fOwner.fHeader) + section->offset() + fAddress - section->addr()) + 1);
579 fType = ObjectFile::Atom::kCStringType;
580 break;
581 case S_REGULAR:
582 case S_ZEROFILL:
583 case S_COALESCED:
584 // size calculate later after next atom is found
585 break;
586 }
587
588 // compute alignment
589 fAlignment = ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
590
591 // compute whether this atom needs to be in symbol table
592 if ( (fSymbol->n_desc() & REFERENCED_DYNAMICALLY) != 0) {
593 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableInAndNeverStrip;
594 }
595 else if ( fOwner.fOptions.fForFinalLinkedImage && !fOwner.fOptions.fForStatic && (fOwner.fStrings[fSymbol->n_strx()] == 'l') ) {
596 // labels beginning with a lowercase ell are automatically removed in final linked images <rdar://problem/4571042>
597 // xnu code base uses a lot of asesembly labels that start with 'l', don't strip those (static executable)
598 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableNotIn;
599 }
600 else {
601 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
602 }
603
604 // work around malformed icc generated .o files <rdar://problem/5349847>
605 // if section starts with a symbol and that symbol address does not match section alignment, then force it to
606 if ( (section->addr() == fAddress) && (fAlignment.modulus != 0) )
607 fAlignment.modulus = 0;
608 }
609
610
611 template <typename A>
612 bool SymbolAtom<A>::dontDeadStrip() const
613 {
614 // the symbol can have a no-dead-strip bit
615 if ( (fSymbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0 )
616 return true;
617 // or the section can have a no-dead-strip bit
618 return ( fSection->flags() & S_ATTR_NO_DEAD_STRIP );
619 }
620
621
622 template <typename A>
623 const char* SymbolAtom<A>::getSectionName() const
624 {
625 if ( fOwner.fOptions.fForFinalLinkedImage ) {
626 if ( strcmp(fSection->sectname(), "__textcoal_nt") == 0 )
627 return "__text";
628 else if ( strcmp(fSection->sectname(), "__const_coal") == 0 )
629 return "__const";
630 else if ( strcmp(fSection->sectname(), "__datacoal_nt") == 0 )
631 return "__data";
632 else if ( fOwner.fOptions.fAutoOrderInitializers && (strcmp(fSection->sectname(), "__StaticInit") == 0) )
633 return "__text";
634 else {
635 switch ( fSection->flags() & SECTION_TYPE ) {
636 case S_4BYTE_LITERALS:
637 case S_8BYTE_LITERALS:
638 case S_16BYTE_LITERALS:
639 return "__const";
640 }
641 }
642 }
643
644 if ( strlen(fSection->sectname()) > 15 ) {
645 static char temp[18];
646 strncpy(temp, fSection->sectname(), 16);
647 temp[17] = '\0';
648 return temp;
649 }
650 return fSection->sectname();
651 }
652
653 template <typename A>
654 ObjectFile::Atom& SymbolAtom<A>::getFollowOnAtom() const
655 {
656 for (ReferenceVectorConstIterator it=fReferences.begin(); it != fReferences.end(); it++) {
657 Reference<A>* ref = *it;
658 if ( ref->getKind() == A::kFollowOn )
659 return ref->getTarget();
660 }
661 return *((ObjectFile::Atom*)NULL);
662 }
663
664 template <typename A>
665 bool SymbolAtom<A>::isZeroFill() const
666 {
667 return ( ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL) && fOwner.fOptions.fOptimizeZeroFill );
668 }
669
670
671 class Beyond
672 {
673 public:
674 Beyond(uint64_t offset) : fOffset(offset) {}
675 bool operator()(ObjectFile::Reference* ref) const {
676 return ( ref->getFixUpOffset() >= fOffset );
677 }
678 private:
679 uint64_t fOffset;
680 };
681
682
683 template <typename A>
684 void SymbolAtom<A>::setSize(uint64_t size)
685 {
686 // when resizing, any references beyond the new size are tossed
687 if ( (fSize != 0) && (fReferences.size() > 0) )
688 fReferences.erase(std::remove_if(fReferences.begin(), fReferences.end(), Beyond(size)), fReferences.end());
689 // set new size
690 fSize = size;
691 }
692
693 template <typename A>
694 void SymbolAtom<A>::copyRawContent(uint8_t buffer[]) const
695 {
696 // copy base bytes
697 if ( isZeroFill() )
698 bzero(buffer, fSize);
699 else {
700 uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
701 memcpy(buffer, (char*)(fOwner.fHeader)+fileOffset, fSize);
702 }
703 }
704
705
706
707
708 //
709 // A SymbolAliasAtom represents an alternate name for a SymbolAtom
710 //
711 //
712 template <typename A>
713 class SymbolAliasAtom : public BaseAtom
714 {
715 public:
716 virtual ObjectFile::Reader* getFile() const { return fAliasOf.getFile(); }
717 virtual bool getTranslationUnitSource(const char** dir, const char** name) const
718 { return fAliasOf.getTranslationUnitSource(dir, name); }
719 virtual const char* getName() const { return fName; }
720 virtual const char* getDisplayName() const { return fName; }
721 virtual ObjectFile::Atom::Scope getScope() const { return fScope; }
722 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return fAliasOf.getDefinitionKind(); }
723 virtual SymbolTableInclusion getSymbolTableInclusion() const { return fAliasOf.getSymbolTableInclusion(); }
724 virtual bool dontDeadStrip() const { return fDontDeadStrip; }
725 virtual bool isZeroFill() const { return fAliasOf.isZeroFill(); }
726 virtual bool isThumb() const { return fAliasOf.isThumb(); }
727 virtual uint64_t getSize() const { return 0; }
728 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
729 virtual bool mustRemainInSection() const { return true; }
730 virtual const char* getSectionName() const { return fAliasOf.getSectionName(); }
731 virtual Segment<A>& getSegment() const { return (Segment<A>&)fAliasOf.getSegment(); }
732 virtual ObjectFile::Atom& getFollowOnAtom() const { return (ObjectFile::Atom&)fAliasOf; }
733 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
734 virtual ObjectFile::Alignment getAlignment() const { return fAliasOf.getAlignment(); }
735 virtual void copyRawContent(uint8_t buffer[]) const {}
736 virtual void setScope(ObjectFile::Atom::Scope newScope) { fScope = newScope; }
737 virtual void setSize(uint64_t size) { }
738 virtual void addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
739 virtual void sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
740 virtual void addLineInfo(const ObjectFile::LineInfo& info) { }
741 virtual const ObjectFile::ReaderOptions& getOptions() const { return fAliasOf.getOptions(); }
742 virtual uint64_t getObjectAddress() const { return fAliasOf.getObjectAddress(); }
743 virtual const void* getSectionRecord() const { return fAliasOf.getSectionRecord(); }
744 virtual unsigned int getSectionIndex() const { return fAliasOf.getSectionIndex(); }
745 virtual bool isAlias() const { return true; }
746
747 protected:
748 typedef typename A::P P;
749 typedef typename std::vector<Reference<A>*> ReferenceVector;
750 typedef typename ReferenceVector::iterator ReferenceVectorIterator; // seems to help C++ parser
751 typedef typename ReferenceVector::const_iterator ReferenceVectorConstIterator; // seems to help C++ parser
752 friend class Reader<A>;
753
754 SymbolAliasAtom(const char* name, const macho_nlist<P>*, const BaseAtom& );
755 virtual ~SymbolAliasAtom() {}
756
757 const char* fName;
758 const BaseAtom& fAliasOf;
759 ObjectFile::Atom::Scope fScope;
760 bool fDontDeadStrip;
761 ReferenceVector fReferences;
762 };
763
764
765 template <typename A>
766 SymbolAliasAtom<A>::SymbolAliasAtom(const char* name, const macho_nlist<P>* symbol, const BaseAtom& aliasOf)
767 : fName(name), fAliasOf(aliasOf)
768 {
769 //fprintf(stderr, "SymbolAliasAtom(%p) %s\n", this, name);
770 if ( symbol != NULL ) {
771 uint8_t type = symbol->n_type();
772 if ( (type & N_EXT) == 0 )
773 fScope = ObjectFile::Atom::scopeTranslationUnit;
774 else if ( (type & N_PEXT) != 0 )
775 fScope = ObjectFile::Atom::scopeLinkageUnit;
776 else
777 fScope = ObjectFile::Atom::scopeGlobal;
778 fDontDeadStrip = ((symbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0);
779 }
780 else {
781 // aliases defined on the command line are initially global scope
782 fScope = ObjectFile::Atom::scopeGlobal;
783 fDontDeadStrip = false;
784 }
785 // add follow-on reference to real atom
786 new Reference<A>(A::kFollowOn, AtomAndOffset(this), AtomAndOffset((ObjectFile::Atom*)&aliasOf));
787 }
788
789
790 //
791 // A TentativeAtom represents a C "common" or "tentative" defintion of data.
792 // For instance, "int foo;" is neither a declaration or a definition and
793 // is represented by a TentativeAtom.
794 //
795 template <typename A>
796 class TentativeAtom : public BaseAtom
797 {
798 public:
799 virtual ObjectFile::Reader* getFile() const { return &fOwner; }
800 virtual bool getTranslationUnitSource(const char** dir, const char** name) const
801 { return fOwner.getTranslationUnitSource(dir, name); }
802 virtual const char* getName() const { return &fOwner.fStrings[fSymbol->n_strx()]; }
803 virtual const char* getDisplayName() const { return getName(); }
804 virtual ObjectFile::Atom::Scope getScope() const { return fScope; }
805 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ObjectFile::Atom::kTentativeDefinition; }
806 virtual bool isZeroFill() const { return fOwner.fOptions.fOptimizeZeroFill; }
807 virtual bool isThumb() const { return false; }
808 virtual SymbolTableInclusion getSymbolTableInclusion() const { return ((fSymbol->n_desc() & REFERENCED_DYNAMICALLY) != 0)
809 ? ObjectFile::Atom::kSymbolTableInAndNeverStrip : ObjectFile::Atom::kSymbolTableIn; }
810 virtual bool dontDeadStrip() const { return ((fSymbol->n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0); }
811 virtual uint64_t getSize() const { return fSymbol->n_value(); }
812 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return fgNoReferences; }
813 virtual bool mustRemainInSection() const { return true; }
814 virtual const char* getSectionName() const;
815 virtual ObjectFile::Segment& getSegment() const { return DataSegment::fgSingleton; }
816 virtual ObjectFile::Atom& getFollowOnAtom() const { return *(ObjectFile::Atom*)NULL; }
817 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
818 virtual ObjectFile::Alignment getAlignment() const;
819 virtual void copyRawContent(uint8_t buffer[]) const;
820 virtual void setScope(ObjectFile::Atom::Scope newScope) { fScope = newScope; }
821 virtual void setSize(uint64_t size) { }
822 virtual void addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; }
823 virtual void sortReferences() { }
824 virtual void addLineInfo(const ObjectFile::LineInfo& info) { throw "ld: can't add line info to tentative definition"; }
825 virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; }
826 virtual uint64_t getObjectAddress() const { return ULLONG_MAX; }
827 virtual const void* getSectionRecord() const { return NULL; }
828 virtual unsigned int getSectionIndex() const { return 0; }
829
830 protected:
831 typedef typename A::P P;
832 typedef typename A::P::E E;
833 typedef typename A::P::uint_t pint_t;
834 typedef typename A::ReferenceKinds Kinds;
835 friend class Reader<A>;
836
837 TentativeAtom(Reader<A>&, const macho_nlist<P>*);
838 virtual ~TentativeAtom() {}
839
840 Reader<A>& fOwner;
841 const macho_nlist<P>* fSymbol;
842 ObjectFile::Atom::Scope fScope;
843 static std::vector<ObjectFile::Reference*> fgNoReferences;
844 };
845
846 template <typename A>
847 std::vector<ObjectFile::Reference*> TentativeAtom<A>::fgNoReferences;
848
849 template <typename A>
850 TentativeAtom<A>::TentativeAtom(Reader<A>& owner, const macho_nlist<P>* symbol)
851 : fOwner(owner), fSymbol(symbol)
852 {
853 uint8_t type = symbol->n_type();
854 if ( (type & N_EXT) == 0 )
855 fScope = ObjectFile::Atom::scopeTranslationUnit;
856 else if ( (type & N_PEXT) != 0 )
857 fScope = ObjectFile::Atom::scopeLinkageUnit;
858 else
859 fScope = ObjectFile::Atom::scopeGlobal;
860 if ( ((type & N_TYPE) == N_UNDF) && (symbol->n_value() != 0) ) {
861 // tentative definition
862 }
863 else {
864 warning("unknown symbol type: %d", type);
865 }
866 //fprintf(stderr, "TentativeAtom(%p) %s\n", this, this->getDisplayName());
867 }
868
869
870 template <typename A>
871 ObjectFile::Alignment TentativeAtom<A>::getAlignment() const
872 {
873 uint8_t alignment = GET_COMM_ALIGN(fSymbol->n_desc());
874 if ( alignment == 0 ) {
875 // common symbols align to their size
876 // that is, a 4-byte common aligns to 4-bytes
877 // if this size is not a power of two,
878 // then round up to the next power of two
879 uint64_t size = this->getSize();
880 alignment = 63 - (uint8_t)__builtin_clzll(size);
881 if ( size != (1ULL << alignment) )
882 ++alignment;
883 }
884 // limit alignment of extremely large commons to 2^15 bytes (8-page)
885 if ( alignment < 12 )
886 return ObjectFile::Alignment(alignment);
887 else
888 return ObjectFile::Alignment(12);
889 }
890
891 template <typename A>
892 const char* TentativeAtom<A>::getSectionName() const
893 {
894 if ( fOwner.fOptions.fForFinalLinkedImage || fOwner.fOptions.fMakeTentativeDefinitionsReal )
895 return "__common";
896 else
897 return "._tentdef";
898 }
899
900
901 template <typename A>
902 void TentativeAtom<A>::copyRawContent(uint8_t buffer[]) const
903 {
904 bzero(buffer, getSize());
905 }
906
907
908 //
909 // An AnonymousAtom represents compiler generated data that has no name.
910 // For instance, a literal C-string or a 64-bit floating point constant
911 // is represented by an AnonymousAtom.
912 //
913 template <typename A>
914 class AnonymousAtom : public BaseAtom
915 {
916 public:
917 virtual ObjectFile::Reader* getFile() const { return &fOwner; }
918 virtual bool getTranslationUnitSource(const char** dir, const char** name) const { return false; }
919 virtual const char* getName() const { return fSynthesizedName; }
920 virtual const char* getDisplayName() const;
921 virtual ObjectFile::Atom::Scope getScope() const;
922 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return fKind; }
923 virtual ObjectFile::Atom::ContentType getContentType() const { return fType; }
924 virtual ObjectFile::Atom::SymbolTableInclusion getSymbolTableInclusion() const { return fSymbolTableInclusion; }
925 virtual bool dontDeadStrip() const { return fDontDeadStrip; }
926 virtual bool isZeroFill() const;
927 virtual bool isThumb() const { return false; }
928 virtual uint64_t getSize() const { return fSize; }
929 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
930 virtual bool mustRemainInSection() const { return true; }
931 virtual const char* getSectionName() const;
932 virtual Segment<A>& getSegment() const { return *fSegment; }
933 virtual ObjectFile::Atom& getFollowOnAtom() const;
934 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
935 virtual ObjectFile::Alignment getAlignment() const;
936 virtual void copyRawContent(uint8_t buffer[]) const;
937 virtual void setScope(ObjectFile::Atom::Scope newScope) { fScope = newScope; }
938 virtual void setSize(uint64_t size) { fSize = size; }
939 virtual void addReference(ObjectFile::Reference* ref) { fReferences.push_back((Reference<A>*)ref); }
940 virtual void sortReferences() { std::sort(fReferences.begin(), fReferences.end(), ReferenceSorter()); }
941 virtual void addLineInfo(const ObjectFile::LineInfo& info);
942 virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; }
943 virtual uint64_t getObjectAddress() const { return fAddress; }
944 virtual const void* getSectionRecord() const { return (const void*)fSection; }
945 virtual unsigned int getSectionIndex() const { return fSectionIndex; }
946 BaseAtom* redirectTo() { return fRedirect; }
947 bool isWeakImportStub() { return fWeakImportStub; }
948 void resolveName();
949 virtual uint8_t getLSDAReferenceKind() const;
950 virtual uint8_t getPersonalityReferenceKind() const;
951 virtual uint32_t getCompactUnwindEncoding(uint64_t ehAtomAddress);
952
953 protected:
954 typedef typename A::P P;
955 typedef typename A::P::E E;
956 typedef typename A::P::uint_t pint_t;
957 typedef typename A::ReferenceKinds Kinds;
958 typedef typename std::vector<Reference<A>*> ReferenceVector;
959 typedef typename ReferenceVector::iterator ReferenceVectorIterator; // seems to help C++ parser
960 typedef typename ReferenceVector::const_iterator ReferenceVectorConstIterator; // seems to help C++ parser
961 friend class Reader<A>;
962
963 AnonymousAtom(Reader<A>&, const macho_section<P>*, pint_t addr, pint_t size);
964 virtual ~AnonymousAtom() {}
965 static bool cstringsHaveLabels();
966
967 Reader<A>& fOwner;
968 const char* fSynthesizedName;
969 const char* fDisplayName;
970 const macho_section<P>* fSection;
971 pint_t fAddress;
972 pint_t fSize;
973 Segment<A>* fSegment;
974 ReferenceVector fReferences;
975 BaseAtom* fRedirect;
976 bool fDontDeadStrip;
977 bool fWeakImportStub;
978 ObjectFile::Atom::SymbolTableInclusion fSymbolTableInclusion;
979 ObjectFile::Atom::Scope fScope;
980 ObjectFile::Atom::DefinitionKind fKind;
981 ObjectFile::Atom::ContentType fType;
982 unsigned int fSectionIndex;
983 };
984
985 template <typename A>
986 AnonymousAtom<A>::AnonymousAtom(Reader<A>& owner, const macho_section<P>* section, pint_t addr, pint_t size)
987 : fOwner(owner), fSynthesizedName(NULL), fDisplayName(NULL), fSection(section), fAddress(addr), fSize(size),
988 fSegment(NULL), fDontDeadStrip(true), fWeakImportStub(false), fSymbolTableInclusion(ObjectFile::Atom::kSymbolTableNotIn),
989 fScope(ObjectFile::Atom::scopeTranslationUnit), fKind(ObjectFile::Atom::kRegularDefinition),
990 fType(ObjectFile::Atom::kUnclassifiedType), fSectionIndex(1 + (section - owner.fSectionsStart))
991 {
992 fSegment = new Segment<A>(fSection);
993 fRedirect = this;
994 uint8_t type = fSection->flags() & SECTION_TYPE;
995 //fprintf(stderr, "AnonymousAtom(%p) addr=0x%llX in %s from %s\n", this, (long long)addr, section->sectname(), owner.getPath());
996 switch ( type ) {
997 case S_ZEROFILL:
998 {
999 asprintf((char**)&fSynthesizedName, "zero-fill-at-0x%08X", addr);
1000 }
1001 break;
1002 case S_COALESCED:
1003 case S_REGULAR:
1004 if ( section == owner.fehFrameSection ) {
1005 if ( fSize == 1 ) {
1006 // is CIE
1007 fSize = 0;
1008 fDontDeadStrip = false;
1009 if ( fOwner.fOptions.fForFinalLinkedImage )
1010 fSynthesizedName = "CIE";
1011 else
1012 fSynthesizedName = "EH_frame1";
1013 }
1014 else {
1015 // is FDE
1016 fSynthesizedName = ".eh_PENDING";
1017 fDontDeadStrip = false;
1018 owner.fAtomsPendingAName.push_back(this);
1019 }
1020 fType = ObjectFile::Atom::kCFIType;
1021 // FDEs and CIEs don't need to be in symbol table of final linked images <rdar://problem/4180168>
1022 if ( !fOwner.fOptions.fNoEHLabels )
1023 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
1024 }
1025 else if ( (strcmp(section->sectname(), "__class") == 0) && (strcmp(section->segname(), "__OBJC") == 0) && owner.fAppleObjc ) {
1026 // special case ObjC classes to synthesize .objc_class_name_* symbols, for Apple runtime only
1027 fSynthesizedName = ".objc_class_name_PENDING";
1028 owner.fAtomsPendingAName.push_back(this);
1029 owner.fSectionsWithAtomsPendingAName.insert(fSection);
1030 if ( fOwner.fOptions.fForFinalLinkedImage )
1031 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
1032 else
1033 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableInAsAbsolute;
1034 fScope = ObjectFile::Atom::scopeGlobal;
1035 }
1036 else if ( strcmp(fSection->sectname(), "__cstring") == 0 ) {
1037 // handle .o files created by old ld64 -r that are missing cstring section type
1038 const char* str = (char*)(owner.fHeader) + section->offset() + addr - section->addr();
1039 asprintf((char**)&fSynthesizedName, "cstring=%s", str);
1040 }
1041 else if ((strcmp(section->sectname(), "__cfstring") == 0) && (strcmp(section->segname(), "__DATA") == 0)) {
1042 fSynthesizedName = "cfstring-pointer-name-PENDING";
1043 fScope = ObjectFile::Atom::scopeLinkageUnit;
1044 owner.fAtomsPendingAName.push_back(this);
1045 owner.fSectionsWithAtomsPendingAName.insert(fSection);
1046 fDontDeadStrip = false;
1047 fKind = ObjectFile::Atom::kWeakDefinition;
1048 }
1049 else if ( (fSection->flags() & S_ATTR_SOME_INSTRUCTIONS) != 0 ) {
1050 fDontDeadStrip = false;
1051 asprintf((char**)&fSynthesizedName, "anon-func-0x%X", addr);
1052 }
1053 else if ( strncmp(fSection->sectname(), "__gcc_except_tab",16) == 0 ) {
1054 fType = ObjectFile::Atom::kLSDAType;
1055 fDontDeadStrip = false;
1056 fSynthesizedName = ".lsda_PENDING";
1057 owner.fAtomsPendingAName.push_back(this);
1058 if ( !fOwner.fOptions.fNoEHLabels )
1059 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
1060 }
1061 else if ( (strncmp(fSection->sectname(), "__objc_classrefs", 16) == 0) && (strcmp(fSection->segname(), "__DATA") == 0) ) {
1062 fSynthesizedName = "objc-class-pointer-name-PENDING";
1063 fScope = ObjectFile::Atom::scopeLinkageUnit;
1064 owner.fAtomsPendingAName.push_back(this);
1065 owner.fSectionsWithAtomsPendingAName.insert(fSection);
1066 fKind = ObjectFile::Atom::kWeakDefinition;
1067 }
1068 else if ( section == owner.fUTF16Section ) {
1069 if ( fOwner.fOptions.fForFinalLinkedImage ) {
1070 fDontDeadStrip = false;
1071 fScope = ObjectFile::Atom::scopeLinkageUnit;
1072 fKind = ObjectFile::Atom::kWeakDefinition;
1073 char* name = new char[16+5*size];
1074 strcpy(name, "utf16-string=");
1075 char* s = &name[13];
1076 const uint16_t* words = (uint16_t*)((char*)(owner.fHeader) + section->offset() + addr - section->addr());
1077 unsigned int wordCount = size/2;
1078 bool needSeperator = false;
1079 for(unsigned int i=0; i < wordCount; ++i) {
1080 if ( needSeperator )
1081 strcpy(s++, ".");
1082 sprintf(s, "%04X", E::get32(words[i]));
1083 s += 4;
1084 needSeperator = true;
1085 }
1086 fSynthesizedName = name;
1087 }
1088 else {
1089 asprintf((char**)&fSynthesizedName, "lutf16-0x%X", addr);
1090 }
1091 }
1092 break;
1093 case S_CSTRING_LITERALS:
1094 {
1095 const char* str = (char*)(owner.fHeader) + section->offset() + addr - section->addr();
1096 if ( (strcmp(fSection->sectname(), "__cstring") == 0) && (strcmp(section->segname(), "__TEXT") == 0) )
1097 asprintf((char**)&fSynthesizedName, "cstring=%s", str);
1098 else
1099 asprintf((char**)&fSynthesizedName, "cstring%s%s=%s", fSection->segname(), fSection->sectname(), str);
1100 fScope = ObjectFile::Atom::scopeLinkageUnit;
1101 fKind = ObjectFile::Atom::kWeakDefinition;
1102 fType = ObjectFile::Atom::kCStringType;
1103 fDontDeadStrip = false;
1104 if ( !fOwner.fOptions.fForFinalLinkedImage && cstringsHaveLabels() )
1105 fSymbolTableInclusion = ObjectFile::Atom::kSymbolTableIn;
1106 }
1107 break;
1108 case S_4BYTE_LITERALS:
1109 {
1110 uint32_t value = E::get32(*(uint32_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
1111 asprintf((char**)&fSynthesizedName, "4-byte-literal=0x%08X", value);
1112 fScope = ObjectFile::Atom::scopeLinkageUnit;
1113 fKind = ObjectFile::Atom::kWeakDefinition;
1114 fDontDeadStrip = false;
1115 }
1116 break;
1117 case S_8BYTE_LITERALS:
1118 {
1119 uint64_t value = E::get64(*(uint64_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
1120 asprintf((char**)&fSynthesizedName, "8-byte-literal=0x%016llX", value);
1121 fScope = ObjectFile::Atom::scopeLinkageUnit;
1122 fKind = ObjectFile::Atom::kWeakDefinition;
1123 fDontDeadStrip = false;
1124 }
1125 break;
1126 case S_16BYTE_LITERALS:
1127 {
1128 uint64_t value1 = E::get64(*(uint64_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
1129 uint64_t value2 = E::get64(*(uint64_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr + 8 - section->addr()));
1130 asprintf((char**)&fSynthesizedName, "16-byte-literal=0x%016llX,%016llX", value1, value2);
1131 fScope = ObjectFile::Atom::scopeLinkageUnit;
1132 fKind = ObjectFile::Atom::kWeakDefinition;
1133 fDontDeadStrip = false;
1134 }
1135 break;
1136 case S_LITERAL_POINTERS:
1137 {
1138 //uint32_t literalNameAddr = P::getP(*(pint_t*)(((uint8_t*)owner.fHeader) + section->offset() + addr - section->addr()));
1139 //const char* str = (char*)(owner.fHeader) + section->offset() + literalNameAddr - section->addr();
1140 //asprintf((char**)&fSynthesizedName, "literal-pointer@%s@%s@%s", section->segname(), section->sectname(), str);
1141 fSynthesizedName = "literal-pointer-name-PENDING";
1142 fScope = ObjectFile::Atom::scopeLinkageUnit;
1143 fKind = ObjectFile::Atom::kWeakDefinition;
1144 fDontDeadStrip = false;
1145 owner.fAtomsPendingAName.push_back(this);
1146 owner.fSectionsWithAtomsPendingAName.insert(fSection);
1147 }
1148 break;
1149 case S_MOD_INIT_FUNC_POINTERS:
1150 asprintf((char**)&fSynthesizedName, "initializer$%d", (addr - (uint32_t)fSection->addr())/sizeof(pint_t));
1151 break;
1152 case S_MOD_TERM_FUNC_POINTERS:
1153 asprintf((char**)&fSynthesizedName, "terminator$%d", (addr - (uint32_t)fSection->addr())/sizeof(pint_t));
1154 break;
1155 case S_SYMBOL_STUBS:
1156 {
1157 uint32_t index = (fAddress - fSection->addr()) / fSection->reserved2();
1158 index += fSection->reserved1();
1159 uint32_t symbolIndex = E::get32(fOwner.fIndirectTable[index]);
1160 const macho_nlist<P>* sym = &fOwner.fSymbols[symbolIndex];
1161 uint32_t strOffset = sym->n_strx();
1162 // want name to not have $stub suffix, this is what automatic stub generation expects
1163 fSynthesizedName = &fOwner.fStrings[strOffset];
1164 // check for weak import
1165 fWeakImportStub = fOwner.isWeakImportSymbol(sym);
1166 // sometimes the compiler gets confused and generates a stub to a static function
1167 // if so, we should redirect any call to the stub to be calls to the real static function atom
1168 if ( ((sym->n_type() & N_TYPE) != N_UNDF) && ((sym->n_type() & N_EXT) == 0) ) {
1169 BaseAtom* staticAtom = fOwner.findAtomByName(fSynthesizedName);
1170 if ( staticAtom != NULL )
1171 fRedirect = staticAtom;
1172 }
1173 fKind = ObjectFile::Atom::kWeakDefinition;
1174 // might be a spurious stub for a static function, make stub static too
1175 if ( (sym->n_type() & N_EXT) == 0 )
1176 fScope = ObjectFile::Atom::scopeTranslationUnit;
1177 else
1178 fScope = ObjectFile::Atom::scopeLinkageUnit;
1179 }
1180 break;
1181 case S_LAZY_SYMBOL_POINTERS:
1182 case S_NON_LAZY_SYMBOL_POINTERS:
1183 {
1184 // transform i386 __IMPORT/__pointers to __DATA/__nl_symbol_ptr when
1185 // generating the new compressed LINKEDIT format
1186 if ( (type == S_NON_LAZY_SYMBOL_POINTERS) && fOwner.fOptions.fMakeCompressedDyldInfo && (strcmp(fSection->segname(),"__IMPORT") == 0) ) {
1187 macho_section<P>* dummySection = new macho_section<P>(*fSection);
1188 dummySection->set_segname("__DATA");
1189 dummySection->set_sectname("__nl_symbol_ptr");
1190 fSection = dummySection;
1191 fSegment = new Segment<A>(fSection);
1192 }
1193
1194 fDontDeadStrip = false;
1195 fScope = ObjectFile::Atom::scopeLinkageUnit;
1196 uint32_t index = (fAddress - fSection->addr()) / sizeof(pint_t);
1197 index += fSection->reserved1();
1198 uint32_t symbolIndex = E::get32(fOwner.fIndirectTable[index]);
1199 if ( symbolIndex == INDIRECT_SYMBOL_LOCAL ) {
1200 // Silly codegen with non-lazy pointer to a local symbol
1201 uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
1202 pint_t nonLazyPtrValue = P::getP(*((pint_t*)((char*)(fOwner.fHeader)+fileOffset)));
1203 // All atoms not created yet, so we need to scan symbol table
1204 const macho_nlist<P>* closestSym = NULL;
1205 const macho_nlist<P>* end = &fOwner.fSymbols[fOwner.fSymbolCount];
1206 for (const macho_nlist<P>* sym = fOwner.fSymbols; sym < end; ++sym) {
1207 if ( ((sym->n_type() & N_TYPE) == N_SECT)
1208 && ((sym->n_type() & N_STAB) == 0) ) {
1209 if ( sym->n_value() == nonLazyPtrValue ) {
1210 const char* name = &fOwner.fStrings[sym->n_strx()];
1211 char* str = new char[strlen(name)+16];
1212 strcpy(str, name);
1213 strcat(str, "$non_lazy_ptr");
1214 fSynthesizedName = str;
1215 // add direct reference to target later, because its atom may not be constructed yet
1216 fOwner.fLocalNonLazys.push_back(this);
1217 fScope = ObjectFile::Atom::scopeTranslationUnit;
1218 fType = ObjectFile::Atom::kNonLazyPointer;
1219 return;
1220 }
1221 else if ( (sym->n_value() < nonLazyPtrValue) && ((closestSym == NULL) || (sym->n_value() > closestSym->n_value())) ) {
1222 closestSym = sym;
1223 }
1224 }
1225 }
1226 // add direct reference to target later, because its atom may not be constructed yet
1227 if ( closestSym != NULL ) {
1228 const char* name = &fOwner.fStrings[closestSym->n_strx()];
1229 char* str;
1230 asprintf(&str, "%s+%u$non_lazy_ptr", name, nonLazyPtrValue - closestSym->n_value());
1231 fSynthesizedName = str;
1232 }
1233 else {
1234 fSynthesizedName = "$interior$non_lazy_ptr";
1235 }
1236 fScope = ObjectFile::Atom::scopeTranslationUnit;
1237 fOwner.fLocalNonLazys.push_back(this);
1238 fType = ObjectFile::Atom::kNonLazyPointer;
1239 return;
1240 }
1241 const macho_nlist<P>* targetSymbol = &fOwner.fSymbols[symbolIndex];
1242 const char* name = &fOwner.fStrings[targetSymbol->n_strx()];
1243 char* str = new char[strlen(name)+16];
1244 strcpy(str, name);
1245 if ( type == S_LAZY_SYMBOL_POINTERS ) {
1246 strcat(str, "$lazy_ptr");
1247 fType = ObjectFile::Atom::kLazyPointer;
1248 }
1249 else {
1250 strcat(str, "$non_lazy_ptr");
1251 fType = ObjectFile::Atom::kNonLazyPointer;
1252 }
1253 fSynthesizedName = str;
1254
1255 if ( type == S_NON_LAZY_SYMBOL_POINTERS )
1256 fKind = ObjectFile::Atom::kWeakDefinition;
1257
1258 if ( (targetSymbol->n_type() & N_EXT) == 0 ) {
1259 // target is translation unit scoped, so add direct reference to target
1260 //fOwner.makeReference(A::kPointer, addr, targetSymbol->n_value());
1261 new Reference<A>(A::kPointer, AtomAndOffset(this), fOwner.findAtomAndOffset(targetSymbol->n_value()));
1262 }
1263 else {
1264 if ( fOwner.isWeakImportSymbol(targetSymbol) )
1265 new Reference<A>(A::kPointerWeakImport, AtomAndOffset(this), name, 0);
1266 else
1267 new Reference<A>(A::kPointer, AtomAndOffset(this), name, 0);
1268 }
1269 }
1270 break;
1271 default:
1272 throwf("section type %d not supported with address=0x%08llX", type, (uint64_t)addr);
1273 }
1274 //fprintf(stderr, "AnonymousAtom(%p) %s \n", this, this->getDisplayName());
1275 }
1276
1277 // x86_64 uses L labels on cstrings to allow relocs with addends
1278 template <> bool AnonymousAtom<x86_64>::cstringsHaveLabels() { return true; }
1279 template <typename A> bool AnonymousAtom<A>::cstringsHaveLabels() { return false; }
1280
1281 template <typename A>
1282 void AnonymousAtom<A>::addLineInfo(const ObjectFile::LineInfo& info)
1283 {
1284 // <rdar://problem/6545406> don't warn if line table has entries for stubs
1285 if ( (fSection->flags() & SECTION_TYPE) != S_SYMBOL_STUBS )
1286 warning("can't add line info to anonymous symbol %s from %s", this->getDisplayName(), this->getFile()->getPath());
1287 }
1288
1289 template <typename A>
1290 void AnonymousAtom<A>::resolveName()
1291 {
1292 if ( (strcmp(fSection->sectname(), "__class") == 0) && (strcmp(fSection->segname(), "__OBJC") == 0) ) {
1293 std::vector<ObjectFile::Reference*>& references = this->getReferences();
1294 // references are not yet sorted, so scan the vector
1295 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1296 if ( ((*rit)->getFixUpOffset() == sizeof(pint_t)) && ((*rit)->getKind() == A::kPointer) ) {
1297 const char* superStr = (*rit)->getTargetName();
1298 if ( strncmp(superStr, "cstring", 7) == 0 ) {
1299 const char* superClassName;
1300 asprintf((char**)&superClassName, ".objc_class_name_%s", &superStr[8]);
1301 new Reference<A>(A::kNoFixUp, AtomAndOffset(this), superClassName, 0);
1302 }
1303 break;
1304 }
1305 }
1306 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1307 if ( ((*rit)->getFixUpOffset() == 2*sizeof(pint_t)) && ((*rit)->getKind() == A::kPointer) ) {
1308 const char* classStr = (*rit)->getTargetName();
1309 if ( strncmp(classStr, "cstring", 7) == 0 ) {
1310 asprintf((char**)&fSynthesizedName, ".objc_class_name_%s", &classStr[8]);
1311 }
1312 break;
1313 }
1314 }
1315 }
1316 else if ( (fSection->flags() & SECTION_TYPE) == S_LITERAL_POINTERS) {
1317 std::vector<ObjectFile::Reference*>& references = this->getReferences();
1318 if ( references.size() < 1 )
1319 throwf("S_LITERAL_POINTERS section %s,%s missing relocs", fSection->segname(), fSection->sectname());
1320 ObjectFile::Reference* ref = references[0];
1321 const char* str = ref->getTargetName();
1322 if ( strncmp(str, "cstring", 7) == 0 ) {
1323 asprintf((char**)&fSynthesizedName, "literal-pointer@%s@%s@%s", fSection->segname(), fSection->sectname(), &str[8]);
1324 }
1325 }
1326 else if ( (strcmp(fSection->sectname(), "__cfstring") == 0) && (strcmp(fSection->segname(), "__DATA") == 0) ) {
1327 // references are not yet sorted, so scan the vector
1328 std::vector<ObjectFile::Reference*>& references = this->getReferences();
1329 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
1330 if ( ((*rit)->getFixUpOffset() == 2*sizeof(pint_t)) && ((*rit)->getKind() == A::kPointer) ) {
1331 const char* superStr = (*rit)->getTargetName();
1332 if ( (superStr != NULL) && (strncmp(superStr, "cstring=", 8) == 0) ) {
1333 asprintf((char**)&fSynthesizedName, "cfstring=%s", &superStr[8]);
1334 }
1335 else if ( (superStr != NULL) && (strncmp(superStr, "utf16-string=", 13) == 0) ) {
1336 asprintf((char**)&fSynthesizedName, "cfstring-utf16=%s", &superStr[13]);
1337 }
1338 else {
1339 // compiled with -fwritable-strings or a non-ASCII string
1340 fKind = ObjectFile::Atom::kRegularDefinition; // these are not coalescable
1341 fScope = ObjectFile::Atom::scopeTranslationUnit;
1342 fSynthesizedName = "cfstring-not-coalesable";
1343 if ( (*rit)->getTargetOffset() != 0 )
1344 warning("-fwritable-strings not compatible with literal CF/NSString in %s", fOwner.getPath());
1345 }
1346 break;
1347 }
1348 }
1349 }
1350 else if ( fSection == fOwner.fehFrameSection ) {
1351 // give name to FDE
1352 ObjectFile::Atom* funcAtom = fOwner.getFunctionAtomFromFDEAddress(fAddress);
1353 if ( funcAtom != NULL )
1354 asprintf((char**)&fSynthesizedName, "%s.eh", funcAtom->getDisplayName());
1355 }
1356 else if ( fOwner.fLSDAAtoms.count(this) != 0) {
1357 // give name to LSDA
1358 ObjectFile::Atom* funcAtom = fOwner.getFunctionAtomFromLSDAAddress(fAddress);
1359 if ( funcAtom != NULL )
1360 asprintf((char**)&fSynthesizedName, "%s.lsda", funcAtom->getDisplayName());
1361 }
1362 else if ( (strncmp(fSection->sectname(), "__objc_classrefs", 16) == 0) && (strcmp(fSection->segname(), "__DATA") == 0) ) {
1363 std::vector<ObjectFile::Reference*>& references = this->getReferences();
1364 if ( references.size() != 1 )
1365 throwf("__objc_classrefs element missing reloc (count=%ld) for target class in %s", references.size(), fOwner.getPath());
1366 const char* targetName = references[0]->getTargetName();
1367 if ( strncmp(targetName, "_OBJC_CLASS_$_", 14) == 0 )
1368 asprintf((char**)&fSynthesizedName, "objc-class-ref-to-%s", &targetName[14]);
1369 else
1370 asprintf((char**)&fSynthesizedName, "objc-class-ref-to-%s", targetName);
1371 }
1372 }
1373
1374
1375 template <typename A>
1376 const char* AnonymousAtom<A>::getDisplayName() const
1377 {
1378 if ( fSynthesizedName != NULL )
1379 return fSynthesizedName;
1380
1381 if ( fDisplayName != NULL )
1382 return fDisplayName;
1383
1384 if ( (fSection->flags() & SECTION_TYPE) == S_CSTRING_LITERALS ) {
1385 uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
1386 asprintf((char**)&fDisplayName, "atom string literal: \"%s\"", (char*)(fOwner.fHeader)+fileOffset);
1387 }
1388 else {
1389 asprintf((char**)&fDisplayName, "%s@%d", fSection->sectname(), fAddress - (uint32_t)fSection->addr() );
1390 }
1391 return fDisplayName;
1392 }
1393
1394
1395 template <typename A>
1396 ObjectFile::Atom::Scope AnonymousAtom<A>::getScope() const
1397 {
1398 return fScope;
1399 }
1400
1401
1402 template <typename A>
1403 bool AnonymousAtom<A>::isZeroFill() const
1404 {
1405 return ( ((fSection->flags() & SECTION_TYPE) == S_ZEROFILL) && fOwner.fOptions.fOptimizeZeroFill );
1406 }
1407
1408
1409 template <typename A>
1410 const char* AnonymousAtom<A>::getSectionName() const
1411 {
1412 if ( fOwner.fOptions.fForFinalLinkedImage ) {
1413 switch ( fSection->flags() & SECTION_TYPE ) {
1414 case S_4BYTE_LITERALS:
1415 case S_8BYTE_LITERALS:
1416 case S_16BYTE_LITERALS:
1417 return "__const";
1418 }
1419 }
1420
1421 if ( strlen(fSection->sectname()) > 15 ) {
1422 static char temp[18];
1423 strncpy(temp, fSection->sectname(), 16);
1424 temp[17] = '\0';
1425 return temp;
1426 }
1427 return fSection->sectname();
1428 }
1429
1430 template <typename A>
1431 ObjectFile::Alignment AnonymousAtom<A>::getAlignment() const
1432 {
1433 // FDEs and CIEs are always packed together in a final linked image, so ignore section alignment
1434 if ( fType == ObjectFile::Atom::kCFIType )
1435 return ObjectFile::Alignment(0);
1436
1437 switch ( fSection->flags() & SECTION_TYPE ) {
1438 case S_4BYTE_LITERALS:
1439 return ObjectFile::Alignment(2);
1440 case S_8BYTE_LITERALS:
1441 return ObjectFile::Alignment(3);
1442 case S_16BYTE_LITERALS:
1443 return ObjectFile::Alignment(4);
1444 case S_NON_LAZY_SYMBOL_POINTERS:
1445 return ObjectFile::Alignment((uint8_t)log2(sizeof(pint_t)));
1446 case S_CSTRING_LITERALS:
1447 if ( ! fOwner.fOptions.fForFinalLinkedImage )
1448 return ObjectFile::Alignment(fSection->align());
1449 default:
1450 return ObjectFile::Alignment(fSection->align(), fAddress % (1 << fSection->align()));
1451 }
1452 }
1453
1454
1455 template <typename A>
1456 ObjectFile::Atom& AnonymousAtom<A>::getFollowOnAtom() const
1457 {
1458 for (ReferenceVectorConstIterator it=fReferences.begin(); it != fReferences.end(); it++) {
1459 Reference<A>* ref = *it;
1460 if ( ref->getKind() == A::kFollowOn )
1461 return ref->getTarget();
1462 }
1463 return *((ObjectFile::Atom*)NULL);
1464 }
1465
1466 template <typename A>
1467 void AnonymousAtom<A>::copyRawContent(uint8_t buffer[]) const
1468 {
1469 // copy base bytes
1470 if ( isZeroFill() )
1471 bzero(buffer, fSize);
1472 else {
1473 uint32_t fileOffset = fSection->offset() - fSection->addr() + fAddress;
1474 memcpy(buffer, (char*)(fOwner.fHeader)+fileOffset, fSize);
1475 }
1476 }
1477
1478 //
1479 // An AbsoluteAtom represents an N_ABS symbol which can only be created in
1480 // assembly language and usable by static executables such as the kernel/
1481 //
1482 template <typename A>
1483 class AbsoluteAtom : public BaseAtom
1484 {
1485 public:
1486 virtual ObjectFile::Reader* getFile() const { return &fOwner; }
1487 virtual bool getTranslationUnitSource(const char** dir, const char** name) const
1488 { return fOwner.getTranslationUnitSource(dir, name); }
1489 virtual const char* getName() const { return &fOwner.fStrings[fSymbol->n_strx()]; }
1490 virtual const char* getDisplayName() const { return getName(); }
1491 virtual ObjectFile::Atom::Scope getScope() const { return fScope; }
1492 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ObjectFile::Atom::kAbsoluteSymbol; }
1493 virtual bool isZeroFill() const { return false; }
1494 virtual bool isThumb() const { return ((fSymbol->n_desc() & N_ARM_THUMB_DEF) != 0); }
1495 virtual SymbolTableInclusion getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableInAsAbsolute; }
1496 virtual bool dontDeadStrip() const { return false; }
1497 virtual uint64_t getSize() const { return 0; }
1498 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return fgNoReferences; }
1499 virtual bool mustRemainInSection() const { return true; }
1500 virtual const char* getSectionName() const { return "._absolute"; }
1501 virtual ObjectFile::Segment& getSegment() const { return LinkEditSegment::fgSingleton; }
1502 virtual ObjectFile::Atom& getFollowOnAtom() const { return *(ObjectFile::Atom*)NULL; }
1503 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
1504 virtual ObjectFile::Alignment getAlignment() const { return ObjectFile::Alignment(0); }
1505 virtual void copyRawContent(uint8_t buffer[]) const { }
1506 virtual void setScope(ObjectFile::Atom::Scope newScope) { fScope = newScope; }
1507 virtual void setSize(uint64_t size) { }
1508 virtual void addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; }
1509 virtual void sortReferences() { }
1510 virtual void addLineInfo(const ObjectFile::LineInfo& info) { throw "ld: can't add line info to tentative definition"; }
1511 virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; }
1512 virtual uint64_t getObjectAddress() const { return fSymbol->n_value(); }
1513 virtual void setSectionOffset(uint64_t offset) { /* don't let fSectionOffset be altered*/ }
1514 virtual const void* getSectionRecord() const { return NULL; }
1515 virtual unsigned int getSectionIndex() const { return 0; }
1516
1517 protected:
1518 typedef typename A::P P;
1519 typedef typename A::P::E E;
1520 typedef typename A::P::uint_t pint_t;
1521 typedef typename A::ReferenceKinds Kinds;
1522 friend class Reader<A>;
1523
1524 AbsoluteAtom(Reader<A>&, const macho_nlist<P>*);
1525 virtual ~AbsoluteAtom() {}
1526
1527 Reader<A>& fOwner;
1528 const macho_nlist<P>* fSymbol;
1529 ObjectFile::Atom::Scope fScope;
1530 static std::vector<ObjectFile::Reference*> fgNoReferences;
1531 };
1532
1533 template <typename A>
1534 std::vector<ObjectFile::Reference*> AbsoluteAtom<A>::fgNoReferences;
1535
1536 template <typename A>
1537 AbsoluteAtom<A>::AbsoluteAtom(Reader<A>& owner, const macho_nlist<P>* symbol)
1538 : fOwner(owner), fSymbol(symbol)
1539 {
1540 // store absolute adress in fSectionOffset
1541 fSectionOffset = symbol->n_value();
1542 // compute scope
1543 uint8_t type = symbol->n_type();
1544 if ( (type & N_EXT) == 0 )
1545 fScope = ObjectFile::Atom::scopeTranslationUnit;
1546 else if ( (type & N_PEXT) != 0 )
1547 fScope = ObjectFile::Atom::scopeLinkageUnit;
1548 else
1549 fScope = ObjectFile::Atom::scopeGlobal;
1550 //fprintf(stderr, "AbsoluteAtom(%p) %s\n", this, this->getDisplayName());
1551 }
1552
1553
1554 //
1555 // An SectionBoundaryAtom represent the start or end of a section
1556 //
1557 template <typename A>
1558 class SectionBoundaryAtom : public BaseAtom
1559 {
1560 public:
1561 virtual ObjectFile::Reader* getFile() const { return &fOwner; }
1562 virtual bool getTranslationUnitSource(const char** dir, const char** name) const
1563 { return fOwner.getTranslationUnitSource(dir, name); }
1564 virtual const char* getName() const { return fSymbolName; }
1565 virtual const char* getDisplayName() const { return fDisplayName; }
1566 virtual ObjectFile::Atom::Scope getScope() const { return ObjectFile::Atom::scopeLinkageUnit; }
1567 virtual ObjectFile::Atom::DefinitionKind getDefinitionKind() const { return ObjectFile::Atom::kWeakDefinition; }
1568 virtual ObjectFile::Atom::ContentType getContentType() const { return fStart ? ObjectFile::Atom::kSectionStart : ObjectFile::Atom::kSectionEnd; }
1569 virtual bool isZeroFill() const { return fZeroFill; }
1570 virtual bool isThumb() const { return false; }
1571 virtual SymbolTableInclusion getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
1572 virtual bool dontDeadStrip() const { return false; }
1573 virtual uint64_t getSize() const { return 0; }
1574 virtual std::vector<ObjectFile::Reference*>& getReferences() const { return fgNoReferences; }
1575 virtual bool mustRemainInSection() const { return true; }
1576 virtual const char* getSectionName() const { return fSectionName; }
1577 virtual ObjectFile::Segment& getSegment() const { return *fSegment; }
1578 virtual ObjectFile::Atom& getFollowOnAtom() const { return *(ObjectFile::Atom*)NULL; }
1579 virtual std::vector<ObjectFile::LineInfo>* getLineInfo() const { return NULL; }
1580 virtual ObjectFile::Alignment getAlignment() const { return ObjectFile::Alignment(0); }
1581 virtual void copyRawContent(uint8_t buffer[]) const { }
1582 virtual void setScope(ObjectFile::Atom::Scope newScope) { }
1583 virtual void setSize(uint64_t size) { }
1584 virtual void addReference(ObjectFile::Reference* ref) { throw "ld: can't add references"; }
1585 virtual void sortReferences() { }
1586 virtual void addLineInfo(const ObjectFile::LineInfo& info) { throw "ld: can't add line info to tentative definition"; }
1587 virtual const ObjectFile::ReaderOptions& getOptions() const { return fOwner.fOptions; }
1588 virtual uint64_t getObjectAddress() const { return 0; }
1589 virtual const void* getSectionRecord() const { return NULL; }
1590 virtual unsigned int getSectionIndex() const { return 0; }
1591
1592 protected:
1593 typedef typename A::P P;
1594 typedef typename A::P::E E;
1595 typedef typename A::P::uint_t pint_t;
1596 typedef typename A::ReferenceKinds Kinds;
1597 friend class Reader<A>;
1598
1599
1600 class Segment : public ObjectFile::Segment
1601 {
1602 public:
1603 Segment(const char* name, bool r, bool w, bool x):
1604 fName(name), fReadable(r), fWritable(w), fExecutable(x) {}
1605
1606 virtual const char* getName() const { return fName; }
1607 virtual bool isContentReadable() const { return fReadable; }
1608 virtual bool isContentWritable() const { return fWritable; }
1609 virtual bool isContentExecutable() const { return fExecutable; }
1610 private:
1611 const char* fName;
1612 bool fReadable;
1613 bool fWritable;
1614 bool fExecutable;
1615 };
1616
1617 SectionBoundaryAtom(Reader<A>&, bool start, const char* symbolName, const char* segSectName);
1618 virtual ~SectionBoundaryAtom() {}
1619
1620 Reader<A>& fOwner;
1621 class Segment* fSegment;
1622 const char* fSymbolName;
1623 const char* fSectionName;
1624 const char* fDisplayName;
1625 bool fStart;
1626 bool fZeroFill;
1627 static std::vector<ObjectFile::Reference*> fgNoReferences;
1628 };
1629
1630 template <typename A>
1631 std::vector<ObjectFile::Reference*> SectionBoundaryAtom<A>::fgNoReferences;
1632
1633 // examples:
1634 // section$start$__DATA$__my
1635 // section$end$__DATA$__my
1636 template <typename A>
1637 SectionBoundaryAtom<A>::SectionBoundaryAtom(Reader<A>& owner, bool start, const char* symbolName, const char* segSectName)
1638 : fOwner(owner), fSymbolName(symbolName), fSectionName(NULL), fStart(start), fZeroFill(false)
1639 {
1640 const char* segSectDividor = strrchr(segSectName, '$');
1641 if ( segSectDividor == NULL )
1642 throwf("malformed section reference name: %s", symbolName);
1643 fSectionName = segSectDividor + 1;
1644 int segNameLen = segSectDividor - segSectName;
1645 if ( segNameLen > 16 )
1646 throwf("malformed section reference name: %s", symbolName);
1647 char segName[18];
1648 strlcpy(segName, segSectName, segNameLen+1);
1649 if ( strcmp(segName, "__TEXT") == 0 )
1650 fSegment = new Segment("__TEXT", true, false, true);
1651 else if ( strcmp(segName, "__DATA") == 0 ) {
1652 fSegment = new Segment("__DATA", true, true, false);
1653 if ( (strcmp(fSectionName, "__bss") == 0) || (strcmp(fSectionName, "__common") == 0) )
1654 fZeroFill = true;
1655 }
1656 else
1657 fSegment = new Segment(strdup(segName), true, true, false);
1658
1659 asprintf((char**)&fDisplayName, "%s of section '%s' in segment '%s'", (start ? "start" : "end"), fSectionName, segName);
1660 }
1661
1662
1663
1664 ///
1665 /// ObjectFileAddressSpace is used as a template parameter to UnwindCursor for parsing
1666 /// dwarf CFI information in an object file.
1667 ///
1668 template <typename A>
1669 class ObjectFileAddressSpace
1670 {
1671 public:
1672 ObjectFileAddressSpace(Reader<A>& reader);
1673
1674 typedef typename A::P::uint_t pint_t;
1675 typedef typename A::P P;
1676 typedef typename A::P::uint_t sint_t;
1677
1678 uint8_t get8(pint_t addr);
1679 uint16_t get16(pint_t addr);
1680 uint32_t get32(pint_t addr);
1681 uint64_t get64(pint_t addr);
1682 pint_t getP(pint_t addr);
1683 uint64_t getULEB128(pint_t& addr, pint_t end);
1684 int64_t getSLEB128(pint_t& addr, pint_t end);
1685 pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
1686 private:
1687 const void* mappedAddress(pint_t addr, pint_t* relocTarget=NULL);
1688 pint_t relocated(uint32_t sectOffset, uint32_t relocsOffset, uint32_t relocsCount);
1689 void buildRelocatedMap(const macho_section<P>* sect, std::map<uint32_t,uint64_t>& map);
1690
1691 Reader<A>& fReader;
1692 const uint8_t* fMappingStart;
1693 const macho_section<P>* fSectionsStart;
1694 const macho_section<P>* fSectionsEnd;
1695 std::map<uint32_t,uint64_t> fEHFrameOffsetToTargetMap;
1696 };
1697
1698
1699 template <typename A>
1700 ObjectFileAddressSpace<A>::ObjectFileAddressSpace(Reader<A>& reader)
1701 : fReader(reader), fMappingStart(NULL), fSectionsStart(NULL), fSectionsEnd(NULL)
1702 {
1703 }
1704
1705
1706
1707 template <typename A>
1708 const void* ObjectFileAddressSpace<A>::mappedAddress(pint_t addr, pint_t* relocTarget)
1709 {
1710 if ( fMappingStart == NULL ) {
1711 // delay initialization until now when fReader.fSegment is set up
1712 fMappingStart = (uint8_t*)fReader.fHeader;
1713 fSectionsStart = (macho_section<P>*)((char*)fReader.fSegment + sizeof(macho_segment_command<P>));
1714 fSectionsEnd = &fSectionsStart[fReader.fSegment->nsects()];
1715 // find __eh_frame section and build map of relocations for performance
1716 buildRelocatedMap(fReader.fehFrameSection, fEHFrameOffsetToTargetMap);
1717 }
1718 // special case lookups in __eh_frame section to be fast
1719 const macho_section<P>* ehSect = fReader.fehFrameSection;
1720 if ( (ehSect->addr() <= addr) && (addr < (ehSect->addr()+ehSect->size())) ) {
1721 pint_t offsetOfAddrInSection = addr - ehSect->addr();
1722 if ( relocTarget != NULL ) {
1723 std::map<uint32_t,uint64_t>::iterator pos = fEHFrameOffsetToTargetMap.find(offsetOfAddrInSection);
1724 if ( pos != fEHFrameOffsetToTargetMap.end() )
1725 *relocTarget = pos->second;
1726 else
1727 *relocTarget = 0;
1728 }
1729 return fMappingStart + ehSect->offset() + offsetOfAddrInSection;
1730 }
1731 else {
1732 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
1733 if ( (sect->addr() <= addr) && (addr < (sect->addr()+sect->size())) ) {
1734 pint_t offsetOfAddrInSection = addr - sect->addr();
1735 if ( (sect->flags() & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS ) {
1736 const uint32_t indirectTableOffset = sect->reserved1();
1737 const uint32_t sectionIndex = offsetOfAddrInSection/sizeof(pint_t);
1738 const uint32_t symbolIndex = A::P::E::get32(fReader.fIndirectTable[indirectTableOffset+sectionIndex]);
1739 // return pointer to symbol name which this non-lazy-pointer will point to
1740 if ( relocTarget != NULL )
1741 *relocTarget = (uintptr_t)&fReader.fStrings[fReader.fSymbols[symbolIndex].n_strx()];
1742 }
1743 else {
1744 if ( relocTarget != NULL )
1745 *relocTarget = relocated(offsetOfAddrInSection, sect->reloff(), sect->nreloc());
1746 }
1747 return fMappingStart + sect->offset() + offsetOfAddrInSection;
1748 }
1749 }
1750 throwf("ObjectFileAddressSpace::mappedAddress(0x%0lX) not in any section", (long)addr);
1751 }
1752 }
1753
1754
1755
1756
1757 template <typename A>
1758 uint8_t ObjectFileAddressSpace<A>::get8(pint_t logicalAddr)
1759 {
1760 return *((uint8_t*)mappedAddress(logicalAddr));
1761 }
1762
1763 template <typename A>
1764 uint16_t ObjectFileAddressSpace<A>::get16(pint_t logicalAddr)
1765 {
1766 return P::E::get16(*((uint16_t*)mappedAddress(logicalAddr)));
1767 }
1768
1769 template <typename A>
1770 uint32_t ObjectFileAddressSpace<A>::get32(pint_t logicalAddr)
1771 {
1772 pint_t relocTarget;
1773 return P::E::get32(*((uint32_t*)mappedAddress(logicalAddr, &relocTarget))) + relocTarget;
1774 }
1775
1776 template <typename A>
1777 uint64_t ObjectFileAddressSpace<A>::get64(pint_t logicalAddr)
1778 {
1779 pint_t relocTarget;
1780 return P::E::get64(*((uint64_t*)mappedAddress(logicalAddr, &relocTarget))) + relocTarget;
1781 }
1782
1783 template <typename A>
1784 typename A::P::uint_t ObjectFileAddressSpace<A>::getP(pint_t logicalAddr)
1785 {
1786 pint_t relocTarget;
1787 return P::getP(*((pint_t*)mappedAddress(logicalAddr, &relocTarget))) + relocTarget;
1788 }
1789
1790 template <typename A>
1791 uint64_t ObjectFileAddressSpace<A>::getULEB128(pint_t& logicalAddr, pint_t end)
1792 {
1793 uintptr_t size = (end - logicalAddr);
1794 libunwind::LocalAddressSpace::pint_t laddr = (libunwind::LocalAddressSpace::pint_t)mappedAddress(logicalAddr);
1795 libunwind::LocalAddressSpace::pint_t sladdr = laddr;
1796 uint64_t result = libunwind::LocalAddressSpace::getULEB128(laddr, laddr+size);
1797 logicalAddr += (laddr-sladdr);
1798 return result;
1799 }
1800
1801 template <typename A>
1802 int64_t ObjectFileAddressSpace<A>::getSLEB128(pint_t& logicalAddr, pint_t end)
1803 {
1804 uintptr_t size = (end - logicalAddr);
1805 libunwind::LocalAddressSpace::pint_t laddr = (libunwind::LocalAddressSpace::pint_t)mappedAddress(logicalAddr);
1806 libunwind::LocalAddressSpace::pint_t sladdr = laddr;
1807 int64_t result = libunwind::LocalAddressSpace::getSLEB128(laddr, laddr+size);
1808 logicalAddr += (laddr-sladdr);
1809 return result;
1810 }
1811
1812
1813
1814
1815
1816
1817 template <typename A>
1818 class Reader : public ObjectFile::Reader
1819 {
1820 public:
1821 static bool validFile(const uint8_t* fileContent, bool subtypeMustMatch=false, cpu_subtype_t subtype=0);
1822 static const char* fileKind(const uint8_t* fileContent);
1823 Reader(const uint8_t* fileContent, const char* path, time_t modTime,
1824 const ObjectFile::ReaderOptions& options, uint32_t ordinalBase);
1825 virtual ~Reader() {}
1826
1827 virtual const char* getPath() { return fPath; }
1828 virtual time_t getModificationTime() { return fModTime; }
1829 virtual ObjectFile::Reader::DebugInfoKind getDebugInfoKind() { return fDebugInfo; }
1830 virtual std::vector<class ObjectFile::Atom*>& getAtoms() { return (std::vector<class ObjectFile::Atom*>&)(fAtoms); }
1831 virtual std::vector<class ObjectFile::Atom*>* getJustInTimeAtomsFor(const char* name) { return NULL; }
1832 virtual std::vector<Stab>* getStabs() { return &fStabs; }
1833 virtual ObjectFile::Reader::ObjcConstraint getObjCConstraint() { return fObjConstraint; }
1834 virtual uint32_t updateCpuConstraint(uint32_t current);
1835 virtual bool canScatterAtoms() { return (fHeader->flags() & MH_SUBSECTIONS_VIA_SYMBOLS); }
1836 virtual bool objcReplacementClasses(){ return fReplacementClasses; }
1837 virtual bool hasLongBranchStubs() { return fHasLongBranchStubs; }
1838
1839 bool getTranslationUnitSource(const char** dir, const char** name) const;
1840
1841 private:
1842 typedef typename A::P P;
1843 typedef typename A::P::E E;
1844 typedef typename A::P::uint_t pint_t;
1845 //typedef typename std::vector<Atom<A>*> AtomVector;
1846 //typedef typename AtomVector::iterator AtomVectorIterator; // seems to help C++ parser
1847 typedef typename A::ReferenceKinds Kinds;
1848 typedef typename libunwind::CFI_Parser<ObjectFileAddressSpace<A> >::FDE_Atom_Info FDE_Atom_Info;
1849 typedef typename libunwind::CFI_Parser<ObjectFileAddressSpace<A> >::CIE_Atom_Info CIE_Atom_Info;
1850 typedef class ObjectFileAddressSpace<A> OAS;
1851 friend class ObjectFileAddressSpace<A>;
1852 friend class AnonymousAtom<A>;
1853 friend class TentativeAtom<A>;
1854 friend class AbsoluteAtom<A>;
1855 friend class SectionBoundaryAtom<A>;
1856 friend class SymbolAtom<A>;
1857 typedef std::map<pint_t, BaseAtom*> AddrToAtomMap;
1858
1859 void addReferencesForSection(const macho_section<P>* sect);
1860 bool addRelocReference(const macho_section<P>* sect, const macho_relocation_info<P>* reloc);
1861 bool addRelocReference_powerpc(const macho_section<P>* sect, const macho_relocation_info<P>* reloc);
1862 const char* getDwarfString(uint64_t form, const uint8_t* p);
1863 bool read_comp_unit(const char ** name, const char ** comp_dir, uint64_t *stmt_list);
1864 static bool isWeakImportSymbol(const macho_nlist<P>* sym);
1865 static bool skip_form(const uint8_t ** offset, const uint8_t * end, uint64_t form, uint8_t addr_size, bool dwarf64);
1866 static const char* assureFullPath(const char* path);
1867 AtomAndOffset findAtomAndOffset(pint_t addr);
1868 AtomAndOffset findAtomAndOffsetForSection(pint_t addr, unsigned int sectionIndex);
1869 AtomAndOffset findAtomAndOffset(pint_t baseAddr, pint_t realAddr);
1870 Reference<A>* makeReference(Kinds kind, pint_t atAddr, pint_t toAddr);
1871 Reference<A>* makeReference(Kinds kind, pint_t atAddr, pint_t fromAddr, pint_t toAddr);
1872 Reference<A>* makeReferenceWithToBase(Kinds kind, pint_t atAddr, pint_t toAddr, pint_t toBaseAddr);
1873 Reference<A>* makeReferenceWithToBase(Kinds kind, pint_t atAddr, pint_t fromAddr, pint_t toAddr, pint_t toBaseAddr);
1874 Reference<A>* makeByNameReference(Kinds kind, pint_t atAddr, const char* toName, uint32_t toOffset);
1875 BaseAtom* makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect);
1876 Reference<A>* makeReferenceToSymbol(Kinds kind, pint_t atAddr, const macho_nlist<P>* toSymbol, pint_t toOffset);
1877 void validSectionType(uint8_t type);
1878 void addDtraceExtraInfos(uint32_t probeAddr, const char* providerName);
1879 void setCpuConstraint(uint32_t cpusubtype);
1880 const macho_section<P>* getSectionForAddress(pint_t);
1881 ObjectFile::Atom* getFunctionAtomFromFDEAddress(pint_t);
1882 ObjectFile::Atom* getFunctionAtomFromLSDAAddress(pint_t);
1883 void addFdeReference(uint8_t encoding, AtomAndOffset inFDE, AtomAndOffset target);
1884 void addCiePersonalityReference(BaseAtom* cieAtom, uint32_t offsetInCIE, uint8_t encoding);
1885 bool isSectDiffReloc(uint8_t r_type);
1886
1887
1888 BaseAtom* findAtomByName(const char*);
1889
1890 const char* fPath;
1891 time_t fModTime;
1892 uint32_t fOrdinalBase;
1893 const ObjectFile::ReaderOptions& fOptions;
1894 const macho_header<P>* fHeader;
1895 const char* fStrings;
1896 const macho_nlist<P>* fSymbols;
1897 uint32_t fSymbolCount;
1898 const macho_segment_command<P>* fSegment;
1899 const uint32_t* fIndirectTable;
1900 std::vector<BaseAtom*> fAtoms;
1901 AddrToAtomMap fAddrToAtom;
1902 AddrToAtomMap fAddrToAbsoluteAtom;
1903 std::vector<class AnonymousAtom<A>*> fLocalNonLazys;
1904 std::vector<class AnonymousAtom<A>*> fAtomsPendingAName;
1905 std::set<const macho_section<P>*> fSectionsWithAtomsPendingAName;
1906 std::vector<const char*> fDtraceProviderInfo;
1907 ObjectFile::Reader::DebugInfoKind fDebugInfo;
1908 bool fHasUUID;
1909 const macho_section<P>* fehFrameSection;
1910 const macho_section<P>* fUTF16Section;
1911 std::set<BaseAtom*> fLSDAAtoms;
1912 const macho_section<P>* fDwarfDebugInfoSect;
1913 const macho_section<P>* fDwarfDebugAbbrevSect;
1914 const macho_section<P>* fDwarfDebugLineSect;
1915 const macho_section<P>* fDwarfDebugStringSect;
1916 const char* fDwarfTranslationUnitDir;
1917 const char* fDwarfTranslationUnitFile;
1918 std::map<uint32_t,const char*> fDwarfIndexToFile;
1919 std::vector<Stab> fStabs;
1920 std::vector<FDE_Atom_Info> fFDEInfos;
1921 std::vector<CIE_Atom_Info> fCIEInfos;
1922 bool fAppleObjc;
1923 bool fHasDTraceProbes;
1924 bool fHaveIndirectSymbols;
1925 bool fReplacementClasses;
1926 bool fHasLongBranchStubs;
1927 ObjectFile::Reader::ObjcConstraint fObjConstraint;
1928 uint32_t fCpuConstraint;
1929 const macho_section<P>* fSectionsStart;
1930 const macho_section<P>* fSectionsEnd;
1931 OAS fObjectAddressSpace;
1932 };
1933
1934 template <typename A>
1935 Reader<A>::Reader(const uint8_t* fileContent, const char* path, time_t modTime, const ObjectFile::ReaderOptions& options, uint32_t ordinalBase)
1936 : fPath(strdup(path)), fModTime(modTime), fOrdinalBase(ordinalBase), fOptions(options), fHeader((const macho_header<P>*)fileContent),
1937 fStrings(NULL), fSymbols(NULL), fSymbolCount(0), fSegment(NULL), fIndirectTable(NULL),
1938 fDebugInfo(kDebugInfoNone), fHasUUID(false), fehFrameSection(NULL), fUTF16Section(NULL),
1939 fDwarfDebugInfoSect(NULL), fDwarfDebugAbbrevSect(NULL), fDwarfDebugLineSect(NULL),
1940 fDwarfTranslationUnitDir(NULL), fDwarfTranslationUnitFile(NULL), fAppleObjc(false), fHasDTraceProbes(false),
1941 fHaveIndirectSymbols(false), fReplacementClasses(false), fHasLongBranchStubs(false),
1942 fObjConstraint(ObjectFile::Reader::kObjcNone), fCpuConstraint(ObjectFile::Reader::kCpuAny),
1943 fSectionsStart(NULL), fSectionsEnd(NULL), fObjectAddressSpace(*this)
1944 {
1945 // sanity check
1946 if ( ! validFile(fileContent, false, 0) )
1947 throw "not a valid mach-o object file";
1948
1949 Reference<A>::fgForFinalLinkedImage = options.fForFinalLinkedImage;
1950
1951 // write out path for -t or -whatsloaded option
1952 if ( options.fLogObjectFiles || options.fLogAllFiles )
1953 printf("%s\n", path);
1954
1955 // cache intersting pointers
1956 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1957 this->setCpuConstraint(header->cpusubtype());
1958 const uint32_t cmd_count = header->ncmds();
1959 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
1960 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
1961 const macho_load_command<P>* cmd = cmds;
1962 uint32_t undefinedStartIndex = 0;
1963 uint32_t undefinedEndIndex = 0;
1964 for (uint32_t i = 0; i < cmd_count; ++i) {
1965 switch (cmd->cmd()) {
1966 case LC_SYMTAB:
1967 {
1968 const macho_symtab_command<P>* symtab = (macho_symtab_command<P>*)cmd;
1969 fSymbolCount = symtab->nsyms();
1970 fSymbols = (const macho_nlist<P>*)((char*)header + symtab->symoff());
1971 fStrings = (char*)header + symtab->stroff();
1972 if ( undefinedEndIndex == 0 ) {
1973 undefinedStartIndex = 0;
1974 undefinedEndIndex = symtab->nsyms();
1975 }
1976 }
1977 break;
1978 case LC_DYSYMTAB:
1979 {
1980 const macho_dysymtab_command<P>* dsymtab = (struct macho_dysymtab_command<P>*)cmd;
1981 fIndirectTable = (uint32_t*)((char*)fHeader + dsymtab->indirectsymoff());
1982 undefinedStartIndex = dsymtab->iundefsym();
1983 undefinedEndIndex = undefinedStartIndex + dsymtab->nundefsym();
1984 }
1985 break;
1986 case LC_UUID:
1987 fHasUUID = true;
1988 break;
1989
1990 default:
1991 if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
1992 fSegment = (macho_segment_command<P>*)cmd;
1993 }
1994 break;
1995 }
1996 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
1997 if ( cmd > cmdsEnd )
1998 throwf("malformed dylb, load command #%d is outside size of load commands in %s", i, path);
1999 }
2000
2001 // if there are no load commands, then this file has no content, so no atoms
2002 if ( header->ncmds() < 1 )
2003 return;
2004
2005 fSectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
2006 fSectionsEnd = &fSectionsStart[fSegment->nsects()];
2007
2008 // inital guess for number of atoms
2009 fAtoms.reserve(fSymbolCount);
2010
2011 // if there is an __eh_frame section, decode it into chunks to get atoms in that
2012 // section as well as division points for functions in __text
2013 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2014 if ( (strcmp(sect->sectname(), "__eh_frame") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) ) {
2015 fehFrameSection = sect;
2016 const char* msg = libunwind::CFI_Parser<ObjectFileAddressSpace<A> >::getCFIs(fObjectAddressSpace, sect->addr(),
2017 sect->size(), fFDEInfos, fCIEInfos);
2018 if ( msg != NULL ) {
2019 throwf("malformed __eh_frame section: %s", msg);
2020 }
2021 else {
2022 //fprintf(stderr, "%lu CIEs, %lu FDEs\n", fCIEInfos.size(), fFDEInfos.size());
2023 // add anonymous atoms for each CIE
2024 for (typename std::vector<CIE_Atom_Info>::const_iterator it = fCIEInfos.begin(); it != fCIEInfos.end(); ++it) {
2025 AnonymousAtom<A>* cieAtom = new AnonymousAtom<A>(*this, sect, it->cieAddress, 1);
2026 fAtoms.push_back(cieAtom);
2027 fAddrToAtom[it->cieAddress] = cieAtom;
2028 }
2029 // add anonymous atoms for each FDE and LSDA
2030 for (typename std::vector<FDE_Atom_Info>::const_iterator it = fFDEInfos.begin(); it != fFDEInfos.end(); ++it) {
2031 //fprintf(stderr, "fdeAddress=0x%08llX, lsdaAddr=0x%08llX, funcAddr=0x%08llX\n", (uint64_t)it->fdeAddress, (uint64_t)it->lsda.address, (uint64_t)it->function.address);
2032 AnonymousAtom<A>* fdeAtom = new AnonymousAtom<A>(*this, sect, it->fdeAddress, 0);
2033 fAtoms.push_back(fdeAtom);
2034 fAddrToAtom[it->fdeAddress] = fdeAtom;
2035 if ( it->lsda.address != 0 ) {
2036 AnonymousAtom<A>* lsdaAtom = new AnonymousAtom<A>(*this, getSectionForAddress(it->lsda.address), it->lsda.address, 0);
2037 fAtoms.push_back(lsdaAtom);
2038 fAddrToAtom[it->lsda.address] = lsdaAtom;
2039 fLSDAAtoms.insert(lsdaAtom);
2040 }
2041 }
2042 }
2043 }
2044 else if ( (strcmp(sect->sectname(), "__ustring") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) && (sect->size() != 0) ) {
2045 // if there is a __ustring section parse it into atoms
2046 fUTF16Section = sect;
2047 // first find all cleave points
2048 const uint16_t* words = (uint16_t*)((char*)(fHeader) + fUTF16Section->offset());
2049 unsigned int wordCount = fUTF16Section->size()/2;
2050 std::vector<pint_t> utf16Addreses;
2051 bool inString = false;
2052 for (unsigned int i=0; i < wordCount; ++i) {
2053 if ( inString ) {
2054 if ( words[i] == 0x0000 ) {
2055 inString = false;
2056 }
2057 }
2058 else {
2059 if ( words[i] == 0x0000 ) {
2060 // skip over zero padding
2061 }
2062 else {
2063 inString = true;
2064 utf16Addreses.push_back(fUTF16Section->addr() + i*2);
2065 }
2066 }
2067 }
2068 utf16Addreses.push_back(fUTF16Section->addr() + sect->size());
2069 // build map of symbols
2070 std::map<pint_t, const macho_nlist<P>* > symbolMap;
2071 for (int i=fSymbolCount-1; i >= 0 ; --i) {
2072 const macho_nlist<P>& sym = fSymbols[i];
2073 if ( (sym.n_type() & N_STAB) == 0 ) {
2074 uint8_t type = (sym.n_type() & N_TYPE);
2075 if ( type == N_SECT ) {
2076 if ( &fSectionsStart[sym.n_sect()-1] == fUTF16Section ) {
2077 // rdar://problem/7429384 don't coalesce UTF16 strings unless label starts with ___utf16_string
2078 if ( strncmp(&fStrings[sym.n_strx()], "___utf16_string", 15) != 0 ) {
2079 symbolMap[sym.n_value()] = &sym;
2080 // <rdar://problem/7516793> if this symbol is a string of just 0x0000, it may not be in utf16Addreses
2081 if ( words[(sym.n_value() - sect->addr())/2] == 0x0000 ) {
2082 for(typename std::vector<pint_t>::iterator sit=utf16Addreses.begin(); sit != utf16Addreses.end(); ++sit) {
2083 if ( *sit == sym.n_value() ) {
2084 // already in utf16Addreses
2085 break;
2086 }
2087 if ( *sit > sym.n_value() ) {
2088 // need to insert
2089 utf16Addreses.insert(sit, sym.n_value());
2090 break;
2091 }
2092 }
2093 }
2094 }
2095 }
2096 }
2097 }
2098 }
2099 // make atom for each string
2100 for(int i=utf16Addreses.size()-2; i >=0 ; --i) {
2101 pint_t size = utf16Addreses[i+1] - utf16Addreses[i];
2102 typename std::map<pint_t, const macho_nlist<P>* >::iterator pos = symbolMap.find(utf16Addreses[i]);
2103 if ( pos == symbolMap.end() ) {
2104 AnonymousAtom<A>* strAtom = new AnonymousAtom<A>(*this, fUTF16Section, utf16Addreses[i], size);
2105 fAtoms.push_back(strAtom);
2106 fAddrToAtom[utf16Addreses[i]] = strAtom;
2107 }
2108 else {
2109 SymbolAtom<A>* newAtom = new SymbolAtom<A>(*this, pos->second, fUTF16Section);
2110 fAtoms.push_back(newAtom);
2111 fAddrToAtom[utf16Addreses[i]] = newAtom;
2112 newAtom->setSize(size);
2113 }
2114 }
2115 }
2116 }
2117
2118
2119 // add all atoms that have entries in symbol table
2120 BaseAtom* sectionEndAtoms[fSegment->nsects()];
2121 for (unsigned int i=0; i < fSegment->nsects(); ++i)
2122 sectionEndAtoms[i] = NULL;
2123 for (int i=fSymbolCount-1; i >= 0 ; --i) {
2124 // walk backwards through symbol table so globals are see before locals, otherwise a local alias would beome the real name
2125 const macho_nlist<P>& sym = fSymbols[i];
2126 if ( (sym.n_type() & N_STAB) == 0 ) {
2127 uint8_t type = (sym.n_type() & N_TYPE);
2128 if ( type == N_SECT ) {
2129 const macho_section<P>* section = &fSectionsStart[sym.n_sect()-1];
2130 const pint_t sectionStartAddr = section->addr();
2131 const pint_t sectionEndAddr = sectionStartAddr + section->size();
2132 bool suppress = false;
2133 // ignore atoms in debugger sections
2134 if ( (section->flags() & S_ATTR_DEBUG) == 0 ) {
2135 if ( strncmp(&fStrings[sym.n_strx()], "__dtrace_probe$", 15) == 0 ) {
2136 // ignore dtrace probe labels
2137 fHasDTraceProbes = true;
2138 }
2139 else if ( fStrings[sym.n_strx()] == 'L' ) {
2140 // ignore L labels, <rdar://problem/3962731>
2141 }
2142 else if ( section == fehFrameSection ) {
2143 // ignore labels in __eh_frame section
2144 }
2145 else if ( section == fUTF16Section ) {
2146 // ignore labels in __ustring section
2147 }
2148 else {
2149 // ignore labels for atoms in other sections
2150 switch ( section->flags() & SECTION_TYPE ) {
2151 case S_REGULAR:
2152 if ( (sym.n_desc() & N_WEAK_DEF) && strcmp(section->sectname(), "__picsymbolstub1__TEXT") == 0 )
2153 suppress = true; // ignore stubs in crt1.o built by old ld64 that was missing S_SYMBOL_STUBS
2154 case S_ZEROFILL:
2155 case S_COALESCED:
2156 case S_4BYTE_LITERALS:
2157 case S_8BYTE_LITERALS:
2158 case S_16BYTE_LITERALS:
2159 case S_CSTRING_LITERALS:
2160 {
2161 BaseAtom* newAtom;
2162 typename AddrToAtomMap::iterator pos = fAddrToAtom.find(sym.n_value());
2163 if ( (pos != fAddrToAtom.end()) && (pos->second->getSectionRecord() == section) ) {
2164 if ( fLSDAAtoms.count(pos->second) != 0 ) {
2165 // already have LSDA atom from for this address, ignore compiler's label
2166 suppress = true;
2167 break;
2168 }
2169 else {
2170 // another label to an existing address in the same section, make this an alias
2171 newAtom = new SymbolAliasAtom<A>(&fStrings[sym.n_strx()], &sym, *pos->second);
2172 }
2173 }
2174 else {
2175 if ( sym.n_value() == sectionEndAddr ) {
2176 // Symbol address is at end of section. This can interfere
2177 // with a symbol at the start of the next section, so don't
2178 // add to fAddrToAtom. But do track in sectionEndAtoms so we
2179 // still make aliases if there are duplicates.
2180 if ( sectionEndAtoms[sym.n_sect()-1] == NULL ) {
2181 newAtom = new SymbolAtom<A>(*this, &sym, section);
2182 sectionEndAtoms[sym.n_sect()-1] = newAtom;
2183 // if this is a zero length section, so add to fAddrToAtom
2184 if ( sym.n_value() == sectionStartAddr )
2185 fAddrToAtom[newAtom->getObjectAddress()] = newAtom;
2186 }
2187 else {
2188 newAtom = new SymbolAliasAtom<A>(&fStrings[sym.n_strx()], &sym, *sectionEndAtoms[sym.n_sect()-1]);
2189 }
2190 }
2191 else {
2192 // make SymbolAtom atom for this address
2193 newAtom = new SymbolAtom<A>(*this, &sym, section);
2194 fAddrToAtom[newAtom->getObjectAddress()] = newAtom;
2195 }
2196 }
2197 if ( ! suppress )
2198 fAtoms.push_back(newAtom);
2199 }
2200 break;
2201 case S_SYMBOL_STUBS:
2202 case S_LAZY_SYMBOL_POINTERS:
2203 case S_NON_LAZY_SYMBOL_POINTERS:
2204 // ignore symboled stubs produces by old ld64
2205 break;
2206 default:
2207 warning("symbol %s found in unsupported section in %s",
2208 &fStrings[sym.n_strx()], this->getPath());
2209 }
2210 }
2211 }
2212 }
2213 else if ( (type == N_UNDF) && (sym.n_value() != 0) ) {
2214 fAtoms.push_back(new TentativeAtom<A>(*this, &sym));
2215 }
2216 else if ( (type == N_UNDF) && (sym.n_value() == 0) ) {
2217 const char* symName = &fStrings[sym.n_strx()];
2218 if ( strncmp(symName, "section$start$", 14) == 0)
2219 fAtoms.push_back(new SectionBoundaryAtom<A>(*this, true, symName, &symName[14]));
2220 else if ( strncmp(symName, "section$end$", 12) == 0)
2221 fAtoms.push_back(new SectionBoundaryAtom<A>(*this, false, symName, &symName[12]));
2222 }
2223 else if ( type == N_ABS ) {
2224 const char* symName = &fStrings[sym.n_strx()];
2225 if ( strncmp(symName, ".objc_class_name_", 17) == 0 ) {
2226 // ignore .objc_class_name_* symbols
2227 fAppleObjc = true;
2228 }
2229 else if ( strcmp(&symName[strlen(symName)-3], ".eh") == 0 ) {
2230 // ignore empty *.eh symbols
2231 }
2232 else {
2233 BaseAtom* abAtom = new AbsoluteAtom<A>(*this, &sym);
2234 fAtoms.push_back(abAtom);
2235 fAddrToAbsoluteAtom[sym.n_value()] = abAtom;
2236 }
2237 }
2238 else if ( type == N_INDR ) {
2239 fHaveIndirectSymbols = true;
2240 }
2241 }
2242 }
2243
2244 // add anonymous atoms for any functions (as determined by dwarf unwind) have no symbol names
2245 if ( fehFrameSection != NULL ) {
2246 for (typename std::vector<FDE_Atom_Info>::const_iterator it = fFDEInfos.begin(); it != fFDEInfos.end(); ++it) {
2247 // add if not already an atom at that address
2248 if ( fAddrToAtom.find(it->function.address) == fAddrToAtom.end() ) {
2249 AnonymousAtom<A>* funcAtom = new AnonymousAtom<A>(*this, getSectionForAddress(it->function.address), it->function.address, 0);
2250 fAtoms.push_back(funcAtom);
2251 fAddrToAtom[it->function.address] = funcAtom;
2252 // even though we've made a new atom, be conservative and make sure they lay out together
2253 if ( canScatterAtoms() ) {
2254 AtomAndOffset prev = findAtomAndOffset(it->function.address-1);
2255 if ( prev.atom != NULL ) {
2256 if ( ((BaseAtom*)(prev.atom))->getSectionRecord() == funcAtom->getSectionRecord() )
2257 new Reference<A>(A::kFollowOn, prev, AtomAndOffset(funcAtom));
2258 }
2259 }
2260 }
2261 }
2262 }
2263
2264
2265 // add all fixed size anonymous atoms from special sections
2266 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2267 pint_t atomSize = 0;
2268 uint8_t type (sect->flags() & SECTION_TYPE);
2269 validSectionType(type);
2270 bool suppress = false;
2271 switch ( type ) {
2272 case S_SYMBOL_STUBS:
2273 suppress = true;
2274 atomSize = sect->reserved2();
2275 break;
2276 case S_LAZY_SYMBOL_POINTERS:
2277 suppress = true;
2278 atomSize = sizeof(pint_t);
2279 break;
2280 case S_NON_LAZY_SYMBOL_POINTERS:
2281 case S_LITERAL_POINTERS:
2282 case S_MOD_INIT_FUNC_POINTERS:
2283 case S_MOD_TERM_FUNC_POINTERS:
2284 atomSize = sizeof(pint_t);
2285 break;
2286 case S_INTERPOSING:
2287 atomSize = sizeof(pint_t)*2;
2288 break;
2289 case S_4BYTE_LITERALS:
2290 atomSize = 4;
2291 break;
2292 case S_8BYTE_LITERALS:
2293 atomSize = 8;
2294 break;
2295 case S_16BYTE_LITERALS:
2296 atomSize = 16;
2297 break;
2298 case S_REGULAR:
2299 // special case ObjC classes to synthesize .objc_class_name_* symbols
2300 if ( (strcmp(sect->sectname(), "__class") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) && fAppleObjc ) {
2301 // gcc sometimes over aligns class structure
2302 uint32_t align = 1 << sect->align();
2303 atomSize = ((12 * sizeof(pint_t)) + align-1) & (-align);
2304 }
2305 // get objc Garbage Collection info
2306 else if ( ((strcmp(sect->sectname(), "__image_info") == 0) && (strcmp(sect->segname(), "__OBJC") == 0))
2307 || ((strncmp(sect->sectname(), "__objc_imageinfo", 16) == 0) && (strcmp(sect->segname(), "__DATA") == 0)) ) {
2308 // struct objc_image_info {
2309 // uint32_t version; // initially 0
2310 // uint32_t flags;
2311 // };
2312 // #define OBJC_IMAGE_SUPPORTS_GC 2
2313 // #define OBJC_IMAGE_GC_ONLY 4
2314 //
2315 const uint32_t* contents = (uint32_t*)(((char*)fHeader) + sect->offset());
2316 if ( (sect->size() >= 8) && (contents[0] == 0) ) {
2317 uint32_t flags = E::get32(contents[1]);
2318 if ( (flags & 4) == 4 )
2319 fObjConstraint = ObjectFile::Reader::kObjcGC;
2320 else if ( (flags & 2) == 2 )
2321 fObjConstraint = ObjectFile::Reader::kObjcRetainReleaseOrGC;
2322 else
2323 fObjConstraint = ObjectFile::Reader::kObjcRetainRelease;
2324 if ( (flags & 1) == 1 )
2325 fReplacementClasses = true;
2326 // don't make atom for this section
2327 atomSize = sect->size();
2328 suppress = true;
2329 }
2330 else {
2331 warning("can't parse __OBJC/__image_info section in %s", fPath);
2332 }
2333 }
2334 // special case constant NS/CFString literals and make an atom out of each one
2335 else if ((strcmp(sect->sectname(), "__cfstring") == 0) && (strcmp(sect->segname(), "__DATA") == 0)) {
2336 atomSize = 4 * sizeof(pint_t);
2337 }
2338 // special case class reference sections
2339 else if ( (strncmp(sect->sectname(), "__objc_classrefs", 16) == 0) && (strcmp(sect->segname(), "__DATA") == 0) ) {
2340 atomSize = sizeof(pint_t);;
2341 }
2342 break;
2343 }
2344 if ( atomSize != 0 ) {
2345 for(pint_t sectOffset=0; sectOffset < sect->size(); sectOffset += atomSize) {
2346 pint_t atomAddr = sect->addr() + sectOffset;
2347 // add if not already an atom at that address
2348 if ( fAddrToAtom.find(atomAddr) == fAddrToAtom.end() ) {
2349 AnonymousAtom<A>* newAtom = new AnonymousAtom<A>(*this, sect, atomAddr, atomSize);
2350 if ( !suppress )
2351 fAtoms.push_back(newAtom);
2352 fAddrToAtom[atomAddr] = newAtom->redirectTo();
2353 }
2354 }
2355 }
2356 }
2357
2358 // add all c-string anonymous atoms
2359 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2360 if ( ((sect->flags() & SECTION_TYPE) == S_CSTRING_LITERALS) || strcmp(sect->sectname(), "__cstring") == 0 ) {
2361 uint32_t stringLen;
2362 pint_t stringAddr;
2363 BaseAtom* mostAlignedEmptyString = NULL;
2364 uint32_t mostAlignedEmptyStringTrailingZeros = 0;
2365 std::vector<std::pair<pint_t,BaseAtom*> > emptyStrings;
2366 for(pint_t sectOffset=0; sectOffset < sect->size(); sectOffset += stringLen) {
2367 stringAddr = sect->addr() + sectOffset;
2368 stringLen = strlen((char*)(fHeader) + sect->offset() + sectOffset) + 1;
2369 // add if not already a non-zero length atom at that address
2370 typename AddrToAtomMap::iterator pos = fAddrToAtom.find(stringAddr);
2371 if ( (pos == fAddrToAtom.end()) || (pos->second->getSize() == 0) ) {
2372 BaseAtom* newAtom = new AnonymousAtom<A>(*this, sect, stringAddr, stringLen);
2373 if ( stringLen == 1 ) {
2374 // because of padding it may look like there are lots of empty strings, keep track of all
2375 emptyStrings.push_back(std::make_pair<pint_t,BaseAtom*>(stringAddr, newAtom));
2376 // record empty string with greatest alignment requirement
2377 uint32_t stringAddrTrailingZeros = (stringAddr==0) ? sect->align() : __builtin_ctz(stringAddr);
2378 if ( (mostAlignedEmptyString == NULL)
2379 || ( stringAddrTrailingZeros > mostAlignedEmptyStringTrailingZeros) ) {
2380 mostAlignedEmptyString = newAtom;
2381 mostAlignedEmptyStringTrailingZeros = stringAddrTrailingZeros;
2382 }
2383 }
2384 else {
2385 fAtoms.push_back(newAtom);
2386 fAddrToAtom[stringAddr] = newAtom;
2387 }
2388 }
2389 }
2390 // map all uses of empty strings to the most aligned one
2391 if ( mostAlignedEmptyString != NULL ) {
2392 // make most aligned atom a real atom
2393 fAtoms.push_back(mostAlignedEmptyString);
2394 // map all other empty atoms to this one
2395 for (typename std::vector<std::pair<pint_t,BaseAtom*> >::iterator it=emptyStrings.begin(); it != emptyStrings.end(); it++) {
2396 fAddrToAtom[it->first] = mostAlignedEmptyString;
2397 }
2398 }
2399 }
2400 }
2401
2402 // sort all atoms so far by address and section
2403 std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
2404
2405 //fprintf(stderr, "sorted atoms:\n");
2406 //for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++)
2407 // fprintf(stderr, "0x%08llX %s\n", (*it)->getObjectAddress(), (*it)->getDisplayName());
2408
2409 // create atoms to cover any non-debug ranges not handled above
2410 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2411 pint_t sectionStartAddr = sect->addr();
2412 pint_t sectionEndAddr = sect->addr() + sect->size();
2413 // don't set follow-on atoms in __eh_frame section
2414 const bool setFollowOnAtom = !canScatterAtoms() && (sect != fehFrameSection);
2415 if ( sect->size() != 0 ) {
2416 // ignore dwarf sections. If ld every supports processing dwarf, this logic will need to change
2417 if ( (sect->flags() & S_ATTR_DEBUG) != 0 ) {
2418 fDebugInfo = kDebugInfoDwarf;
2419 if ( strcmp(sect->sectname(), "__debug_info") == 0 )
2420 fDwarfDebugInfoSect = sect;
2421 else if ( strcmp(sect->sectname(), "__debug_abbrev") == 0 )
2422 fDwarfDebugAbbrevSect = sect;
2423 else if ( strcmp(sect->sectname(), "__debug_line") == 0 )
2424 fDwarfDebugLineSect = sect;
2425 else if ( strcmp(sect->sectname(), "__debug_str") == 0 )
2426 fDwarfDebugStringSect = sect;
2427 }
2428 else {
2429 if ( strcmp(sect->segname(), "__DWARFA") == 0 ) {
2430 throw "object file contains old DWARF debug info - rebuild with newer compiler";
2431 }
2432 uint8_t type (sect->flags() & SECTION_TYPE);
2433 switch ( type ) {
2434 case S_REGULAR:
2435 case S_ZEROFILL:
2436 case S_COALESCED:
2437 // if there is not an atom already at the start of this section, add an anonymous one
2438 pint_t previousAtomAddr = 0;
2439 BaseAtom* previousAtom = NULL;
2440 if ( fAddrToAtom.find(sectionStartAddr) == fAddrToAtom.end() ) {
2441 BaseAtom* newAtom = new AnonymousAtom<A>(*this, sect, sect->addr(), 0);
2442 fAddrToAtom[sect->addr()] = newAtom;
2443 fAtoms.push_back(newAtom);
2444 previousAtomAddr = sectionStartAddr;
2445 previousAtom = newAtom;
2446 std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
2447 }
2448 // calculate size of all atoms in this section and add follow-on references
2449 for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
2450 BaseAtom* atom = (BaseAtom*)(*it);
2451 pint_t atomAddr = atom->getObjectAddress();
2452 if ( atom->getSectionRecord() == sect ) {
2453 //fprintf(stderr, "addr=0x%08llX, atom=%s\n", (uint64_t)atomAddr, atom->getDisplayName());
2454 if ( (previousAtom != NULL) && (previousAtomAddr != atomAddr) ) {
2455 previousAtom->setSize(atomAddr - previousAtomAddr);
2456 if ( setFollowOnAtom && (atom != previousAtom) )
2457 new Reference<A>(A::kFollowOn, AtomAndOffset(previousAtom), AtomAndOffset(atom));
2458 }
2459 previousAtomAddr = atomAddr;
2460 previousAtom = atom;
2461 }
2462 }
2463 if ( previousAtom != NULL ) {
2464 // set last atom in section
2465 previousAtom->setSize(sectionEndAddr - previousAtomAddr);
2466 }
2467 break;
2468 }
2469 }
2470 }
2471 }
2472
2473 // check for object file that defines no objc classes, but uses objc classes
2474 // check for dtrace provider info
2475 for (uint32_t i=undefinedStartIndex; i < undefinedEndIndex; ++i) {
2476 const macho_nlist<P>& sym = fSymbols[i];
2477 if ( (sym.n_type() & N_STAB) == 0 ) {
2478 if ( (sym.n_type() & N_TYPE) == N_UNDF ) {
2479 const char* undefinedName = &fStrings[sym.n_strx()];
2480 if ( !fAppleObjc && (strncmp(undefinedName, ".objc_class_name_", 17) == 0) ) {
2481 fAppleObjc = true;
2482 }
2483 else if ( strncmp(undefinedName, "___dtrace_", 10) == 0 ) {
2484 if ( strchr(undefinedName, '$') != NULL ) {
2485 if ( (strncmp(&undefinedName[10], "probe$", 6) != 0) && (strncmp(&undefinedName[10], "isenabled$", 10) != 0) ) {
2486 // any undefined starting with __dtrace_*$ that is not ___dtrace_probe$* or ___dtrace_isenabled$*
2487 // is extra provider info
2488 fDtraceProviderInfo.push_back(undefinedName);
2489 }
2490 }
2491 }
2492 }
2493 }
2494 }
2495
2496 // add relocation based references to sections that have atoms with pending names
2497 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2498 if ( fSectionsWithAtomsPendingAName.count(sect) != 0 )
2499 addReferencesForSection(sect);
2500 }
2501
2502 // update any anonymous atoms that need references built in order to name themselves
2503 for (typename std::vector<AnonymousAtom<A>*>::iterator it=fAtomsPendingAName.begin(); it != fAtomsPendingAName.end(); it++) {
2504 (*it)->resolveName();
2505 }
2506
2507 // add relocation based references to other sections
2508 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2509 if ( fSectionsWithAtomsPendingAName.count(sect) == 0 )
2510 addReferencesForSection(sect);
2511 }
2512
2513 // add objective-c references
2514 if ( fAppleObjc ) {
2515 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2516 if ( (strcmp(sect->sectname(), "__cls_refs") == 0) && (strcmp(sect->segname(), "__OBJC") == 0) ) {
2517 for (uint32_t offset = 0; offset < sect->size(); offset += sizeof(pint_t)) {
2518 AtomAndOffset ao = this->findAtomAndOffset(sect->addr()+offset);
2519 ObjectFile::Reference* classRef = ao.atom->getReferences()[0];
2520 if ( classRef->getFixUpOffset() == 0 ) {
2521 const char* classStr = classRef->getTargetName();
2522 if ( strncmp(classStr, "cstring=", 8) == 0 ) {
2523 const char* className;
2524 asprintf((char**)&className, ".objc_class_name_%s", &classStr[8]);
2525 new Reference<A>(A::kNoFixUp, ao, className, 0);
2526 }
2527 }
2528 }
2529 }
2530 }
2531 }
2532
2533 // add direct references to local non-lazy-pointers, can do this now that all atoms are constructed
2534 for (typename std::vector<AnonymousAtom<A>*>::iterator it=fLocalNonLazys.begin(); it != fLocalNonLazys.end(); it++) {
2535 AnonymousAtom<A>* localNonLazy = *it;
2536 uint32_t fileOffset = localNonLazy->fSection->offset() - localNonLazy->fSection->addr() + localNonLazy->fAddress;
2537 pint_t nonLazyPtrValue = P::getP(*((pint_t*)((char*)(fHeader)+fileOffset)));
2538 makeReference(A::kPointer, localNonLazy->fAddress, nonLazyPtrValue);
2539 }
2540
2541
2542 // add personality references to CIEs
2543 for (typename std::vector<CIE_Atom_Info>::const_iterator it = fCIEInfos.begin(); it != fCIEInfos.end(); ++it) {
2544 if ( it->personality.offsetInFDE != 0 )
2545 addCiePersonalityReference(fAddrToAtom[it->cieAddress], it->personality.offsetInFDE, it->personality.encodingOfAddress);
2546 }
2547
2548 // add all references for FDEs, including implicit group references
2549 for (typename std::vector<FDE_Atom_Info>::const_iterator it = fFDEInfos.begin(); it != fFDEInfos.end(); ++it) {
2550 AtomAndOffset funcAO = this->findAtomAndOffset(it->function.address);
2551 if ( funcAO.offset != 0 )
2552 warning("FDE does not point to start of function %s\n", funcAO.atom->getDisplayName());
2553 AtomAndOffset fdeAO = this->findAtomAndOffset(it->fdeAddress);
2554 if ( fdeAO.offset != 0 )
2555 warning("FDE does start its own atom %s\n", funcAO.atom->getDisplayName());
2556 AtomAndOffset cieAO = this->findAtomAndOffset(it->cie.address);
2557 if ( cieAO.offset != 0 )
2558 warning("CIE does start its own atom %s\n", cieAO.atom->getDisplayName());
2559 AtomAndOffset lsdaAO;
2560 if ( it->lsda.address != 0 ) {
2561 lsdaAO = this->findAtomAndOffset(it->lsda.address);
2562 if ( lsdaAO.offset != 0 )
2563 warning("LSDA does start its own atom %s\n", lsdaAO.atom->getDisplayName());
2564 }
2565
2566 // add reference from FDE to CIE
2567 AtomAndOffset cieInfdeAO = AtomAndOffset(fdeAO.atom, it->cie.offsetInFDE);
2568 new Reference<A>(A::kPointerDiff32, cieInfdeAO, cieAO, cieInfdeAO);
2569
2570 // add reference from FDE to function
2571 addFdeReference(it->function.encodingOfAddress, AtomAndOffset(fdeAO.atom, it->function.offsetInFDE), funcAO);
2572
2573 // add reference from FDE to LSDA
2574 if ( it->lsda.address != 0 ) {
2575 addFdeReference(it->lsda.encodingOfAddress, AtomAndOffset(fdeAO.atom, it->lsda.offsetInFDE), lsdaAO);
2576 }
2577
2578 // FDE is in group lead by function atom
2579 new Reference<A>(A::kGroupSubordinate, funcAO, fdeAO);
2580
2581 // LSDA is in group lead by function atom
2582 if ( it->lsda.address != 0 ) {
2583 new Reference<A>(A::kGroupSubordinate, funcAO, lsdaAO);
2584 // add back reference from LSDA to owning function
2585 new Reference<A>(A::kNoFixUp, lsdaAO, funcAO);
2586 }
2587
2588 // compute compact encoding for this FDE
2589 if ( fOptions.fAddCompactUnwindEncoding ) {
2590 ((BaseAtom*)(funcAO.atom))->setCompactUnwindEncoding(it->fdeAddress);
2591 // add reference from function atom to personality function
2592 // the only reference a CIE can have is the reference to the personality function
2593 std::vector<class ObjectFile::Reference*>& cieRefs = cieAO.atom->getReferences();
2594 if ( cieRefs.size() == 1 ) {
2595 new Reference<A>((typename A::ReferenceKinds)((BaseAtom*)(funcAO.atom))->getPersonalityReferenceKind(),
2596 funcAO, cieRefs[0]->getTargetName(), 0);
2597 }
2598 }
2599 }
2600
2601 // add command line aliases
2602 for(std::vector<ObjectFile::ReaderOptions::AliasPair>::const_iterator it = fOptions.fAliases.begin(); it != fOptions.fAliases.end(); ++it) {
2603 BaseAtom* target = this->findAtomByName(it->realName);
2604 if ( (target != NULL) && target->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn )
2605 fAtoms.push_back(new SymbolAliasAtom<A>(it->alias, NULL, *target));
2606 }
2607
2608 // add dtrace probe locations
2609 if ( fHasDTraceProbes ) {
2610 for (uint32_t i=0; i < fSymbolCount; ++i) {
2611 const macho_nlist<P>& sym = fSymbols[i];
2612 if ( (sym.n_type() & N_STAB) == 0 ) {
2613 if ( (sym.n_type() & N_TYPE) == N_SECT ) {
2614 const char* symbolName = &fStrings[sym.n_strx()];
2615 if ( strncmp(symbolName, "__dtrace_probe$", 15) == 0 ) {
2616 //fprintf(stderr, "adding dtrace probe at 0x%08llX %s\n", sym.n_value(), symbolName);
2617 makeByNameReference(A::kDtraceProbe, sym.n_value(), symbolName, 0);
2618 }
2619 }
2620 }
2621 }
2622 }
2623
2624 // turn indirect symbols into SymbolAliasAtom
2625 if ( fHaveIndirectSymbols ) {
2626 for (uint32_t i=0; i < fSymbolCount; ++i) {
2627 const macho_nlist<P>& sym = fSymbols[i];
2628 if ( (sym.n_type() & N_STAB) == 0 ) {
2629 if ( (sym.n_type() & N_TYPE) == N_INDR ) {
2630 const char* aliasName = &fStrings[sym.n_strx()];
2631 const char* targetName = &fStrings[sym.n_value()];
2632 //fprintf(stderr, "found alias %s for %s\n", aliasName, targetName);
2633 BaseAtom* target = this->findAtomByName(targetName);
2634 // only currently support N_INDR based aliases to something in the same .o file
2635 if ( target != NULL ) {
2636 fAtoms.push_back(new SymbolAliasAtom<A>(aliasName, &sym, *target));
2637 //fprintf(stderr, "creating alias %s for %s\n", aliasName, targetName);
2638 }
2639 }
2640 }
2641 }
2642 }
2643
2644 //for (typename AddrToAtomMap::iterator it=fAddrToAtom.begin(); it != fAddrToAtom.end(); it++) {
2645 // fprintf(stderr, "[0x%0X -> 0x%0llX) : %s\n", it->first, it->first+it->second->getSize(), it->second->getDisplayName());
2646 //}
2647
2648 // add translation unit info from dwarf
2649 uint64_t stmtList;
2650 if ( (fDebugInfo == kDebugInfoDwarf) && (fOptions.fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone) ) {
2651 // compiler sometimes emits emtpty dwarf sections when there is no debug info, skip those
2652 if ( (fDwarfDebugInfoSect != NULL) && (fDwarfDebugInfoSect->size() != 0) ) {
2653 if ( !read_comp_unit(&fDwarfTranslationUnitFile, &fDwarfTranslationUnitDir, &stmtList) ) {
2654 // if can't parse dwarf, warn and give up
2655 fDwarfTranslationUnitFile = NULL;
2656 fDwarfTranslationUnitDir = NULL;
2657 warning("can't parse dwarf compilation unit info in %s", this->getPath());
2658 fDebugInfo = kDebugInfoNone;
2659 }
2660 }
2661 }
2662
2663 // add line number info to atoms from dwarf
2664 if ( (fDebugInfo == kDebugInfoDwarf) && (fOptions.fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone) ) {
2665 // file with just data will have no __debug_line info
2666 if ( (fDwarfDebugLineSect != NULL) && (fDwarfDebugLineSect->size() != 0) && (fAddrToAtom.size() != 0)
2667 && (fDwarfDebugInfoSect != NULL) && (fDwarfDebugInfoSect->size() != 0) ) {
2668 // validate stmt_list
2669 if ( (stmtList != (uint64_t)-1) && (stmtList < fDwarfDebugLineSect->size()) ) {
2670 const uint8_t* debug_line = (uint8_t*)(fHeader) + fDwarfDebugLineSect->offset();
2671 if ( debug_line != NULL ) {
2672 struct line_reader_data* lines = line_open(&debug_line[stmtList],
2673 fDwarfDebugLineSect->size() - stmtList, E::little_endian);
2674 struct line_info result;
2675 ObjectFile::Atom* curAtom = NULL;
2676 uint32_t curAtomOffset = 0;
2677 uint32_t curAtomAddress = 0;
2678 uint32_t curAtomSize = 0;
2679 if ( lines != NULL ) {
2680 while ( line_next (lines, &result, line_stop_pc) ) {
2681 //fprintf(stderr, "curAtom=%p, result.pc=0x%llX, result.line=%llu, result.end_of_sequence=%d, curAtomAddress=0x%X, curAtomSize=0x%X\n",
2682 // curAtom, result.pc, result.line, result.end_of_sequence, curAtomAddress, curAtomSize);
2683 // work around weird debug line table compiler generates if no functions in __text section
2684 if ( (curAtom == NULL) && (result.pc == 0) && result.end_of_sequence && (result.file == 1))
2685 continue;
2686 // for performance, see if in next pc is in current atom
2687 if ( (curAtom != NULL) && (curAtomAddress <= result.pc) && (result.pc < (curAtomAddress+curAtomSize)) ) {
2688 curAtomOffset = result.pc - curAtomAddress;
2689 }
2690 // or pc at end of current atom
2691 else if ( result.end_of_sequence && (curAtom != NULL) && (result.pc == (curAtomAddress+curAtomSize)) ) {
2692 curAtomOffset = result.pc - curAtomAddress;
2693 }
2694 else {
2695 // do slow look up of atom by address
2696 AtomAndOffset ao = this->findAtomAndOffset(result.pc);
2697 curAtom = ao.atom;
2698 if ( curAtom == NULL )
2699 break; // file has line info but no functions
2700 if ( result.end_of_sequence && (curAtomAddress+curAtomSize < result.pc) ) {
2701 // a one line function can be returned by line_next() as one entry with pc at end of blob
2702 // look for alt atom starting at end of previous atom
2703 uint32_t previousEnd = curAtomAddress+curAtomSize;
2704 AtomAndOffset alt = this->findAtomAndOffset(previousEnd);
2705 if ( result.pc <= previousEnd - alt.offset + alt.atom->getSize() ) {
2706 curAtom = alt.atom;
2707 curAtomOffset = alt.offset;
2708 curAtomAddress = previousEnd - alt.offset;
2709 curAtomSize = curAtom->getSize();
2710 }
2711 else {
2712 curAtomOffset = ao.offset;
2713 curAtomAddress = result.pc - ao.offset;
2714 curAtomSize = curAtom->getSize();
2715 }
2716 }
2717 else {
2718 curAtomOffset = ao.offset;
2719 curAtomAddress = result.pc - ao.offset;
2720 curAtomSize = curAtom->getSize();
2721 }
2722 }
2723 const char* filename;
2724 std::map<uint32_t,const char*>::iterator pos = fDwarfIndexToFile.find(result.file);
2725 if ( pos == fDwarfIndexToFile.end() ) {
2726 filename = line_file(lines, result.file);
2727 fDwarfIndexToFile[result.file] = filename;
2728 }
2729 else {
2730 filename = pos->second;
2731 }
2732 ObjectFile::LineInfo info;
2733 info.atomOffset = curAtomOffset;
2734 info.fileName = filename;
2735 info.lineNumber = result.line;
2736 //fprintf(stderr, "addr=0x%08llX, line=%lld, file=%s, atom=%s, atom.size=0x%X, end=%d\n",
2737 // result.pc, result.line, filename, curAtom->getDisplayName(), curAtomSize, result.end_of_sequence);
2738 ((BaseAtom*)curAtom)->addLineInfo(info);
2739 if ( result.end_of_sequence ) {
2740 curAtom = NULL;
2741 }
2742 }
2743 line_free(lines);
2744 }
2745 }
2746 else {
2747 warning("could not parse dwarf line number info in %s", this->getPath());
2748 }
2749 }
2750 }
2751 }
2752
2753 // if no dwarf, try processing stabs debugging info
2754 if ( (fDebugInfo == kDebugInfoNone) && (fOptions.fDebugInfoStripping != ObjectFile::ReaderOptions::kDebugInfoNone) ) {
2755 // scan symbol table for stabs entries
2756 fStabs.reserve(fSymbolCount); // reduce re-allocations
2757 BaseAtom* currentAtom = NULL;
2758 pint_t currentAtomAddress = 0;
2759 enum { start, inBeginEnd, inFun } state = start;
2760 for (uint32_t symbolIndex = 0; symbolIndex < fSymbolCount; ++symbolIndex ) {
2761 const macho_nlist<P>* sym = &fSymbols[symbolIndex];
2762 bool useStab = true;
2763 uint8_t type = sym->n_type();
2764 const char* symString = (sym->n_strx() != 0) ? &fStrings[sym->n_strx()] : NULL;
2765 if ( (type & N_STAB) != 0 ) {
2766 fDebugInfo = (fHasUUID ? kDebugInfoStabsUUID : kDebugInfoStabs);
2767 Stab stab;
2768 stab.atom = NULL;
2769 stab.type = type;
2770 stab.other = sym->n_sect();
2771 stab.desc = sym->n_desc();
2772 stab.value = sym->n_value();
2773 stab.string = NULL;
2774 switch (state) {
2775 case start:
2776 switch (type) {
2777 case N_BNSYM:
2778 // beginning of function block
2779 state = inBeginEnd;
2780 // fall into case to lookup atom by addresss
2781 case N_LCSYM:
2782 case N_STSYM:
2783 currentAtomAddress = sym->n_value();
2784 currentAtom = (BaseAtom*)this->findAtomAndOffset(currentAtomAddress).atom;
2785 if ( currentAtom != NULL ) {
2786 stab.atom = currentAtom;
2787 stab.string = symString;
2788 }
2789 else {
2790 fprintf(stderr, "can't find atom for stabs BNSYM at %08llX in %s",
2791 (uint64_t)sym->n_value(), path);
2792 }
2793 break;
2794 case N_SO:
2795 case N_OSO:
2796 case N_OPT:
2797 case N_LSYM:
2798 case N_RSYM:
2799 case N_PSYM:
2800 // not associated with an atom, just copy
2801 stab.string = symString;
2802 break;
2803 case N_GSYM:
2804 {
2805 // n_value field is NOT atom address ;-(
2806 // need to find atom by name match
2807 const char* colon = strchr(symString, ':');
2808 if ( colon != NULL ) {
2809 // build underscore leading name
2810 int nameLen = colon - symString;
2811 char symName[nameLen+2];
2812 strlcpy(&symName[1], symString, nameLen+1);
2813 symName[0] = '_';
2814 symName[nameLen+1] = '\0';
2815 currentAtom = findAtomByName(symName);
2816 if ( currentAtom != NULL ) {
2817 stab.atom = currentAtom;
2818 stab.string = symString;
2819 }
2820 }
2821 else {
2822 // might be a debug-note without trailing :G()
2823 currentAtom = findAtomByName(symString);
2824 if ( currentAtom != NULL ) {
2825 stab.atom = currentAtom;
2826 stab.string = symString;
2827 }
2828 }
2829 if ( stab.atom == NULL ) {
2830 // ld_classic added bogus GSYM stabs for old style dtrace probes
2831 if ( (strncmp(symString, "__dtrace_probe$", 15) != 0) )
2832 warning("can't find atom for N_GSYM stabs %s in %s", symString, path);
2833 useStab = false;
2834 }
2835 break;
2836 }
2837 case N_FUN:
2838 // old style stabs without BNSYM
2839 state = inFun;
2840 currentAtomAddress = sym->n_value();
2841 currentAtom = (BaseAtom*)this->findAtomAndOffset(currentAtomAddress).atom;
2842 if ( currentAtom != NULL ) {
2843 stab.atom = currentAtom;
2844 stab.string = symString;
2845 }
2846 else {
2847 warning("can't find atom for stabs FUN at %08llX in %s",
2848 (uint64_t)currentAtomAddress, path);
2849 }
2850 break;
2851 case N_SOL:
2852 case N_SLINE:
2853 stab.string = symString;
2854 // old stabs
2855 break;
2856 case N_BINCL:
2857 case N_EINCL:
2858 case N_EXCL:
2859 stab.string = symString;
2860 // -gfull built .o file
2861 break;
2862 default:
2863 warning("unknown stabs type 0x%X in %s", type, path);
2864 }
2865 break;
2866 case inBeginEnd:
2867 stab.atom = currentAtom;
2868 switch (type) {
2869 case N_ENSYM:
2870 state = start;
2871 currentAtom = NULL;
2872 break;
2873 case N_LCSYM:
2874 case N_STSYM:
2875 {
2876 BaseAtom* nestedAtom = (BaseAtom*)this->findAtomAndOffset(sym->n_value()).atom;
2877 if ( nestedAtom != NULL ) {
2878 stab.atom = nestedAtom;
2879 stab.string = symString;
2880 }
2881 else {
2882 warning("can't find atom for stabs 0x%X at %08llX in %s",
2883 type, (uint64_t)sym->n_value(), path);
2884 }
2885 break;
2886 }
2887 case N_LBRAC:
2888 case N_RBRAC:
2889 case N_SLINE:
2890 // adjust value to be offset in atom
2891 stab.value -= currentAtomAddress;
2892 default:
2893 stab.string = symString;
2894 break;
2895 }
2896 break;
2897 case inFun:
2898 switch (type) {
2899 case N_FUN:
2900 if ( sym->n_sect() != 0 ) {
2901 // found another start stab, must be really old stabs...
2902 currentAtomAddress = sym->n_value();
2903 currentAtom = (BaseAtom*)this->findAtomAndOffset(currentAtomAddress).atom;
2904 if ( currentAtom != NULL ) {
2905 stab.atom = currentAtom;
2906 stab.string = symString;
2907 }
2908 else {
2909 warning("can't find atom for stabs FUN at %08llX in %s",
2910 (uint64_t)currentAtomAddress, path);
2911 }
2912 }
2913 else {
2914 // found ending stab, switch back to start state
2915 stab.string = symString;
2916 stab.atom = currentAtom;
2917 state = start;
2918 currentAtom = NULL;
2919 }
2920 break;
2921 case N_LBRAC:
2922 case N_RBRAC:
2923 case N_SLINE:
2924 // adjust value to be offset in atom
2925 stab.value -= currentAtomAddress;
2926 stab.atom = currentAtom;
2927 break;
2928 case N_SO:
2929 stab.string = symString;
2930 state = start;
2931 break;
2932 default:
2933 stab.atom = currentAtom;
2934 stab.string = symString;
2935 break;
2936 }
2937 break;
2938 }
2939 // add to list of stabs for this .o file
2940 if ( useStab )
2941 fStabs.push_back(stab);
2942 }
2943 }
2944 }
2945
2946 #if 0
2947 // special case precompiled header .o file (which has no content) to have one empty atom
2948 if ( fAtoms.size() == 0 ) {
2949 int pathLen = strlen(path);
2950 if ( (pathLen > 6) && (strcmp(&path[pathLen-6], ".gch.o")==0) ) {
2951 ObjectFile::Atom* phony = new AnonymousAtom<A>(*this, (uint32_t)0);
2952 //phony->fSynthesizedName = ".gch.o";
2953 fAtoms.push_back(phony);
2954 }
2955 }
2956 #endif
2957
2958 // sort all atoms by address
2959 std::sort(fAtoms.begin(), fAtoms.end(), BaseAtomSorter());
2960
2961 // set ordinal and sort references in each atom
2962 uint32_t index = fOrdinalBase;
2963 for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
2964 BaseAtom* atom = (BaseAtom*)(*it);
2965 atom->setOrdinal(index++);
2966 atom->sortReferences();
2967 }
2968
2969 }
2970
2971 template <typename A>
2972 const macho_section<typename A::P>* Reader<A>::getSectionForAddress(pint_t addr)
2973 {
2974 for (const macho_section<P>* sect=fSectionsStart; sect < fSectionsEnd; ++sect) {
2975 if ( (sect->addr() <= addr) && (addr < (sect->addr()+sect->size())) )
2976 return sect;
2977 }
2978 throwf("section not found for address 0x%08llX", (uint64_t)addr);
2979 }
2980
2981 template <typename A>
2982 ObjectFile::Atom* Reader<A>::getFunctionAtomFromFDEAddress(pint_t addr)
2983 {
2984 for (typename std::vector<FDE_Atom_Info>::const_iterator it = fFDEInfos.begin(); it != fFDEInfos.end(); ++it) {
2985 if ( it->fdeAddress == addr ) {
2986 return findAtomAndOffset(it->function.address).atom;
2987 }
2988 }
2989 // CIEs won't be in fFDEInfos
2990 return NULL;
2991 }
2992
2993 template <typename A>
2994 ObjectFile::Atom* Reader<A>::getFunctionAtomFromLSDAAddress(pint_t addr)
2995 {
2996 for (typename std::vector<FDE_Atom_Info>::const_iterator it = fFDEInfos.begin(); it != fFDEInfos.end(); ++it) {
2997 if ( it->lsda.address == addr ) {
2998 return findAtomAndOffset(it->function.address).atom;
2999 }
3000 }
3001 return NULL;
3002 }
3003
3004
3005 template <>
3006 void ObjectFileAddressSpace<x86_64>::buildRelocatedMap(const macho_section<P>* sect, std::map<uint32_t,uint64_t>& map)
3007 {
3008 // mach-o x86_64 is different, the content of a section with a relocation is the addend
3009 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fReader.fHeader) + sect->reloff());
3010 const macho_relocation_info<P>* relocsEnd = &relocs[sect->nreloc()];
3011 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
3012 std::map<uint32_t,uint64_t>::iterator pos;
3013 switch ( reloc->r_type() ) {
3014 case X86_64_RELOC_UNSIGNED:
3015 pos = map.find(reloc->r_address());
3016 if ( pos != map.end() )
3017 pos->second += fReader.fSymbols[reloc->r_symbolnum()].n_value();
3018 else
3019 map[reloc->r_address()] = fReader.fSymbols[reloc->r_symbolnum()].n_value();
3020 break;
3021 case X86_64_RELOC_SUBTRACTOR:
3022 map[reloc->r_address()] = -fReader.fSymbols[reloc->r_symbolnum()].n_value();
3023 break;
3024 case X86_64_RELOC_GOT:
3025 // there is no good address to return here.
3026 // GOT slots are synthsized by the linker
3027 // this is used for the reference to the personality function in CIEs
3028 map[reloc->r_address()] = 0;
3029 break;
3030 default:
3031 fprintf(stderr, "ObjectFileAddressSpace::buildRelocatedMap() unexpected relocation at r_address=0x%08X\n", reloc->r_address());
3032 break;
3033 }
3034 }
3035 }
3036
3037 template <typename A>
3038 void ObjectFileAddressSpace<A>::buildRelocatedMap(const macho_section<P>* sect, std::map<uint32_t,uint64_t>& map)
3039 {
3040 // in all architectures except x86_64, the section contents are already fixed up to point
3041 // to content in the same object file.
3042 }
3043
3044 template <>
3045 uint64_t ObjectFileAddressSpace<x86_64>::relocated(uint32_t sectOffset, uint32_t relocsOffset, uint32_t relocsCount)
3046 {
3047 // mach-o x86_64 is different, the content of a section with a relocation is the addend
3048 uint64_t result = 0;
3049 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fReader.fHeader) + relocsOffset);
3050 const macho_relocation_info<P>* relocsEnd = &relocs[relocsCount];
3051 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
3052 //fprintf(stderr, "ObjectFileAddressSpace::relocated(0x%08X), r_address=0x%08X\n", sectOffset, reloc->r_address());
3053 if ( reloc->r_address() == sectOffset ) {
3054 switch ( reloc->r_type() ) {
3055 case X86_64_RELOC_UNSIGNED:
3056 result += fReader.fSymbols[reloc->r_symbolnum()].n_value();
3057 break;
3058 case X86_64_RELOC_SUBTRACTOR:
3059 result -= fReader.fSymbols[reloc->r_symbolnum()].n_value();
3060 break;
3061 case X86_64_RELOC_GOT:
3062 // there is no good address to return here.
3063 // GOT slots are synthsized by the linker
3064 // this is used for the reference to the personality function in CIEs
3065 result = 0;
3066 break;
3067 default:
3068 fprintf(stderr, "ObjectFileAddressSpace::relocated(0x%08X) => type=%d, value=0x%08X\n", sectOffset, reloc->r_type(), reloc->r_symbolnum());
3069 break;
3070 }
3071 }
3072 }
3073 //fprintf(stderr, "ObjectFileAddressSpace::relocated(0x%08X) => 0x%0llX\n", sectOffset, result);
3074 return result;
3075 }
3076
3077 template <typename A>
3078 typename A::P::uint_t ObjectFileAddressSpace<A>::relocated(uint32_t sectOffset, uint32_t relocsOffset, uint32_t relocsCount)
3079 {
3080 // in all architectures except x86_64, the section contents are already fixed up to point
3081 // to content in the same object file.
3082 return 0;
3083 }
3084
3085
3086
3087 // FSF exception handling Pointer-Encoding constants
3088 // Used in CFI augmentation by gcc compiler
3089 enum {
3090 DW_EH_PE_ptr = 0x00,
3091 DW_EH_PE_uleb128 = 0x01,
3092 DW_EH_PE_udata2 = 0x02,
3093 DW_EH_PE_udata4 = 0x03,
3094 DW_EH_PE_udata8 = 0x04,
3095 DW_EH_PE_signed = 0x08,
3096 DW_EH_PE_sleb128 = 0x09,
3097 DW_EH_PE_sdata2 = 0x0A,
3098 DW_EH_PE_sdata4 = 0x0B,
3099 DW_EH_PE_sdata8 = 0x0C,
3100 DW_EH_PE_absptr = 0x00,
3101 DW_EH_PE_pcrel = 0x10,
3102 DW_EH_PE_textrel = 0x20,
3103 DW_EH_PE_datarel = 0x30,
3104 DW_EH_PE_funcrel = 0x40,
3105 DW_EH_PE_aligned = 0x50,
3106 DW_EH_PE_indirect = 0x80,
3107 DW_EH_PE_omit = 0xFF
3108 };
3109
3110 template <>
3111 void Reader<x86_64>::addCiePersonalityReference(BaseAtom* cieAtom, uint32_t offsetInCIE, uint8_t encoding)
3112 {
3113 if ( encoding != (DW_EH_PE_indirect|DW_EH_PE_pcrel|DW_EH_PE_sdata4) )
3114 throw "unexpected personality encoding in CIE";
3115
3116 // walk relocs looking for reloc in this CIE
3117 uint32_t sectOffset = (cieAtom->getObjectAddress() + offsetInCIE) - fehFrameSection->addr();
3118 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + fehFrameSection->reloff());
3119 const macho_relocation_info<P>* relocsEnd = &relocs[fehFrameSection->nreloc()];
3120 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
3121 if ( reloc->r_address() == sectOffset ) {
3122 switch ( reloc->r_type() ) {
3123 case X86_64_RELOC_GOT:
3124 if ( !reloc->r_extern() )
3125 throw "GOT reloc not extern for personality function";
3126 new Reference<x86_64>(x86_64::kPCRel32GOT, AtomAndOffset(cieAtom, offsetInCIE), &fStrings[fSymbols[reloc->r_symbolnum()].n_strx()], 4);
3127 return;
3128 default:
3129 throw "expected GOT reloc for personality function";
3130 }
3131 }
3132 }
3133 throw "personality function not found for CIE";
3134 }
3135
3136 template <>
3137 bool Reader<ppc>::isSectDiffReloc(uint8_t r_type)
3138 {
3139 switch ( r_type ) {
3140 case PPC_RELOC_LOCAL_SECTDIFF:
3141 case PPC_RELOC_SECTDIFF:
3142 return true;
3143 }
3144 return false;
3145 }
3146
3147 template <>
3148 bool Reader<ppc64>::isSectDiffReloc(uint8_t r_type)
3149 {
3150 switch ( r_type ) {
3151 case PPC_RELOC_LOCAL_SECTDIFF:
3152 case PPC_RELOC_SECTDIFF:
3153 return true;
3154 }
3155 return false;
3156 }
3157
3158 template <>
3159 bool Reader<x86>::isSectDiffReloc(uint8_t r_type)
3160 {
3161 switch ( r_type ) {
3162 case GENERIC_RELOC_LOCAL_SECTDIFF:
3163 case GENERIC_RELOC_SECTDIFF:
3164 return true;
3165 }
3166 return false;
3167 }
3168
3169 template <>
3170 bool Reader<arm>::isSectDiffReloc(uint8_t r_type)
3171 {
3172 switch ( r_type ) {
3173 case ARM_RELOC_LOCAL_SECTDIFF:
3174 case ARM_RELOC_SECTDIFF:
3175 return true;
3176 }
3177 return false;
3178 }
3179
3180 template <typename A>
3181 void Reader<A>::addCiePersonalityReference(BaseAtom* cieAtom, uint32_t offsetInCIE, uint8_t encoding)
3182 {
3183 if ( (encoding != (DW_EH_PE_indirect|DW_EH_PE_pcrel|DW_EH_PE_sdata4)) && (encoding != (DW_EH_PE_indirect|DW_EH_PE_pcrel)) )
3184 throw "unexpected personality encoding in CIE";
3185
3186 // walk relocs looking for personality reloc in this CIE
3187 uint32_t sectOffset = (cieAtom->getObjectAddress() + offsetInCIE) - fehFrameSection->addr();
3188 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + fehFrameSection->reloff());
3189 const macho_relocation_info<P>* relocsEnd = &relocs[fehFrameSection->nreloc()];
3190 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
3191 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
3192 // ignore
3193 }
3194 else {
3195 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
3196 if ( sreloc->r_address() == sectOffset ) {
3197 if ( isSectDiffReloc(sreloc->r_type()) ) {
3198 // r_value is address of non-lazy-pointer to personality function
3199 new Reference<A>(A::kPointerDiff32, AtomAndOffset(cieAtom, offsetInCIE), AtomAndOffset(cieAtom, offsetInCIE),
3200 findAtomAndOffset(sreloc->r_value()));
3201 return;
3202 }
3203 }
3204 }
3205 }
3206 throw "can't find relocation for personality in CIE";
3207 }
3208
3209 template <typename A>
3210 void Reader<A>::addFdeReference(uint8_t encoding, AtomAndOffset inFDE, AtomAndOffset target)
3211 {
3212 if ( (encoding & 0xF0) != DW_EH_PE_pcrel )
3213 throw "unsupported encoding in FDE";
3214 Kinds kind = A::kNoFixUp;
3215 switch ( encoding & 0xF ) {
3216 case DW_EH_PE_ptr:
3217 kind = A::kPointerDiff;
3218 break;
3219 case DW_EH_PE_sdata4:
3220 kind = A::kPointerDiff32;
3221 break;
3222 default:
3223 throw "unsupported encoding in FDE";
3224 }
3225 new Reference<A>(kind, inFDE, inFDE, target);
3226 }
3227
3228 template <typename A>
3229 typename A::P::uint_t ObjectFileAddressSpace<A>::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
3230 {
3231 pint_t startAddr = addr;
3232 pint_t p = addr;
3233 pint_t result;
3234
3235 // first get value
3236 switch (encoding & 0x0F) {
3237 case DW_EH_PE_ptr:
3238 result = getP(addr);
3239 p += sizeof(pint_t);
3240 addr = (pint_t)p;
3241 break;
3242 case DW_EH_PE_uleb128:
3243 result = getULEB128(addr, end);
3244 break;
3245 case DW_EH_PE_udata2:
3246 result = get16(addr);
3247 p += 2;
3248 addr = (pint_t)p;
3249 break;
3250 case DW_EH_PE_udata4:
3251 result = get32(addr);
3252 p += 4;
3253 addr = (pint_t)p;
3254 break;
3255 case DW_EH_PE_udata8:
3256 result = get64(addr);
3257 p += 8;
3258 addr = (pint_t)p;
3259 break;
3260 case DW_EH_PE_sleb128:
3261 result = getSLEB128(addr, end);
3262 break;
3263 case DW_EH_PE_sdata2:
3264 result = (int16_t)get16(addr);
3265 p += 2;
3266 addr = (pint_t)p;
3267 break;
3268 case DW_EH_PE_sdata4:
3269 result = (int32_t)get32(addr);
3270 p += 4;
3271 addr = (pint_t)p;
3272 break;
3273 case DW_EH_PE_sdata8:
3274 result = get64(addr);
3275 p += 8;
3276 addr = (pint_t)p;
3277 break;
3278 default:
3279 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
3280 }
3281
3282 // then add relative offset
3283 switch ( encoding & 0x70 ) {
3284 case DW_EH_PE_absptr:
3285 // do nothing
3286 break;
3287 case DW_EH_PE_pcrel:
3288 // <rdar://problem/7200658> pc-rel sdata4 should return zero if content is zero
3289 if ( (result != 0) || ((encoding & DW_EH_PE_indirect) != 0) )
3290 result += startAddr;
3291 break;
3292 case DW_EH_PE_textrel:
3293 throw "DW_EH_PE_textrel pointer encoding not supported";
3294 break;
3295 case DW_EH_PE_datarel:
3296 throw "DW_EH_PE_datarel pointer encoding not supported";
3297 break;
3298 case DW_EH_PE_funcrel:
3299 throw "DW_EH_PE_funcrel pointer encoding not supported";
3300 break;
3301 case DW_EH_PE_aligned:
3302 throw "DW_EH_PE_aligned pointer encoding not supported";
3303 break;
3304 default:
3305 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
3306 break;
3307 }
3308
3309 if ( encoding & DW_EH_PE_indirect )
3310 result = getP(result);
3311
3312 return result;
3313 }
3314
3315 template <>
3316 uint32_t SymbolAtom<x86>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3317 {
3318 pint_t lsda;
3319 pint_t personality;
3320 char warningBuffer[1024];
3321 uint32_t result = libunwind::DwarfInstructions<class ObjectFileAddressSpace<x86>, libunwind::Registers_x86>::createCompactEncodingFromFDE(
3322 fOwner.fObjectAddressSpace, ehAtomAddress, &lsda, &personality, warningBuffer);
3323 if ( (result & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF ) {
3324 //if ( fOwner.fOptions.fForDyld )
3325 // throwf("can't make compact unwind encoding from dwarf for %s", this->getDisplayName());
3326 //else
3327 if ( fOwner.fOptions.fWarnCompactUnwind )
3328 warning("can't make compact unwind encoding from dwarf for %s in %s because %s", this->getDisplayName(), fOwner.getPath(), warningBuffer);
3329 }
3330 return result;
3331 }
3332
3333 template <>
3334 uint32_t SymbolAtom<x86_64>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3335 {
3336 pint_t lsda;
3337 pint_t personality;
3338 char warningBuffer[1024];
3339 uint32_t result = libunwind::DwarfInstructions<class ObjectFileAddressSpace<x86_64>, libunwind::Registers_x86_64>::createCompactEncodingFromFDE(
3340 fOwner.fObjectAddressSpace, ehAtomAddress, &lsda, &personality, warningBuffer);
3341 if ( (result & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF ) {
3342 //if ( fOwner.fOptions.fForDyld )
3343 // throwf("can't make compact unwind encoding from dwarf for %s", this->getDisplayName());
3344 //else
3345 if ( fOwner.fOptions.fWarnCompactUnwind )
3346 warning("can't make compact unwind encoding from dwarf for %s in %s because %s", this->getDisplayName(), fOwner.getPath(), warningBuffer);
3347 }
3348 return result;
3349 }
3350
3351 template <>
3352 uint32_t SymbolAtom<ppc>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3353 {
3354 // compact encoding not supported for ppc
3355 return 0;
3356 }
3357
3358 template <>
3359 uint32_t SymbolAtom<ppc64>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3360 {
3361 // compact encoding not supported for ppc64
3362 return 0;
3363 }
3364
3365 template <>
3366 uint32_t SymbolAtom<arm>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3367 {
3368 // compact encoding not supported for arm
3369 return 0;
3370 }
3371
3372
3373 template <typename A>
3374 uint8_t SymbolAtom<A>::getLSDAReferenceKind() const
3375 {
3376 return A::kGroupSubordinate;
3377 }
3378
3379 template <>
3380 uint8_t SymbolAtom<x86_64>::getPersonalityReferenceKind() const
3381 {
3382 return x86_64::kGOTNoFixUp;
3383 }
3384
3385 template <>
3386 uint8_t SymbolAtom<x86>::getPersonalityReferenceKind() const
3387 {
3388 return x86::kNoFixUp;
3389 }
3390
3391 template <typename A>
3392 uint8_t SymbolAtom<A>::getPersonalityReferenceKind() const
3393 {
3394 // only used with architectures that support compact unwinding
3395 return 0;
3396 }
3397
3398
3399 template <>
3400 uint32_t AnonymousAtom<x86>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3401 {
3402 pint_t lsda;
3403 pint_t personality;
3404 char warningBuffer[1024];
3405 uint32_t result = libunwind::DwarfInstructions<class ObjectFileAddressSpace<x86>, libunwind::Registers_x86>::createCompactEncodingFromFDE(
3406 fOwner.fObjectAddressSpace, ehAtomAddress, &lsda, &personality, warningBuffer);
3407 if ( (result & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF ) {
3408 //if ( fOwner.fOptions.fForDyld )
3409 // throwf("can't make compact unwind encoding from dwarf for %s", this->getDisplayName());
3410 //else
3411 if ( fOwner.fOptions.fWarnCompactUnwind )
3412 warning("can't make compact unwind encoding from dwarf for %s in %s", this->getDisplayName(), fOwner.getPath());
3413 }
3414 return result;
3415 }
3416
3417 template <>
3418 uint32_t AnonymousAtom<x86_64>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3419 {
3420 pint_t lsda;
3421 pint_t personality;
3422 char warningBuffer[1024];
3423 uint32_t result = libunwind::DwarfInstructions<class ObjectFileAddressSpace<x86_64>, libunwind::Registers_x86_64>::createCompactEncodingFromFDE(
3424 fOwner.fObjectAddressSpace, ehAtomAddress, &lsda, &personality, warningBuffer);
3425 if ( (result & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF ) {
3426 //if ( fOwner.fOptions.fForDyld )
3427 // throwf("can't make compact unwind encoding from dwarf for %s", this->getDisplayName());
3428 //else
3429 if ( fOwner.fOptions.fWarnCompactUnwind )
3430 warning("can't make compact unwind encoding from dwarf for %s in %s", this->getDisplayName(), fOwner.getPath());
3431 }
3432 return result;
3433 }
3434
3435 template <>
3436 uint32_t AnonymousAtom<ppc>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3437 {
3438 // compact encoding not supported for ppc
3439 return 0;
3440 }
3441
3442 template <>
3443 uint32_t AnonymousAtom<ppc64>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3444 {
3445 // compact encoding not supported for ppc64
3446 return 0;
3447 }
3448
3449 template <>
3450 uint32_t AnonymousAtom<arm>::getCompactUnwindEncoding(uint64_t ehAtomAddress)
3451 {
3452 // compact encoding not supported for arm
3453 return 0;
3454 }
3455
3456
3457 template <typename A>
3458 uint8_t AnonymousAtom<A>::getLSDAReferenceKind() const
3459 {
3460 return A::kGroupSubordinate;
3461 }
3462
3463 template <>
3464 uint8_t AnonymousAtom<x86_64>::getPersonalityReferenceKind() const
3465 {
3466 return x86_64::kGOTNoFixUp;
3467 }
3468
3469 template <>
3470 uint8_t AnonymousAtom<x86>::getPersonalityReferenceKind() const
3471 {
3472 return x86::kNoFixUp;
3473 }
3474
3475 template <typename A>
3476 uint8_t AnonymousAtom<A>::getPersonalityReferenceKind() const
3477 {
3478 // only used with architectures that support compact unwinding
3479 return 0;
3480 }
3481
3482
3483
3484
3485
3486
3487
3488 template <>
3489 void Reader<ppc>::setCpuConstraint(uint32_t cpusubtype)
3490 {
3491 switch (cpusubtype) {
3492 case CPU_SUBTYPE_POWERPC_ALL:
3493 case CPU_SUBTYPE_POWERPC_750:
3494 case CPU_SUBTYPE_POWERPC_7400:
3495 case CPU_SUBTYPE_POWERPC_7450:
3496 case CPU_SUBTYPE_POWERPC_970:
3497 fCpuConstraint = cpusubtype;
3498 break;
3499 default:
3500 warning("unknown ppc subtype 0x%08X in %s, defaulting to ALL", cpusubtype, fPath);
3501 fCpuConstraint = CPU_SUBTYPE_POWERPC_ALL;
3502 break;
3503 }
3504 }
3505
3506 template <>
3507 void Reader<arm>::setCpuConstraint(uint32_t cpusubtype)
3508 {
3509 switch (cpusubtype) {
3510 case CPU_SUBTYPE_ARM_ALL:
3511 case CPU_SUBTYPE_ARM_V4T:
3512 case CPU_SUBTYPE_ARM_V5TEJ:
3513 case CPU_SUBTYPE_ARM_V6:
3514 case CPU_SUBTYPE_ARM_XSCALE:
3515 case CPU_SUBTYPE_ARM_V7:
3516 fCpuConstraint = cpusubtype;
3517 break;
3518 default:
3519 warning("unknown arm subtype 0x%08X in %s, defaulting to ALL", cpusubtype, fPath);
3520 fCpuConstraint = CPU_SUBTYPE_ARM_ALL;
3521 break;
3522 }
3523 }
3524
3525 template <typename A>
3526 void Reader<A>::setCpuConstraint(uint32_t cpusubtype)
3527 {
3528 // no cpu sub types for this architecture
3529 }
3530
3531 template <>
3532 uint32_t Reader<ppc>::updateCpuConstraint(uint32_t previous)
3533 {
3534 switch ( previous ) {
3535 case CPU_SUBTYPE_POWERPC_ALL:
3536 return fCpuConstraint;
3537 break;
3538 case CPU_SUBTYPE_POWERPC_750:
3539 if ( fCpuConstraint == CPU_SUBTYPE_POWERPC_7400 ||
3540 fCpuConstraint == CPU_SUBTYPE_POWERPC_7450 ||
3541 fCpuConstraint == CPU_SUBTYPE_POWERPC_970 )
3542 return fCpuConstraint;
3543 break;
3544 case CPU_SUBTYPE_POWERPC_7400:
3545 case CPU_SUBTYPE_POWERPC_7450:
3546 if ( fCpuConstraint == CPU_SUBTYPE_POWERPC_970 )
3547 return fCpuConstraint;
3548 break;
3549 case CPU_SUBTYPE_POWERPC_970:
3550 // G5 can run everything
3551 break;
3552 default:
3553 throw "Unhandled PPC cpu subtype!";
3554 break;
3555 }
3556 return previous;
3557 }
3558
3559
3560
3561 template <>
3562 uint32_t Reader<arm>::updateCpuConstraint(uint32_t previous)
3563 {
3564 switch (previous) {
3565 case CPU_SUBTYPE_ARM_ALL:
3566 return fCpuConstraint;
3567 break;
3568 case CPU_SUBTYPE_ARM_V5TEJ:
3569 // v6, v7, and xscale are more constrained than previous file (v5), so use it
3570 if ( (fCpuConstraint == CPU_SUBTYPE_ARM_V6)
3571 || (fCpuConstraint == CPU_SUBTYPE_ARM_V7)
3572 || (fCpuConstraint == CPU_SUBTYPE_ARM_XSCALE) )
3573 return fCpuConstraint;
3574 break;
3575 case CPU_SUBTYPE_ARM_V4T:
3576 // v5, v6, v7, and xscale are more constrained than previous file (v4t), so use it
3577 if ( (fCpuConstraint == CPU_SUBTYPE_ARM_V7)
3578 || (fCpuConstraint == CPU_SUBTYPE_ARM_V6)
3579 || (fCpuConstraint == CPU_SUBTYPE_ARM_V5TEJ)
3580 || (fCpuConstraint == CPU_SUBTYPE_ARM_XSCALE) )
3581 return fCpuConstraint;
3582 break;
3583 case CPU_SUBTYPE_ARM_V6:
3584 // v6 can run everything except xscale and v7
3585 if ( fCpuConstraint == CPU_SUBTYPE_ARM_XSCALE )
3586 throw "can't mix xscale and v6 code";
3587 if ( fCpuConstraint == CPU_SUBTYPE_ARM_V7 )
3588 return fCpuConstraint;
3589 break;
3590 case CPU_SUBTYPE_ARM_XSCALE:
3591 // xscale can run everything except v6 and v7
3592 if ( fCpuConstraint == CPU_SUBTYPE_ARM_V6 )
3593 throw "can't mix xscale and v6 code";
3594 if ( fCpuConstraint == CPU_SUBTYPE_ARM_V7 )
3595 throw "can't mix xscale and v7 code";
3596 break;
3597 case CPU_SUBTYPE_ARM_V7:
3598 // v7 can run everything except xscale
3599 if ( fCpuConstraint == CPU_SUBTYPE_ARM_XSCALE )
3600 throw "can't mix xscale and v7 code";
3601 break;
3602 default:
3603 throw "Unhandled ARM cpu subtype!";
3604 }
3605 return previous;
3606 }
3607
3608 template <typename A>
3609 uint32_t Reader<A>::updateCpuConstraint(uint32_t current)
3610 {
3611 // no cpu sub types for this architecture
3612 return current;
3613 }
3614
3615 template <typename A>
3616 void Reader<A>::addDtraceExtraInfos(uint32_t probeAddr, const char* providerName)
3617 {
3618 // for every ___dtrace_stability$* and ___dtrace_typedefs$* undefine with
3619 // a matching provider name, add a by-name kDtraceTypeReference at probe site
3620 const char* dollar = strchr(providerName, '$');
3621 if ( dollar != NULL ) {
3622 int providerNameLen = dollar-providerName+1;
3623 for ( std::vector<const char*>::iterator it = fDtraceProviderInfo.begin(); it != fDtraceProviderInfo.end(); ++it) {
3624 const char* typeDollar = strchr(*it, '$');
3625 if ( typeDollar != NULL ) {
3626 if ( strncmp(typeDollar+1, providerName, providerNameLen) == 0 ) {
3627 makeByNameReference(A::kDtraceTypeReference, probeAddr, *it, 0);
3628 }
3629 }
3630 }
3631 }
3632 }
3633
3634
3635 template <>
3636 void Reader<x86_64>::validSectionType(uint8_t type)
3637 {
3638 switch ( type ) {
3639 case S_SYMBOL_STUBS:
3640 throw "symbol_stub sections not valid in x86_64 object files";
3641 case S_LAZY_SYMBOL_POINTERS:
3642 throw "lazy pointer sections not valid in x86_64 object files";
3643 case S_NON_LAZY_SYMBOL_POINTERS:
3644 throw "non lazy pointer sections not valid in x86_64 object files";
3645 }
3646 }
3647
3648 template <typename A>
3649 void Reader<A>::validSectionType(uint8_t type)
3650 {
3651 }
3652
3653 template <typename A>
3654 bool Reader<A>::getTranslationUnitSource(const char** dir, const char** name) const
3655 {
3656 if ( fDebugInfo == kDebugInfoDwarf ) {
3657 *dir = fDwarfTranslationUnitDir;
3658 *name = fDwarfTranslationUnitFile;
3659 return (fDwarfTranslationUnitFile != NULL);
3660 }
3661 return false;
3662 }
3663
3664 template <typename A>
3665 BaseAtom* Reader<A>::findAtomByName(const char* name)
3666 {
3667 // first search the more important atoms
3668 for (typename AddrToAtomMap::iterator it=fAddrToAtom.begin(); it != fAddrToAtom.end(); it++) {
3669 const char* atomName = it->second->getName();
3670 if ( (atomName != NULL) && (strcmp(atomName, name) == 0) ) {
3671 return it->second;
3672 }
3673 }
3674 // try all atoms, because this might have been a tentative definition
3675 for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); it++) {
3676 BaseAtom* atom = (BaseAtom*)(*it);
3677 const char* atomName = atom->getName();
3678 if ( (atomName != NULL) && (strcmp(atomName, name) == 0) ) {
3679 return atom;
3680 }
3681 }
3682 return NULL;
3683 }
3684
3685 template <typename A>
3686 Reference<A>* Reader<A>::makeReference(Kinds kind, pint_t atAddr, pint_t toAddr)
3687 {
3688 return new Reference<A>(kind, findAtomAndOffset(atAddr), findAtomAndOffset(toAddr));
3689 }
3690
3691 template <typename A>
3692 Reference<A>* Reader<A>::makeReference(Kinds kind, pint_t atAddr, pint_t fromAddr, pint_t toAddr)
3693 {
3694 return new Reference<A>(kind, findAtomAndOffset(atAddr), findAtomAndOffset(fromAddr), findAtomAndOffset(toAddr));
3695 }
3696
3697 template <typename A>
3698 Reference<A>* Reader<A>::makeReferenceWithToBase(Kinds kind, pint_t atAddr, pint_t toAddr, pint_t toBaseAddr)
3699 {
3700 return new Reference<A>(kind, findAtomAndOffset(atAddr), findAtomAndOffset(toBaseAddr, toAddr));
3701 }
3702
3703 template <typename A>
3704 Reference<A>* Reader<A>::makeReferenceWithToBase(Kinds kind, pint_t atAddr, pint_t fromAddr, pint_t toAddr, pint_t toBaseAddr)
3705 {
3706 return new Reference<A>(kind, findAtomAndOffset(atAddr), findAtomAndOffset(fromAddr), findAtomAndOffset(toBaseAddr, toAddr));
3707 }
3708
3709 template <typename A>
3710 Reference<A>* Reader<A>::makeByNameReference(Kinds kind, pint_t atAddr, const char* toName, uint32_t toOffset)
3711 {
3712 return new Reference<A>(kind, findAtomAndOffset(atAddr), toName, toOffset);
3713 }
3714
3715 template <typename A>
3716 BaseAtom* Reader<A>::makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect)
3717 {
3718 // add a group subordinate reference from function atom to its eh frame atom
3719 const uint8_t* ehContent = (const uint8_t*)(fHeader) + ehAtomAddress - ehSect->addr() + ehSect->offset();
3720 int32_t deltaMinus8 = P::getP(*(pint_t*)(&ehContent[8])); // offset 8 in eh info is delta to function
3721 pint_t funcAddr = ehAtomAddress + deltaMinus8 + 8;
3722 ObjectFile::Atom* funcAtom = findAtomAndOffset(funcAddr).atom;
3723 ObjectFile::Atom* ehAtom = findAtomAndOffset(ehAtomAddress).atom;
3724 new Reference<A>(A::kGroupSubordinate, funcAtom, ehAtom);
3725 return (BaseAtom*)funcAtom;
3726 }
3727
3728
3729 template <>
3730 Reference<x86_64>* Reader<x86_64>::makeByNameReference(Kinds kind, pint_t atAddr, const char* toName, uint32_t toOffset)
3731 {
3732 // x86_64 uses external relocations everywhere, so external relocations do not imply by-name references
3733 // instead check scope of target
3734 BaseAtom* target = findAtomByName(toName);
3735 if ( (target != NULL) && (target->getScope() == ObjectFile::Atom::scopeTranslationUnit) )
3736 return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), AtomAndOffset(target, toOffset));
3737 else
3738 return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), toName, toOffset);
3739 }
3740
3741 template <>
3742 Reference<x86_64>* Reader<x86_64>::makeReferenceToSymbol(Kinds kind, pint_t atAddr, const macho_nlist<P>* toSymbol, pint_t toOffset)
3743 {
3744 // x86_64 uses external relocations everywhere, so external relocations do not imply by-name references
3745 // instead check scope of target
3746 const char* symbolName = &fStrings[toSymbol->n_strx()];
3747 if ( ((toSymbol->n_type() & N_TYPE) == N_SECT) && (((toSymbol->n_type() & N_EXT) == 0) || (symbolName[0] == 'L')) ) {
3748 AtomAndOffset targetAO = findAtomAndOffsetForSection(toSymbol->n_value(), toSymbol->n_sect());
3749 targetAO.offset = toOffset;
3750 return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), targetAO);
3751 }
3752 else
3753 return new Reference<x86_64>(kind, findAtomAndOffset(atAddr), symbolName, toOffset);
3754 }
3755
3756
3757 template <>
3758 BaseAtom* Reader<x86_64>::makeReferenceToEH(const char* ehName, pint_t ehAtomAddress, const macho_section<P>* ehSect)
3759 {
3760 // add a group subordinate reference from function atom to its eh frame atom
3761 // for x86_64 the __eh_frame section contains the addends, so need to use relocs to find target
3762 uint32_t ehAtomDeltaSectionOffset = ehAtomAddress + 8 - ehSect->addr(); // offset 8 in eh info is delta to function
3763 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + ehSect->reloff());
3764 const macho_relocation_info<P>* relocsEnd = &relocs[ehSect->nreloc()];
3765 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
3766 if ( (reloc->r_address() == ehAtomDeltaSectionOffset) && (reloc->r_type() == X86_64_RELOC_UNSIGNED) ) {
3767 pint_t funcAddr = fSymbols[reloc->r_symbolnum()].n_value();
3768 ObjectFile::Atom* funcAtom = findAtomAndOffset(funcAddr).atom;
3769 ObjectFile::Atom* ehAtom = findAtomAndOffset(ehAtomAddress).atom;
3770 new Reference<x86_64>(x86_64::kGroupSubordinate, funcAtom, ehAtom);
3771 return (BaseAtom*)funcAtom;
3772 }
3773 }
3774 warning("can't find matching function for eh symbol %s", ehName);
3775 return NULL;
3776 }
3777
3778 template <typename A>
3779 AtomAndOffset Reader<A>::findAtomAndOffsetForSection(pint_t addr, unsigned int expectedSectionIndex)
3780 {
3781 AtomAndOffset ao = findAtomAndOffset(addr);
3782 if ( ao.atom != NULL ) {
3783 if ( ((BaseAtom*)(ao.atom))->getSectionIndex() == expectedSectionIndex )
3784 return ao;
3785 }
3786 // The atom found is not in the section expected.
3787 // This probably means there was a label at the end of the section.
3788 // Do a slow sequential lookup
3789 for (std::vector<BaseAtom*>::iterator it=fAtoms.begin(); it != fAtoms.end(); ++it) {
3790 BaseAtom* atom = *it;
3791 if ( atom->getSectionIndex() == expectedSectionIndex ) {
3792 pint_t objAddr = atom->getObjectAddress();
3793 if ( (objAddr == addr) || ((objAddr < addr) && (objAddr+atom->getSize() > addr)) ) {
3794 return AtomAndOffset(atom, addr-atom->getObjectAddress());
3795 }
3796 }
3797 }
3798 // no atom found that matched section, fall back to one orginally found
3799 return ao;
3800 }
3801
3802 template <typename A>
3803 AtomAndOffset Reader<A>::findAtomAndOffset(pint_t addr)
3804 {
3805 // STL has no built-in for "find largest key that is same or less than"
3806 typename AddrToAtomMap::iterator it = fAddrToAtom.upper_bound(addr);
3807 // if no atoms up to this address return none found
3808 if ( it == fAddrToAtom.begin() )
3809 return AtomAndOffset(NULL);
3810 // otherwise upper_bound gets us next key, so we back up one
3811 --it;
3812 AtomAndOffset result;
3813 result.atom = it->second;
3814 result.offset = addr - it->first;
3815 //fprintf(stderr, "findAtomAndOffset(0x%0llX) ==> %s (0x%0llX -> 0x%0llX)\n",
3816 // (uint64_t)addr, result.atom->getDisplayName(), (uint64_t)it->first, it->first+result.atom->getSize());
3817 return result;
3818 }
3819
3820 // "scattered" relocations enable you to offset into an atom past the end of it
3821 // baseAddr is the address of the target atom,
3822 // realAddr is the points into it
3823 template <typename A>
3824 AtomAndOffset Reader<A>::findAtomAndOffset(pint_t baseAddr, pint_t realAddr)
3825 {
3826 typename AddrToAtomMap::iterator it = fAddrToAtom.find(baseAddr);
3827 if ( it != fAddrToAtom.end() ) {
3828 AtomAndOffset result;
3829 result.atom = it->second;
3830 result.offset = realAddr - it->first;
3831 if ( result.atom->isThumb() )
3832 result.offset &= -2;
3833 //fprintf(stderr, "findAtomAndOffset(0x%08X, 0x%08X) => %s + 0x%08X\n", baseAddr, realAddr, result.atom->getDisplayName(), result.offset);
3834 return result;
3835 }
3836 // getting here means we have a scattered relocation to an address without a label
3837 // so, find the atom that contains the baseAddr, and offset from that to the readAddr
3838 AtomAndOffset result = findAtomAndOffset(baseAddr);
3839 result.offset += (realAddr-baseAddr);
3840 return result;
3841 }
3842
3843
3844 /* Skip over a LEB128 value (signed or unsigned). */
3845 static void
3846 skip_leb128 (const uint8_t ** offset, const uint8_t * end)
3847 {
3848 while (*offset != end && **offset >= 0x80)
3849 (*offset)++;
3850 if (*offset != end)
3851 (*offset)++;
3852 }
3853
3854 /* Read a ULEB128 into a 64-bit word. Return (uint64_t)-1 on overflow
3855 or error. On overflow, skip past the rest of the uleb128. */
3856 static uint64_t
3857 read_uleb128 (const uint8_t ** offset, const uint8_t * end)
3858 {
3859 uint64_t result = 0;
3860 int bit = 0;
3861
3862 do {
3863 uint64_t b;
3864
3865 if (*offset == end)
3866 return (uint64_t) -1;
3867
3868 b = **offset & 0x7f;
3869
3870 if (bit >= 64 || b << bit >> bit != b)
3871 result = (uint64_t) -1;
3872 else
3873 result |= b << bit, bit += 7;
3874 } while (*(*offset)++ >= 0x80);
3875 return result;
3876 }
3877
3878
3879 /* Skip over a DWARF attribute of form FORM. */
3880 template <typename A>
3881 bool Reader<A>::skip_form(const uint8_t ** offset, const uint8_t * end, uint64_t form,
3882 uint8_t addr_size, bool dwarf64)
3883 {
3884 int64_t sz=0;
3885
3886 switch (form)
3887 {
3888 case DW_FORM_addr:
3889 sz = addr_size;
3890 break;
3891
3892 case DW_FORM_block2:
3893 if (end - *offset < 2)
3894 return false;
3895 sz = 2 + A::P::E::get16(*(uint16_t*)offset);
3896 break;
3897
3898 case DW_FORM_block4:
3899 if (end - *offset < 4)
3900 return false;
3901 sz = 2 + A::P::E::get32(*(uint32_t*)offset);
3902 break;
3903
3904 case DW_FORM_data2:
3905 case DW_FORM_ref2:
3906 sz = 2;
3907 break;
3908
3909 case DW_FORM_data4:
3910 case DW_FORM_ref4:
3911 sz = 4;
3912 break;
3913
3914 case DW_FORM_data8:
3915 case DW_FORM_ref8:
3916 sz = 8;
3917 break;
3918
3919 case DW_FORM_string:
3920 while (*offset != end && **offset)
3921 ++*offset;
3922 case DW_FORM_data1:
3923 case DW_FORM_flag:
3924 case DW_FORM_ref1:
3925 sz = 1;
3926 break;
3927
3928 case DW_FORM_block:
3929 sz = read_uleb128 (offset, end);
3930 break;
3931
3932 case DW_FORM_block1:
3933 if (*offset == end)
3934 return false;
3935 sz = 1 + **offset;
3936 break;
3937
3938 case DW_FORM_sdata:
3939 case DW_FORM_udata:
3940 case DW_FORM_ref_udata:
3941 skip_leb128 (offset, end);
3942 return true;
3943
3944 case DW_FORM_strp:
3945 case DW_FORM_ref_addr:
3946 sz = 4;
3947 break;
3948
3949 default:
3950 return false;
3951 }
3952 if (end - *offset < sz)
3953 return false;
3954 *offset += sz;
3955 return true;
3956 }
3957
3958 template <typename A>
3959 const char* Reader<A>::getDwarfString(uint64_t form, const uint8_t* p)
3960 {
3961 if ( form == DW_FORM_string )
3962 return (const char*)p;
3963 else if ( form == DW_FORM_strp ) {
3964 uint32_t offset = E::get32(*((uint32_t*)p));
3965 const char* dwarfStrings = (char*)(fHeader) + fDwarfDebugStringSect->offset();
3966 if ( offset > fDwarfDebugStringSect->size() ) {
3967 warning("unknown dwarf DW_FORM_strp (offset=0x%08X) is too big in %s\n", offset, this->getPath());
3968 return NULL;
3969 }
3970 return &dwarfStrings[offset];
3971 }
3972 warning("unknown dwarf string encoding (form=%lld) in %s\n", form, this->getPath());
3973 return NULL;
3974 }
3975
3976
3977 // Look at the compilation unit DIE and determine
3978 // its NAME, compilation directory (in COMP_DIR) and its
3979 // line number information offset (in STMT_LIST). NAME and COMP_DIR
3980 // may be NULL (especially COMP_DIR) if they are not in the .o file;
3981 // STMT_LIST will be (uint64_t) -1.
3982 //
3983 // At present this assumes that there's only one compilation unit DIE.
3984 //
3985 template <typename A>
3986 bool Reader<A>::read_comp_unit(const char ** name, const char ** comp_dir,
3987 uint64_t *stmt_list)
3988 {
3989 const uint8_t * debug_info;
3990 const uint8_t * debug_abbrev;
3991 const uint8_t * di;
3992 const uint8_t * da;
3993 const uint8_t * end;
3994 const uint8_t * enda;
3995 uint64_t sz;
3996 uint16_t vers;
3997 uint64_t abbrev_base;
3998 uint64_t abbrev;
3999 uint8_t address_size;
4000 bool dwarf64;
4001
4002 *name = NULL;
4003 *comp_dir = NULL;
4004 *stmt_list = (uint64_t) -1;
4005
4006 if ( (fDwarfDebugInfoSect == NULL) || (fDwarfDebugAbbrevSect == NULL) )
4007 return false;
4008
4009 debug_info = (uint8_t*)(fHeader) + fDwarfDebugInfoSect->offset();
4010 debug_abbrev = (uint8_t*)(fHeader) + fDwarfDebugAbbrevSect->offset();
4011 di = debug_info;
4012
4013 if (fDwarfDebugInfoSect->size() < 12)
4014 /* Too small to be a real debug_info section. */
4015 return false;
4016 sz = A::P::E::get32(*(uint32_t*)di);
4017 di += 4;
4018 dwarf64 = sz == 0xffffffff;
4019 if (dwarf64)
4020 sz = A::P::E::get64(*(uint64_t*)di), di += 8;
4021 else if (sz > 0xffffff00)
4022 /* Unknown dwarf format. */
4023 return false;
4024
4025 /* Verify claimed size. */
4026 if (sz + (di - debug_info) > fDwarfDebugInfoSect->size() || sz <= (dwarf64 ? 23 : 11))
4027 return false;
4028
4029 vers = A::P::E::get16(*(uint16_t*)di);
4030 if (vers < 2 || vers > 3)
4031 /* DWARF version wrong for this code.
4032 Chances are we could continue anyway, but we don't know for sure. */
4033 return false;
4034 di += 2;
4035
4036 /* Find the debug_abbrev section. */
4037 abbrev_base = dwarf64 ? A::P::E::get64(*(uint64_t*)di) : A::P::E::get32(*(uint32_t*)di);
4038 di += dwarf64 ? 8 : 4;
4039
4040 if (abbrev_base > fDwarfDebugAbbrevSect->size())
4041 return false;
4042 da = debug_abbrev + abbrev_base;
4043 enda = debug_abbrev + fDwarfDebugAbbrevSect->size();
4044
4045 address_size = *di++;
4046
4047 /* Find the abbrev number we're looking for. */
4048 end = di + sz;
4049 abbrev = read_uleb128 (&di, end);
4050 if (abbrev == (uint64_t) -1)
4051 return false;
4052
4053 /* Skip through the debug_abbrev section looking for that abbrev. */
4054 for (;;)
4055 {
4056 uint64_t this_abbrev = read_uleb128 (&da, enda);
4057 uint64_t attr;
4058
4059 if (this_abbrev == abbrev)
4060 /* This is almost always taken. */
4061 break;
4062 skip_leb128 (&da, enda); /* Skip the tag. */
4063 if (da == enda)
4064 return false;
4065 da++; /* Skip the DW_CHILDREN_* value. */
4066
4067 do {
4068 attr = read_uleb128 (&da, enda);
4069 skip_leb128 (&da, enda);
4070 } while (attr != 0 && attr != (uint64_t) -1);
4071 if (attr != 0)
4072 return false;
4073 }
4074
4075 /* Check that the abbrev is one for a DW_TAG_compile_unit. */
4076 if (read_uleb128 (&da, enda) != DW_TAG_compile_unit)
4077 return false;
4078 if (da == enda)
4079 return false;
4080 da++; /* Skip the DW_CHILDREN_* value. */
4081
4082 /* Now, go through the DIE looking for DW_AT_name,
4083 DW_AT_comp_dir, and DW_AT_stmt_list. */
4084 for (;;)
4085 {
4086 uint64_t attr = read_uleb128 (&da, enda);
4087 uint64_t form = read_uleb128 (&da, enda);
4088
4089 if (attr == (uint64_t) -1)
4090 return false;
4091 else if (attr == 0)
4092 return true;
4093
4094 if (form == DW_FORM_indirect)
4095 form = read_uleb128 (&di, end);
4096
4097 if (attr == DW_AT_name)
4098 *name = getDwarfString(form, di);
4099 else if (attr == DW_AT_comp_dir)
4100 *comp_dir = getDwarfString(form, di);
4101 else if (attr == DW_AT_stmt_list && form == DW_FORM_data4)
4102 *stmt_list = A::P::E::get32(*(uint32_t*)di);
4103 else if (attr == DW_AT_stmt_list && form == DW_FORM_data8)
4104 *stmt_list = A::P::E::get64(*(uint64_t*)di);
4105 if (! skip_form (&di, end, form, address_size, dwarf64))
4106 return false;
4107 }
4108 }
4109
4110 template <typename A>
4111 const char* Reader<A>::assureFullPath(const char* path)
4112 {
4113 if ( path[0] == '/' )
4114 return path;
4115 char cwdbuff[MAXPATHLEN];
4116 if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
4117 char* result;
4118 asprintf(&result, "%s/%s", cwdbuff, path);
4119 if ( result != NULL )
4120 return result;
4121 }
4122 return path;
4123 }
4124
4125
4126 //
4127 //
4128 // To implement architecture xxx, you must write template specializations for the following six methods:
4129 // Reader<xxx>::validFile()
4130 // Reader<xxx>::addRelocReference()
4131 // Reference<xxx>::getDescription()
4132 //
4133 //
4134
4135
4136 template <>
4137 bool Reader<ppc>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
4138 {
4139 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4140 if ( header->magic() != MH_MAGIC )
4141 return false;
4142 if ( header->cputype() != CPU_TYPE_POWERPC )
4143 return false;
4144 if ( header->filetype() != MH_OBJECT )
4145 return false;
4146 return true;
4147 }
4148
4149 template <>
4150 bool Reader<ppc64>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
4151 {
4152 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4153 if ( header->magic() != MH_MAGIC_64 )
4154 return false;
4155 if ( header->cputype() != CPU_TYPE_POWERPC64 )
4156 return false;
4157 if ( header->filetype() != MH_OBJECT )
4158 return false;
4159 return true;
4160 }
4161
4162 template <>
4163 bool Reader<x86>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
4164 {
4165 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4166 if ( header->magic() != MH_MAGIC )
4167 return false;
4168 if ( header->cputype() != CPU_TYPE_I386 )
4169 return false;
4170 if ( header->filetype() != MH_OBJECT )
4171 return false;
4172 return true;
4173 }
4174
4175 template <>
4176 bool Reader<x86_64>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
4177 {
4178 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4179 if ( header->magic() != MH_MAGIC_64 )
4180 return false;
4181 if ( header->cputype() != CPU_TYPE_X86_64 )
4182 return false;
4183 if ( header->filetype() != MH_OBJECT )
4184 return false;
4185 return true;
4186 }
4187
4188 template <>
4189 bool Reader<arm>::validFile(const uint8_t* fileContent, bool subtypeMustMatch, cpu_subtype_t subtype)
4190 {
4191 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4192 if ( header->magic() != MH_MAGIC )
4193 return false;
4194 if ( header->cputype() != CPU_TYPE_ARM )
4195 return false;
4196 if ( header->filetype() != MH_OBJECT )
4197 return false;
4198 if ( subtypeMustMatch && ((cpu_subtype_t)header->cpusubtype() != subtype) )
4199 return false;
4200 return true;
4201 }
4202
4203
4204 template <>
4205 const char* Reader<ppc>::fileKind(const uint8_t* fileContent)
4206 {
4207 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4208 if ( header->magic() != MH_MAGIC )
4209 return NULL;
4210 if ( header->cputype() != CPU_TYPE_POWERPC )
4211 return NULL;
4212 switch ( header->cpusubtype() ) {
4213 case CPU_SUBTYPE_POWERPC_750:
4214 return "ppc750";
4215 case CPU_SUBTYPE_POWERPC_7400:
4216 return "ppc7400";
4217 case CPU_SUBTYPE_POWERPC_7450:
4218 return "ppc7450";
4219 case CPU_SUBTYPE_POWERPC_970:
4220 return "ppc970";
4221 case CPU_SUBTYPE_POWERPC_ALL:
4222 return "ppc";
4223 }
4224 return "ppc???";
4225 }
4226
4227 template <>
4228 const char* Reader<ppc64>::fileKind(const uint8_t* fileContent)
4229 {
4230 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4231 if ( header->magic() != MH_MAGIC )
4232 return NULL;
4233 if ( header->cputype() != CPU_TYPE_POWERPC64 )
4234 return NULL;
4235 return "ppc64";
4236 }
4237
4238 template <>
4239 const char* Reader<x86>::fileKind(const uint8_t* fileContent)
4240 {
4241 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4242 if ( header->magic() != MH_MAGIC )
4243 return NULL;
4244 if ( header->cputype() != CPU_TYPE_I386 )
4245 return NULL;
4246 return "i386";
4247 }
4248
4249 template <>
4250 const char* Reader<x86_64>::fileKind(const uint8_t* fileContent)
4251 {
4252 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4253 if ( header->magic() != MH_MAGIC )
4254 return NULL;
4255 if ( header->cputype() != CPU_TYPE_X86_64 )
4256 return NULL;
4257 return "x86_64";
4258 }
4259
4260 template <>
4261 const char* Reader<arm>::fileKind(const uint8_t* fileContent)
4262 {
4263 const macho_header<P>* header = (const macho_header<P>*)fileContent;
4264 if ( header->magic() != MH_MAGIC )
4265 return NULL;
4266 if ( header->cputype() != CPU_TYPE_ARM )
4267 return NULL;
4268 switch ( header->cpusubtype() ) {
4269 case CPU_SUBTYPE_ARM_V4T:
4270 return "armv4t";
4271 case CPU_SUBTYPE_ARM_V5TEJ:
4272 return "armv5";
4273 case CPU_SUBTYPE_ARM_V6:
4274 return "armv6";
4275 case CPU_SUBTYPE_ARM_V7:
4276 return "armv7";
4277 }
4278 return "arm???";
4279 }
4280
4281
4282 template <typename A>
4283 bool Reader<A>::isWeakImportSymbol(const macho_nlist<P>* sym)
4284 {
4285 return ( ((sym->n_type() & N_TYPE) == N_UNDF) && ((sym->n_desc() & N_WEAK_REF) != 0) );
4286 }
4287
4288 template <>
4289 bool Reader<ppc64>::addRelocReference(const macho_section<ppc64::P>* sect, const macho_relocation_info<ppc64::P>* reloc)
4290 {
4291 return addRelocReference_powerpc(sect, reloc);
4292 }
4293
4294 template <>
4295 bool Reader<ppc>::addRelocReference(const macho_section<ppc::P>* sect, const macho_relocation_info<ppc::P>* reloc)
4296 {
4297 return addRelocReference_powerpc(sect, reloc);
4298 }
4299
4300
4301 //
4302 // ppc and ppc64 both use the same relocations, so process them in one common routine
4303 //
4304 template <typename A>
4305 bool Reader<A>::addRelocReference_powerpc(const macho_section<typename A::P>* sect,
4306 const macho_relocation_info<typename A::P>* reloc)
4307 {
4308 uint32_t srcAddr;
4309 uint32_t dstAddr;
4310 uint32_t* fixUpPtr;
4311 int32_t displacement = 0;
4312 uint32_t instruction = 0;
4313 uint32_t offsetInTarget;
4314 int16_t lowBits;
4315 bool result = false;
4316 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
4317 const macho_relocation_info<P>* nextReloc = &reloc[1];
4318 const char* targetName = NULL;
4319 bool weakImport = false;
4320 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + reloc->r_address());
4321 if ( reloc->r_type() != PPC_RELOC_PAIR )
4322 instruction = BigEndian::get32(*fixUpPtr);
4323 srcAddr = sect->addr() + reloc->r_address();
4324 if ( reloc->r_extern() ) {
4325 const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
4326 targetName = &fStrings[targetSymbol->n_strx()];
4327 weakImport = this->isWeakImportSymbol(targetSymbol);
4328 }
4329 switch ( reloc->r_type() ) {
4330 case PPC_RELOC_BR24:
4331 {
4332 if ( (instruction & 0x4C000000) == 0x48000000 ) {
4333 displacement = (instruction & 0x03FFFFFC);
4334 if ( (displacement & 0x02000000) != 0 )
4335 displacement |= 0xFC000000;
4336 }
4337 else {
4338 printf("bad instruction for BR24 reloc");
4339 }
4340 if ( reloc->r_extern() ) {
4341 offsetInTarget = srcAddr + displacement;
4342 if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
4343 makeByNameReference(A::kDtraceProbeSite, srcAddr, targetName, 0);
4344 addDtraceExtraInfos(srcAddr, &targetName[16]);
4345 }
4346 else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
4347 makeByNameReference(A::kDtraceIsEnabledSite, srcAddr, targetName, 0);
4348 addDtraceExtraInfos(srcAddr, &targetName[20]);
4349 }
4350 else if ( weakImport )
4351 makeByNameReference(A::kBranch24WeakImport, srcAddr, targetName, offsetInTarget);
4352 else
4353 makeByNameReference(A::kBranch24, srcAddr, targetName, offsetInTarget);
4354 }
4355 else {
4356 dstAddr = srcAddr + displacement;
4357 // if this is a branch to a stub, we need to see if the stub is for a weak imported symbol
4358 ObjectFile::Atom* atom = findAtomAndOffset(dstAddr).atom;
4359 targetName = atom->getName();
4360 if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
4361 makeByNameReference(A::kDtraceProbeSite, srcAddr, targetName, 0);
4362 addDtraceExtraInfos(srcAddr, &targetName[16]);
4363 }
4364 else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
4365 makeByNameReference(A::kDtraceIsEnabledSite, srcAddr, targetName, 0);
4366 addDtraceExtraInfos(srcAddr, &targetName[20]);
4367 }
4368 else if ( (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
4369 && ((AnonymousAtom<A>*)atom)->isWeakImportStub() )
4370 makeReference(A::kBranch24WeakImport, srcAddr, dstAddr);
4371 else
4372 makeReference(A::kBranch24, srcAddr, dstAddr);
4373 }
4374 }
4375 break;
4376 case PPC_RELOC_BR14:
4377 {
4378 displacement = (instruction & 0x0000FFFC);
4379 if ( (displacement & 0x00008000) != 0 )
4380 displacement |= 0xFFFF0000;
4381 if ( reloc->r_extern() ) {
4382 offsetInTarget = srcAddr + displacement;
4383 makeByNameReference(A::kBranch14, srcAddr, targetName, offsetInTarget);
4384 }
4385 else {
4386 dstAddr = srcAddr + displacement;
4387 makeReference(A::kBranch14, srcAddr, dstAddr);
4388 }
4389 }
4390 break;
4391 case PPC_RELOC_PAIR:
4392 // skip, processed by a previous look ahead
4393 break;
4394 case PPC_RELOC_LO16:
4395 {
4396 if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
4397 throw "PPC_RELOC_LO16 missing following pair";
4398 }
4399 result = true;
4400 lowBits = (instruction & 0xFFFF);
4401 if ( reloc->r_extern() ) {
4402 offsetInTarget = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
4403 makeByNameReference(A::kAbsLow16, srcAddr, targetName, offsetInTarget);
4404 }
4405 else {
4406 dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
4407 if ( reloc->r_symbolnum() == R_ABS ) {
4408 // find absolute symbol that corresponds to pointerValue
4409 typename AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
4410 if ( pos != fAddrToAbsoluteAtom.end() )
4411 makeByNameReference(A::kAbsLow16, srcAddr, pos->second->getName(), 0);
4412 else
4413 makeReference(A::kAbsLow16, srcAddr, dstAddr);
4414 }
4415 else {
4416 makeReference(A::kAbsLow16, srcAddr, dstAddr);
4417 }
4418 }
4419 }
4420 break;
4421 case PPC_RELOC_LO14:
4422 {
4423 if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
4424 throw "PPC_RELOC_LO14 missing following pair";
4425 }
4426 result = true;
4427 lowBits = (instruction & 0xFFFC);
4428 if ( reloc->r_extern() ) {
4429 offsetInTarget = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
4430 makeByNameReference(A::kAbsLow14, srcAddr, targetName, offsetInTarget);
4431 }
4432 else {
4433 dstAddr = (nextReloc->r_address() << 16) | ((uint32_t)lowBits & 0x0000FFFF);
4434 if ( reloc->r_symbolnum() == R_ABS ) {
4435 // find absolute symbol that corresponds to pointerValue
4436 typename AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
4437 if ( pos != fAddrToAbsoluteAtom.end() )
4438 makeByNameReference(A::kAbsLow14, srcAddr, pos->second->getName(), 0);
4439 else
4440 makeReference(A::kAbsLow14, srcAddr, dstAddr);
4441 }
4442 else {
4443 makeReference(A::kAbsLow14, srcAddr, dstAddr);
4444 }
4445 }
4446 }
4447 break;
4448 case PPC_RELOC_HI16:
4449 {
4450 if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
4451 throw "PPC_RELOC_HI16 missing following pair";
4452 }
4453 result = true;
4454 if ( reloc->r_extern() ) {
4455 offsetInTarget = ((instruction & 0x0000FFFF) << 16) | (nextReloc->r_address() & 0x0000FFFF);
4456 makeByNameReference(A::kAbsHigh16, srcAddr, targetName, offsetInTarget);
4457 }
4458 else {
4459 dstAddr = ((instruction & 0x0000FFFF) << 16) | (nextReloc->r_address() & 0x0000FFFF);
4460 if ( reloc->r_symbolnum() == R_ABS ) {
4461 // find absolute symbol that corresponds to pointerValue
4462 typename AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
4463 if ( pos != fAddrToAbsoluteAtom.end() )
4464 makeByNameReference(A::kAbsHigh16, srcAddr, pos->second->getName(), 0);
4465 else
4466 makeReference(A::kAbsHigh16, srcAddr, dstAddr);
4467 }
4468 else {
4469 makeReference(A::kAbsHigh16, srcAddr, dstAddr);
4470 }
4471 }
4472 }
4473 break;
4474 case PPC_RELOC_HA16:
4475 {
4476 if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
4477 throw "PPC_RELOC_HA16 missing following pair";
4478 }
4479 result = true;
4480 lowBits = (nextReloc->r_address() & 0x0000FFFF);
4481 if ( reloc->r_extern() ) {
4482 offsetInTarget = ((instruction & 0x0000FFFF) << 16) + (int32_t)lowBits;
4483 makeByNameReference(A::kAbsHigh16AddLow, srcAddr, targetName, offsetInTarget);
4484 }
4485 else {
4486 dstAddr = ((instruction & 0x0000FFFF) << 16) + (int32_t)lowBits;
4487 if ( reloc->r_symbolnum() == R_ABS ) {
4488 // find absolute symbol that corresponds to pointerValue
4489 typename AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
4490 if ( pos != fAddrToAbsoluteAtom.end() )
4491 makeByNameReference(A::kAbsHigh16AddLow, srcAddr, pos->second->getName(), 0);
4492 else
4493 makeReference(A::kAbsHigh16AddLow, srcAddr, dstAddr);
4494 }
4495 else {
4496 makeReference(A::kAbsHigh16AddLow, srcAddr, dstAddr);
4497 }
4498 }
4499 }
4500 break;
4501 case PPC_RELOC_VANILLA:
4502 {
4503 pint_t pointerValue = P::getP(*((pint_t*)fixUpPtr));
4504 if ( reloc->r_extern() ) {
4505 if ( weakImport )
4506 makeByNameReference(A::kPointerWeakImport, srcAddr, targetName, pointerValue);
4507 else
4508 makeByNameReference(A::kPointer, srcAddr, targetName, pointerValue);
4509 }
4510 else {
4511 new Reference<A>(A::kPointer, findAtomAndOffset(srcAddr), findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum()));
4512 }
4513 }
4514 break;
4515 case PPC_RELOC_JBSR:
4516 // this is from -mlong-branch codegen. We ignore the jump island and make reference to the real target
4517 if ( nextReloc->r_type() != PPC_RELOC_PAIR ) {
4518 throw "PPC_RELOC_JBSR missing following pair";
4519 }
4520 if ( !fHasLongBranchStubs )
4521 warning("object file compiled with -mlong-branch which is no longer needed. To remove this warning, recompile without -mlong-branch: %s", fPath);
4522 fHasLongBranchStubs = true;
4523 result = true;
4524 if ( reloc->r_extern() ) {
4525 throw "PPC_RELOC_JBSR should not be using an external relocation";
4526 }
4527 makeReference(A::kBranch24, srcAddr, nextReloc->r_address());
4528 if ( (instruction & 0x4C000000) == 0x48000000 ) {
4529 displacement = (instruction & 0x03FFFFFC);
4530 if ( (displacement & 0x02000000) != 0 )
4531 displacement |= 0xFC000000;
4532 }
4533 else {
4534 fprintf(stderr, "bad instruction for BR24 reloc");
4535 }
4536 break;
4537 default:
4538 warning("unknown relocation type %d", reloc->r_type());
4539 }
4540 }
4541 else {
4542 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
4543 srcAddr = sect->addr() + sreloc->r_address();
4544 dstAddr = sreloc->r_value();
4545 uint32_t betterDstAddr;
4546 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + sreloc->r_address());
4547 const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
4548 const macho_relocation_info<P>* nextReloc = &reloc[1];
4549 // file format allows pair to be scattered or not
4550 bool nextRelocIsPair = false;
4551 uint32_t nextRelocAddress = 0;
4552 uint32_t nextRelocValue = 0;
4553 if ( (nextReloc->r_address() & R_SCATTERED) == 0 ) {
4554 if ( nextReloc->r_type() == PPC_RELOC_PAIR ) {
4555 nextRelocIsPair = true;
4556 nextRelocAddress = nextReloc->r_address();
4557 result = true;
4558 }
4559 }
4560 else {
4561 if ( nextSReloc->r_type() == PPC_RELOC_PAIR ) {
4562 nextRelocIsPair = true;
4563 nextRelocAddress = nextSReloc->r_address();
4564 nextRelocValue = nextSReloc->r_value();
4565 result = true;
4566 }
4567 }
4568 switch (sreloc->r_type()) {
4569 case PPC_RELOC_VANILLA:
4570 {
4571 betterDstAddr = P::getP(*(pint_t*)fixUpPtr);
4572 //fprintf(stderr, "scattered pointer reloc: srcAddr=0x%08X, dstAddr=0x%08X, pointer=0x%08X\n", srcAddr, dstAddr, betterDstAddr);
4573 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
4574 makeReferenceWithToBase(A::kPointer, srcAddr, betterDstAddr, dstAddr);
4575 }
4576 break;
4577 case PPC_RELOC_BR14:
4578 {
4579 instruction = BigEndian::get32(*fixUpPtr);
4580 displacement = (instruction & 0x0000FFFC);
4581 if ( (displacement & 0x00008000) != 0 )
4582 displacement |= 0xFFFF0000;
4583 betterDstAddr = srcAddr+displacement;
4584 //fprintf(stderr, "betterDstAddr=0x%08X, srcAddr=0x%08X, displacement=0x%08X\n", betterDstAddr, srcAddr, displacement);
4585 makeReferenceWithToBase(A::kBranch14, srcAddr, betterDstAddr, dstAddr);
4586 }
4587 break;
4588 case PPC_RELOC_BR24:
4589 {
4590 instruction = BigEndian::get32(*fixUpPtr);
4591 if ( (instruction & 0x4C000000) == 0x48000000 ) {
4592 displacement = (instruction & 0x03FFFFFC);
4593 if ( (displacement & 0x02000000) != 0 )
4594 displacement |= 0xFC000000;
4595 betterDstAddr = srcAddr+displacement;
4596 makeReferenceWithToBase(A::kBranch24, srcAddr, betterDstAddr, dstAddr);
4597 }
4598 }
4599 break;
4600 case PPC_RELOC_LO16_SECTDIFF:
4601 {
4602 if ( ! nextRelocIsPair ) {
4603 throw "PPC_RELOC_LO16_SECTDIFF missing following pair";
4604 }
4605 instruction = BigEndian::get32(*fixUpPtr);
4606 lowBits = (instruction & 0xFFFF);
4607 displacement = (nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF);
4608 makeReferenceWithToBase(A::kPICBaseLow16, srcAddr, nextRelocValue, nextRelocValue + displacement, dstAddr);
4609 }
4610 break;
4611 case PPC_RELOC_LO14_SECTDIFF:
4612 {
4613 if ( ! nextRelocIsPair ) {
4614 throw "PPC_RELOC_LO14_SECTDIFF missing following pair";
4615 }
4616 instruction = BigEndian::get32(*fixUpPtr);
4617 lowBits = (instruction & 0xFFFC);
4618 displacement = (nextRelocAddress << 16) | ((uint32_t)lowBits & 0x0000FFFF);
4619 makeReferenceWithToBase(A::kPICBaseLow14, srcAddr, nextRelocValue, nextRelocValue + displacement, dstAddr);
4620 }
4621 break;
4622 case PPC_RELOC_HA16_SECTDIFF:
4623 {
4624 if ( ! nextRelocIsPair ) {
4625 throw "PPC_RELOC_HA16_SECTDIFF missing following pair";
4626 }
4627 instruction = BigEndian::get32(*fixUpPtr);
4628 lowBits = (nextRelocAddress & 0x0000FFFF);
4629 displacement = ((instruction & 0x0000FFFF) << 16) + (int32_t)lowBits;
4630 makeReferenceWithToBase(A::kPICBaseHigh16, srcAddr, nextRelocValue, nextRelocValue + displacement, dstAddr);
4631 }
4632 break;
4633 case PPC_RELOC_LO14:
4634 {
4635 if ( ! nextRelocIsPair ) {
4636 throw "PPC_RELOC_LO14 missing following pair";
4637 }
4638 instruction = BigEndian::get32(*fixUpPtr);
4639 lowBits = (instruction & 0xFFFC);
4640 betterDstAddr = (nextRelocAddress << 16) + ((uint32_t)lowBits & 0x0000FFFF);
4641 makeReferenceWithToBase(A::kAbsLow14, srcAddr, betterDstAddr, dstAddr);
4642 }
4643 break;
4644 case PPC_RELOC_LO16:
4645 {
4646 if ( ! nextRelocIsPair ) {
4647 throw "PPC_RELOC_LO16 missing following pair";
4648 }
4649 instruction = BigEndian::get32(*fixUpPtr);
4650 lowBits = (instruction & 0xFFFF);
4651 betterDstAddr = (nextRelocAddress << 16) + ((uint32_t)lowBits & 0x0000FFFF);
4652 makeReferenceWithToBase(A::kAbsLow16, srcAddr, betterDstAddr, dstAddr);
4653 }
4654 break;
4655 case PPC_RELOC_HA16:
4656 {
4657 if ( ! nextRelocIsPair ) {
4658 throw "PPC_RELOC_HA16 missing following pair";
4659 }
4660 instruction = BigEndian::get32(*fixUpPtr);
4661 lowBits = (nextRelocAddress & 0xFFFF);
4662 betterDstAddr = ((instruction & 0xFFFF) << 16) + (int32_t)lowBits;
4663 makeReferenceWithToBase(A::kAbsHigh16AddLow, srcAddr, betterDstAddr, dstAddr);
4664 }
4665 break;
4666 case PPC_RELOC_HI16:
4667 {
4668 if ( ! nextRelocIsPair ) {
4669 throw "PPC_RELOC_HI16 missing following pair";
4670 }
4671 instruction = BigEndian::get32(*fixUpPtr);
4672 lowBits = (nextRelocAddress & 0xFFFF);
4673 betterDstAddr = ((instruction & 0xFFFF) << 16) | (lowBits & 0x0000FFFF);
4674 makeReferenceWithToBase(A::kAbsHigh16, srcAddr, betterDstAddr, dstAddr);
4675 }
4676 break;
4677 case PPC_RELOC_SECTDIFF:
4678 case PPC_RELOC_LOCAL_SECTDIFF:
4679 {
4680 if ( ! nextRelocIsPair ) {
4681 throw "PPC_RELOC_SECTDIFF missing following pair";
4682 }
4683 Kinds kind = A::kPointerDiff32;;
4684 uint32_t contentAddr = 0;
4685 switch ( sreloc->r_length() ) {
4686 case 0:
4687 throw "bad diff relocations r_length (0) for ppc architecture";
4688 case 1:
4689 kind = A::kPointerDiff16;
4690 contentAddr = BigEndian::get16(*((uint16_t*)fixUpPtr));
4691 break;
4692 case 2:
4693 kind = A::kPointerDiff32;
4694 contentAddr = BigEndian::get32(*fixUpPtr);
4695 break;
4696 case 3:
4697 kind = A::kPointerDiff64;
4698 contentAddr = BigEndian::get64(*((uint64_t*)fixUpPtr));
4699 break;
4700 }
4701 AtomAndOffset srcao = findAtomAndOffset(srcAddr);
4702 AtomAndOffset fromao = findAtomAndOffset(nextRelocValue);
4703 AtomAndOffset toao = findAtomAndOffset(dstAddr);
4704 // check for addend encoded in the section content
4705 //fprintf(stderr, "addRef: dstAddr=0x%X, nextRelocValue=0x%X, contentAddr=0x%X\n",
4706 // dstAddr, nextRelocValue, contentAddr);
4707 if ( (dstAddr - nextRelocValue) != contentAddr ) {
4708 if ( toao.atom == srcao.atom )
4709 toao.offset += (contentAddr + nextRelocValue) - dstAddr;
4710 else if ( fromao.atom == srcao.atom )
4711 toao.offset += (contentAddr + nextRelocValue) - dstAddr;
4712 else
4713 fromao.offset += (dstAddr - contentAddr) - nextRelocValue;
4714 }
4715 //fprintf(stderr, "addRef: src=%s+0x%X, from=%s+0x%X, to=%s+0x%X\n",
4716 // srcao.atom->getDisplayName(), srcao.offset,
4717 // fromao.atom->getDisplayName(), fromao.offset,
4718 // toao.atom->getDisplayName(), toao.offset);
4719 new Reference<A>(kind, srcao, fromao, toao);
4720 }
4721 break;
4722 case PPC_RELOC_PAIR:
4723 break;
4724 case PPC_RELOC_HI16_SECTDIFF:
4725 warning("unexpected scattered relocation type PPC_RELOC_HI16_SECTDIFF");
4726 break;
4727 default:
4728 warning("unknown scattered relocation type %d", sreloc->r_type());
4729 }
4730 }
4731 return result;
4732 }
4733
4734
4735 template <>
4736 bool Reader<x86>::addRelocReference(const macho_section<x86::P>* sect, const macho_relocation_info<x86::P>* reloc)
4737 {
4738 uint32_t srcAddr;
4739 uint32_t dstAddr;
4740 uint32_t* fixUpPtr;
4741 bool result = false;
4742 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
4743 srcAddr = sect->addr() + reloc->r_address();
4744 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + reloc->r_address());
4745 switch ( reloc->r_type() ) {
4746 case GENERIC_RELOC_VANILLA:
4747 {
4748 x86::ReferenceKinds kind = x86::kPointer;
4749 uint32_t pointerValue = E::get32(*fixUpPtr);
4750 if ( reloc->r_pcrel() ) {
4751 switch( reloc->r_length() ) {
4752 case 0:
4753 kind = x86::kPCRel8;
4754 pointerValue = srcAddr + *((int8_t*)fixUpPtr) + sizeof(int8_t);
4755 break;
4756 case 1:
4757 kind = x86::kPCRel16;
4758 pointerValue = srcAddr + (int16_t)E::get16(*((uint16_t*)fixUpPtr)) + sizeof(uint16_t);
4759 break;
4760 case 2:
4761 kind = x86::kPCRel32;
4762 pointerValue += srcAddr + sizeof(uint32_t);
4763 break;
4764 case 3:
4765 throw "bad pc-rel vanilla relocation length";
4766 }
4767 }
4768 else if ( strcmp(sect->segname(), "__TEXT") == 0 ) {
4769 kind = x86::kAbsolute32;
4770 if ( reloc->r_length() != 2 )
4771 throw "bad vanilla relocation length";
4772 }
4773 else {
4774 kind = x86::kPointer;
4775 if ( reloc->r_length() != 2 )
4776 throw "bad vanilla relocation length";
4777 }
4778 if ( reloc->r_extern() ) {
4779 const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
4780 if ( this->isWeakImportSymbol(targetSymbol) ) {
4781 if ( reloc->r_pcrel() )
4782 kind = x86::kPCRel32WeakImport;
4783 else
4784 kind = x86::kPointerWeakImport;
4785 }
4786 const char* targetName = &fStrings[targetSymbol->n_strx()];
4787 if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
4788 makeByNameReference(x86::kDtraceProbeSite, srcAddr, targetName, 0);
4789 addDtraceExtraInfos(srcAddr, &targetName[16]);
4790 }
4791 else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
4792 makeByNameReference(x86::kDtraceIsEnabledSite, srcAddr, targetName, 0);
4793 addDtraceExtraInfos(srcAddr, &targetName[20]);
4794 }
4795 else
4796 makeByNameReference(kind, srcAddr, targetName, pointerValue);
4797 }
4798 else {
4799 AtomAndOffset targetAO = findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum());
4800 const char* targetName = targetAO.atom->getName();
4801 if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
4802 makeByNameReference(x86::kDtraceProbeSite, srcAddr, targetName, 0);
4803 addDtraceExtraInfos(srcAddr, &targetName[16]);
4804 }
4805 else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
4806 makeByNameReference(x86::kDtraceIsEnabledSite, srcAddr, targetName, 0);
4807 addDtraceExtraInfos(srcAddr, &targetName[20]);
4808 }
4809 // if this is a reference to a stub, we need to see if the stub is for a weak imported symbol
4810 else if ( reloc->r_pcrel() && (targetAO.atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
4811 && ((AnonymousAtom<x86>*)targetAO.atom)->isWeakImportStub() )
4812 new Reference<x86>(x86::kPCRel32WeakImport, findAtomAndOffset(srcAddr), targetAO);
4813 else if ( reloc->r_symbolnum() != R_ABS )
4814 new Reference<x86>(kind, findAtomAndOffset(srcAddr), targetAO);
4815 else {
4816 // find absolute symbol that corresponds to pointerValue
4817 AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(pointerValue);
4818 if ( pos != fAddrToAbsoluteAtom.end() )
4819 makeByNameReference(kind, srcAddr, pos->second->getName(), 0);
4820 else
4821 throwf("R_ABS reloc but no absolute symbol at target address");
4822 }
4823 }
4824 }
4825 break;
4826 default:
4827 warning("unknown relocation type %d", reloc->r_type());
4828 }
4829 }
4830 else {
4831 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
4832 srcAddr = sect->addr() + sreloc->r_address();
4833 dstAddr = sreloc->r_value();
4834 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + sreloc->r_address());
4835 const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
4836 const macho_relocation_info<P>* nextReloc = &reloc[1];
4837 pint_t betterDstAddr;
4838 // file format allows pair to be scattered or not
4839 bool nextRelocIsPair = false;
4840 uint32_t nextRelocAddress = 0;
4841 uint32_t nextRelocValue = 0;
4842 if ( (nextReloc->r_address() & R_SCATTERED) == 0 ) {
4843 if ( nextReloc->r_type() == GENERIC_RELOC_PAIR ) {
4844 nextRelocIsPair = true;
4845 nextRelocAddress = nextReloc->r_address();
4846 result = true;
4847 }
4848 }
4849 else {
4850 if ( nextSReloc->r_type() == GENERIC_RELOC_PAIR ) {
4851 nextRelocIsPair = true;
4852 nextRelocAddress = nextSReloc->r_address();
4853 nextRelocValue = nextSReloc->r_value();
4854 }
4855 }
4856 switch (sreloc->r_type()) {
4857 case GENERIC_RELOC_VANILLA:
4858 betterDstAddr = LittleEndian::get32(*fixUpPtr);
4859 //fprintf(stderr, "pointer reloc: srcAddr=0x%08X, dstAddr=0x%08X, pointer=0x%08lX\n", srcAddr, dstAddr, betterDstAddr);
4860 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
4861 if ( sreloc->r_pcrel() ) {
4862 switch ( sreloc->r_length() ) {
4863 case 2:
4864 betterDstAddr += srcAddr + 4;
4865 makeReferenceWithToBase(x86::kPCRel32, srcAddr, betterDstAddr, dstAddr);
4866 break;
4867 case 1:
4868 betterDstAddr = LittleEndian::get16(*((uint16_t*)fixUpPtr)) + srcAddr + 2;
4869 makeReferenceWithToBase(x86::kPCRel16, srcAddr, betterDstAddr, dstAddr);
4870 break;
4871 case 0:
4872 betterDstAddr = *((uint8_t*)fixUpPtr) + srcAddr + 1;
4873 makeReferenceWithToBase(x86::kPCRel8, srcAddr, betterDstAddr, dstAddr);
4874 break;
4875 case 3:
4876 throwf("unsupported r_length=3 for scattered pc-rel vanilla reloc");
4877 break;
4878 }
4879 }
4880 else {
4881 if ( sreloc->r_length() != 2 )
4882 throwf("unsupported r_length=%d for scattered vanilla reloc", sreloc->r_length());
4883 if ( strcmp(sect->segname(), "__TEXT") == 0 )
4884 makeReferenceWithToBase(x86::kAbsolute32, srcAddr, betterDstAddr, dstAddr);
4885 else
4886 makeReferenceWithToBase(x86::kPointer, srcAddr, betterDstAddr, dstAddr);
4887 }
4888 break;
4889 case GENERIC_RELOC_SECTDIFF:
4890 case GENERIC_RELOC_LOCAL_SECTDIFF:
4891 {
4892 if ( !nextRelocIsPair ) {
4893 throw "GENERIC_RELOC_SECTDIFF missing following pair";
4894 }
4895 x86::ReferenceKinds kind = x86::kPointerDiff;
4896 uint32_t contentAddr = 0;
4897 switch ( sreloc->r_length() ) {
4898 case 0:
4899 case 3:
4900 throw "bad length for GENERIC_RELOC_SECTDIFF";
4901 case 1:
4902 kind = x86::kPointerDiff16;
4903 contentAddr = LittleEndian::get16(*((uint16_t*)fixUpPtr));
4904 break;
4905 case 2:
4906 kind = x86::kPointerDiff;
4907 contentAddr = LittleEndian::get32(*fixUpPtr);
4908 break;
4909 }
4910 AtomAndOffset srcao = findAtomAndOffset(srcAddr);
4911 AtomAndOffset fromao = findAtomAndOffset(nextRelocValue);
4912 AtomAndOffset toao = findAtomAndOffset(dstAddr);
4913 // check for addend encoded in the section content
4914 //fprintf(stderr, "addRef: dstAddr=0x%X, nextRelocValue=0x%X, contentAddr=0x%X\n",
4915 // dstAddr, nextRelocValue, contentAddr);
4916 if ( (dstAddr - nextRelocValue) != contentAddr ) {
4917 if ( toao.atom == srcao.atom )
4918 toao.offset += (contentAddr + nextRelocValue) - dstAddr;
4919 else if ( fromao.atom == srcao.atom )
4920 toao.offset += (contentAddr + nextRelocValue) - dstAddr;
4921 else
4922 fromao.offset += (dstAddr - contentAddr) - nextRelocValue;
4923 }
4924 //fprintf(stderr, "addRef: src=%s+0x%X, from=%s+0x%X, to=%s+0x%X\n",
4925 // srcao.atom->getDisplayName(), srcao.offset,
4926 // fromao.atom->getDisplayName(), fromao.offset,
4927 // toao.atom->getDisplayName(), toao.offset);
4928 new Reference<x86>(kind, srcao, fromao, toao);
4929 }
4930 break;
4931 case GENERIC_RELOC_PAIR:
4932 // do nothing, already used via a look ahead
4933 break;
4934 default:
4935 warning("unknown scattered relocation type %d", sreloc->r_type());
4936 }
4937 }
4938 return result;
4939 }
4940
4941 template <>
4942 bool Reader<x86_64>::addRelocReference(const macho_section<x86_64::P>* sect, const macho_relocation_info<x86_64::P>* reloc)
4943 {
4944 uint64_t srcAddr;
4945 uint64_t dstAddr = 0;
4946 uint64_t addend;
4947 uint32_t* fixUpPtr;
4948 x86_64::ReferenceKinds kind = x86_64::kNoFixUp;
4949 bool result = false;
4950 const macho_nlist<P>* targetSymbol = NULL;
4951 const char* targetName = NULL;
4952 srcAddr = sect->addr() + reloc->r_address();
4953 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + reloc->r_address());
4954 //fprintf(stderr, "addReloc type=%d, len=%d, address=0x%X\n", reloc->r_type(), reloc->r_length(), reloc->r_address());
4955 if ( reloc->r_extern() ) {
4956 targetSymbol = &fSymbols[reloc->r_symbolnum()];
4957 targetName = &fStrings[targetSymbol->n_strx()];
4958 }
4959 switch ( reloc->r_type() ) {
4960 case X86_64_RELOC_UNSIGNED:
4961 if ( reloc->r_pcrel() )
4962 throw "pcrel and X86_64_RELOC_UNSIGNED not supported";
4963 switch ( reloc->r_length() ) {
4964 case 0:
4965 case 1:
4966 throw "length < 2 and X86_64_RELOC_UNSIGNED not supported";
4967 case 2:
4968 kind = x86_64::kPointer32;
4969 break;
4970 case 3:
4971 if ( reloc->r_extern() && isWeakImportSymbol(targetSymbol) )
4972 kind = x86_64::kPointerWeakImport;
4973 else
4974 kind = x86_64::kPointer;
4975 break;
4976 }
4977 dstAddr = E::get64(*((uint64_t*)fixUpPtr));
4978 if ( reloc->r_extern() ) {
4979 makeReferenceToSymbol(kind, srcAddr, targetSymbol, dstAddr);
4980 }
4981 else {
4982 makeReference(kind, srcAddr, dstAddr);
4983 // verify that dstAddr is in the section being targeted
4984 int sectNum = reloc->r_symbolnum();
4985 const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
4986 const macho_section<P>* const targetSection = &sectionsStart[sectNum-1];
4987 if ( (dstAddr < targetSection->addr()) || (dstAddr > (targetSection->addr()+targetSection->size())) ) {
4988 throwf("local relocation for address 0x%08llX in section %s does not target section %s",
4989 srcAddr, sect->sectname(), targetSection->sectname());
4990 }
4991 }
4992 break;
4993 case X86_64_RELOC_SIGNED:
4994 case X86_64_RELOC_SIGNED_1:
4995 case X86_64_RELOC_SIGNED_2:
4996 case X86_64_RELOC_SIGNED_4:
4997 if ( ! reloc->r_pcrel() )
4998 throw "not pcrel and X86_64_RELOC_SIGNED* not supported";
4999 if ( reloc->r_length() != 2 )
5000 throw "length != 2 and X86_64_RELOC_SIGNED* not supported";
5001 addend = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
5002 if ( reloc->r_extern() ) {
5003 switch ( reloc->r_type() ) {
5004 case X86_64_RELOC_SIGNED:
5005 kind = x86_64::kPCRel32;
5006 // begin support for old .o files before X86_64_RELOC_SIGNED_1 was created
5007 if ( addend == (uint64_t)(-1) ) {
5008 addend = 0;
5009 kind = x86_64::kPCRel32_1;
5010 }
5011 else if ( addend == (uint64_t)(-2) ) {
5012 addend = 0;
5013 kind = x86_64::kPCRel32_2;
5014 }
5015 else if ( addend == (uint64_t)(-4) ) {
5016 addend = 0;
5017 kind = x86_64::kPCRel32_4;
5018 }
5019 break;
5020 // end support for old .o files before X86_64_RELOC_SIGNED_1 was created
5021 case X86_64_RELOC_SIGNED_1:
5022 kind = x86_64::kPCRel32_1;
5023 addend += 1;
5024 break;
5025 case X86_64_RELOC_SIGNED_2:
5026 kind = x86_64::kPCRel32_2;
5027 addend += 2;
5028 break;
5029 case X86_64_RELOC_SIGNED_4:
5030 kind = x86_64::kPCRel32_4;
5031 addend += 4;
5032 break;
5033 }
5034 makeReferenceToSymbol(kind, srcAddr, targetSymbol, addend);
5035 }
5036 else {
5037 uint64_t ripRelativeOffset = addend;
5038 switch ( reloc->r_type() ) {
5039 case X86_64_RELOC_SIGNED:
5040 dstAddr = srcAddr + 4 + ripRelativeOffset;
5041 kind = x86_64::kPCRel32;
5042 break;
5043 case X86_64_RELOC_SIGNED_1:
5044 dstAddr = srcAddr + 5 + ripRelativeOffset;
5045 kind = x86_64::kPCRel32_1;
5046 break;
5047 case X86_64_RELOC_SIGNED_2:
5048 dstAddr = srcAddr + 6 + ripRelativeOffset;
5049 kind = x86_64::kPCRel32_2;
5050 break;
5051 case X86_64_RELOC_SIGNED_4:
5052 dstAddr = srcAddr + 8 + ripRelativeOffset;
5053 kind = x86_64::kPCRel32_4;
5054 break;
5055 }
5056 makeReference(kind, srcAddr, dstAddr);
5057 // verify that dstAddr is in the section being targeted
5058 int sectNum = reloc->r_symbolnum();
5059 const macho_section<P>* const sectionsStart = (macho_section<P>*)((char*)fSegment + sizeof(macho_segment_command<P>));
5060 const macho_section<P>* const targetSection = &sectionsStart[sectNum-1];
5061 if ( (dstAddr < targetSection->addr()) || (dstAddr > (targetSection->addr()+targetSection->size())) ) {
5062 throwf("local relocation for address 0x%08llX in section %s does not target section %s",
5063 srcAddr, sect->sectname(), targetSection->sectname());
5064 }
5065 }
5066 break;
5067 case X86_64_RELOC_BRANCH:
5068 if ( ! reloc->r_pcrel() )
5069 throw "not pcrel and X86_64_RELOC_BRANCH not supported";
5070 if ( reloc->r_length() == 2 ) {
5071 dstAddr = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
5072 if ( reloc->r_extern() ) {
5073 if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
5074 makeByNameReference(x86_64::kDtraceProbeSite, srcAddr, targetName, 0);
5075 addDtraceExtraInfos(srcAddr, &targetName[16]);
5076 }
5077 else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
5078 makeByNameReference(x86_64::kDtraceIsEnabledSite, srcAddr, targetName, 0);
5079 addDtraceExtraInfos(srcAddr, &targetName[16]);
5080 }
5081 else if ( isWeakImportSymbol(targetSymbol) )
5082 makeReferenceToSymbol(x86_64::kBranchPCRel32WeakImport, srcAddr, targetSymbol, dstAddr);
5083 else
5084 makeReferenceToSymbol(x86_64::kBranchPCRel32, srcAddr, targetSymbol, dstAddr);
5085 }
5086 else {
5087 makeReference(x86_64::kBranchPCRel32, srcAddr, srcAddr+4+dstAddr);
5088 }
5089 }
5090 else if ( reloc->r_length() == 0 ) {
5091 dstAddr = *((int8_t*)fixUpPtr);
5092 if ( reloc->r_extern() ) {
5093 makeReferenceToSymbol(x86_64::kBranchPCRel8, srcAddr, targetSymbol, dstAddr);
5094 }
5095 else {
5096 makeReference(x86_64::kBranchPCRel8, srcAddr, srcAddr+1+dstAddr);
5097 }
5098 }
5099 else {
5100 throwf("length=%d and X86_64_RELOC_BRANCH not supported", reloc->r_length());;
5101 }
5102 break;
5103 case X86_64_RELOC_GOT:
5104 if ( ! reloc->r_extern() )
5105 throw "not extern and X86_64_RELOC_GOT not supported";
5106 if ( ! reloc->r_pcrel() )
5107 throw "not pcrel and X86_64_RELOC_GOT not supported";
5108 if ( reloc->r_length() != 2 )
5109 throw "length != 2 and X86_64_RELOC_GOT not supported";
5110 addend = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
5111 if ( isWeakImportSymbol(targetSymbol) )
5112 makeReferenceToSymbol(x86_64::kPCRel32GOTWeakImport, srcAddr, targetSymbol, addend);
5113 else
5114 makeReferenceToSymbol(x86_64::kPCRel32GOT, srcAddr, targetSymbol, addend);
5115 break;
5116 case X86_64_RELOC_GOT_LOAD:
5117 if ( ! reloc->r_extern() )
5118 throw "not extern and X86_64_RELOC_GOT_LOAD not supported";
5119 if ( ! reloc->r_pcrel() )
5120 throw "not pcrel and X86_64_RELOC_GOT_LOAD not supported";
5121 if ( reloc->r_length() != 2 )
5122 throw "length != 2 and X86_64_RELOC_GOT_LOAD not supported";
5123 addend = (int64_t)((int32_t)(E::get32(*fixUpPtr)));
5124 if ( isWeakImportSymbol(targetSymbol) )
5125 makeReferenceToSymbol(x86_64::kPCRel32GOTLoadWeakImport, srcAddr, targetSymbol, addend);
5126 else
5127 makeReferenceToSymbol(x86_64::kPCRel32GOTLoad, srcAddr, targetSymbol, addend);
5128 break;
5129 case X86_64_RELOC_SUBTRACTOR:
5130 {
5131 if ( reloc->r_pcrel() )
5132 throw "X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
5133 if ( reloc->r_length() < 2 )
5134 throw "X86_64_RELOC_SUBTRACTOR must have r_length of 2 or 3";
5135 if ( !reloc->r_extern() )
5136 throw "X86_64_RELOC_SUBTRACTOR must have r_extern=1";
5137 const macho_relocation_info<x86_64::P>* nextReloc = &reloc[1];
5138 if ( nextReloc->r_type() != X86_64_RELOC_UNSIGNED )
5139 throw "X86_64_RELOC_SUBTRACTOR must be followed by X86_64_RELOC_UNSIGNED";
5140 result = true;
5141 if ( nextReloc->r_pcrel() )
5142 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
5143 if ( nextReloc->r_length() != reloc->r_length() )
5144 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR must have same r_length";
5145 Reference<x86_64>* ref;
5146 bool negativeAddend;
5147 if ( reloc->r_length() == 2 ) {
5148 kind = x86_64::kPointerDiff32;
5149 dstAddr = E::get32(*fixUpPtr); // addend is in content
5150 negativeAddend = ((dstAddr & 0x80000000) != 0);
5151 }
5152 else {
5153 kind = x86_64::kPointerDiff;
5154 dstAddr = E::get64(*((uint64_t*)fixUpPtr)); // addend is in content
5155 negativeAddend = ((dstAddr & 0x8000000000000000ULL) != 0);
5156 }
5157 AtomAndOffset inAtomAndOffset = this->findAtomAndOffset(srcAddr);
5158 ObjectFile::Atom* inAtom = inAtomAndOffset.atom;
5159 // create reference with "to" target
5160 if ( nextReloc->r_extern() ) {
5161 const macho_nlist<P>* targetSymbol = &fSymbols[nextReloc->r_symbolnum()];
5162 const char* targetName = &fStrings[targetSymbol->n_strx()];
5163 ref = makeReferenceToSymbol(kind, srcAddr, targetSymbol, 0);
5164 // if "to" is in this atom, change by-name to a direct reference
5165 if ( strcmp(targetName, inAtom->getName()) == 0 )
5166 ref->setTarget(*inAtom, 0);
5167 }
5168 else {
5169 ref = makeReference(kind, srcAddr, dstAddr);
5170 }
5171 // add in "from" target
5172 if ( reloc->r_extern() ) {
5173 const macho_nlist<P>* targetFromSymbol = &fSymbols[reloc->r_symbolnum()];
5174 const char* fromTargetName = &fStrings[targetFromSymbol->n_strx()];
5175 if ( (targetFromSymbol->n_type() & N_EXT) == 0 ) {
5176 // from target is translation unit scoped, so use a direct reference
5177 ref->setFromTarget(*(findAtomAndOffset(targetSymbol->n_value()).atom));
5178 }
5179 else if ( strcmp(fromTargetName, inAtom->getName()) == 0 ) {
5180 // if "from" is in this atom, change by-name to a direct reference
5181 ref->setFromTarget(*inAtom);
5182 }
5183 else {
5184 // some non-static other atom
5185 ref->setFromTargetName(fromTargetName);
5186 }
5187 }
5188 else {
5189 throw "X86_64_RELOC_SUBTRACTOR not supported with r_extern=0";
5190 }
5191 // addend goes in from side iff negative
5192 if ( negativeAddend )
5193 ref->setFromTargetOffset(-dstAddr);
5194 else
5195 ref->setToTargetOffset(dstAddr);
5196 break;
5197 }
5198 default:
5199 warning("unknown relocation type %d", reloc->r_type());
5200 }
5201 return result;
5202 }
5203
5204
5205 /// Reader<arm>::addRelocReference -
5206 /// turns arm relocation entries into references. Returns true if the next
5207 /// relocation should be skipped, false otherwise.
5208 template <>
5209 bool Reader<arm>::addRelocReference(const macho_section<arm::P>* sect,
5210 const macho_relocation_info<arm::P>* reloc)
5211 {
5212 uint32_t * fixUpPtr;
5213 int32_t displacement;
5214 uint32_t instruction = 0;
5215 bool result = false;
5216 uint32_t srcAddr;
5217 uint32_t dstAddr;
5218 uint32_t pointerValue;
5219 arm::ReferenceKinds kind = arm::kNoFixUp;
5220
5221 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
5222 // non-scattered relocation
5223 const char* targetName = NULL;
5224 bool weakImport = false;
5225
5226 srcAddr = sect->addr() + reloc->r_address();
5227 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + reloc->r_address());
5228 if ( reloc->r_type() != ARM_RELOC_PAIR )
5229 instruction = LittleEndian::get32(*fixUpPtr);
5230
5231 if ( reloc->r_extern() ) {
5232 const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
5233 targetName = &fStrings[targetSymbol->n_strx()];
5234 weakImport = this->isWeakImportSymbol(targetSymbol);
5235 }
5236
5237 switch ( reloc->r_type() ) {
5238 case ARM_RELOC_BR24:
5239 // Sign-extend displacement
5240 displacement = (instruction & 0x00FFFFFF) << 2;
5241 if ( (displacement & 0x02000000) != 0 )
5242 displacement |= 0xFC000000;
5243 // The pc added will be +8 from the pc
5244 displacement += 8;
5245 // If this is BLX add H << 1
5246 if ((instruction & 0xFE000000) == 0xFA000000)
5247 displacement += ((instruction & 0x01000000) >> 23);
5248
5249 if ( reloc->r_extern() ) {
5250 uint32_t offsetInTarget = srcAddr + displacement;
5251 if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
5252 makeByNameReference(arm::kDtraceProbeSite, srcAddr, targetName, 0);
5253 addDtraceExtraInfos(srcAddr, &targetName[16]);
5254 }
5255 else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
5256 makeByNameReference(arm::kDtraceIsEnabledSite, srcAddr, targetName, 0);
5257 addDtraceExtraInfos(srcAddr, &targetName[20]);
5258 }
5259 else if ( weakImport )
5260 makeByNameReference(arm::kBranch24WeakImport, srcAddr, targetName, offsetInTarget);
5261 else
5262 makeByNameReference(arm::kBranch24, srcAddr, targetName, offsetInTarget);
5263 }
5264 else {
5265 dstAddr = srcAddr + displacement;
5266 ObjectFile::Atom* atom = findAtomAndOffset(dstAddr).atom;
5267 // check for dtrace probes and weak_import stubs
5268 const char* targetName = atom->getName();
5269 if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
5270 makeByNameReference(arm::kDtraceProbeSite, srcAddr, targetName, 0);
5271 addDtraceExtraInfos(srcAddr, &targetName[16]);
5272 }
5273 else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
5274 makeByNameReference(arm::kDtraceIsEnabledSite, srcAddr, targetName, 0);
5275 addDtraceExtraInfos(srcAddr, &targetName[20]);
5276 }
5277 else if ( (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
5278 && ((AnonymousAtom<x86>*)atom)->isWeakImportStub() )
5279 makeReference(arm::kBranch24WeakImport, srcAddr, dstAddr);
5280 else if ( reloc->r_symbolnum() != R_ABS )
5281 makeReference(arm::kBranch24, srcAddr, dstAddr);
5282 else {
5283 // find absolute symbol that corresponds to pointerValue
5284 AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
5285 if ( pos != fAddrToAbsoluteAtom.end() )
5286 makeByNameReference(arm::kBranch24, srcAddr, pos->second->getName(), 0);
5287 else
5288 throwf("R_ABS reloc but no absolute symbol at target address");
5289 }
5290 }
5291 break;
5292
5293 case ARM_THUMB_RELOC_BR22:
5294 // thumb2 added two more bits to displacement, complicating the displacement decoding
5295 {
5296 uint32_t s = (instruction >> 10) & 0x1;
5297 uint32_t j1 = (instruction >> 29) & 0x1;
5298 uint32_t j2 = (instruction >> 27) & 0x1;
5299 uint32_t imm10 = instruction & 0x3FF;
5300 uint32_t imm11 = (instruction >> 16) & 0x7FF;
5301 uint32_t i1 = (j1 == s);
5302 uint32_t i2 = (j2 == s);
5303 uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
5304 int32_t sdis = dis;
5305 if ( s )
5306 sdis |= 0xFE000000;
5307 displacement = sdis;
5308 }
5309 // The pc added will be +4 from the pc
5310 displacement += 4;
5311 // If the instruction was blx, force the low 2 bits to be clear
5312 dstAddr = srcAddr + displacement;
5313 if ((instruction & 0xF8000000) == 0xE8000000)
5314 dstAddr &= 0xFFFFFFFC;
5315
5316 if ( reloc->r_extern() ) {
5317 uint32_t offsetInTarget = dstAddr;
5318 if ( strncmp(targetName, "___dtrace_probe$", 16) == 0 ) {
5319 makeByNameReference(arm::kDtraceProbeSite, srcAddr, targetName, 0);
5320 addDtraceExtraInfos(srcAddr, &targetName[16]);
5321 }
5322 else if ( strncmp(targetName, "___dtrace_isenabled$", 20) == 0 ) {
5323 makeByNameReference(arm::kDtraceIsEnabledSite, srcAddr, targetName, 0);
5324 addDtraceExtraInfos(srcAddr, &targetName[20]);
5325 }
5326 else if ( weakImport )
5327 makeByNameReference(arm::kThumbBranch22WeakImport, srcAddr, targetName, offsetInTarget);
5328 else
5329 makeByNameReference(arm::kThumbBranch22, srcAddr, targetName, offsetInTarget);
5330 }
5331 else {
5332 ObjectFile::Atom* atom = findAtomAndOffset(dstAddr).atom;
5333 // check for dtrace probes and weak_import stubs
5334 const char* targetName = atom->getName();
5335 if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_probe$", 16) == 0) ) {
5336 makeByNameReference(arm::kDtraceProbeSite, srcAddr, targetName, 0);
5337 addDtraceExtraInfos(srcAddr, &targetName[16]);
5338 }
5339 else if ( (targetName != NULL) && (strncmp(targetName, "___dtrace_isenabled$", 20) == 0) ) {
5340 makeByNameReference(arm::kDtraceIsEnabledSite, srcAddr, targetName, 0);
5341 addDtraceExtraInfos(srcAddr, &targetName[20]);
5342 }
5343 else if ( (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn)
5344 && ((AnonymousAtom<x86>*)atom)->isWeakImportStub() )
5345 makeReference(arm::kThumbBranch22WeakImport, srcAddr, dstAddr);
5346 else if ( reloc->r_symbolnum() != R_ABS )
5347 makeReference(arm::kThumbBranch22, srcAddr, dstAddr);
5348 else {
5349 // find absolute symbol that corresponds to pointerValue
5350 AddrToAtomMap::iterator pos = fAddrToAbsoluteAtom.find(dstAddr);
5351 if ( pos != fAddrToAbsoluteAtom.end() )
5352 makeByNameReference(arm::kThumbBranch22, srcAddr, pos->second->getName(), 0);
5353 else
5354 throwf("R_ABS reloc but no absolute symbol at target address");
5355 }
5356 }
5357 break;
5358
5359 case ARM_RELOC_VANILLA:
5360 if ( reloc->r_length() != 2 )
5361 throw "bad length for ARM_RELOC_VANILLA";
5362
5363 pointerValue = instruction;
5364 kind = arm::kPointer;
5365 if ( strcmp(sect->segname(), "__TEXT") == 0 )
5366 kind = arm::kReadOnlyPointer;
5367 if ( weakImport )
5368 kind = arm::kPointerWeakImport;
5369 if ( reloc->r_extern() ) {
5370 const macho_nlist<P>* targetSymbol = &fSymbols[reloc->r_symbolnum()];
5371 if ( (targetSymbol->n_desc() & N_ARM_THUMB_DEF) && (pointerValue == 1) )
5372 pointerValue = 0;
5373 makeByNameReference(kind, srcAddr, targetName, pointerValue);
5374 }
5375 else {
5376 AtomAndOffset at = findAtomAndOffset(srcAddr);
5377 AtomAndOffset to = findAtomAndOffsetForSection(pointerValue, reloc->r_symbolnum());
5378 if ( to.atom->isThumb() )
5379 to.offset &= -2;
5380 new Reference<arm>(kind, at, to);
5381 }
5382 break;
5383
5384 case ARM_THUMB_32BIT_BRANCH:
5385 // ignore old unnecessary relocs
5386 break;
5387
5388 default:
5389 warning("unexpected relocation type %u", reloc->r_type());
5390 break;
5391 }
5392 }
5393 else {
5394 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
5395 const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
5396 int32_t addend;
5397 srcAddr = sect->addr() + sreloc->r_address();
5398 dstAddr = sreloc->r_value();
5399 uint32_t betterDstAddr;
5400 fixUpPtr = (uint32_t*)((char*)(fHeader) + sect->offset() + sreloc->r_address());
5401 instruction = LittleEndian::get32(*fixUpPtr);
5402
5403 // A ARM_RELOC_PAIR only follows ARM_RELOC_{SECTDIFF,LOCAL_SECTDIFF}
5404 // relocation types, and it is an error to see one otherwise.
5405 bool nextRelocIsPair = false;
5406 uint32_t nextRelocAddress = 0;
5407 uint32_t nextRelocValue = 0;
5408 if ( nextSReloc->r_type() == ARM_RELOC_PAIR ) {
5409 nextRelocIsPair = true;
5410 nextRelocAddress = nextSReloc->r_address();
5411 nextRelocValue = nextSReloc->r_value();
5412 result = true;
5413 }
5414
5415 switch (sreloc->r_type()) {
5416 case ARM_RELOC_VANILLA:
5417 if ( sreloc->r_length() != 2 )
5418 throw "bad length for ARM_RELOC_VANILLA";
5419
5420 //fprintf(stderr, "scattered pointer reloc: srcAddr=0x%08X, dstAddr=0x%08X, pointer=0x%08X\n", srcAddr, dstAddr, betterDstAddr);
5421 betterDstAddr = LittleEndian::get32(*fixUpPtr);
5422 kind = arm::kPointer;
5423 if ( strcmp(sect->segname(), "__TEXT") == 0 )
5424 kind = arm::kReadOnlyPointer;
5425 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
5426 makeReferenceWithToBase(kind, srcAddr, betterDstAddr, dstAddr);
5427 break;
5428
5429 case ARM_RELOC_BR24:
5430 // Sign-extend displacement
5431 displacement = (instruction & 0x00FFFFFF) << 2;
5432 if ( (displacement & 0x02000000) != 0 )
5433 displacement |= 0xFC000000;
5434 // The pc added will be +8 from the pc
5435 displacement += 8;
5436 // If this is BLX add H << 1
5437 if ((instruction & 0xFE000000) == 0xFA000000)
5438 displacement += ((instruction & 0x01000000) >> 23);
5439 betterDstAddr = srcAddr+displacement;
5440 makeReferenceWithToBase(arm::kBranch24, srcAddr, betterDstAddr, dstAddr);
5441 break;
5442
5443 case ARM_THUMB_RELOC_BR22:
5444 // thumb2 added two more bits to displacement, complicating the displacement decoding
5445 {
5446 uint32_t s = (instruction >> 10) & 0x1;
5447 uint32_t j1 = (instruction >> 29) & 0x1;
5448 uint32_t j2 = (instruction >> 27) & 0x1;
5449 uint32_t imm10 = instruction & 0x3FF;
5450 uint32_t imm11 = (instruction >> 16) & 0x7FF;
5451 uint32_t i1 = (j1 == s);
5452 uint32_t i2 = (j2 == s);
5453 uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
5454 int32_t sdis = dis;
5455 if ( s )
5456 sdis |= 0xFE000000;
5457 displacement = sdis;
5458 }
5459 // The pc added will be +4 from the pc
5460 displacement += 4;
5461 betterDstAddr = srcAddr+displacement;
5462 // If the instruction was blx, force the low 2 bits to be clear
5463 if ((instruction & 0xF8000000) == 0xE8000000)
5464 betterDstAddr &= 0xFFFFFFFC;
5465 makeReferenceWithToBase(arm::kThumbBranch22, srcAddr, betterDstAddr, dstAddr);
5466 break;
5467
5468 case ARM_RELOC_SECTDIFF:
5469 case ARM_RELOC_LOCAL_SECTDIFF:
5470 if ( !nextRelocIsPair ) {
5471 throw "ARM_RELOC_SECTDIFF missing following pair";
5472 }
5473 if ( sreloc->r_length() != 2 )
5474 throw "bad length for ARM_RELOC_SECTDIFF";
5475 {
5476 AtomAndOffset srcao = findAtomAndOffset(srcAddr);
5477 AtomAndOffset fromao = findAtomAndOffset(nextRelocValue);
5478 AtomAndOffset toao = findAtomAndOffset(dstAddr);
5479 // check for addend encoded in the section content
5480 pointerValue = LittleEndian::get32(*fixUpPtr);
5481 addend = pointerValue - (dstAddr - nextRelocValue);
5482 if ( toao.atom->isThumb() && (addend & 1) )
5483 addend &= -2; // remove thumb bit
5484 if ( (dstAddr - nextRelocValue) != pointerValue ) {
5485 if ( fromao.atom == srcao.atom ) {
5486 if ( ((const macho_section<P>*)(((BaseAtom*)(srcao.atom))->getSectionRecord()))->flags() & S_ATTR_PURE_INSTRUCTIONS ) {
5487 int pcBaseOffset = srcao.atom->isThumb() ? 4 : 8;
5488 if ( addend == -pcBaseOffset ) {
5489 fromao.offset -= addend;
5490 }
5491 else {
5492 toao.offset += addend;
5493 }
5494 }
5495 else {
5496 toao.offset += addend;
5497 }
5498 }
5499 else if ( toao.atom == srcao.atom )
5500 toao.offset += addend;
5501 else
5502 fromao.offset -= addend;
5503 }
5504 new Reference<arm>(arm::kPointerDiff, srcao, fromao, toao);
5505 }
5506 break;
5507
5508 default:
5509 warning("unexpected srelocation type %u", sreloc->r_type());
5510 break;
5511 }
5512 }
5513 return result;
5514 }
5515
5516 template <typename A>
5517 void Reader<A>::addReferencesForSection(const macho_section<P>* sect)
5518 {
5519 // ignore dwarf sections. If ld ever supports processing dwarf, this logic will need to change
5520 if ( (sect->flags() & S_ATTR_DEBUG) == 0 ) {
5521 switch ( sect->flags() & SECTION_TYPE ) {
5522 case S_SYMBOL_STUBS:
5523 case S_LAZY_SYMBOL_POINTERS:
5524 // we ignore compiler generated stubs, so ignore those relocs too
5525 break;
5526 default:
5527 // ignore all relocations in __eh_frame section
5528 if ( sect == fehFrameSection )
5529 return;
5530 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)((char*)(fHeader) + sect->reloff());
5531 const uint32_t relocCount = sect->nreloc();
5532 //fprintf(stderr, "relocCount = %d in section %s\n", relocCount, sect->sectname());
5533 for (uint32_t r = 0; r < relocCount; ++r) {
5534 try {
5535 if ( addRelocReference(sect, &relocs[r]) )
5536 ++r; // skip next
5537 }
5538 catch (const char* msg) {
5539 throwf("in section %s,%s reloc %u: %s", sect->segname(), sect->sectname(), r, msg);
5540 }
5541 }
5542 }
5543 }
5544 }
5545
5546
5547 template <>
5548 const char* Reference<x86>::getDescription() const
5549 {
5550 static char temp[2048];
5551 switch( fKind ) {
5552 case x86::kNoFixUp:
5553 sprintf(temp, "reference to ");
5554 break;
5555 case x86::kFollowOn:
5556 sprintf(temp, "followed by ");
5557 break;
5558 case x86::kGroupSubordinate:
5559 sprintf(temp, "group subordinate ");
5560 break;
5561 case x86::kPointerWeakImport:
5562 sprintf(temp, "offset 0x%04X, weak import pointer to ", fFixUpOffsetInSrc);
5563 break;
5564 case x86::kPointer:
5565 sprintf(temp, "offset 0x%04X, pointer to ", fFixUpOffsetInSrc);
5566 break;
5567 case x86::kPointerDiff:
5568 {
5569 // by-name references have quoted names
5570 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5571 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5572 sprintf(temp, "offset 0x%04X, 32-bit pointer difference: (&%s%s%s + 0x%08X) - (&%s%s%s + 0x%08X)",
5573 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5574 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5575 return temp;
5576 }
5577 break;
5578 case x86::kPointerDiff16:
5579 {
5580 // by-name references have quoted names
5581 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5582 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5583 sprintf(temp, "offset 0x%04X, 16-bit pointer difference: (&%s%s%s + 0x%08X) - (&%s%s%s + 0x%08X)",
5584 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5585 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5586 return temp;
5587 }
5588 break;
5589 case x86::kPCRel32WeakImport:
5590 sprintf(temp, "offset 0x%04X, rel32 reference to weak imported ", fFixUpOffsetInSrc);
5591 break;
5592 case x86::kPCRel32:
5593 sprintf(temp, "offset 0x%04X, rel32 reference to ", fFixUpOffsetInSrc);
5594 break;
5595 case x86::kPCRel16:
5596 sprintf(temp, "offset 0x%04X, rel16 reference to ", fFixUpOffsetInSrc);
5597 break;
5598 case x86::kPCRel8:
5599 sprintf(temp, "offset 0x%04X, rel8 reference to ", fFixUpOffsetInSrc);
5600 break;
5601 case x86::kAbsolute32:
5602 sprintf(temp, "offset 0x%04X, absolute32 reference to ", fFixUpOffsetInSrc);
5603 break;
5604 case x86::kImageOffset32:
5605 sprintf(temp, "offset 0x%04X, 32-bit offset of ", fFixUpOffsetInSrc);
5606 break;
5607 case x86::kPointerDiff24:
5608 sprintf(temp, "offset 0x%04X, 24-bit pointer difference: (&%s + 0x%08X) - (&%s + 0x%08X)",
5609 fFixUpOffsetInSrc, this->getTargetDisplayName(), fToTarget.offset,
5610 this->getFromTargetDisplayName(), fFromTarget.offset );
5611 return temp;
5612 break;
5613 case x86::kSectionOffset24:
5614 sprintf(temp, "offset 0x%04X, 24-bit section offset of ", fFixUpOffsetInSrc);
5615 break;
5616 case x86::kDtraceProbe:
5617 sprintf(temp, "offset 0x%04X, dtrace static probe ", fFixUpOffsetInSrc);
5618 break;
5619 case x86::kDtraceProbeSite:
5620 sprintf(temp, "offset 0x%04X, dtrace static probe site", fFixUpOffsetInSrc);
5621 break;
5622 case x86::kDtraceIsEnabledSite:
5623 sprintf(temp, "offset 0x%04X, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
5624 break;
5625 case x86::kDtraceTypeReference:
5626 sprintf(temp, "offset 0x%04X, dtrace type/stability reference", fFixUpOffsetInSrc);
5627 break;
5628 }
5629 // always quote by-name references
5630 if ( fToTargetName != NULL ) {
5631 strcat(temp, "\"");
5632 strcat(temp, fToTargetName);
5633 strcat(temp, "\"");
5634 }
5635 else if ( fToTarget.atom != NULL ) {
5636 strcat(temp, fToTarget.atom->getDisplayName());
5637 }
5638 else {
5639 strcat(temp, "NULL target");
5640 }
5641 if ( fToTarget.offset != 0 )
5642 sprintf(&temp[strlen(temp)], " plus 0x%08X", fToTarget.offset);
5643
5644 return temp;
5645 }
5646
5647
5648 template <>
5649 const char* Reference<ppc>::getDescription() const
5650 {
5651 static char temp[2048];
5652 switch( fKind ) {
5653 case ppc::kNoFixUp:
5654 sprintf(temp, "reference to ");
5655 break;
5656 case ppc::kFollowOn:
5657 sprintf(temp, "followed by ");
5658 break;
5659 case ppc::kGroupSubordinate:
5660 sprintf(temp, "group subordinate ");
5661 break;
5662 case ppc::kPointerWeakImport:
5663 sprintf(temp, "offset 0x%04X, weak import pointer to ", fFixUpOffsetInSrc);
5664 break;
5665 case ppc::kPointer:
5666 sprintf(temp, "offset 0x%04X, pointer to ", fFixUpOffsetInSrc);
5667 break;
5668 case ppc::kPointerDiff16:
5669 {
5670 // by-name references have quoted names
5671 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5672 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5673 sprintf(temp, "offset 0x%04X, 16-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)",
5674 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5675 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5676 return temp;
5677 }
5678 case ppc::kPointerDiff32:
5679 {
5680 // by-name references have quoted names
5681 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5682 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5683 sprintf(temp, "offset 0x%04X, 32-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)",
5684 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5685 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5686 return temp;
5687 }
5688 case ppc::kPointerDiff64:
5689 throw "unsupported refrence kind";
5690 break;
5691 case ppc::kBranch24WeakImport:
5692 sprintf(temp, "offset 0x%04X, pc-rel branch fixup to weak imported ", fFixUpOffsetInSrc);
5693 break;
5694 case ppc::kBranch24:
5695 case ppc::kBranch14:
5696 sprintf(temp, "offset 0x%04X, pc-rel branch fixup to ", fFixUpOffsetInSrc);
5697 break;
5698 case ppc::kPICBaseLow16:
5699 sprintf(temp, "offset 0x%04X, low 16 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
5700 break;
5701 case ppc::kPICBaseLow14:
5702 sprintf(temp, "offset 0x%04X, low 14 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
5703 break;
5704 case ppc::kPICBaseHigh16:
5705 sprintf(temp, "offset 0x%04X, high 16 fixup from pic-base of %s plus 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.atom->getDisplayName(), fFromTarget.offset);
5706 break;
5707 case ppc::kAbsLow16:
5708 sprintf(temp, "offset 0x%04X, low 16 fixup to absolute address of ", fFixUpOffsetInSrc);
5709 break;
5710 case ppc::kAbsLow14:
5711 sprintf(temp, "offset 0x%04X, low 14 fixup to absolute address of ", fFixUpOffsetInSrc);
5712 break;
5713 case ppc::kAbsHigh16:
5714 sprintf(temp, "offset 0x%04X, high 16 fixup or to absolute address of ", fFixUpOffsetInSrc);
5715 break;
5716 case ppc::kAbsHigh16AddLow:
5717 sprintf(temp, "offset 0x%04X, high 16 fixup add to absolute address of ", fFixUpOffsetInSrc);
5718 break;
5719 case ppc::kDtraceProbe:
5720 sprintf(temp, "offset 0x%04X, dtrace static probe ", fFixUpOffsetInSrc);
5721 break;
5722 case ppc::kDtraceProbeSite:
5723 sprintf(temp, "offset 0x%04X, dtrace static probe site", fFixUpOffsetInSrc);
5724 break;
5725 case ppc::kDtraceIsEnabledSite:
5726 sprintf(temp, "offset 0x%04X, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
5727 break;
5728 case ppc::kDtraceTypeReference:
5729 sprintf(temp, "offset 0x%04X, dtrace type/stability reference", fFixUpOffsetInSrc);
5730 break;
5731 }
5732 // always quote by-name references
5733 if ( fToTargetName != NULL ) {
5734 strcat(temp, "\"");
5735 strcat(temp, fToTargetName);
5736 strcat(temp, "\"");
5737 }
5738 else if ( fToTarget.atom != NULL ) {
5739 strcat(temp, fToTarget.atom->getDisplayName());
5740 }
5741 else {
5742 strcat(temp, "NULL target");
5743 }
5744 if ( fToTarget.offset != 0 )
5745 sprintf(&temp[strlen(temp)], " plus 0x%08X", fToTarget.offset);
5746
5747 return temp;
5748 }
5749
5750 template <>
5751 const char* Reference<ppc64>::getDescription() const
5752 {
5753 static char temp[2048];
5754 switch( fKind ) {
5755 case ppc64::kNoFixUp:
5756 sprintf(temp, "reference to ");
5757 break;
5758 case ppc64::kFollowOn:
5759 sprintf(temp, "followed by ");
5760 break;
5761 case ppc64::kGroupSubordinate:
5762 sprintf(temp, "group subordinate ");
5763 break;
5764 case ppc64::kPointerWeakImport:
5765 sprintf(temp, "offset 0x%04llX, weak import pointer to ", fFixUpOffsetInSrc);
5766 break;
5767 case ppc64::kPointer:
5768 sprintf(temp, "offset 0x%04llX, pointer to ", fFixUpOffsetInSrc);
5769 break;
5770 case ppc64::kPointerDiff64:
5771 {
5772 // by-name references have quoted names
5773 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5774 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5775 sprintf(temp, "offset 0x%04llX, 64-bit pointer difference: (&%s%s%s + %u) - (&%s%s%s + %u)",
5776 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5777 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5778 return temp;
5779 }
5780 case ppc64::kPointerDiff32:
5781 {
5782 // by-name references have quoted names
5783 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5784 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5785 sprintf(temp, "offset 0x%04llX, 32-bit pointer difference: (&%s%s%s + %u) - (&%s%s%s + %u)",
5786 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5787 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5788 return temp;
5789 }
5790 case ppc64::kPointerDiff16:
5791 {
5792 // by-name references have quoted names
5793 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5794 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5795 sprintf(temp, "offset 0x%04llX, 16-bit pointer difference: (&%s%s%s + %u) - (&%s%s%s + %u)",
5796 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5797 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5798 return temp;
5799 }
5800 case ppc64::kBranch24WeakImport:
5801 sprintf(temp, "offset 0x%04llX, pc-rel branch fixup to weak imported ", fFixUpOffsetInSrc);
5802 break;
5803 case ppc64::kBranch24:
5804 case ppc64::kBranch14:
5805 sprintf(temp, "offset 0x%04llX, pc-rel branch fixup to ", fFixUpOffsetInSrc);
5806 break;
5807 case ppc64::kPICBaseLow16:
5808 sprintf(temp, "offset 0x%04llX, low 16 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
5809 break;
5810 case ppc64::kPICBaseLow14:
5811 sprintf(temp, "offset 0x%04llX, low 14 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
5812 break;
5813 case ppc64::kPICBaseHigh16:
5814 sprintf(temp, "offset 0x%04llX, high 16 fixup from pic-base offset 0x%04X to ", fFixUpOffsetInSrc, fFromTarget.offset);
5815 break;
5816 case ppc64::kAbsLow16:
5817 sprintf(temp, "offset 0x%04llX, low 16 fixup to absolute address of ", fFixUpOffsetInSrc);
5818 break;
5819 case ppc64::kAbsLow14:
5820 sprintf(temp, "offset 0x%04llX, low 14 fixup to absolute address of ", fFixUpOffsetInSrc);
5821 break;
5822 case ppc64::kAbsHigh16:
5823 sprintf(temp, "offset 0x%04llX, high 16 fixup or to absolute address of ", fFixUpOffsetInSrc);
5824 break;
5825 case ppc64::kAbsHigh16AddLow:
5826 sprintf(temp, "offset 0x%04llX, high 16 fixup add to absolute address of ", fFixUpOffsetInSrc);
5827 break;
5828 case ppc64::kDtraceProbe:
5829 sprintf(temp, "offset 0x%04llX, dtrace static probe ", fFixUpOffsetInSrc);
5830 break;
5831 case ppc64::kDtraceProbeSite:
5832 sprintf(temp, "offset 0x%04llX, dtrace static probe site", fFixUpOffsetInSrc);
5833 break;
5834 case ppc64::kDtraceIsEnabledSite:
5835 sprintf(temp, "offset 0x%04llX, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
5836 break;
5837 case ppc64::kDtraceTypeReference:
5838 sprintf(temp, "offset 0x%04llX, dtrace type/stability reference", fFixUpOffsetInSrc);
5839 break;
5840 }
5841 // always quote by-name references
5842 if ( fToTargetName != NULL ) {
5843 strcat(temp, "\"");
5844 strcat(temp, fToTargetName);
5845 strcat(temp, "\"");
5846 }
5847 else if ( fToTarget.atom != NULL ) {
5848 strcat(temp, fToTarget.atom->getDisplayName());
5849 }
5850 else {
5851 strcat(temp, "NULL target");
5852 }
5853 if ( fToTarget.offset != 0 )
5854 sprintf(&temp[strlen(temp)], " plus 0x%llX", this->getTargetOffset());
5855
5856 return temp;
5857 }
5858
5859
5860 template <>
5861 const char* Reference<x86_64>::getDescription() const
5862 {
5863 static char temp[2048];
5864 switch( fKind ) {
5865 case x86_64::kNoFixUp:
5866 sprintf(temp, "reference to ");
5867 break;
5868 case x86_64::kFollowOn:
5869 sprintf(temp, "followed by ");
5870 break;
5871 case x86_64::kGroupSubordinate:
5872 sprintf(temp, "group subordinate ");
5873 break;
5874 case x86_64::kPointerWeakImport:
5875 sprintf(temp, "offset 0x%04llX, weak import pointer to ", fFixUpOffsetInSrc);
5876 break;
5877 case x86_64::kPointer:
5878 sprintf(temp, "offset 0x%04llX, pointer to ", fFixUpOffsetInSrc);
5879 break;
5880 case x86_64::kPointer32:
5881 sprintf(temp, "offset 0x%04llX, 32-bit pointer to ", fFixUpOffsetInSrc);
5882 break;
5883 case x86_64::kPointerDiff32:
5884 case x86_64::kPointerDiff:
5885 {
5886 // by-name references have quoted names
5887 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5888 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
5889 const char* size = (fKind == x86_64::kPointerDiff32) ? "32-bit" : "64-bit";
5890 sprintf(temp, "offset 0x%04llX, %s pointer difference: (&%s%s%s + 0x%08X) - (&%s%s%s + 0x%08X)",
5891 fFixUpOffsetInSrc, size, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
5892 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
5893 return temp;
5894 }
5895 break;
5896 case x86_64::kPCRel32:
5897 sprintf(temp, "offset 0x%04llX, rel32 reference to ", fFixUpOffsetInSrc);
5898 break;
5899 case x86_64::kPCRel32_1:
5900 sprintf(temp, "offset 0x%04llX, rel32-1 reference to ", fFixUpOffsetInSrc);
5901 break;
5902 case x86_64::kPCRel32_2:
5903 sprintf(temp, "offset 0x%04llX, rel32-2 reference to ", fFixUpOffsetInSrc);
5904 break;
5905 case x86_64::kPCRel32_4:
5906 sprintf(temp, "offset 0x%04llX, rel32-4 reference to ", fFixUpOffsetInSrc);
5907 break;
5908 case x86_64::kBranchPCRel32:
5909 sprintf(temp, "offset 0x%04llX, branch rel32 reference to ", fFixUpOffsetInSrc);
5910 break;
5911 case x86_64::kBranchPCRel32WeakImport:
5912 sprintf(temp, "offset 0x%04llX, branch rel32 reference to weak imported ", fFixUpOffsetInSrc);
5913 break;
5914 case x86_64::kPCRel32GOT:
5915 sprintf(temp, "offset 0x%04llX, rel32 reference to GOT entry for ", fFixUpOffsetInSrc);
5916 break;
5917 case x86_64::kPCRel32GOTWeakImport:
5918 sprintf(temp, "offset 0x%04llX, rel32 reference to GOT entry for weak imported ", fFixUpOffsetInSrc);
5919 break;
5920 case x86_64::kPCRel32GOTLoad:
5921 sprintf(temp, "offset 0x%04llX, rel32 reference to GOT entry for ", fFixUpOffsetInSrc);
5922 break;
5923 case x86_64::kPCRel32GOTLoadWeakImport:
5924 sprintf(temp, "offset 0x%04llX, rel32 reference to GOT entry for weak imported ", fFixUpOffsetInSrc);
5925 break;
5926 case x86_64::kGOTNoFixUp:
5927 sprintf(temp, "reference to GOT entry for ");
5928 break;
5929 case x86_64::kBranchPCRel8:
5930 sprintf(temp, "offset 0x%04llX, branch rel8 reference to ", fFixUpOffsetInSrc);
5931 break;
5932 case x86_64::kPointerDiff24:
5933 sprintf(temp, "offset 0x%04llX, 24-bit pointer difference: (&%s + 0x%08X) - (&%s + 0x%08X)",
5934 fFixUpOffsetInSrc, this->getTargetDisplayName(), fToTarget.offset,
5935 this->getFromTargetDisplayName(), fFromTarget.offset );
5936 return temp;
5937 case x86_64::kImageOffset32:
5938 sprintf(temp, "offset 0x%04llX, 32bit offset of ", fFixUpOffsetInSrc);
5939 break;
5940 case x86_64::kSectionOffset24:
5941 sprintf(temp, "offset 0x%04llX, 24-bit section offset of ", fFixUpOffsetInSrc);
5942 break;
5943 case x86_64::kDtraceProbe:
5944 sprintf(temp, "offset 0x%04llX, dtrace static probe ", fFixUpOffsetInSrc);
5945 break;
5946 case x86_64::kDtraceProbeSite:
5947 sprintf(temp, "offset 0x%04llX, dtrace static probe site", fFixUpOffsetInSrc);
5948 break;
5949 case x86_64::kDtraceIsEnabledSite:
5950 sprintf(temp, "offset 0x%04llX, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
5951 break;
5952 case x86_64::kDtraceTypeReference:
5953 sprintf(temp, "offset 0x%04llX, dtrace type/stability reference", fFixUpOffsetInSrc);
5954 break;
5955 }
5956 // always quote by-name references
5957 if ( fToTargetName != NULL ) {
5958 strcat(temp, "\"");
5959 strcat(temp, fToTargetName);
5960 strcat(temp, "\"");
5961 }
5962 else if ( fToTarget.atom != NULL ) {
5963 strcat(temp, fToTarget.atom->getDisplayName());
5964 }
5965 else {
5966 strcat(temp, "NULL target");
5967 }
5968 if ( fToTarget.offset != 0 )
5969 sprintf(&temp[strlen(temp)], " plus 0x%llX", this->getTargetOffset());
5970
5971 return temp;
5972 }
5973
5974
5975 template <>
5976 const char* Reference<arm>::getDescription() const
5977 {
5978 static char temp[2048];
5979 switch( fKind ) {
5980 case arm::kNoFixUp:
5981 sprintf(temp, "reference to ");
5982 break;
5983 case arm::kFollowOn:
5984 sprintf(temp, "followed by ");
5985 break;
5986 case arm::kGroupSubordinate:
5987 sprintf(temp, "group subordinate ");
5988 break;
5989 case arm::kPointer:
5990 sprintf(temp, "offset 0x%04X, pointer to ", fFixUpOffsetInSrc);
5991 break;
5992 case arm::kPointerWeakImport:
5993 sprintf(temp, "offset 0x%04X, weak import pointer to ", fFixUpOffsetInSrc);
5994 break;
5995 case arm::kPointerDiff:
5996 {
5997 // by-name references have quoted names
5998 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
5999 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
6000 sprintf(temp, "offset 0x%04X, 32-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)",
6001 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
6002 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
6003 return temp;
6004 }
6005 case arm::kPointerDiff12:
6006 {
6007 // by-name references have quoted names
6008 const char* targetQuotes = (&(this->getTarget()) == NULL) ? "\"" : "";
6009 const char* fromQuotes = (&(this->getFromTarget()) == NULL) ? "\"" : "";
6010 sprintf(temp, "offset 0x%04X, 12-bit pointer difference: (&%s%s%s + %d) - (&%s%s%s + %d)",
6011 fFixUpOffsetInSrc, targetQuotes, this->getTargetDisplayName(), targetQuotes, fToTarget.offset,
6012 fromQuotes, this->getFromTargetDisplayName(), fromQuotes, fFromTarget.offset );
6013 return temp;
6014 }
6015 case arm::kReadOnlyPointer:
6016 sprintf(temp, "offset 0x%04X, read-only pointer to ", fFixUpOffsetInSrc);
6017 break;
6018 case arm::kBranch24:
6019 case arm::kThumbBranch22:
6020 sprintf(temp, "offset 0x%04X, pc-rel branch fixup to ", fFixUpOffsetInSrc);
6021 break;
6022 case arm::kBranch24WeakImport:
6023 case arm::kThumbBranch22WeakImport:
6024 sprintf(temp, "offset 0x%04X, pc-rel branch fixup to weak imported ", fFixUpOffsetInSrc);
6025 break;
6026 case arm::kDtraceProbe:
6027 sprintf(temp, "offset 0x%04X, dtrace static probe ", fFixUpOffsetInSrc);
6028 break;
6029 case arm::kDtraceProbeSite:
6030 sprintf(temp, "offset 0x%04X, dtrace static probe site", fFixUpOffsetInSrc);
6031 break;
6032 case arm::kDtraceIsEnabledSite:
6033 sprintf(temp, "offset 0x%04X, dtrace static probe is-enabled site", fFixUpOffsetInSrc);
6034 break;
6035 case arm::kDtraceTypeReference:
6036 sprintf(temp, "offset 0x%04X, dtrace type/stability reference", fFixUpOffsetInSrc);
6037 break;
6038 }
6039 // always quote by-name references
6040 if ( fToTargetName != NULL ) {
6041 strcat(temp, "\"");
6042 strcat(temp, fToTargetName);
6043 strcat(temp, "\"");
6044 }
6045 else if ( fToTarget.atom != NULL ) {
6046 strcat(temp, fToTarget.atom->getDisplayName());
6047 }
6048 else {
6049 strcat(temp, "NULL target");
6050 }
6051 if ( fToTarget.offset != 0 )
6052 sprintf(&temp[strlen(temp)], " plus 0x%08X", fToTarget.offset);
6053
6054 return temp;
6055 }
6056
6057
6058 template <>
6059 bool Reference<x86>::isBranch() const
6060 {
6061 switch ( fKind ) {
6062 case x86::kPCRel32:
6063 case x86::kPCRel32WeakImport:
6064 return true;
6065 default:
6066 return false;
6067 }
6068 }
6069
6070 template <>
6071 bool Reference<x86_64>::isBranch() const
6072 {
6073 switch ( fKind ) {
6074 case x86_64::kBranchPCRel32:
6075 case x86_64::kBranchPCRel32WeakImport:
6076 return true;
6077 default:
6078 return false;
6079 }
6080 }
6081
6082 template <>
6083 bool Reference<ppc>::isBranch() const
6084 {
6085 switch ( fKind ) {
6086 case ppc::kBranch24:
6087 case ppc::kBranch24WeakImport:
6088 return true;
6089 default:
6090 return false;
6091 }
6092 }
6093
6094 template <>
6095 bool Reference<ppc64>::isBranch() const
6096 {
6097 switch ( fKind ) {
6098 case ppc64::kBranch24:
6099 case ppc64::kBranch24WeakImport:
6100 return true;
6101 default:
6102 return false;
6103 }
6104 }
6105
6106 template <>
6107 bool Reference<arm>::isBranch() const
6108 {
6109 switch ( fKind ) {
6110 case arm::kBranch24:
6111 case arm::kBranch24WeakImport:
6112 case arm::kThumbBranch22:
6113 case arm::kThumbBranch22WeakImport:
6114 return true;
6115 default:
6116 return false;
6117 }
6118 }
6119
6120
6121
6122 }; // namespace relocatable
6123 }; // namespace mach_o
6124
6125 #endif // __OBJECT_FILE_MACH_O__