1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
31 #include <sys/param.h>
35 #include "MachOFileAbstraction.hpp"
37 #include <libunwind/DwarfInstructions.hpp>
38 #include <libunwind/AddressSpace.hpp>
39 #include <libunwind/Registers.hpp>
47 #include "debugline.h"
49 #include "Architectures.hpp"
51 #include "macho_relocatable_file.h"
55 extern void throwf(const char* format
, ...) __attribute__ ((noreturn
,format(printf
, 1, 2)));
56 extern void warning(const char* format
, ...) __attribute__((format(printf
, 1, 2)));
59 namespace relocatable
{
63 template <typename A
> class Parser
;
64 template <typename A
> class Atom
;
65 template <typename A
> class Section
;
66 template <typename A
> class CFISection
;
69 class File
: public ld::relocatable::File
72 File(const char* p
, time_t mTime
, const uint8_t* content
, uint32_t ord
) :
73 ld::relocatable::File(p
,mTime
,ord
), _fileContent(content
),
74 _sectionsArray(NULL
), _atomsArray(NULL
),
75 _sectionsArrayCount(0), _atomsArrayCount(0),
76 _debugInfoKind(ld::relocatable::File::kDebugInfoNone
),
77 _dwarfTranslationUnitDir(NULL
), _dwarfTranslationUnitFile(NULL
),
78 _dwarfDebugInfoSect(NULL
), _dwarfDebugAbbrevSect(NULL
),
79 _dwarfDebugLineSect(NULL
), _dwarfDebugStringSect(NULL
),
80 _objConstraint(ld::File::objcConstraintNone
),
82 _ojcReplacmentClass(false), _canScatterAtoms(false) {}
85 // overrides of ld::File
86 virtual bool forEachAtom(ld::File::AtomHandler
&) const;
87 virtual bool justInTimeforEachAtom(const char* name
, ld::File::AtomHandler
&) const
90 // overrides of ld::relocatable::File
91 virtual bool objcReplacementClasses() const { return _ojcReplacmentClass
; }
92 virtual ObjcConstraint
objCConstraint() const { return _objConstraint
; }
93 virtual uint32_t cpuSubType() const { return _cpuSubType
; }
94 virtual DebugInfoKind
debugInfo() const { return _debugInfoKind
; }
95 virtual const std::vector
<ld::relocatable::File::Stab
>* stabs() const { return &_stabs
; }
96 virtual bool canScatterAtoms() const { return _canScatterAtoms
; }
97 bool translationUnitSource(const char** dir
, const char** name
) const;
99 const uint8_t* fileContent() { return _fileContent
; }
101 friend class Atom
<A
>;
102 friend class Section
<A
>;
103 friend class Parser
<A
>;
104 friend class CFISection
<A
>::OAS
;
106 typedef typename
A::P P
;
108 const uint8_t* _fileContent
;
109 Section
<A
>** _sectionsArray
;
110 uint8_t* _atomsArray
;
111 uint32_t _sectionsArrayCount
;
112 uint32_t _atomsArrayCount
;
113 std::vector
<ld::Fixup
> _fixups
;
114 std::vector
<ld::Atom::UnwindInfo
> _unwindInfos
;
115 std::vector
<ld::Atom::LineInfo
> _lineInfos
;
116 std::vector
<ld::relocatable::File::Stab
>_stabs
;
117 ld::relocatable::File::DebugInfoKind _debugInfoKind
;
118 const char* _dwarfTranslationUnitDir
;
119 const char* _dwarfTranslationUnitFile
;
120 const macho_section
<P
>* _dwarfDebugInfoSect
;
121 const macho_section
<P
>* _dwarfDebugAbbrevSect
;
122 const macho_section
<P
>* _dwarfDebugLineSect
;
123 const macho_section
<P
>* _dwarfDebugStringSect
;
124 ld::File::ObjcConstraint _objConstraint
;
125 uint32_t _cpuSubType
;
126 bool _ojcReplacmentClass
;
127 bool _canScatterAtoms
;
131 template <typename A
>
132 class Section
: public ld::Section
135 typedef typename
A::P::uint_t pint_t
;
136 typedef typename
A::P P
;
137 typedef typename
A::P::E E
;
139 virtual ~Section() { }
140 class File
<A
>& file() const { return _file
; }
141 const macho_section
<P
>* machoSection() const { return _machOSection
; }
142 uint32_t sectionNum(class Parser
<A
>&) const;
143 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
);
144 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeUnclassified
; }
145 virtual bool dontDeadStrip() { return (this->_machOSection
->flags() & S_ATTR_NO_DEAD_STRIP
); }
146 virtual Atom
<A
>* findAtomByAddress(pint_t addr
) { return this->findContentAtomByAddress(addr
, this->_beginAtoms
, this->_endAtoms
); }
147 virtual bool addFollowOnFixups() const { return ! _file
.canScatterAtoms(); }
148 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
,
149 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
150 const struct Parser
<A
>::CFIInfoArray
&) = 0;
151 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
,
152 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
153 const struct Parser
<A
>::CFIInfoArray
&) = 0;
154 virtual void makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&);
155 virtual bool addRelocFixup(class Parser
<A
>& parser
, const macho_relocation_info
<P
>*);
156 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const { return 0; }
157 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
158 const ld::IndirectBindingTable
& ind
) const { return false; }
161 Section(File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
162 : ld::Section(makeSegmentName(s
), makeSectionName(s
), sectionType(s
)),
163 _file(f
), _machOSection(s
), _beginAtoms(NULL
), _endAtoms(NULL
), _hasAliases(false) { }
164 Section(File
<A
>& f
, const char* segName
, const char* sectName
, ld::Section::Type t
, bool hidden
=false)
165 : ld::Section(segName
, sectName
, t
, hidden
), _file(f
), _machOSection(NULL
),
166 _beginAtoms(NULL
), _endAtoms(NULL
), _hasAliases(false) { }
169 bool addRelocFixup_powerpc(class Parser
<A
>& parser
,const macho_relocation_info
<typename
A::P
>* reloc
);
170 Atom
<A
>* findContentAtomByAddress(pint_t addr
, class Atom
<A
>* start
, class Atom
<A
>* end
);
171 uint32_t x86_64PcRelOffset(uint8_t r_type
);
172 static const char* makeSegmentName(const macho_section
<typename
A::P
>* s
);
173 static const char* makeSectionName(const macho_section
<typename
A::P
>* s
);
174 static bool readable(const macho_section
<typename
A::P
>* s
);
175 static bool writable(const macho_section
<typename
A::P
>* s
);
176 static bool exectuable(const macho_section
<typename
A::P
>* s
);
177 static ld::Section::Type
sectionType(const macho_section
<typename
A::P
>* s
);
180 const macho_section
<P
>* _machOSection
;
181 class Atom
<A
>* _beginAtoms
;
182 class Atom
<A
>* _endAtoms
;
187 template <typename A
>
188 class CFISection
: public Section
<A
>
191 CFISection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
192 : Section
<A
>(f
, s
) { }
195 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeCFI
; }
196 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, const struct Parser
<A
>::CFIInfoArray
&);
197 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, const struct Parser
<A
>::CFIInfoArray
&);
198 virtual void makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&);
199 virtual bool addFollowOnFixups() const { return false; }
203 /// ObjectFileAddressSpace is used as a template parameter to UnwindCursor for parsing
204 /// dwarf CFI information in an object file.
209 typedef typename
A::P::uint_t pint_t
;
210 typedef typename
A::P P
;
211 typedef typename
A::P::E E
;
212 typedef typename
A::P::uint_t sint_t
;
214 OAS(CFISection
<A
>& ehFrameSection
, const uint8_t* ehFrameBuffer
) :
215 _ehFrameSection(ehFrameSection
),
216 _ehFrameContent(ehFrameBuffer
),
217 _ehFrameStartAddr(ehFrameSection
.machoSection()->addr()),
218 _ehFrameEndAddr(ehFrameSection
.machoSection()->addr()+ehFrameSection
.machoSection()->size()) {}
220 uint8_t get8(pint_t addr
) { return *((uint8_t*)mappedAddress(addr
)); }
221 uint16_t get16(pint_t addr
) { return E::get16(*((uint16_t*)mappedAddress(addr
))); }
222 uint32_t get32(pint_t addr
) { return E::get32(*((uint32_t*)mappedAddress(addr
))); }
223 uint64_t get64(pint_t addr
) { return E::get64(*((uint64_t*)mappedAddress(addr
))); }
224 pint_t
getP(pint_t addr
) { return P::getP(*((pint_t
*)mappedAddress(addr
))); }
225 uint64_t getULEB128(pint_t
& addr
, pint_t end
);
226 int64_t getSLEB128(pint_t
& addr
, pint_t end
);
227 pint_t
getEncodedP(pint_t
& addr
, pint_t end
, uint8_t encoding
);
229 const void* mappedAddress(pint_t addr
);
231 CFISection
<A
>& _ehFrameSection
;
232 const uint8_t* _ehFrameContent
;
233 pint_t _ehFrameStartAddr
;
234 pint_t _ehFrameEndAddr
;
238 typedef typename
A::P::uint_t pint_t
;
239 typedef libunwind::CFI_Atom_Info
<OAS
> CFI_Atom_Info
;
241 void cfiParse(class Parser
<A
>& parser
, uint8_t* buffer
, CFI_Atom_Info cfiArray
[], uint32_t cfiCount
);
242 bool needsRelocating();
244 static bool bigEndian();
246 void addCiePersonalityFixups(class Parser
<A
>& parser
, const CFI_Atom_Info
* cieInfo
);
247 static void warnFunc(void* ref
, uint64_t funcAddr
, const char* msg
);
251 template <typename A
>
252 class TentativeDefinitionSection
: public Section
<A
>
255 TentativeDefinitionSection(Parser
<A
>& parser
, File
<A
>& f
)
256 : Section
<A
>(f
, "__DATA", "__comm/tent", ld::Section::typeTentativeDefs
) {}
258 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeZeroFill
; }
259 virtual bool addFollowOnFixups() const { return false; }
260 virtual Atom
<A
>* findAtomByAddress(typename
A::P::uint_t addr
) { throw "TentativeDefinitionSection::findAtomByAddress() should never be called"; }
261 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
262 const struct Parser
<A
>::CFIInfoArray
&);
263 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
,
264 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
265 const struct Parser
<A
>::CFIInfoArray
&);
266 virtual void makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&) {}
268 typedef typename
A::P::uint_t pint_t
;
269 typedef typename
A::P P
;
273 template <typename A
>
274 class AbsoluteSymbolSection
: public Section
<A
>
277 AbsoluteSymbolSection(Parser
<A
>& parser
, File
<A
>& f
)
278 : Section
<A
>(f
, "__DATA", "__abs", ld::Section::typeAbsoluteSymbols
, true) {}
280 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeUnclassified
; }
281 virtual bool dontDeadStrip() { return false; }
282 virtual ld::Atom::Alignment
alignmentForAddress(typename
A::P::uint_t addr
) { return ld::Atom::Alignment(0); }
283 virtual bool addFollowOnFixups() const { return false; }
284 virtual Atom
<A
>* findAtomByAddress(typename
A::P::uint_t addr
) { throw "AbsoluteSymbolSection::findAtomByAddress() should never be called"; }
285 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
286 const struct Parser
<A
>::CFIInfoArray
&);
287 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
,
288 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
289 const struct Parser
<A
>::CFIInfoArray
&);
290 virtual void makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&) {}
291 virtual Atom
<A
>* findAbsAtomForValue(typename
A::P::uint_t
);
294 typedef typename
A::P::uint_t pint_t
;
295 typedef typename
A::P P
;
299 template <typename A
>
300 class SymboledSection
: public Section
<A
>
303 SymboledSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
);
304 virtual ld::Atom::ContentType
contentType() { return _type
; }
305 virtual bool dontDeadStrip();
306 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
307 const struct Parser
<A
>::CFIInfoArray
&);
308 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
,
309 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
310 const struct Parser
<A
>::CFIInfoArray
&);
312 typedef typename
A::P::uint_t pint_t
;
313 typedef typename
A::P P
;
315 ld::Atom::ContentType _type
;
319 template <typename A
>
320 class TLVDefsSection
: public SymboledSection
<A
>
323 TLVDefsSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
) :
324 SymboledSection
<A
>(parser
, f
, s
) { }
331 template <typename A
>
332 class ImplicitSizeSection
: public Section
<A
>
335 ImplicitSizeSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
336 : Section
<A
>(f
, s
) { }
337 virtual uint32_t computeAtomCount(class Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, const struct Parser
<A
>::CFIInfoArray
&);
338 virtual uint32_t appendAtoms(class Parser
<A
>& parser
, uint8_t* buffer
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, const struct Parser
<A
>::CFIInfoArray
&);
340 typedef typename
A::P::uint_t pint_t
;
341 typedef typename
A::P P
;
343 virtual bool addFollowOnFixups() const { return false; }
344 virtual const char* unlabeledAtomName(Parser
<A
>& parser
, pint_t addr
) = 0;
345 virtual ld::Atom::SymbolTableInclusion
symbolTableInclusion() { return ld::Atom::symbolTableNotIn
; }
346 virtual pint_t
elementSizeAtAddress(pint_t addr
) = 0;
347 virtual ld::Atom::Scope
scopeAtAddress(Parser
<A
>& parser
, pint_t addr
) { return ld::Atom::scopeLinkageUnit
; }
348 virtual bool useElementAt(Parser
<A
>& parser
,
349 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, pint_t addr
) = 0;
350 virtual ld::Atom::Definition
definition() { return ld::Atom::definitionRegular
; }
351 virtual ld::Atom::Combine
combine(Parser
<A
>& parser
, pint_t addr
) = 0;
352 virtual bool ignoreLabel(const char* label
) { return (label
[0] == 'L'); }
355 template <typename A
>
356 class FixedSizeSection
: public ImplicitSizeSection
<A
>
359 FixedSizeSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
360 : ImplicitSizeSection
<A
>(parser
, f
, s
) { }
362 typedef typename
A::P::uint_t pint_t
;
363 typedef typename
A::P P
;
364 typedef typename
A::P::E E
;
366 virtual bool useElementAt(Parser
<A
>& parser
,
367 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, pint_t addr
)
372 template <typename A
>
373 class Literal4Section
: public FixedSizeSection
<A
>
376 Literal4Section(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
377 : FixedSizeSection
<A
>(parser
, f
, s
) {}
379 typedef typename
A::P::uint_t pint_t
;
380 typedef typename
A::P P
;
382 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(2); }
383 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "4-byte-literal"; }
384 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return 4; }
385 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndContent
; }
386 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
387 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
388 const ld::IndirectBindingTable
& ind
) const;
391 template <typename A
>
392 class Literal8Section
: public FixedSizeSection
<A
>
395 Literal8Section(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
396 : FixedSizeSection
<A
>(parser
, f
, s
) {}
398 typedef typename
A::P::uint_t pint_t
;
399 typedef typename
A::P P
;
401 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(3); }
402 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "8-byte-literal"; }
403 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return 8; }
404 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndContent
; }
405 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
406 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
407 const ld::IndirectBindingTable
& ind
) const;
410 template <typename A
>
411 class Literal16Section
: public FixedSizeSection
<A
>
414 Literal16Section(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
415 : FixedSizeSection
<A
>(parser
, f
, s
) {}
417 typedef typename
A::P::uint_t pint_t
;
418 typedef typename
A::P P
;
420 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(4); }
421 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "16-byte-literal"; }
422 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return 16; }
423 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndContent
; }
424 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
425 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
426 const ld::IndirectBindingTable
& ind
) const;
430 template <typename A
>
431 class NonLazyPointerSection
: public FixedSizeSection
<A
>
434 NonLazyPointerSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
435 : FixedSizeSection
<A
>(parser
, f
, s
) {}
437 typedef typename
A::P::uint_t pint_t
;
438 typedef typename
A::P P
;
440 virtual void makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&);
441 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeNonLazyPointer
; }
442 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(log2(sizeof(pint_t
))); }
443 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "non_lazy_ptr"; }
444 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return sizeof(pint_t
); }
445 virtual ld::Atom::Scope
scopeAtAddress(Parser
<A
>& parser
, pint_t addr
);
446 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
);
447 virtual bool ignoreLabel(const char* label
) { return true; }
448 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
449 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
450 const ld::IndirectBindingTable
& ind
) const;
453 static const char* targetName(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
);
454 static ld::Fixup::Kind
fixupKind();
458 template <typename A
>
459 class CFStringSection
: public FixedSizeSection
<A
>
462 CFStringSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
463 : FixedSizeSection
<A
>(parser
, f
, s
) {}
465 typedef typename
A::P::uint_t pint_t
;
467 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(log2(sizeof(pint_t
))); }
468 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "CFString"; }
469 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return 4*sizeof(pint_t
); }
470 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndReferences
; }
471 virtual bool ignoreLabel(const char* label
) { return true; }
472 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
473 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
474 const ld::IndirectBindingTable
& ind
) const;
476 enum ContentType
{ contentUTF8
, contentUTF16
, contentUnknown
};
477 static const uint8_t* targetContent(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
,
478 ContentType
* ct
, unsigned int* count
);
482 template <typename A
>
483 class ObjC1ClassSection
: public FixedSizeSection
<A
>
486 ObjC1ClassSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
487 : FixedSizeSection
<A
>(parser
, f
, s
) {}
489 typedef typename
A::P::uint_t pint_t
;
490 typedef typename
A::P P
;
491 typedef typename
A::P::E E
;
493 virtual ld::Atom::Scope
scopeAtAddress(Parser
<A
>& , pint_t
) { return ld::Atom::scopeGlobal
; }
494 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(2); }
495 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
);
496 virtual ld::Atom::SymbolTableInclusion
symbolTableInclusion() { return ld::Atom::symbolTableIn
; }
497 virtual pint_t
elementSizeAtAddress(pint_t addr
);
498 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineNever
; }
499 virtual bool ignoreLabel(const char* label
) { return true; }
500 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
502 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
503 const ld::IndirectBindingTable
& ind
) const { return false; }
504 virtual bool addRelocFixup(class Parser
<A
>& parser
, const macho_relocation_info
<P
>*);
508 template <typename A
>
509 class ObjC2ClassRefsSection
: public FixedSizeSection
<A
>
512 ObjC2ClassRefsSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
513 : FixedSizeSection
<A
>(parser
, f
, s
) {}
515 typedef typename
A::P::uint_t pint_t
;
517 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(log2(sizeof(pint_t
))); }
518 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "objc-class-ref"; }
519 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return sizeof(pint_t
); }
520 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndReferences
; }
521 virtual bool ignoreLabel(const char* label
) { return true; }
522 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
523 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
524 const ld::IndirectBindingTable
& ind
) const;
526 const char* targetClassName(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
530 template <typename A
>
531 class ObjC2CategoryListSection
: public FixedSizeSection
<A
>
534 ObjC2CategoryListSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
535 : FixedSizeSection
<A
>(parser
, f
, s
) {}
537 typedef typename
A::P::uint_t pint_t
;
539 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(log2(sizeof(pint_t
))); }
540 virtual ld::Atom::Scope
scopeAtAddress(Parser
<A
>& parser
, pint_t addr
) { return ld::Atom::scopeTranslationUnit
; }
541 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "objc-cat-list"; }
542 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return sizeof(pint_t
); }
543 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineNever
; }
544 virtual bool ignoreLabel(const char* label
) { return true; }
546 const char* targetClassName(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
550 template <typename A
>
551 class PointerToCStringSection
: public FixedSizeSection
<A
>
554 PointerToCStringSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
555 : FixedSizeSection
<A
>(parser
, f
, s
) {}
557 typedef typename
A::P::uint_t pint_t
;
559 virtual ld::Atom::Alignment
alignmentForAddress(pint_t addr
) { return ld::Atom::Alignment(log2(sizeof(pint_t
))); }
560 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "pointer-to-literal-cstring"; }
561 virtual pint_t
elementSizeAtAddress(pint_t addr
) { return sizeof(pint_t
); }
562 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndReferences
; }
563 virtual bool ignoreLabel(const char* label
) { return true; }
564 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
565 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
566 const ld::IndirectBindingTable
& ind
) const;
567 virtual const char* targetCString(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
571 template <typename A
>
572 class Objc1ClassReferences
: public PointerToCStringSection
<A
>
575 Objc1ClassReferences(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
576 : PointerToCStringSection
<A
>(parser
, f
, s
) {}
578 typedef typename
A::P::uint_t pint_t
;
579 typedef typename
A::P P
;
581 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "pointer-to-literal-objc-class-name"; }
582 virtual bool addRelocFixup(class Parser
<A
>& parser
, const macho_relocation_info
<P
>*);
583 virtual const char* targetCString(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
587 template <typename A
>
588 class CStringSection
: public ImplicitSizeSection
<A
>
591 CStringSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
592 : ImplicitSizeSection
<A
>(parser
, f
, s
) {}
594 typedef typename
A::P::uint_t pint_t
;
595 typedef typename
A::P P
;
597 virtual ld::Atom::ContentType
contentType() { return ld::Atom::typeCString
; }
598 virtual Atom
<A
>* findAtomByAddress(pint_t addr
);
599 virtual const char* unlabeledAtomName(Parser
<A
>&, pint_t
) { return "cstring"; }
600 virtual pint_t
elementSizeAtAddress(pint_t addr
);
601 virtual bool useElementAt(Parser
<A
>& parser
,
602 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, pint_t addr
);
603 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndContent
; }
604 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
605 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
606 const ld::IndirectBindingTable
& ind
) const;
611 template <typename A
>
612 class UTF16StringSection
: public SymboledSection
<A
>
615 UTF16StringSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
616 : SymboledSection
<A
>(parser
, f
, s
) {}
618 typedef typename
A::P::uint_t pint_t
;
619 typedef typename
A::P P
;
621 virtual ld::Atom::Combine
combine(Parser
<A
>&, pint_t
) { return ld::Atom::combineByNameAndContent
; }
622 virtual unsigned long contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const;
623 virtual bool canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
624 const ld::IndirectBindingTable
& ind
) const;
629 // Atoms in mach-o files
631 template <typename A
>
632 class Atom
: public ld::Atom
635 // overrides of ld::Atom
636 virtual ld::File
* file() const { return §().file(); }
637 virtual bool translationUnitSource(const char** dir
, const char** nm
) const
638 { return sect().file().translationUnitSource(dir
, nm
); }
639 virtual const char* name() const { return _name
; }
640 virtual uint64_t size() const { return _size
; }
641 virtual uint64_t objectAddress() const { return _objAddress
; }
642 virtual void copyRawContent(uint8_t buffer
[]) const;
643 virtual const uint8_t* rawContentPointer() const { return contentPointer(); }
644 virtual unsigned long contentHash(const ld::IndirectBindingTable
& ind
) const
645 { if ( _hash
== 0 ) _hash
= sect().contentHash(this, ind
); return _hash
; }
646 virtual bool canCoalesceWith(const ld::Atom
& rhs
, const ld::IndirectBindingTable
& ind
) const
647 { return sect().canCoalesceWith(this, rhs
, ind
); }
648 virtual ld::Fixup::iterator
fixupsBegin() const { return &machofile()._fixups
[_fixupsStartIndex
]; }
649 virtual ld::Fixup::iterator
fixupsEnd() const { return &machofile()._fixups
[_fixupsStartIndex
+_fixupsCount
]; }
650 virtual ld::Atom::UnwindInfo::iterator
beginUnwind() const { return &machofile()._unwindInfos
[_unwindInfoStartIndex
]; }
651 virtual ld::Atom::UnwindInfo::iterator
endUnwind() const { return &machofile()._unwindInfos
[_unwindInfoStartIndex
+_unwindInfoCount
]; }
652 virtual ld::Atom::LineInfo::iterator
beginLineInfo() const{ return &machofile()._lineInfos
[_lineInfoStartIndex
]; }
653 virtual ld::Atom::LineInfo::iterator
endLineInfo() const { return &machofile()._lineInfos
[_lineInfoStartIndex
+_lineInfoCount
]; }
657 enum { kFixupStartIndexBits
= 32,
658 kLineInfoStartIndexBits
= 32,
659 kUnwindInfoStartIndexBits
= 24,
660 kFixupCountBits
= 24,
661 kLineInfoCountBits
= 12,
662 kUnwindInfoCountBits
= 4
663 }; // must sum to 128
666 // methods for all atoms from mach-o object file
667 Section
<A
>& sect() const { return (Section
<A
>&)section(); }
668 File
<A
>& machofile() const { return ((Section
<A
>*)(this->_section
))->file(); }
669 void setFixupsRange(uint32_t s
, uint32_t c
);
670 void setUnwindInfoRange(uint32_t s
, uint32_t c
);
671 void setLineInfoRange(uint32_t s
, uint32_t c
);
672 bool roomForMoreLineInfoCount() { return (_lineInfoCount
< ((1<<kLineInfoCountBits
)-1)); }
673 void incrementLineInfoCount() { assert(roomForMoreLineInfoCount()); ++_lineInfoCount
; }
674 void incrementFixupCount() { if (_fixupsCount
== ((1 << kFixupCountBits
)-1))
675 throwf("too may fixups in %s", name()); ++_fixupsCount
; }
676 const uint8_t* contentPointer() const;
677 uint32_t fixupCount() const { return _fixupsCount
; }
678 void verifyAlignment() const;
680 typedef typename
A::P P
;
681 typedef typename
A::P::E E
;
682 typedef typename
A::P::uint_t pint_t
;
683 // constuct via all attributes
684 Atom(Section
<A
>& sct
, const char* nm
, pint_t addr
, uint64_t sz
,
685 ld::Atom::Definition d
, ld::Atom::Combine c
, ld::Atom::Scope s
,
686 ld::Atom::ContentType ct
, ld::Atom::SymbolTableInclusion i
,
687 bool dds
, bool thumb
, bool al
, ld::Atom::Alignment a
)
688 : ld::Atom((ld::Section
&)sct
, d
, c
, s
, ct
, i
, dds
, thumb
, al
, a
),
689 _size(sz
), _objAddress(addr
), _name(nm
), _hash(0),
690 _fixupsStartIndex(0), _lineInfoStartIndex(0),
691 _unwindInfoStartIndex(0), _fixupsCount(0),
692 _lineInfoCount(0), _unwindInfoCount(0) { }
693 // construct via symbol table entry
694 Atom(Section
<A
>& sct
, Parser
<A
>& parser
, const macho_nlist
<P
>& sym
,
695 uint64_t sz
, bool alias
=false)
696 : ld::Atom((ld::Section
&)sct
, parser
.definitionFromSymbol(sym
),
697 parser
.combineFromSymbol(sym
), parser
.scopeFromSymbol(sym
),
698 parser
.resolverFromSymbol(sym
) ? ld::Atom::typeResolver
: sct
.contentType(),
699 parser
.inclusionFromSymbol(sym
),
700 parser
.dontDeadStripFromSymbol(sym
) || sct
.dontDeadStrip(),
701 parser
.isThumbFromSymbol(sym
), alias
,
702 sct
.alignmentForAddress(sym
.n_value())),
703 _size(sz
), _objAddress(sym
.n_value()),
704 _name(parser
.nameFromSymbol(sym
)), _hash(0),
705 _fixupsStartIndex(0), _lineInfoStartIndex(0),
706 _unwindInfoStartIndex(0), _fixupsCount(0),
707 _lineInfoCount(0), _unwindInfoCount(0) {
708 // <rdar://problem/6783167> support auto-hidden weak symbols
709 if ( _scope
== ld::Atom::scopeGlobal
&&
710 (sym
.n_desc() & (N_WEAK_DEF
|N_WEAK_REF
)) == (N_WEAK_DEF
|N_WEAK_REF
) )
712 this->verifyAlignment();
716 friend class Parser
<A
>;
717 friend class Section
<A
>;
718 friend class CStringSection
<A
>;
719 friend class AbsoluteSymbolSection
<A
>;
724 mutable unsigned long _hash
;
726 uint64_t _fixupsStartIndex
: kFixupStartIndexBits
,
727 _lineInfoStartIndex
: kLineInfoStartIndexBits
,
728 _unwindInfoStartIndex
: kUnwindInfoStartIndexBits
,
729 _fixupsCount
: kFixupCountBits
,
730 _lineInfoCount
: kLineInfoCountBits
,
731 _unwindInfoCount
: kUnwindInfoCountBits
;
737 template <typename A
>
738 void Atom
<A
>::setFixupsRange(uint32_t startIndex
, uint32_t count
)
740 if ( count
>= (1 << kFixupCountBits
) )
741 throwf("too many fixups in function %s", this->name());
742 if ( startIndex
>= (1 << kFixupStartIndexBits
) )
743 throwf("too many fixups in file");
744 assert(((startIndex
+count
) <= sect().file()._fixups
.size()) && "fixup index out of range");
745 _fixupsStartIndex
= startIndex
;
746 _fixupsCount
= count
;
749 template <typename A
>
750 void Atom
<A
>::setUnwindInfoRange(uint32_t startIndex
, uint32_t count
)
752 if ( count
>= (1 << kUnwindInfoCountBits
) )
753 throwf("too many compact unwind infos in function %s", this->name());
754 if ( startIndex
>= (1 << kUnwindInfoStartIndexBits
) )
755 throwf("too many compact unwind infos (%d) in file", startIndex
);
756 assert((startIndex
+count
) <= sect().file()._unwindInfos
.size() && "unwindinfo index out of range");
757 _unwindInfoStartIndex
= startIndex
;
758 _unwindInfoCount
= count
;
761 template <typename A
>
762 void Atom
<A
>::setLineInfoRange(uint32_t startIndex
, uint32_t count
)
764 assert((count
< (1 << kLineInfoCountBits
)) && "too many line infos");
765 assert((startIndex
+count
) < sect().file()._lineInfos
.size() && "line info index out of range");
766 _lineInfoStartIndex
= startIndex
;
767 _lineInfoCount
= count
;
770 template <typename A
>
771 const uint8_t* Atom
<A
>::contentPointer() const
773 const macho_section
<P
>* sct
= this->sect().machoSection();
774 uint32_t fileOffset
= sct
->offset() - sct
->addr() + this->_objAddress
;
775 return this->sect().file().fileContent()+fileOffset
;
779 template <typename A
>
780 void Atom
<A
>::copyRawContent(uint8_t buffer
[]) const
783 if ( this->contentType() == ld::Atom::typeZeroFill
) {
784 bzero(buffer
, _size
);
786 else if ( _size
!= 0 ) {
787 memcpy(buffer
, this->contentPointer(), _size
);
792 void Atom
<arm
>::verifyAlignment() const
794 if ( (this->section().type() == ld::Section::typeCode
) && ! isThumb() ) {
795 if ( (_objAddress
% 4) != 0 )
796 warning("ARM function %s not 4-byte aligned", this->name());
800 template <typename A
>
801 void Atom
<A
>::verifyAlignment() const
806 template <typename A
>
810 static bool validFile(const uint8_t* fileContent
, bool subtypeMustMatch
=false,
811 cpu_subtype_t subtype
=0);
812 static const char* fileKind(const uint8_t* fileContent
);
813 static bool hasObjC2Categories(const uint8_t* fileContent
);
814 static ld::relocatable::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
815 const char* path
, time_t modTime
, uint32_t ordinal
,
816 const ParserOptions
& opts
) {
817 Parser
p(fileContent
, fileLength
, path
, modTime
,
818 ordinal
, opts
.convertUnwindInfo
);
819 return p
.parse(opts
);
822 typedef typename
A::P P
;
823 typedef typename
A::P::E E
;
824 typedef typename
A::P::uint_t pint_t
;
826 struct SourceLocation
{
828 SourceLocation(Atom
<A
>* a
, uint32_t o
) : atom(a
), offsetInAtom(o
) {}
830 uint32_t offsetInAtom
;
835 const char* name
; // only used if targetAtom is NULL
837 bool weakImport
; // only used if targetAtom is NULL
841 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, Atom
<A
>* target
) :
842 fixup(src
.offsetInAtom
, c
, k
, target
), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
844 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, ld::Fixup::TargetBinding b
, Atom
<A
>* target
) :
845 fixup(src
.offsetInAtom
, c
, k
, b
, target
), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
847 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, bool wi
, const char* name
) :
848 fixup(src
.offsetInAtom
, c
, k
, wi
, name
), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
850 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, ld::Fixup::TargetBinding b
, const char* name
) :
851 fixup(src
.offsetInAtom
, c
, k
, b
, name
), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
853 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, uint64_t addend
) :
854 fixup(src
.offsetInAtom
, c
, k
, addend
), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
856 FixupInAtom(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
) :
857 fixup(src
.offsetInAtom
, c
, k
, (uint64_t)0), atom(src
.atom
) { src
.atom
->incrementFixupCount(); }
863 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, Atom
<A
>* target
) {
864 _allFixups
.push_back(FixupInAtom(src
, c
, k
, target
));
867 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, ld::Fixup::TargetBinding b
, Atom
<A
>* target
) {
868 _allFixups
.push_back(FixupInAtom(src
, c
, k
, b
, target
));
871 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, bool wi
, const char* name
) {
872 _allFixups
.push_back(FixupInAtom(src
, c
, k
, wi
, name
));
875 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, ld::Fixup::TargetBinding b
, const char* name
) {
876 _allFixups
.push_back(FixupInAtom(src
, c
, k
, b
, name
));
879 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
, uint64_t addend
) {
880 _allFixups
.push_back(FixupInAtom(src
, c
, k
, addend
));
883 void addFixup(const SourceLocation
& src
, ld::Fixup::Cluster c
, ld::Fixup::Kind k
) {
884 _allFixups
.push_back(FixupInAtom(src
, c
, k
));
888 uint32_t symbolCount() { return _symbolCount
; }
889 uint32_t indirectSymbol(uint32_t indirectIndex
);
890 const macho_nlist
<P
>& symbolFromIndex(uint32_t index
);
891 const char* nameFromSymbol(const macho_nlist
<P
>& sym
);
892 ld::Atom::Scope
scopeFromSymbol(const macho_nlist
<P
>& sym
);
893 static ld::Atom::Definition
definitionFromSymbol(const macho_nlist
<P
>& sym
);
894 static ld::Atom::Combine
combineFromSymbol(const macho_nlist
<P
>& sym
);
895 ld::Atom::SymbolTableInclusion
inclusionFromSymbol(const macho_nlist
<P
>& sym
);
896 static bool dontDeadStripFromSymbol(const macho_nlist
<P
>& sym
);
897 static bool isThumbFromSymbol(const macho_nlist
<P
>& sym
);
898 static bool weakImportFromSymbol(const macho_nlist
<P
>& sym
);
899 static bool resolverFromSymbol(const macho_nlist
<P
>& sym
);
900 uint32_t symbolIndexFromIndirectSectionAddress(pint_t
,const macho_section
<P
>*);
901 const macho_section
<P
>* firstMachOSection() { return _sectionsStart
; }
902 const macho_section
<P
>* machOSectionFromSectionIndex(uint32_t index
);
903 uint32_t machOSectionCount() { return _machOSectionsCount
; }
904 uint32_t undefinedStartIndex() { return _undefinedStartIndex
; }
905 uint32_t undefinedEndIndex() { return _undefinedEndIndex
; }
906 void addFixup(FixupInAtom f
) { _allFixups
.push_back(f
); }
907 Section
<A
>* sectionForNum(unsigned int sectNum
);
908 Section
<A
>* sectionForAddress(pint_t addr
);
909 Atom
<A
>* findAtomByAddress(pint_t addr
);
910 Atom
<A
>* findAtomByAddressOrNullIfStub(pint_t addr
);
911 Atom
<A
>* findAtomByAddressOrLocalTargetOfStub(pint_t addr
, uint32_t* offsetInAtom
);
912 Atom
<A
>* findAtomByName(const char* name
); // slow!
913 void findTargetFromAddress(pint_t addr
, TargetDesc
& target
);
914 void findTargetFromAddress(pint_t baseAddr
, pint_t addr
, TargetDesc
& target
);
915 void findTargetFromAddressAndSectionNum(pint_t addr
, unsigned int sectNum
,
917 uint32_t tentativeDefinitionCount() { return _tentativeDefinitionCount
; }
918 uint32_t absoluteSymbolCount() { return _absoluteSymbolCount
; }
920 bool hasStubsSection() { return (_stubsSectionNum
!= 0); }
921 unsigned int stubsSectionNum() { return _stubsSectionNum
; }
922 void addDtraceExtraInfos(const SourceLocation
& src
, const char* provider
);
923 const char* scanSymbolTableForAddress(uint64_t addr
);
924 bool convertUnwindInfo() { return _convertUnwindInfo
; }
927 void addFixups(const SourceLocation
& src
, ld::Fixup::Kind kind
, const TargetDesc
& target
);
928 void addFixups(const SourceLocation
& src
, ld::Fixup::Kind kind
, const TargetDesc
& target
, const TargetDesc
& picBase
);
932 struct LabelAndCFIBreakIterator
{
933 typedef typename CFISection
<A
>::CFI_Atom_Info CFI_Atom_Info
;
934 LabelAndCFIBreakIterator(const uint32_t* ssa
, uint32_t ssc
, const pint_t
* cfisa
,
935 uint32_t cfisc
, bool ols
)
936 : sortedSymbolIndexes(ssa
), sortedSymbolCount(ssc
), cfiStartsArray(cfisa
),
937 cfiStartsCount(cfisc
), fileHasOverlappingSymbols(ols
),
938 newSection(false), cfiIndex(0), symIndex(0) {}
939 bool next(Parser
<A
>& parser
, uint32_t sectNum
, pint_t startAddr
, pint_t endAddr
,
940 pint_t
* addr
, pint_t
* size
, const macho_nlist
<P
>** sym
);
941 pint_t
peek(Parser
<A
>& parser
, pint_t startAddr
, pint_t endAddr
);
942 void beginSection() { newSection
= true; symIndex
= 0; }
944 const uint32_t* const sortedSymbolIndexes
;
945 const uint32_t sortedSymbolCount
;
946 const pint_t
* cfiStartsArray
;
947 const uint32_t cfiStartsCount
;
948 const bool fileHasOverlappingSymbols
;
954 struct CFIInfoArray
{
955 typedef typename CFISection
<A
>::CFI_Atom_Info CFI_Atom_Info
;
956 CFIInfoArray(const CFI_Atom_Info
* cfia
, uint32_t cfiac
) : array(cfia
), count(cfiac
) {}
957 const CFI_Atom_Info
* const array
;
958 const uint32_t count
;
963 friend class Section
<A
>;
965 enum SectionType
{ sectionTypeIgnore
, sectionTypeLiteral4
, sectionTypeLiteral8
, sectionTypeLiteral16
,
966 sectionTypeNonLazy
, sectionTypeCFI
, sectionTypeCString
, sectionTypeCStringPointer
,
967 sectionTypeUTF16Strings
, sectionTypeCFString
, sectionTypeObjC2ClassRefs
, typeObjC2CategoryList
,
968 sectionTypeObjC1Classes
, sectionTypeSymboled
, sectionTypeObjC1ClassRefs
,
969 sectionTypeTentativeDefinitions
, sectionTypeAbsoluteSymbols
, sectionTypeTLVDefs
};
971 template <typename P
>
972 struct MachOSectionAndSectionClass
974 const macho_section
<P
>* sect
;
977 static int sorter(const void* l
, const void* r
) {
978 const MachOSectionAndSectionClass
<P
>* left
= (MachOSectionAndSectionClass
<P
>*)l
;
979 const MachOSectionAndSectionClass
<P
>* right
= (MachOSectionAndSectionClass
<P
>*)r
;
980 int64_t diff
= left
->sect
->addr() - right
->sect
->addr();
990 Parser(const uint8_t* fileContent
, uint64_t fileLength
,
991 const char* path
, time_t modTime
,
992 uint32_t ordinal
, bool convertUnwindInfo
);
993 ld::relocatable::File
* parse(const ParserOptions
& opts
);
994 uint8_t loadCommandSizeMask();
995 bool parseLoadCommands();
998 void prescanSymbolTable();
999 void makeSortedSymbolsArray(uint32_t array
[]);
1000 static int pointerSorter(const void* l
, const void* r
);
1001 static int symbolIndexSorter(void* extra
, const void* l
, const void* r
);
1002 void parseDebugInfo();
1004 static bool isConstFunStabs(const char *stabStr
);
1005 bool read_comp_unit(const char ** name
, const char ** comp_dir
,
1006 uint64_t *stmt_list
);
1007 const char* getDwarfString(uint64_t form
, const uint8_t* p
);
1008 bool skip_form(const uint8_t ** offset
, const uint8_t * end
,
1009 uint64_t form
, uint8_t addr_size
, bool dwarf64
);
1012 // filled in by constructor
1013 const uint8_t* _fileContent
;
1014 uint32_t _fileLength
;
1019 // filled in by parseLoadCommands()
1021 const macho_nlist
<P
>* _symbols
;
1022 uint32_t _symbolCount
;
1023 const char* _strings
;
1024 uint32_t _stringsSize
;
1025 const uint32_t* _indirectTable
;
1026 uint32_t _indirectTableCount
;
1027 uint32_t _undefinedStartIndex
;
1028 uint32_t _undefinedEndIndex
;
1029 const macho_section
<P
>* _sectionsStart
;
1030 uint32_t _machOSectionsCount
;
1033 // filled in by parse()
1034 CFISection
<A
>* _EHFrameSection
;
1035 AbsoluteSymbolSection
<A
>* _absoluteSection
;
1036 uint32_t _lsdaTextSectionNum
;
1037 uint32_t _lsdaDataSectionNum
;
1038 uint32_t _tentativeDefinitionCount
;
1039 uint32_t _absoluteSymbolCount
;
1040 uint32_t _symbolsInSections
;
1041 bool _hasLongBranchStubs
;
1042 bool _AppleObjc
; // FSF has objc that uses different data layout
1043 bool _overlappingSymbols
;
1044 bool _convertUnwindInfo
;
1045 unsigned int _stubsSectionNum
;
1046 const macho_section
<P
>* _stubsMachOSection
;
1047 std::vector
<const char*> _dtraceProviderInfo
;
1048 std::vector
<FixupInAtom
> _allFixups
;
1053 template <typename A
>
1054 Parser
<A
>::Parser(const uint8_t* fileContent
, uint64_t fileLength
, const char* path
, time_t modTime
,
1055 uint32_t ordinal
, bool convertDUI
)
1056 : _fileContent(fileContent
), _fileLength(fileLength
), _path(path
), _modTime(modTime
),
1057 _ordinal(ordinal
), _file(NULL
),
1058 _symbols(NULL
), _symbolCount(0), _strings(NULL
), _stringsSize(0),
1059 _indirectTable(NULL
), _indirectTableCount(0),
1060 _undefinedStartIndex(0), _undefinedEndIndex(0),
1061 _sectionsStart(NULL
), _machOSectionsCount(0), _hasUUID(false),
1062 _EHFrameSection(NULL
), _absoluteSection(NULL
),
1063 _lsdaTextSectionNum(0), _lsdaDataSectionNum(0),
1064 _tentativeDefinitionCount(0), _absoluteSymbolCount(0),
1065 _symbolsInSections(0), _hasLongBranchStubs(false), _AppleObjc(false),
1066 _overlappingSymbols(false), _convertUnwindInfo(convertDUI
),
1067 _stubsSectionNum(0), _stubsMachOSection(NULL
)
1072 bool Parser
<ppc
>::validFile(const uint8_t* fileContent
, bool, cpu_subtype_t
)
1074 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1075 if ( header
->magic() != MH_MAGIC
)
1077 if ( header
->cputype() != CPU_TYPE_POWERPC
)
1079 if ( header
->filetype() != MH_OBJECT
)
1085 bool Parser
<ppc64
>::validFile(const uint8_t* fileContent
, bool, cpu_subtype_t
)
1087 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1088 if ( header
->magic() != MH_MAGIC_64
)
1090 if ( header
->cputype() != CPU_TYPE_POWERPC64
)
1092 if ( header
->filetype() != MH_OBJECT
)
1098 bool Parser
<x86
>::validFile(const uint8_t* fileContent
, bool, cpu_subtype_t
)
1100 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1101 if ( header
->magic() != MH_MAGIC
)
1103 if ( header
->cputype() != CPU_TYPE_I386
)
1105 if ( header
->filetype() != MH_OBJECT
)
1111 bool Parser
<x86_64
>::validFile(const uint8_t* fileContent
, bool, cpu_subtype_t
)
1113 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1114 if ( header
->magic() != MH_MAGIC_64
)
1116 if ( header
->cputype() != CPU_TYPE_X86_64
)
1118 if ( header
->filetype() != MH_OBJECT
)
1124 bool Parser
<arm
>::validFile(const uint8_t* fileContent
, bool subtypeMustMatch
, cpu_subtype_t subtype
)
1126 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1127 if ( header
->magic() != MH_MAGIC
)
1129 if ( header
->cputype() != CPU_TYPE_ARM
)
1131 if ( header
->filetype() != MH_OBJECT
)
1133 if ( subtypeMustMatch
) {
1134 if ( (cpu_subtype_t
)header
->cpusubtype() == subtype
)
1136 // hack until libcc_kext.a is made fat
1137 if ( header
->cpusubtype() == CPU_SUBTYPE_ARM_ALL
)
1146 const char* Parser
<ppc
>::fileKind(const uint8_t* fileContent
)
1148 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1149 if ( header
->magic() != MH_MAGIC
)
1151 if ( header
->cputype() != CPU_TYPE_POWERPC
)
1153 switch ( header
->cpusubtype() ) {
1154 case CPU_SUBTYPE_POWERPC_750
:
1156 case CPU_SUBTYPE_POWERPC_7400
:
1158 case CPU_SUBTYPE_POWERPC_7450
:
1160 case CPU_SUBTYPE_POWERPC_970
:
1162 case CPU_SUBTYPE_POWERPC_ALL
:
1169 const char* Parser
<ppc64
>::fileKind(const uint8_t* fileContent
)
1171 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1172 if ( header
->magic() != MH_MAGIC
)
1174 if ( header
->cputype() != CPU_TYPE_POWERPC64
)
1180 const char* Parser
<x86
>::fileKind(const uint8_t* fileContent
)
1182 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1183 if ( header
->magic() != MH_MAGIC
)
1185 if ( header
->cputype() != CPU_TYPE_I386
)
1191 const char* Parser
<x86_64
>::fileKind(const uint8_t* fileContent
)
1193 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1194 if ( header
->magic() != MH_MAGIC
)
1196 if ( header
->cputype() != CPU_TYPE_X86_64
)
1202 const char* Parser
<arm
>::fileKind(const uint8_t* fileContent
)
1204 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1205 if ( header
->magic() != MH_MAGIC
)
1207 if ( header
->cputype() != CPU_TYPE_ARM
)
1209 switch ( header
->cpusubtype() ) {
1210 case CPU_SUBTYPE_ARM_V4T
:
1212 case CPU_SUBTYPE_ARM_V5TEJ
:
1214 case CPU_SUBTYPE_ARM_V6
:
1216 case CPU_SUBTYPE_ARM_V7
:
1218 case CPU_SUBTYPE_ARM_ALL
:
1225 template <typename A
>
1226 bool Parser
<A
>::hasObjC2Categories(const uint8_t* fileContent
)
1228 const macho_header
<P
>* header
= (const macho_header
<P
>*)fileContent
;
1229 const uint32_t cmd_count
= header
->ncmds();
1230 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>));
1231 const macho_load_command
<P
>* const cmdsEnd
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>) + header
->sizeofcmds());
1232 const macho_load_command
<P
>* cmd
= cmds
;
1233 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1234 if ( cmd
->cmd() == macho_segment_command
<P
>::CMD
) {
1235 const macho_segment_command
<P
>* segment
= (macho_segment_command
<P
>*)cmd
;
1236 const macho_section
<P
>* sectionsStart
= (macho_section
<P
>*)((char*)segment
+ sizeof(macho_segment_command
<P
>));
1237 for (uint32_t si
=0; si
< segment
->nsects(); ++si
) {
1238 const macho_section
<P
>* sect
= §ionsStart
[si
];
1239 if ( (sect
->size() > 0)
1240 && (strcmp(sect
->sectname(), "__objc_catlist") == 0)
1241 && (strcmp(sect
->segname(), "__DATA") == 0) ) {
1246 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
1247 if ( cmd
> cmdsEnd
)
1248 throwf("malformed mach-o file, load command #%d is outside size of load commands", i
);
1253 template <typename A
>
1254 int Parser
<A
>::pointerSorter(const void* l
, const void* r
)
1256 // sort references by address
1257 const pint_t
* left
= (pint_t
*)l
;
1258 const pint_t
* right
= (pint_t
*)r
;
1259 return (*left
- *right
);
1262 template <typename A
>
1263 typename
A::P::uint_t Parser
<A
>::LabelAndCFIBreakIterator::peek(Parser
<A
>& parser
, pint_t startAddr
, pint_t endAddr
)
1266 if ( symIndex
< sortedSymbolCount
)
1267 symbolAddr
= parser
.symbolFromIndex(sortedSymbolIndexes
[symIndex
]).n_value();
1269 symbolAddr
= endAddr
;
1271 if ( cfiIndex
< cfiStartsCount
)
1272 cfiAddr
= cfiStartsArray
[cfiIndex
];
1275 if ( (cfiAddr
< symbolAddr
) && (cfiAddr
>= startAddr
) ) {
1276 if ( cfiAddr
< endAddr
)
1282 if ( symbolAddr
< endAddr
)
1290 // Parses up a section into chunks based on labels and CFI information.
1291 // Each call returns the next chunk address and size, and (if the break
1292 // was becuase of a label, the symbol). Returns false when no more chunks.
1294 template <typename A
>
1295 bool Parser
<A
>::LabelAndCFIBreakIterator::next(Parser
<A
>& parser
, uint32_t sectNum
, pint_t startAddr
, pint_t endAddr
,
1296 pint_t
* addr
, pint_t
* size
, const macho_nlist
<P
>** symbol
)
1298 // may not be a label on start of section, but need atom demarcation there
1301 // advance symIndex until we get to the first label at or past the start of this section
1302 while ( symIndex
< sortedSymbolCount
) {
1303 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(sortedSymbolIndexes
[symIndex
]);
1304 pint_t nextSymbolAddr
= sym
.n_value();
1305 if ( (nextSymbolAddr
>= startAddr
) && (sym
.n_sect() >= sectNum
) )
1309 if ( symIndex
< sortedSymbolCount
) {
1310 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(sortedSymbolIndexes
[symIndex
]);
1311 pint_t nextSymbolAddr
= sym
.n_value();
1312 // if next symbol found is not in this section
1313 if ( sym
.n_sect() != sectNum
) {
1314 // check for CFI break instead of symbol break
1315 if ( cfiIndex
< cfiStartsCount
) {
1316 pint_t nextCfiAddr
= cfiStartsArray
[cfiIndex
];
1317 if ( nextCfiAddr
< endAddr
) {
1320 *addr
= nextCfiAddr
;
1321 *size
= peek(parser
, startAddr
, endAddr
) - nextCfiAddr
;
1327 *size
= endAddr
- startAddr
;
1329 if ( startAddr
== endAddr
)
1330 return false; // zero size section
1332 return true; // whole section is one atom with no label
1334 // if also CFI break here, eat it
1335 if ( cfiIndex
< cfiStartsCount
) {
1336 if ( cfiStartsArray
[cfiIndex
] == nextSymbolAddr
)
1339 if ( nextSymbolAddr
== startAddr
) {
1340 // label at start of section, return it as chunk
1343 *size
= peek(parser
, startAddr
, endAddr
) - startAddr
;
1347 // return chunk before first symbol
1349 *size
= nextSymbolAddr
- startAddr
;
1353 // no symbols left in whole file, so entire section is one chunk
1355 *size
= endAddr
- startAddr
;
1357 if ( startAddr
== endAddr
)
1358 return false; // zero size section
1360 return true; // whole section is one atom with no label
1363 while ( (symIndex
< sortedSymbolCount
) && (cfiIndex
< cfiStartsCount
) ) {
1364 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(sortedSymbolIndexes
[symIndex
]);
1365 pint_t nextSymbolAddr
= sym
.n_value();
1366 pint_t nextCfiAddr
= cfiStartsArray
[cfiIndex
];
1367 if ( nextSymbolAddr
< nextCfiAddr
) {
1368 if ( nextSymbolAddr
>= endAddr
)
1371 if ( nextSymbolAddr
< startAddr
)
1373 *addr
= nextSymbolAddr
;
1374 *size
= peek(parser
, startAddr
, endAddr
) - nextSymbolAddr
;
1378 else if ( nextCfiAddr
< nextSymbolAddr
) {
1379 if ( nextCfiAddr
>= endAddr
)
1382 if ( nextCfiAddr
< startAddr
)
1384 *addr
= nextCfiAddr
;
1385 *size
= peek(parser
, startAddr
, endAddr
) - nextCfiAddr
;
1390 if ( nextCfiAddr
>= endAddr
)
1394 if ( nextCfiAddr
< startAddr
)
1396 *addr
= nextCfiAddr
;
1397 *size
= peek(parser
, startAddr
, endAddr
) - nextCfiAddr
;
1402 while ( symIndex
< sortedSymbolCount
) {
1403 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(sortedSymbolIndexes
[symIndex
]);
1404 pint_t nextSymbolAddr
= sym
.n_value();
1405 // if next symbol found is not in this section, then done with iteration
1406 if ( sym
.n_sect() != sectNum
)
1409 if ( nextSymbolAddr
< startAddr
)
1411 *addr
= nextSymbolAddr
;
1412 *size
= peek(parser
, startAddr
, endAddr
) - nextSymbolAddr
;
1416 while ( cfiIndex
< cfiStartsCount
) {
1417 pint_t nextCfiAddr
= cfiStartsArray
[cfiIndex
];
1418 if ( nextCfiAddr
>= endAddr
)
1421 if ( nextCfiAddr
< startAddr
)
1423 *addr
= nextCfiAddr
;
1424 *size
= peek(parser
, startAddr
, endAddr
) - nextCfiAddr
;
1433 template <typename A
>
1434 ld::relocatable::File
* Parser
<A
>::parse(const ParserOptions
& opts
)
1436 // create file object
1437 _file
= new File
<A
>(_path
, _modTime
, _fileContent
, _ordinal
);
1439 // respond to -t option
1440 if ( opts
.logAllFiles
)
1441 printf("%s\n", _path
);
1443 // parse start of mach-o file
1444 if ( ! parseLoadCommands() )
1447 // make symbol table sorted by address
1448 this->checkForLSDA();
1449 this->prescanSymbolTable();
1450 uint32_t sortedSymbolIndexes
[_symbolsInSections
];
1451 this->makeSortedSymbolsArray(sortedSymbolIndexes
);
1453 // allocate Section<A> object for each mach-o section
1456 // if it exists, do special parsing of __eh_frame section
1457 // stack allocate array of CFI_Atom_Info
1458 uint32_t countOfCFIs
= 0;
1459 if ( _EHFrameSection
!= NULL
)
1460 countOfCFIs
= _EHFrameSection
->cfiCount();
1461 typename CFISection
<A
>::CFI_Atom_Info cfiArray
[countOfCFIs
];
1462 // stack allocate (if not too large) a copy of __eh_frame to apply relocations to
1463 uint8_t* ehBuffer
= NULL
;
1464 uint32_t stackAllocSize
= 0;
1465 if ( (countOfCFIs
!= 0) && _EHFrameSection
->needsRelocating() ) {
1466 uint32_t sectSize
= _EHFrameSection
->machoSection()->size();
1467 if ( sectSize
> 50*1024 )
1468 ehBuffer
= (uint8_t*)malloc(sectSize
);
1470 stackAllocSize
= sectSize
;
1472 uint32_t ehStackBuffer
[1+stackAllocSize
/4]; // make 4-byte aligned stack bufffer
1473 if ( ehBuffer
== NULL
)
1474 ehBuffer
= (uint8_t*)&ehStackBuffer
;
1475 uint32_t cfiStartsCount
= 0;
1476 if ( countOfCFIs
!= 0 ) {
1477 _EHFrameSection
->cfiParse(*this, ehBuffer
, cfiArray
, countOfCFIs
);
1478 // count functions and lsdas
1479 for(uint32_t i
=0; i
< countOfCFIs
; ++i
) {
1480 if ( cfiArray
[i
].isCIE
)
1482 //fprintf(stderr, "cfiArray[i].func = 0x%08llX, cfiArray[i].lsda = 0x%08llX, encoding=0x%08X\n",
1483 // (uint64_t)cfiArray[i].u.fdeInfo.function.targetAddress,
1484 // (uint64_t)cfiArray[i].u.fdeInfo.lsda.targetAddress,
1485 // cfiArray[i].u.fdeInfo.compactUnwindInfo);
1486 if ( cfiArray
[i
].u
.fdeInfo
.function
.targetAddress
!= CFI_INVALID_ADDRESS
)
1488 if ( cfiArray
[i
].u
.fdeInfo
.lsda
.targetAddress
!= CFI_INVALID_ADDRESS
)
1492 CFIInfoArray
cfis(cfiArray
, countOfCFIs
);
1494 // create sorted array of function starts and lsda starts
1495 pint_t cfiStartsArray
[cfiStartsCount
];
1496 uint32_t countOfFDEs
= 0;
1497 if ( countOfCFIs
!= 0 ) {
1499 for(uint32_t i
=0; i
< countOfCFIs
; ++i
) {
1500 if ( cfiArray
[i
].isCIE
)
1502 if ( cfiArray
[i
].u
.fdeInfo
.function
.targetAddress
!= CFI_INVALID_ADDRESS
)
1503 cfiStartsArray
[index
++] = cfiArray
[i
].u
.fdeInfo
.function
.targetAddress
;
1504 if ( cfiArray
[i
].u
.fdeInfo
.lsda
.targetAddress
!= CFI_INVALID_ADDRESS
)
1505 cfiStartsArray
[index
++] = cfiArray
[i
].u
.fdeInfo
.lsda
.targetAddress
;
1508 ::qsort(cfiStartsArray
, cfiStartsCount
, sizeof(pint_t
), pointerSorter
);
1510 // scan for FDEs claming the same function
1511 for(int i
=1; i
< index
; ++i
) {
1512 assert( cfiStartsArray
[i
] != cfiStartsArray
[i
-1] );
1517 Section
<A
>** sections
= _file
->_sectionsArray
;
1518 uint32_t sectionsCount
= _file
->_sectionsArrayCount
;
1520 // figure out how many atoms will be allocated and allocate
1521 LabelAndCFIBreakIterator
breakIterator(sortedSymbolIndexes
, _symbolsInSections
, cfiStartsArray
,
1522 cfiStartsCount
, _overlappingSymbols
);
1523 uint32_t computedAtomCount
= 0;
1524 for (uint32_t i
=0; i
< sectionsCount
; ++i
) {
1525 breakIterator
.beginSection();
1526 uint32_t count
= sections
[i
]->computeAtomCount(*this, breakIterator
, cfis
);
1527 //const macho_section<P>* sect = sections[i]->machoSection();
1528 //fprintf(stderr, "computed count=%u for section %s size=%llu\n", count, sect->sectname(), (sect != NULL) ? sect->size() : 0);
1529 computedAtomCount
+= count
;
1531 //fprintf(stderr, "allocating %d atoms * sizeof(Atom<A>)=%ld, sizeof(ld::Atom)=%ld\n", computedAtomCount, sizeof(Atom<A>), sizeof(ld::Atom));
1532 _file
->_atomsArray
= new uint8_t[computedAtomCount
*sizeof(Atom
<A
>)];
1533 _file
->_atomsArrayCount
= 0;
1535 // have each section append atoms to _atomsArray
1536 LabelAndCFIBreakIterator
breakIterator2(sortedSymbolIndexes
, _symbolsInSections
, cfiStartsArray
,
1537 cfiStartsCount
, _overlappingSymbols
);
1538 for (uint32_t i
=0; i
< sectionsCount
; ++i
) {
1539 uint8_t* atoms
= _file
->_atomsArray
+ _file
->_atomsArrayCount
*sizeof(Atom
<A
>);
1540 breakIterator2
.beginSection();
1541 uint32_t count
= sections
[i
]->appendAtoms(*this, atoms
, breakIterator2
, cfis
);
1542 //fprintf(stderr, "append count=%u for section %s\n", count, sections[i]->machoSection()->sectname());
1543 _file
->_atomsArrayCount
+= count
;
1545 assert( _file
->_atomsArrayCount
== computedAtomCount
&& "more atoms allocated than expected");
1548 // have each section add all fix-ups for its atoms
1549 _allFixups
.reserve(computedAtomCount
*5);
1550 for (uint32_t i
=0; i
< sectionsCount
; ++i
)
1551 sections
[i
]->makeFixups(*this, cfis
);
1553 // assign fixups start offset for each atom
1554 uint8_t* p
= _file
->_atomsArray
;
1555 uint32_t fixupOffset
= 0;
1556 for(int i
=_file
->_atomsArrayCount
; i
> 0; --i
) {
1557 Atom
<A
>* atom
= (Atom
<A
>*)p
;
1558 atom
->_fixupsStartIndex
= fixupOffset
;
1559 fixupOffset
+= atom
->_fixupsCount
;
1560 atom
->_fixupsCount
= 0;
1561 p
+= sizeof(Atom
<A
>);
1563 assert(fixupOffset
== _allFixups
.size());
1564 _file
->_fixups
.reserve(fixupOffset
);
1566 // copy each fixup for each atom
1567 for(typename
std::vector
<FixupInAtom
>::iterator it
=_allFixups
.begin(); it
!= _allFixups
.end(); ++it
) {
1568 uint32_t slot
= it
->atom
->_fixupsStartIndex
+ it
->atom
->_fixupsCount
;
1569 _file
->_fixups
[slot
] = it
->fixup
;
1570 it
->atom
->_fixupsCount
++;
1573 // done with temp vector
1577 _file
->_unwindInfos
.reserve(countOfFDEs
);
1578 for(uint32_t i
=0; i
< countOfCFIs
; ++i
) {
1579 if ( cfiArray
[i
].isCIE
)
1581 if ( cfiArray
[i
].u
.fdeInfo
.function
.targetAddress
!= CFI_INVALID_ADDRESS
) {
1582 ld::Atom::UnwindInfo info
;
1583 info
.startOffset
= 0;
1584 info
.unwindInfo
= cfiArray
[i
].u
.fdeInfo
.compactUnwindInfo
;
1585 _file
->_unwindInfos
.push_back(info
);
1586 Atom
<A
>* func
= findAtomByAddress(cfiArray
[i
].u
.fdeInfo
.function
.targetAddress
);
1587 func
->setUnwindInfoRange(_file
->_unwindInfos
.size()-1, 1);
1591 // parse dwarf debug info to get line info
1592 this->parseDebugInfo();
1599 template <> uint8_t Parser
<ppc
>::loadCommandSizeMask() { return 0x03; }
1600 template <> uint8_t Parser
<ppc64
>::loadCommandSizeMask() { return 0x07; }
1601 template <> uint8_t Parser
<x86
>::loadCommandSizeMask() { return 0x03; }
1602 template <> uint8_t Parser
<x86_64
>::loadCommandSizeMask() { return 0x07; }
1603 template <> uint8_t Parser
<arm
>::loadCommandSizeMask() { return 0x03; }
1605 template <typename A
>
1606 bool Parser
<A
>::parseLoadCommands()
1608 const macho_header
<P
>* header
= (const macho_header
<P
>*)_fileContent
;
1610 // set File attributes
1611 _file
->_canScatterAtoms
= (header
->flags() & MH_SUBSECTIONS_VIA_SYMBOLS
);
1612 _file
->_cpuSubType
= header
->cpusubtype();
1614 const macho_segment_command
<P
>* segment
= NULL
;
1615 const uint8_t* const endOfFile
= _fileContent
+ _fileLength
;
1616 const uint32_t cmd_count
= header
->ncmds();
1617 // <rdar://problem/5394172> an empty .o file with zero load commands will crash linker
1618 if ( cmd_count
== 0 )
1620 const macho_load_command
<P
>* const cmds
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>));
1621 const macho_load_command
<P
>* const cmdsEnd
= (macho_load_command
<P
>*)((char*)header
+ sizeof(macho_header
<P
>) + header
->sizeofcmds());
1622 const macho_load_command
<P
>* cmd
= cmds
;
1623 for (uint32_t i
= 0; i
< cmd_count
; ++i
) {
1624 uint32_t size
= cmd
->cmdsize();
1625 if ( (size
& this->loadCommandSizeMask()) != 0 )
1626 throwf("load command #%d has a unaligned size", i
);
1627 const uint8_t* endOfCmd
= ((uint8_t*)cmd
)+cmd
->cmdsize();
1628 if ( endOfCmd
> (uint8_t*)cmdsEnd
)
1629 throwf("load command #%d extends beyond the end of the load commands", i
);
1630 if ( endOfCmd
> endOfFile
)
1631 throwf("load command #%d extends beyond the end of the file", i
);
1632 switch (cmd
->cmd()) {
1635 const macho_symtab_command
<P
>* symtab
= (macho_symtab_command
<P
>*)cmd
;
1636 _symbolCount
= symtab
->nsyms();
1637 _symbols
= (const macho_nlist
<P
>*)(_fileContent
+ symtab
->symoff());
1638 _strings
= (char*)_fileContent
+ symtab
->stroff();
1639 _stringsSize
= symtab
->strsize();
1640 if ( (symtab
->symoff() + _symbolCount
*sizeof(macho_nlist
<P
>)) > _fileLength
)
1641 throw "mach-o symbol table extends beyond end of file";
1642 if ( (_strings
+ _stringsSize
) > (char*)endOfFile
)
1643 throw "mach-o string pool extends beyond end of file";
1644 if ( _indirectTable
== NULL
) {
1645 if ( _undefinedEndIndex
== 0 ) {
1646 _undefinedStartIndex
= 0;
1647 _undefinedEndIndex
= symtab
->nsyms();
1654 const macho_dysymtab_command
<P
>* dsymtab
= (macho_dysymtab_command
<P
>*)cmd
;
1655 _indirectTable
= (uint32_t*)(_fileContent
+ dsymtab
->indirectsymoff());
1656 _indirectTableCount
= dsymtab
->nindirectsyms();
1657 if ( &_indirectTable
[_indirectTableCount
] > (uint32_t*)endOfFile
)
1658 throw "indirect symbol table extends beyond end of file";
1659 _undefinedStartIndex
= dsymtab
->iundefsym();
1660 _undefinedEndIndex
= _undefinedStartIndex
+ dsymtab
->nundefsym();
1668 if ( cmd
->cmd() == macho_segment_command
<P
>::CMD
) {
1669 if ( segment
!= NULL
)
1670 throw "more than one LC_SEGMENT found in object file";
1671 segment
= (macho_segment_command
<P
>*)cmd
;
1675 cmd
= (const macho_load_command
<P
>*)(((char*)cmd
)+cmd
->cmdsize());
1676 if ( cmd
> cmdsEnd
)
1677 throwf("malformed mach-o file, load command #%d is outside size of load commands", i
);
1680 // record range of sections
1681 if ( segment
== NULL
)
1682 throw "missing LC_SEGMENT";
1683 _sectionsStart
= (macho_section
<P
>*)((char*)segment
+ sizeof(macho_segment_command
<P
>));
1684 _machOSectionsCount
= segment
->nsects();
1690 void Parser
<arm
>::checkForLSDA()
1692 // ARM has no FDEs, so need labels to break up section into atoms
1695 template <typename A
>
1696 void Parser
<A
>::checkForLSDA()
1698 // ignore labels on __gcc_except_tab section, we'll break it into atoms based on FDE info
1699 for (uint32_t i
=0; i
< _machOSectionsCount
; ++i
) {
1700 const macho_section
<P
>* sect
= &_sectionsStart
[i
];
1701 if ( strncmp(sect
->sectname(), "__gcc_except_tab", 16) == 0 ) {
1702 if ( strcmp(sect
->segname(), "__TEXT") == 0 ) {
1703 assert(_lsdaTextSectionNum
== 0);
1704 _lsdaTextSectionNum
= i
+1;
1706 else if ( strcmp(sect
->segname(), "__DATA") == 0 ) {
1707 assert(_lsdaDataSectionNum
== 0);
1708 _lsdaDataSectionNum
= i
+1;
1715 template <typename A
>
1716 void Parser
<A
>::prescanSymbolTable()
1718 _tentativeDefinitionCount
= 0;
1719 _absoluteSymbolCount
= 0;
1720 _symbolsInSections
= 0;
1721 for (uint32_t i
=0; i
< this->_symbolCount
; ++i
) {
1722 const macho_nlist
<P
>& sym
= symbolFromIndex(i
);
1724 if ( (sym
.n_type() & N_STAB
) != 0 )
1727 // look at undefines
1728 const char* symbolName
= this->nameFromSymbol(sym
);
1729 if ( (sym
.n_type() & N_TYPE
) == N_UNDF
) {
1730 if ( sym
.n_value() != 0 ) {
1731 // count tentative definitions
1732 ++_tentativeDefinitionCount
;
1734 else if ( strncmp(symbolName
, "___dtrace_", 10) == 0 ) {
1735 // any undefined starting with __dtrace_*$ that is not ___dtrace_probe$* or ___dtrace_isenabled$*
1736 // is extra provider info
1737 if ( (strncmp(&symbolName
[10], "probe$", 6) != 0) && (strncmp(&symbolName
[10], "isenabled$", 10) != 0) ) {
1738 _dtraceProviderInfo
.push_back(symbolName
);
1744 // count absolute symbols
1745 if ( (sym
.n_type() & N_TYPE
) == N_ABS
) {
1746 const char* absName
= this->nameFromSymbol(sym
);
1747 // ignore .objc_class_name_* symbols
1748 if ( strncmp(absName
, ".objc_class_name_", 17) == 0 ) {
1752 // ignore .objc_class_name_* symbols
1753 if ( strncmp(absName
, ".objc_category_name_", 20) == 0 )
1755 // ignore empty *.eh symbols
1756 if ( strcmp(&absName
[strlen(absName
)-3], ".eh") == 0 )
1758 ++_absoluteSymbolCount
;
1761 // only look at definitions
1762 if ( (sym
.n_type() & N_TYPE
) != N_SECT
)
1765 // 'L' labels do not denote atom breaks
1766 if ( symbolName
[0] == 'L' )
1769 // ignore labels in __gcc_except_tab section
1770 if ( (_lsdaTextSectionNum
!= 0) && (sym
.n_sect() == _lsdaTextSectionNum
) )
1772 if ( (_lsdaDataSectionNum
!= 0) && (sym
.n_sect() == _lsdaDataSectionNum
) )
1775 // how many def syms in each section
1776 if ( sym
.n_sect() > _machOSectionsCount
)
1777 throw "bad n_sect in symbol table";
1779 _symbolsInSections
++;
1783 template <typename A
>
1784 int Parser
<A
>::symbolIndexSorter(void* extra
, const void* l
, const void* r
)
1786 Parser
<A
>* parser
= (Parser
<A
>*)extra
;
1787 const uint32_t* left
= (uint32_t*)l
;
1788 const uint32_t* right
= (uint32_t*)r
;
1789 const macho_nlist
<P
>& leftSym
= parser
->symbolFromIndex(*left
);
1790 const macho_nlist
<P
>& rightSym
= parser
->symbolFromIndex(*right
);
1791 // can't just return difference because 64-bit diff does not fit in 32-bit return type
1792 int64_t result
= leftSym
.n_value() - rightSym
.n_value();
1793 if ( result
== 0 ) {
1794 // two symbols with same address
1795 // if in different sections, sort earlier section first
1796 if ( leftSym
.n_sect() != rightSym
.n_sect() )
1797 return (leftSym
.n_sect() - rightSym
.n_sect());
1798 //, means one is an alias
1799 // if only one is global, make the other an alias (sort first)
1800 if ( (leftSym
.n_type() & N_EXT
) != (rightSym
.n_type() & N_EXT
) ) {
1801 if ( (rightSym
.n_type() & N_EXT
) != 0 )
1806 // if both are global, make alphabetically last one be the alias
1807 return ( strcmp(parser
->nameFromSymbol(rightSym
), parser
->nameFromSymbol(leftSym
)) );
1809 else if ( result
< 0 )
1815 template <typename A
>
1816 void Parser
<A
>::makeSortedSymbolsArray(uint32_t array
[])
1818 uint32_t* p
= array
;
1819 for (uint32_t i
=0; i
< this->_symbolCount
; ++i
) {
1820 const macho_nlist
<P
>& sym
= symbolFromIndex(i
);
1822 if ( (sym
.n_type() & N_STAB
) != 0 )
1825 // only look at definitions
1826 if ( (sym
.n_type() & N_TYPE
) != N_SECT
)
1829 // 'L' labels do not denote atom breaks
1830 const char* symbolName
= this->nameFromSymbol(sym
);
1831 if ( symbolName
[0] == 'L' )
1834 // ignore labels in __gcc_except_tab section
1835 if ( (_lsdaTextSectionNum
!= 0) && (sym
.n_sect() == _lsdaTextSectionNum
) )
1837 if ( (_lsdaDataSectionNum
!= 0) && (sym
.n_sect() == _lsdaDataSectionNum
) )
1840 // how many def syms in each section
1841 if ( sym
.n_sect() > _machOSectionsCount
)
1842 throw "bad n_sect in symbol table";
1847 assert(p
== &array
[_symbolsInSections
] && "second pass over symbol table yield a different number of symbols");
1849 // sort by symbol table address
1850 ::qsort_r(array
, _symbolsInSections
, sizeof(uint32_t), this, &symbolIndexSorter
);
1852 // look for two symbols at same address
1853 _overlappingSymbols
= false;
1854 for (unsigned int i
=1; i
< _symbolsInSections
; ++i
) {
1855 if ( symbolFromIndex(array
[i
-1]).n_value() == symbolFromIndex(array
[i
]).n_value() ) {
1856 //fprintf(stderr, "overlapping symbols at 0x%08llX\n", symbolFromIndex(array[i-1]).n_value());
1857 _overlappingSymbols
= true;
1861 //fprintf(stderr, "sorted symbols:\n");
1862 //for(unsigned int i=0; i < _symbolsInSections; ++i )
1863 // fprintf(stderr, "0x%09llX symIndex=%3d sectNum=%2d, %s\n", symbolFromIndex(array[i]).n_value(), array[i], symbolFromIndex(array[i]).n_sect(), nameFromSymbol(symbolFromIndex(array[i])) );
1867 template <typename A
>
1868 void Parser
<A
>::makeSections()
1870 // classify each section by type
1871 // compute how many Section objects will be needed and total size for all
1872 unsigned int totalSectionsSize
= 0;
1873 uint8_t machOSectsStorage
[sizeof(MachOSectionAndSectionClass
<P
>)*(_machOSectionsCount
+2)]; // also room for tentative-defs and absolute symbols
1874 // allocate raw storage for all section objects on stack
1875 MachOSectionAndSectionClass
<P
>* machOSects
= (MachOSectionAndSectionClass
<P
>*)machOSectsStorage
;
1876 unsigned int count
= 0;
1877 for (uint32_t i
=0; i
< _machOSectionsCount
; ++i
) {
1878 const macho_section
<P
>* sect
= &_sectionsStart
[i
];
1879 // ignore dwarf sections
1880 if ( (sect
->flags() & S_ATTR_DEBUG
) != 0 ) {
1881 // note that .o file has dwarf
1882 _file
->_debugInfoKind
= ld::relocatable::File::kDebugInfoDwarf
;
1883 // save off iteresting dwarf sections
1884 if ( strcmp(sect
->sectname(), "__debug_info") == 0 )
1885 _file
->_dwarfDebugInfoSect
= sect
;
1886 else if ( strcmp(sect
->sectname(), "__debug_abbrev") == 0 )
1887 _file
->_dwarfDebugAbbrevSect
= sect
;
1888 else if ( strcmp(sect
->sectname(), "__debug_line") == 0 )
1889 _file
->_dwarfDebugLineSect
= sect
;
1890 else if ( strcmp(sect
->sectname(), "__debug_str") == 0 )
1891 _file
->_dwarfDebugStringSect
= sect
;
1892 // linker does not propagate dwarf sections to output file
1895 // ignore empty __OBJC sections
1896 if ( (sect
->size() == 0) && (strcmp(sect
->segname(), "__OBJC") == 0) )
1898 // objc image info section is really attributes and not content
1899 if ( ((strcmp(sect
->sectname(), "__image_info") == 0) && (strcmp(sect
->segname(), "__OBJC") == 0))
1900 || ((strncmp(sect
->sectname(), "__objc_imageinfo", 16) == 0) && (strcmp(sect
->segname(), "__DATA") == 0)) ) {
1901 // struct objc_image_info {
1902 // uint32_t version; // initially 0
1905 // #define OBJC_IMAGE_SUPPORTS_GC 2
1906 // #define OBJC_IMAGE_GC_ONLY 4
1908 const uint32_t* contents
= (uint32_t*)(_file
->fileContent()+sect
->offset());
1909 if ( (sect
->size() >= 8) && (contents
[0] == 0) ) {
1910 uint32_t flags
= E::get32(contents
[1]);
1911 if ( (flags
& 4) == 4 )
1912 _file
->_objConstraint
= ld::File::objcConstraintGC
;
1913 else if ( (flags
& 2) == 2 )
1914 _file
->_objConstraint
= ld::File::objcConstraintRetainReleaseOrGC
;
1916 _file
->_objConstraint
= ld::File::objcConstraintRetainRelease
;
1917 if ( (flags
& 1) == 1 )
1918 _file
->_ojcReplacmentClass
= true;
1919 if ( sect
->size() > 8 ) {
1920 warning("section %s/%s has unexpectedly large size %llu in %s",
1921 sect
->segname(), sect
->sectname(), sect
->size(), _file
->path());
1925 warning("can't parse %s/%s section in %s", sect
->segname(), sect
->sectname(), _file
->path());
1929 machOSects
[count
].sect
= sect
;
1930 switch ( sect
->flags() & SECTION_TYPE
) {
1931 case S_SYMBOL_STUBS
:
1932 if ( _stubsSectionNum
== 0 ) {
1933 _stubsSectionNum
= i
+1;
1934 _stubsMachOSection
= sect
;
1937 assert(1 && "multiple S_SYMBOL_STUBS sections");
1938 case S_LAZY_SYMBOL_POINTERS
:
1940 case S_4BYTE_LITERALS
:
1941 totalSectionsSize
+= sizeof(Literal4Section
<A
>);
1942 machOSects
[count
++].type
= sectionTypeLiteral4
;
1944 case S_8BYTE_LITERALS
:
1945 totalSectionsSize
+= sizeof(Literal8Section
<A
>);
1946 machOSects
[count
++].type
= sectionTypeLiteral8
;
1948 case S_16BYTE_LITERALS
:
1949 totalSectionsSize
+= sizeof(Literal16Section
<A
>);
1950 machOSects
[count
++].type
= sectionTypeLiteral16
;
1952 case S_NON_LAZY_SYMBOL_POINTERS
:
1953 totalSectionsSize
+= sizeof(NonLazyPointerSection
<A
>);
1954 machOSects
[count
++].type
= sectionTypeNonLazy
;
1956 case S_LITERAL_POINTERS
:
1957 if ( (strcmp(sect
->segname(), "__OBJC") == 0) && (strcmp(sect
->sectname(), "__cls_refs") == 0) ) {
1958 totalSectionsSize
+= sizeof(Objc1ClassReferences
<A
>);
1959 machOSects
[count
++].type
= sectionTypeObjC1ClassRefs
;
1962 totalSectionsSize
+= sizeof(PointerToCStringSection
<A
>);
1963 machOSects
[count
++].type
= sectionTypeCStringPointer
;
1966 case S_CSTRING_LITERALS
:
1967 totalSectionsSize
+= sizeof(CStringSection
<A
>);
1968 machOSects
[count
++].type
= sectionTypeCString
;
1970 case S_MOD_INIT_FUNC_POINTERS
:
1971 case S_MOD_TERM_FUNC_POINTERS
:
1972 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS
:
1977 case S_THREAD_LOCAL_REGULAR
:
1978 case S_THREAD_LOCAL_ZEROFILL
:
1979 if ( (strcmp(sect
->segname(), "__TEXT") == 0) && (strcmp(sect
->sectname(), "__eh_frame") == 0) ) {
1980 totalSectionsSize
+= sizeof(CFISection
<A
>);
1981 machOSects
[count
++].type
= sectionTypeCFI
;
1983 else if ( (strcmp(sect
->segname(), "__DATA") == 0) && (strcmp(sect
->sectname(), "__cfstring") == 0) ) {
1984 totalSectionsSize
+= sizeof(CFStringSection
<A
>);
1985 machOSects
[count
++].type
= sectionTypeCFString
;
1987 else if ( (strcmp(sect
->segname(), "__TEXT") == 0) && (strcmp(sect
->sectname(), "__ustring") == 0) ) {
1988 totalSectionsSize
+= sizeof(UTF16StringSection
<A
>);
1989 machOSects
[count
++].type
= sectionTypeUTF16Strings
;
1991 else if ( (strcmp(sect
->segname(), "__DATA") == 0) && (strncmp(sect
->sectname(), "__objc_classrefs", 16) == 0) ) {
1992 totalSectionsSize
+= sizeof(ObjC2ClassRefsSection
<A
>);
1993 machOSects
[count
++].type
= sectionTypeObjC2ClassRefs
;
1995 else if ( (strcmp(sect
->segname(), "__DATA") == 0) && (strcmp(sect
->sectname(), "__objc_catlist") == 0) ) {
1996 totalSectionsSize
+= sizeof(ObjC2CategoryListSection
<A
>);
1997 machOSects
[count
++].type
= typeObjC2CategoryList
;
1999 else if ( _AppleObjc
&& (strcmp(sect
->segname(), "__OBJC") == 0) && (strcmp(sect
->sectname(), "__class") == 0) ) {
2000 totalSectionsSize
+= sizeof(ObjC1ClassSection
<A
>);
2001 machOSects
[count
++].type
= sectionTypeObjC1Classes
;
2004 totalSectionsSize
+= sizeof(SymboledSection
<A
>);
2005 machOSects
[count
++].type
= sectionTypeSymboled
;
2008 case S_THREAD_LOCAL_VARIABLES
:
2009 totalSectionsSize
+= sizeof(TLVDefsSection
<A
>);
2010 machOSects
[count
++].type
= sectionTypeTLVDefs
;
2012 case S_THREAD_LOCAL_VARIABLE_POINTERS
:
2014 throwf("unknown section type %d", sect
->flags() & SECTION_TYPE
);
2018 // sort by address (mach-o object files don't aways have sections sorted)
2019 ::qsort(machOSects
, count
, sizeof(MachOSectionAndSectionClass
<P
>), MachOSectionAndSectionClass
<P
>::sorter
);
2021 // we will synthesize a dummy Section<A> object for tentative definitions
2022 if ( _tentativeDefinitionCount
> 0 ) {
2023 totalSectionsSize
+= sizeof(TentativeDefinitionSection
<A
>);
2024 machOSects
[count
++].type
= sectionTypeTentativeDefinitions
;
2027 // we will synthesize a dummy Section<A> object for Absolute symbols
2028 if ( _absoluteSymbolCount
> 0 ) {
2029 totalSectionsSize
+= sizeof(AbsoluteSymbolSection
<A
>);
2030 machOSects
[count
++].type
= sectionTypeAbsoluteSymbols
;
2033 // allocate one block for all Section objects as well as pointers to each
2034 uint8_t* space
= new uint8_t[totalSectionsSize
+count
*sizeof(Section
<A
>*)];
2035 _file
->_sectionsArray
= (Section
<A
>**)space
;
2036 _file
->_sectionsArrayCount
= count
;
2037 Section
<A
>** objects
= _file
->_sectionsArray
;
2038 space
+= count
*sizeof(Section
<A
>*);
2039 for (uint32_t i
=0; i
< count
; ++i
) {
2040 switch ( machOSects
[i
].type
) {
2041 case sectionTypeIgnore
:
2043 case sectionTypeLiteral4
:
2044 *objects
++ = new (space
) Literal4Section
<A
>(*this, *_file
, machOSects
[i
].sect
);
2045 space
+= sizeof(Literal4Section
<A
>);
2047 case sectionTypeLiteral8
:
2048 *objects
++ = new (space
) Literal8Section
<A
>(*this, *_file
, machOSects
[i
].sect
);
2049 space
+= sizeof(Literal8Section
<A
>);
2051 case sectionTypeLiteral16
:
2052 *objects
++ = new (space
) Literal16Section
<A
>(*this, *_file
, machOSects
[i
].sect
);
2053 space
+= sizeof(Literal16Section
<A
>);
2055 case sectionTypeNonLazy
:
2056 *objects
++ = new (space
) NonLazyPointerSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2057 space
+= sizeof(NonLazyPointerSection
<A
>);
2059 case sectionTypeCFI
:
2060 _EHFrameSection
= new (space
) CFISection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2061 *objects
++ = _EHFrameSection
;
2062 space
+= sizeof(CFISection
<A
>);
2064 case sectionTypeCString
:
2065 *objects
++ = new (space
) CStringSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2066 space
+= sizeof(CStringSection
<A
>);
2068 case sectionTypeCStringPointer
:
2069 *objects
++ = new (space
) PointerToCStringSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2070 space
+= sizeof(PointerToCStringSection
<A
>);
2072 case sectionTypeObjC1ClassRefs
:
2073 *objects
++ = new (space
) Objc1ClassReferences
<A
>(*this, *_file
, machOSects
[i
].sect
);
2074 space
+= sizeof(Objc1ClassReferences
<A
>);
2076 case sectionTypeUTF16Strings
:
2077 *objects
++ = new (space
) UTF16StringSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2078 space
+= sizeof(UTF16StringSection
<A
>);
2080 case sectionTypeCFString
:
2081 *objects
++ = new (space
) CFStringSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2082 space
+= sizeof(CFStringSection
<A
>);
2084 case sectionTypeObjC2ClassRefs
:
2085 *objects
++ = new (space
) ObjC2ClassRefsSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2086 space
+= sizeof(ObjC2ClassRefsSection
<A
>);
2088 case typeObjC2CategoryList
:
2089 *objects
++ = new (space
) ObjC2CategoryListSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2090 space
+= sizeof(ObjC2CategoryListSection
<A
>);
2092 case sectionTypeObjC1Classes
:
2093 *objects
++ = new (space
) ObjC1ClassSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2094 space
+= sizeof(ObjC1ClassSection
<A
>);
2096 case sectionTypeSymboled
:
2097 *objects
++ = new (space
) SymboledSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2098 space
+= sizeof(SymboledSection
<A
>);
2100 case sectionTypeTLVDefs
:
2101 *objects
++ = new (space
) TLVDefsSection
<A
>(*this, *_file
, machOSects
[i
].sect
);
2102 space
+= sizeof(TLVDefsSection
<A
>);
2104 case sectionTypeTentativeDefinitions
:
2105 *objects
++ = new (space
) TentativeDefinitionSection
<A
>(*this, *_file
);
2106 space
+= sizeof(TentativeDefinitionSection
<A
>);
2108 case sectionTypeAbsoluteSymbols
:
2109 _absoluteSection
= new (space
) AbsoluteSymbolSection
<A
>(*this, *_file
);
2110 *objects
++ = _absoluteSection
;
2111 space
+= sizeof(AbsoluteSymbolSection
<A
>);
2114 throw "internal error uknown SectionType";
2120 template <typename A
>
2121 Section
<A
>* Parser
<A
>::sectionForAddress(typename
A::P::uint_t addr
)
2123 for (uint32_t i
=0; i
< _file
->_sectionsArrayCount
; ++i
) {
2124 const macho_section
<typename
A::P
>* sect
= _file
->_sectionsArray
[i
]->machoSection();
2125 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2126 if ( sect
!= NULL
) {
2127 if ( (sect
->addr() <= addr
) && (addr
< (sect
->addr()+sect
->size())) ) {
2128 return _file
->_sectionsArray
[i
];
2132 // not strictly in any section
2133 // may be in a zero length section
2134 for (uint32_t i
=0; i
< _file
->_sectionsArrayCount
; ++i
) {
2135 const macho_section
<typename
A::P
>* sect
= _file
->_sectionsArray
[i
]->machoSection();
2136 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2137 if ( sect
!= NULL
) {
2138 if ( (sect
->addr() == addr
) && (sect
->size() == 0) ) {
2139 return _file
->_sectionsArray
[i
];
2144 throwf("sectionForAddress(0x%llX) address not in any section", (uint64_t)addr
);
2147 template <typename A
>
2148 Section
<A
>* Parser
<A
>::sectionForNum(unsigned int num
)
2150 for (uint32_t i
=0; i
< _file
->_sectionsArrayCount
; ++i
) {
2151 const macho_section
<typename
A::P
>* sect
= _file
->_sectionsArray
[i
]->machoSection();
2152 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2153 if ( sect
!= NULL
) {
2154 if ( num
== (unsigned int)((sect
- _sectionsStart
)+1) )
2155 return _file
->_sectionsArray
[i
];
2158 throwf("sectionForNum(%u) section number not for any section", num
);
2161 template <typename A
>
2162 Atom
<A
>* Parser
<A
>::findAtomByAddress(pint_t addr
)
2164 Section
<A
>* section
= this->sectionForAddress(addr
);
2165 return section
->findAtomByAddress(addr
);
2168 template <typename A
>
2169 Atom
<A
>* Parser
<A
>::findAtomByAddressOrNullIfStub(pint_t addr
)
2171 if ( hasStubsSection() && (_stubsMachOSection
->addr() <= addr
) && (addr
< (_stubsMachOSection
->addr()+_stubsMachOSection
->size())) )
2173 return findAtomByAddress(addr
);
2176 template <typename A
>
2177 Atom
<A
>* Parser
<A
>::findAtomByAddressOrLocalTargetOfStub(pint_t addr
, uint32_t* offsetInAtom
)
2179 if ( hasStubsSection() && (_stubsMachOSection
->addr() <= addr
) && (addr
< (_stubsMachOSection
->addr()+_stubsMachOSection
->size())) ) {
2180 // target is a stub, remove indirection
2181 uint32_t symbolIndex
= this->symbolIndexFromIndirectSectionAddress(addr
, _stubsMachOSection
);
2182 assert(symbolIndex
!= INDIRECT_SYMBOL_LOCAL
);
2183 const macho_nlist
<P
>& sym
= this->symbolFromIndex(symbolIndex
);
2184 // can't be to external weak symbol
2185 assert( (this->combineFromSymbol(sym
) != ld::Atom::combineByName
) || (this->scopeFromSymbol(sym
) != ld::Atom::scopeGlobal
) );
2187 return this->findAtomByName(this->nameFromSymbol(sym
));
2189 Atom
<A
>* target
= this->findAtomByAddress(addr
);
2190 *offsetInAtom
= addr
- target
->_objAddress
;
2194 template <typename A
>
2195 Atom
<A
>* Parser
<A
>::findAtomByName(const char* name
)
2197 uint8_t* p
= _file
->_atomsArray
;
2198 for(int i
=_file
->_atomsArrayCount
; i
> 0; --i
) {
2199 Atom
<A
>* atom
= (Atom
<A
>*)p
;
2200 if ( strcmp(name
, atom
->name()) == 0 )
2202 p
+= sizeof(Atom
<A
>);
2207 template <typename A
>
2208 void Parser
<A
>::findTargetFromAddress(pint_t addr
, TargetDesc
& target
)
2210 if ( hasStubsSection() && (_stubsMachOSection
->addr() <= addr
) && (addr
< (_stubsMachOSection
->addr()+_stubsMachOSection
->size())) ) {
2211 // target is a stub, remove indirection
2212 uint32_t symbolIndex
= this->symbolIndexFromIndirectSectionAddress(addr
, _stubsMachOSection
);
2213 assert(symbolIndex
!= INDIRECT_SYMBOL_LOCAL
);
2214 const macho_nlist
<P
>& sym
= this->symbolFromIndex(symbolIndex
);
2216 target
.name
= this->nameFromSymbol(sym
);
2217 target
.weakImport
= this->weakImportFromSymbol(sym
);
2221 Section
<A
>* section
= this->sectionForAddress(addr
);
2222 target
.atom
= section
->findAtomByAddress(addr
);
2223 target
.addend
= addr
- target
.atom
->_objAddress
;
2224 target
.weakImport
= false;
2228 template <typename A
>
2229 void Parser
<A
>::findTargetFromAddress(pint_t baseAddr
, pint_t addr
, TargetDesc
& target
)
2231 findTargetFromAddress(baseAddr
, target
);
2232 target
.addend
= addr
- target
.atom
->_objAddress
;
2235 template <typename A
>
2236 void Parser
<A
>::findTargetFromAddressAndSectionNum(pint_t addr
, unsigned int sectNum
, TargetDesc
& target
)
2238 if ( sectNum
== R_ABS
) {
2239 // target is absolute symbol that corresponds to addr
2240 if ( _absoluteSection
!= NULL
) {
2241 target
.atom
= _absoluteSection
->findAbsAtomForValue(addr
);
2242 if ( target
.atom
!= NULL
) {
2244 target
.weakImport
= false;
2249 throwf("R_ABS reloc but no absolute symbol at target address");
2252 if ( hasStubsSection() && (stubsSectionNum() == sectNum
) ) {
2253 // target is a stub, remove indirection
2254 uint32_t symbolIndex
= this->symbolIndexFromIndirectSectionAddress(addr
, _stubsMachOSection
);
2255 assert(symbolIndex
!= INDIRECT_SYMBOL_LOCAL
);
2256 const macho_nlist
<P
>& sym
= this->symbolFromIndex(symbolIndex
);
2257 // use direct reference when stub is to a static function
2258 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && (((sym
.n_type() & N_EXT
) == 0) || (this->nameFromSymbol(sym
)[0] == 'L')) ) {
2259 this->findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), target
);
2263 target
.name
= this->nameFromSymbol(sym
);
2264 target
.weakImport
= this->weakImportFromSymbol(sym
);
2269 Section
<A
>* section
= this->sectionForNum(sectNum
);
2270 target
.atom
= section
->findAtomByAddress(addr
);
2271 if ( target
.atom
== NULL
) {
2272 typedef typename
A::P::sint_t sint_t
;
2273 sint_t a
= (sint_t
)addr
;
2274 sint_t sectStart
= (sint_t
)(section
->machoSection()->addr());
2275 sint_t sectEnd
= sectStart
+ section
->machoSection()->size();
2276 if ( a
< sectStart
) {
2277 // target address is before start of section, so must be negative addend
2278 target
.atom
= section
->findAtomByAddress(sectStart
);
2279 target
.addend
= a
- sectStart
;
2280 target
.weakImport
= false;
2284 else if ( a
>= sectEnd
) {
2285 target
.atom
= section
->findAtomByAddress(sectEnd
-1);
2286 target
.addend
= a
- sectEnd
;
2287 target
.weakImport
= false;
2292 assert(target
.atom
!= NULL
);
2293 target
.addend
= addr
- target
.atom
->_objAddress
;
2294 target
.weakImport
= false;
2298 template <typename A
>
2299 void Parser
<A
>::addDtraceExtraInfos(const SourceLocation
& src
, const char* providerName
)
2301 // for every ___dtrace_stability$* and ___dtrace_typedefs$* undefine with
2302 // a matching provider name, add a by-name kDtraceTypeReference at probe site
2303 const char* dollar
= strchr(providerName
, '$');
2304 if ( dollar
!= NULL
) {
2305 int providerNameLen
= dollar
-providerName
+1;
2306 for ( std::vector
<const char*>::iterator it
= _dtraceProviderInfo
.begin(); it
!= _dtraceProviderInfo
.end(); ++it
) {
2307 const char* typeDollar
= strchr(*it
, '$');
2308 if ( typeDollar
!= NULL
) {
2309 if ( strncmp(typeDollar
+1, providerName
, providerNameLen
) == 0 ) {
2310 addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindDtraceExtra
,false, *it
);
2317 template <typename A
>
2318 const char* Parser
<A
>::scanSymbolTableForAddress(uint64_t addr
)
2320 uint64_t closestSymAddr
= 0;
2321 const char* closestSymName
= NULL
;
2322 for (uint32_t i
=0; i
< this->_symbolCount
; ++i
) {
2323 const macho_nlist
<P
>& sym
= symbolFromIndex(i
);
2325 if ( (sym
.n_type() & N_STAB
) != 0 )
2328 // only look at definitions
2329 if ( (sym
.n_type() & N_TYPE
) != N_SECT
)
2332 // return with exact match
2333 if ( sym
.n_value() == addr
)
2334 return nameFromSymbol(sym
);
2336 // record closest seen so far
2337 if ( (sym
.n_value() < addr
) && ((sym
.n_value() > closestSymAddr
) || (closestSymName
== NULL
)) )
2338 closestSymName
= nameFromSymbol(sym
);
2341 return (closestSymName
!= NULL
) ? closestSymName
: "unknown";
2345 template <typename A
>
2346 void Parser
<A
>::addFixups(const SourceLocation
& src
, ld::Fixup::Kind setKind
, const TargetDesc
& target
)
2348 // some fixup pairs can be combined
2349 ld::Fixup::Cluster cl
= ld::Fixup::k1of3
;
2350 ld::Fixup::Kind firstKind
= ld::Fixup::kindSetTargetAddress
;
2351 bool combined
= false;
2352 if ( target
.addend
== 0 ) {
2353 cl
= ld::Fixup::k1of1
;
2355 switch ( setKind
) {
2356 case ld::Fixup::kindStoreLittleEndian32
:
2357 firstKind
= ld::Fixup::kindStoreTargetAddressLittleEndian32
;
2359 case ld::Fixup::kindStoreLittleEndian64
:
2360 firstKind
= ld::Fixup::kindStoreTargetAddressLittleEndian64
;
2362 case ld::Fixup::kindStoreBigEndian32
:
2363 firstKind
= ld::Fixup::kindStoreTargetAddressBigEndian32
;
2365 case ld::Fixup::kindStoreBigEndian64
:
2366 firstKind
= ld::Fixup::kindStoreTargetAddressBigEndian64
;
2368 case ld::Fixup::kindStoreX86BranchPCRel32
:
2369 firstKind
= ld::Fixup::kindStoreTargetAddressX86BranchPCRel32
;
2371 case ld::Fixup::kindStoreX86PCRel32
:
2372 firstKind
= ld::Fixup::kindStoreTargetAddressX86PCRel32
;
2374 case ld::Fixup::kindStoreX86PCRel32GOTLoad
:
2375 firstKind
= ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad
;
2377 case ld::Fixup::kindStoreX86PCRel32TLVLoad
:
2378 firstKind
= ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad
;
2380 case ld::Fixup::kindStoreX86Abs32TLVLoad
:
2381 firstKind
= ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad
;
2383 case ld::Fixup::kindStoreARMBranch24
:
2384 firstKind
= ld::Fixup::kindStoreTargetAddressARMBranch24
;
2386 case ld::Fixup::kindStoreThumbBranch22
:
2387 firstKind
= ld::Fixup::kindStoreTargetAddressThumbBranch22
;
2389 case ld::Fixup::kindStorePPCBranch24
:
2390 firstKind
= ld::Fixup::kindStoreTargetAddressPPCBranch24
;
2394 cl
= ld::Fixup::k1of2
;
2399 if ( target
.atom
!= NULL
) {
2400 if ( target
.atom
->scope() == ld::Atom::scopeTranslationUnit
) {
2401 addFixup(src
, cl
, firstKind
, target
.atom
);
2403 else if ( (target
.atom
->combine() == ld::Atom::combineByNameAndContent
) || (target
.atom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
2404 addFixup(src
, cl
, firstKind
, ld::Fixup::bindingByContentBound
, target
.atom
);
2406 else if ( (src
.atom
->section().type() == ld::Section::typeCFString
) && (src
.offsetInAtom
!= 0) ) {
2407 // backing string in CFStrings should always be direct
2408 addFixup(src
, cl
, firstKind
, target
.atom
);
2411 // change direct fixup to by-name fixup
2412 addFixup(src
, cl
, firstKind
, false, target
.atom
->name());
2416 addFixup(src
, cl
, firstKind
, target
.weakImport
, target
.name
);
2418 if ( target
.addend
== 0 ) {
2420 addFixup(src
, ld::Fixup::k2of2
, setKind
);
2423 addFixup(src
, ld::Fixup::k2of3
, ld::Fixup::kindAddAddend
, target
.addend
);
2424 addFixup(src
, ld::Fixup::k3of3
, setKind
);
2428 template <typename A
>
2429 void Parser
<A
>::addFixups(const SourceLocation
& src
, ld::Fixup::Kind kind
, const TargetDesc
& target
, const TargetDesc
& picBase
)
2431 ld::Fixup::Cluster cl
= (target
.addend
== 0) ? ld::Fixup::k1of4
: ld::Fixup::k1of5
;
2432 if ( target
.atom
!= NULL
) {
2433 if ( target
.atom
->scope() == ld::Atom::scopeTranslationUnit
) {
2434 addFixup(src
, cl
, ld::Fixup::kindSetTargetAddress
, target
.atom
);
2436 else if ( (target
.atom
->combine() == ld::Atom::combineByNameAndContent
) || (target
.atom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
2437 addFixup(src
, cl
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, target
.atom
);
2440 addFixup(src
, cl
, ld::Fixup::kindSetTargetAddress
, false, target
.atom
->name());
2444 addFixup(src
, cl
, ld::Fixup::kindSetTargetAddress
, target
.weakImport
, target
.name
);
2446 if ( target
.addend
== 0 ) {
2447 assert(picBase
.atom
!= NULL
);
2448 addFixup(src
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, picBase
.atom
);
2449 addFixup(src
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, picBase
.addend
);
2450 addFixup(src
, ld::Fixup::k4of4
, kind
);
2453 addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, target
.addend
);
2454 addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, picBase
.atom
);
2455 addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, picBase
.addend
);
2456 addFixup(src
, ld::Fixup::k5of5
, kind
);
2462 template <typename A
>
2463 uint32_t TentativeDefinitionSection
<A
>::computeAtomCount(class Parser
<A
>& parser
,
2464 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
2465 const struct Parser
<A
>::CFIInfoArray
&)
2467 return parser
.tentativeDefinitionCount();
2470 template <typename A
>
2471 uint32_t TentativeDefinitionSection
<A
>::appendAtoms(class Parser
<A
>& parser
, uint8_t* p
,
2472 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
2473 const struct Parser
<A
>::CFIInfoArray
&)
2475 this->_beginAtoms
= (Atom
<A
>*)p
;
2477 for (uint32_t i
=parser
.undefinedStartIndex(); i
< parser
.undefinedEndIndex(); ++i
) {
2478 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(i
);
2479 if ( ((sym
.n_type() & N_TYPE
) == N_UNDF
) && (sym
.n_value() != 0) ) {
2480 uint64_t size
= sym
.n_value();
2481 uint8_t alignP2
= GET_COMM_ALIGN(sym
.n_desc());
2482 if ( alignP2
== 0 ) {
2483 // common symbols align to their size
2484 // that is, a 4-byte common aligns to 4-bytes
2485 // if this size is not a power of two,
2486 // then round up to the next power of two
2487 alignP2
= 63 - (uint8_t)__builtin_clzll(size
);
2488 if ( size
!= (1ULL << alignP2
) )
2491 // limit alignment of extremely large commons to 2^15 bytes (8-page)
2494 Atom
<A
>* allocatedSpace
= (Atom
<A
>*)p
;
2495 new (allocatedSpace
) Atom
<A
>(*this, parser
.nameFromSymbol(sym
), (pint_t
)ULLONG_MAX
, size
,
2496 ld::Atom::definitionTentative
, ld::Atom::combineByName
,
2497 parser
.scopeFromSymbol(sym
), ld::Atom::typeZeroFill
, ld::Atom::symbolTableIn
,
2498 parser
.dontDeadStripFromSymbol(sym
), false, false, ld::Atom::Alignment(alignP2
) );
2499 p
+= sizeof(Atom
<A
>);
2503 this->_endAtoms
= (Atom
<A
>*)p
;
2508 template <typename A
>
2509 uint32_t AbsoluteSymbolSection
<A
>::computeAtomCount(class Parser
<A
>& parser
,
2510 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
2511 const struct Parser
<A
>::CFIInfoArray
&)
2513 return parser
.absoluteSymbolCount();
2516 template <typename A
>
2517 uint32_t AbsoluteSymbolSection
<A
>::appendAtoms(class Parser
<A
>& parser
, uint8_t* p
,
2518 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
2519 const struct Parser
<A
>::CFIInfoArray
&)
2521 this->_beginAtoms
= (Atom
<A
>*)p
;
2523 for (uint32_t i
=0; i
< parser
.symbolCount(); ++i
) {
2524 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(i
);
2525 if ( (sym
.n_type() & N_TYPE
) != N_ABS
)
2527 const char* absName
= parser
.nameFromSymbol(sym
);
2528 // ignore .objc_class_name_* symbols
2529 if ( strncmp(absName
, ".objc_class_name_", 17) == 0 )
2531 // ignore .objc_class_name_* symbols
2532 if ( strncmp(absName
, ".objc_category_name_", 20) == 0 )
2534 // ignore empty *.eh symbols
2535 if ( strcmp(&absName
[strlen(absName
)-3], ".eh") == 0 )
2538 Atom
<A
>* allocatedSpace
= (Atom
<A
>*)p
;
2539 new (allocatedSpace
) Atom
<A
>(*this, parser
, sym
, 0);
2540 p
+= sizeof(Atom
<A
>);
2543 this->_endAtoms
= (Atom
<A
>*)p
;
2547 template <typename A
>
2548 Atom
<A
>* AbsoluteSymbolSection
<A
>::findAbsAtomForValue(typename
A::P::uint_t value
)
2550 Atom
<A
>* end
= this->_endAtoms
;
2551 for(Atom
<A
>* p
= this->_beginAtoms
; p
< end
; ++p
) {
2552 if ( p
->_objAddress
== value
)
2559 template <typename A
>
2560 uint32_t Parser
<A
>::indirectSymbol(uint32_t indirectIndex
)
2562 if ( indirectIndex
>= _indirectTableCount
)
2563 throw "indirect symbol index out of range";
2564 return E::get32(_indirectTable
[indirectIndex
]);
2567 template <typename A
>
2568 const macho_nlist
<typename
A::P
>& Parser
<A
>::symbolFromIndex(uint32_t index
)
2570 if ( index
> _symbolCount
)
2571 throw "symbol index out of range";
2572 return _symbols
[index
];
2575 template <typename A
>
2576 const macho_section
<typename
A::P
>* Parser
<A
>::machOSectionFromSectionIndex(uint32_t index
)
2578 if ( index
>= _machOSectionsCount
)
2579 throw "section index out of range";
2580 return &_sectionsStart
[index
];
2583 template <typename A
>
2584 uint32_t Parser
<A
>::symbolIndexFromIndirectSectionAddress(pint_t addr
, const macho_section
<P
>* sect
)
2586 uint32_t elementSize
= 0;
2587 switch ( sect
->flags() & SECTION_TYPE
) {
2588 case S_SYMBOL_STUBS
:
2589 elementSize
= sect
->reserved2();
2591 case S_LAZY_SYMBOL_POINTERS
:
2592 case S_NON_LAZY_SYMBOL_POINTERS
:
2593 elementSize
= sizeof(pint_t
);
2596 throw "section does not use inirect symbol table";
2598 uint32_t indexInSection
= (addr
- sect
->addr()) / elementSize
;
2599 uint32_t indexIntoIndirectTable
= sect
->reserved1() + indexInSection
;
2600 return this->indirectSymbol(indexIntoIndirectTable
);
2605 template <typename A
>
2606 const char* Parser
<A
>::nameFromSymbol(const macho_nlist
<P
>& sym
)
2608 return &_strings
[sym
.n_strx()];
2611 template <typename A
>
2612 ld::Atom::Scope Parser
<A
>::scopeFromSymbol(const macho_nlist
<P
>& sym
)
2614 if ( (sym
.n_type() & N_EXT
) == 0 )
2615 return ld::Atom::scopeTranslationUnit
;
2616 else if ( (sym
.n_type() & N_PEXT
) != 0 )
2617 return ld::Atom::scopeLinkageUnit
;
2618 else if ( this->nameFromSymbol(sym
)[0] == 'l' ) // since all 'l' symbols will be remove, don't make them global
2619 return ld::Atom::scopeLinkageUnit
;
2621 return ld::Atom::scopeGlobal
;
2624 template <typename A
>
2625 ld::Atom::Definition Parser
<A
>::definitionFromSymbol(const macho_nlist
<P
>& sym
)
2627 switch ( sym
.n_type() & N_TYPE
) {
2629 return ld::Atom::definitionAbsolute
;
2631 return ld::Atom::definitionRegular
;
2633 if ( sym
.n_value() != 0 )
2634 return ld::Atom::definitionTentative
;
2636 throw "definitionFromSymbol() bad symbol";
2639 template <typename A
>
2640 ld::Atom::Combine Parser
<A
>::combineFromSymbol(const macho_nlist
<P
>& sym
)
2642 if ( sym
.n_desc() & N_WEAK_DEF
)
2643 return ld::Atom::combineByName
;
2645 return ld::Atom::combineNever
;
2649 template <typename A
>
2650 ld::Atom::SymbolTableInclusion Parser
<A
>::inclusionFromSymbol(const macho_nlist
<P
>& sym
)
2652 const char* symbolName
= nameFromSymbol(sym
);
2653 // labels beginning with 'l' (lowercase ell) are automatically removed in final linked images <rdar://problem/4571042>
2654 // labels beginning with 'L' should have been stripped by the assembler, so are stripped now
2655 if ( sym
.n_desc() & REFERENCED_DYNAMICALLY
)
2656 return ld::Atom::symbolTableInAndNeverStrip
;
2657 else if ( symbolName
[0] == 'l' )
2658 return ld::Atom::symbolTableNotInFinalLinkedImages
;
2659 else if ( symbolName
[0] == 'L' )
2660 return ld::Atom::symbolTableNotIn
;
2662 return ld::Atom::symbolTableIn
;
2665 template <typename A
>
2666 bool Parser
<A
>::dontDeadStripFromSymbol(const macho_nlist
<P
>& sym
)
2668 return ( (sym
.n_desc() & (N_NO_DEAD_STRIP
|REFERENCED_DYNAMICALLY
)) != 0 );
2671 template <typename A
>
2672 bool Parser
<A
>::isThumbFromSymbol(const macho_nlist
<P
>& sym
)
2674 return ( sym
.n_desc() & N_ARM_THUMB_DEF
);
2677 template <typename A
>
2678 bool Parser
<A
>::weakImportFromSymbol(const macho_nlist
<P
>& sym
)
2680 return ( ((sym
.n_type() & N_TYPE
) == N_UNDF
) && ((sym
.n_desc() & N_WEAK_REF
) != 0) );
2683 template <typename A
>
2684 bool Parser
<A
>::resolverFromSymbol(const macho_nlist
<P
>& sym
)
2686 return ( sym
.n_desc() & N_SYMBOL_RESOLVER
);
2690 /* Skip over a LEB128 value (signed or unsigned). */
2692 skip_leb128 (const uint8_t ** offset
, const uint8_t * end
)
2694 while (*offset
!= end
&& **offset
>= 0x80)
2700 /* Read a ULEB128 into a 64-bit word. Return (uint64_t)-1 on overflow
2701 or error. On overflow, skip past the rest of the uleb128. */
2703 read_uleb128 (const uint8_t ** offset
, const uint8_t * end
)
2705 uint64_t result
= 0;
2712 return (uint64_t) -1;
2714 b
= **offset
& 0x7f;
2716 if (bit
>= 64 || b
<< bit
>> bit
!= b
)
2717 result
= (uint64_t) -1;
2719 result
|= b
<< bit
, bit
+= 7;
2720 } while (*(*offset
)++ >= 0x80);
2725 /* Skip over a DWARF attribute of form FORM. */
2726 template <typename A
>
2727 bool Parser
<A
>::skip_form(const uint8_t ** offset
, const uint8_t * end
, uint64_t form
,
2728 uint8_t addr_size
, bool dwarf64
)
2738 case DW_FORM_block2
:
2739 if (end
- *offset
< 2)
2741 sz
= 2 + A::P::E::get16(*(uint16_t*)offset
);
2744 case DW_FORM_block4
:
2745 if (end
- *offset
< 4)
2747 sz
= 2 + A::P::E::get32(*(uint32_t*)offset
);
2765 case DW_FORM_string
:
2766 while (*offset
!= end
&& **offset
)
2775 sz
= read_uleb128 (offset
, end
);
2778 case DW_FORM_block1
:
2786 case DW_FORM_ref_udata
:
2787 skip_leb128 (offset
, end
);
2791 case DW_FORM_ref_addr
:
2798 if (end
- *offset
< sz
)
2805 template <typename A
>
2806 const char* Parser
<A
>::getDwarfString(uint64_t form
, const uint8_t* p
)
2808 if ( form
== DW_FORM_string
)
2809 return (const char*)p
;
2810 else if ( form
== DW_FORM_strp
) {
2811 uint32_t offset
= E::get32(*((uint32_t*)p
));
2812 const char* dwarfStrings
= (char*)_file
->fileContent() + _file
->_dwarfDebugStringSect
->offset();
2813 if ( offset
> _file
->_dwarfDebugStringSect
->size() ) {
2814 warning("unknown dwarf DW_FORM_strp (offset=0x%08X) is too big in %s\n", offset
, this->_path
);
2817 return &dwarfStrings
[offset
];
2819 warning("unknown dwarf string encoding (form=%lld) in %s\n", form
, this->_path
);
2824 template <typename A
>
2825 struct AtomAndLineInfo
{
2827 ld::Atom::LineInfo info
;
2831 // <rdar://problem/5591394> Add support to ld64 for N_FUN stabs when used for symbolic constants
2832 // Returns whether a stabStr belonging to an N_FUN stab represents a
2833 // symbolic constant rather than a function
2834 template <typename A
>
2835 bool Parser
<A
>::isConstFunStabs(const char *stabStr
)
2838 // N_FUN can be used for both constants and for functions. In case it's a constant,
2839 // the format of the stabs string is "symname:c=<value>;"
2840 // ':' cannot appear in the symbol name, except if it's an Objective-C method
2841 // (in which case the symbol name starts with + or -, and then it's definitely
2843 return (stabStr
!= NULL
) && (stabStr
[0] != '+') && (stabStr
[0] != '-')
2844 && ((colon
= strchr(stabStr
, ':')) != NULL
)
2845 && (colon
[1] == 'c') && (colon
[2] == '=');
2849 template <typename A
>
2850 void Parser
<A
>::parseDebugInfo()
2852 // check for dwarf __debug_info section
2853 if ( _file
->_dwarfDebugInfoSect
== NULL
) {
2854 // if no DWARF debug info, look for stabs
2858 if ( _file
->_dwarfDebugInfoSect
->size() == 0 )
2862 if ( !read_comp_unit(&_file
->_dwarfTranslationUnitFile
, &_file
->_dwarfTranslationUnitDir
, &stmtList
) ) {
2863 // if can't parse dwarf, warn and give up
2864 _file
->_dwarfTranslationUnitFile
= NULL
;
2865 _file
->_dwarfTranslationUnitDir
= NULL
;
2866 warning("can't parse dwarf compilation unit info in %s", _path
);
2867 _file
->_debugInfoKind
= ld::relocatable::File::kDebugInfoNone
;
2871 // add line number info to atoms from dwarf
2872 std::vector
<AtomAndLineInfo
<A
> > entries
;
2873 entries
.reserve(64);
2874 if ( _file
->_debugInfoKind
== ld::relocatable::File::kDebugInfoDwarf
) {
2875 // file with just data will have no __debug_line info
2876 if ( (_file
->_dwarfDebugLineSect
!= NULL
) && (_file
->_dwarfDebugLineSect
->size() != 0) ) {
2877 // validate stmt_list
2878 if ( (stmtList
!= (uint64_t)-1) && (stmtList
< _file
->_dwarfDebugLineSect
->size()) ) {
2879 const uint8_t* debug_line
= (uint8_t*)_file
->fileContent() + _file
->_dwarfDebugLineSect
->offset();
2880 struct line_reader_data
* lines
= line_open(&debug_line
[stmtList
],
2881 _file
->_dwarfDebugLineSect
->size() - stmtList
, E::little_endian
);
2882 struct line_info result
;
2883 Atom
<A
>* curAtom
= NULL
;
2884 uint32_t curAtomOffset
= 0;
2885 uint32_t curAtomAddress
= 0;
2886 uint32_t curAtomSize
= 0;
2887 std::map
<uint32_t,const char*> dwarfIndexToFile
;
2888 if ( lines
!= NULL
) {
2889 while ( line_next(lines
, &result
, line_stop_pc
) ) {
2890 //fprintf(stderr, "curAtom=%p, result.pc=0x%llX, result.line=%llu, result.end_of_sequence=%d,"
2891 // " curAtomAddress=0x%X, curAtomSize=0x%X\n",
2892 // curAtom, result.pc, result.line, result.end_of_sequence, curAtomAddress, curAtomSize);
2893 // work around weird debug line table compiler generates if no functions in __text section
2894 if ( (curAtom
== NULL
) && (result
.pc
== 0) && result
.end_of_sequence
&& (result
.file
== 1))
2896 // for performance, see if in next pc is in current atom
2897 if ( (curAtom
!= NULL
) && (curAtomAddress
<= result
.pc
) && (result
.pc
< (curAtomAddress
+curAtomSize
)) ) {
2898 curAtomOffset
= result
.pc
- curAtomAddress
;
2900 // or pc at end of current atom
2901 else if ( result
.end_of_sequence
&& (curAtom
!= NULL
) && (result
.pc
== (curAtomAddress
+curAtomSize
)) ) {
2902 curAtomOffset
= result
.pc
- curAtomAddress
;
2904 // or only one function that is a one line function
2905 else if ( result
.end_of_sequence
&& (curAtom
== NULL
) && (this->findAtomByAddress(0) != NULL
) && (result
.pc
== this->findAtomByAddress(0)->size()) ) {
2906 curAtom
= this->findAtomByAddress(0);
2907 curAtomOffset
= result
.pc
- curAtom
->objectAddress();
2908 curAtomAddress
= curAtom
->objectAddress();
2909 curAtomSize
= curAtom
->size();
2912 // do slow look up of atom by address
2914 curAtom
= this->findAtomByAddress(result
.pc
);
2917 // in case of bug in debug info, don't abort link, just limp on
2920 if ( curAtom
== NULL
)
2921 break; // file has line info but no functions
2922 if ( result
.end_of_sequence
&& (curAtomAddress
+curAtomSize
< result
.pc
) ) {
2923 // a one line function can be returned by line_next() as one entry with pc at end of blob
2924 // look for alt atom starting at end of previous atom
2925 uint32_t previousEnd
= curAtomAddress
+curAtomSize
;
2926 Atom
<A
>* alt
= this->findAtomByAddressOrNullIfStub(previousEnd
);
2928 continue; // ignore spurious debug info for stubs
2929 if ( result
.pc
<= alt
->objectAddress() + alt
->size() ) {
2931 curAtomOffset
= result
.pc
- alt
->objectAddress();
2932 curAtomAddress
= alt
->objectAddress();
2933 curAtomSize
= alt
->size();
2936 curAtomOffset
= result
.pc
- curAtom
->objectAddress();
2937 curAtomAddress
= curAtom
->objectAddress();
2938 curAtomSize
= curAtom
->size();
2942 curAtomOffset
= result
.pc
- curAtom
->objectAddress();
2943 curAtomAddress
= curAtom
->objectAddress();
2944 curAtomSize
= curAtom
->size();
2947 const char* filename
;
2948 std::map
<uint32_t,const char*>::iterator pos
= dwarfIndexToFile
.find(result
.file
);
2949 if ( pos
== dwarfIndexToFile
.end() ) {
2950 filename
= line_file(lines
, result
.file
);
2951 dwarfIndexToFile
[result
.file
] = filename
;
2954 filename
= pos
->second
;
2956 // only record for ~8000 line info records per function
2957 if ( curAtom
->roomForMoreLineInfoCount() ) {
2958 AtomAndLineInfo
<A
> entry
;
2959 entry
.atom
= curAtom
;
2960 entry
.info
.atomOffset
= curAtomOffset
;
2961 entry
.info
.fileName
= filename
;
2962 entry
.info
.lineNumber
= result
.line
;
2963 //fprintf(stderr, "addr=0x%08llX, line=%lld, file=%s, atom=%s, atom.size=0x%X, end=%d\n",
2964 // result.pc, result.line, filename, curAtom->name(), curAtomSize, result.end_of_sequence);
2965 entries
.push_back(entry
);
2966 curAtom
->incrementLineInfoCount();
2968 if ( result
.end_of_sequence
) {
2978 // assign line info start offset for each atom
2979 uint8_t* p
= _file
->_atomsArray
;
2980 uint32_t liOffset
= 0;
2981 for(int i
=_file
->_atomsArrayCount
; i
> 0; --i
) {
2982 Atom
<A
>* atom
= (Atom
<A
>*)p
;
2983 atom
->_lineInfoStartIndex
= liOffset
;
2984 liOffset
+= atom
->_lineInfoCount
;
2985 atom
->_lineInfoCount
= 0;
2986 p
+= sizeof(Atom
<A
>);
2988 assert(liOffset
== entries
.size());
2989 _file
->_lineInfos
.reserve(liOffset
);
2991 // copy each line info for each atom
2992 for (typename
std::vector
<AtomAndLineInfo
<A
> >::iterator it
= entries
.begin(); it
!= entries
.end(); ++it
) {
2993 uint32_t slot
= it
->atom
->_lineInfoStartIndex
+ it
->atom
->_lineInfoCount
;
2994 _file
->_lineInfos
[slot
] = it
->info
;
2995 it
->atom
->_lineInfoCount
++;
2998 // done with temp vector
3002 template <typename A
>
3003 void Parser
<A
>::parseStabs()
3005 // scan symbol table for stabs entries
3006 Atom
<A
>* currentAtom
= NULL
;
3007 pint_t currentAtomAddress
= 0;
3008 enum { start
, inBeginEnd
, inFun
} state
= start
;
3009 for (uint32_t symbolIndex
= 0; symbolIndex
< _symbolCount
; ++symbolIndex
) {
3010 const macho_nlist
<P
>& sym
= this->symbolFromIndex(symbolIndex
);
3011 bool useStab
= true;
3012 uint8_t type
= sym
.n_type();
3013 const char* symString
= (sym
.n_strx() != 0) ? this->nameFromSymbol(sym
) : NULL
;
3014 if ( (type
& N_STAB
) != 0 ) {
3015 _file
->_debugInfoKind
= (_hasUUID
? ld::relocatable::File::kDebugInfoStabsUUID
: ld::relocatable::File::kDebugInfoStabs
);
3016 ld::relocatable::File::Stab stab
;
3019 stab
.other
= sym
.n_sect();
3020 stab
.desc
= sym
.n_desc();
3021 stab
.value
= sym
.n_value();
3027 // beginning of function block
3029 // fall into case to lookup atom by addresss
3032 currentAtomAddress
= sym
.n_value();
3033 currentAtom
= this->findAtomByAddress(currentAtomAddress
);
3034 if ( currentAtom
!= NULL
) {
3035 stab
.atom
= currentAtom
;
3036 stab
.string
= symString
;
3039 fprintf(stderr
, "can't find atom for stabs BNSYM at %08llX in %s",
3040 (uint64_t)sym
.n_value(), _path
);
3049 // not associated with an atom, just copy
3050 stab
.string
= symString
;
3054 // n_value field is NOT atom address ;-(
3055 // need to find atom by name match
3056 const char* colon
= strchr(symString
, ':');
3057 if ( colon
!= NULL
) {
3058 // build underscore leading name
3059 int nameLen
= colon
- symString
;
3060 char symName
[nameLen
+2];
3061 strlcpy(&symName
[1], symString
, nameLen
+1);
3063 symName
[nameLen
+1] = '\0';
3064 currentAtom
= this->findAtomByName(symName
);
3065 if ( currentAtom
!= NULL
) {
3066 stab
.atom
= currentAtom
;
3067 stab
.string
= symString
;
3071 // might be a debug-note without trailing :G()
3072 currentAtom
= this->findAtomByName(symString
);
3073 if ( currentAtom
!= NULL
) {
3074 stab
.atom
= currentAtom
;
3075 stab
.string
= symString
;
3078 if ( stab
.atom
== NULL
) {
3079 // ld_classic added bogus GSYM stabs for old style dtrace probes
3080 if ( (strncmp(symString
, "__dtrace_probe$", 15) != 0) )
3081 warning("can't find atom for N_GSYM stabs %s in %s", symString
, _path
);
3087 if ( isConstFunStabs(symString
) ) {
3088 // constant not associated with a function
3089 stab
.string
= symString
;
3092 // old style stabs without BNSYM
3094 currentAtomAddress
= sym
.n_value();
3095 currentAtom
= this->findAtomByAddress(currentAtomAddress
);
3096 if ( currentAtom
!= NULL
) {
3097 stab
.atom
= currentAtom
;
3098 stab
.string
= symString
;
3101 warning("can't find atom for stabs FUN at %08llX in %s",
3102 (uint64_t)currentAtomAddress
, _path
);
3108 stab
.string
= symString
;
3114 stab
.string
= symString
;
3115 // -gfull built .o file
3118 warning("unknown stabs type 0x%X in %s", type
, _path
);
3122 stab
.atom
= currentAtom
;
3131 Atom
<A
>* nestedAtom
= this->findAtomByAddress(sym
.n_value());
3132 if ( nestedAtom
!= NULL
) {
3133 stab
.atom
= nestedAtom
;
3134 stab
.string
= symString
;
3137 warning("can't find atom for stabs 0x%X at %08llX in %s",
3138 type
, (uint64_t)sym
.n_value(), _path
);
3145 // adjust value to be offset in atom
3146 stab
.value
-= currentAtomAddress
;
3148 stab
.string
= symString
;
3155 if ( isConstFunStabs(symString
) ) {
3156 stab
.atom
= currentAtom
;
3157 stab
.string
= symString
;
3160 if ( sym
.n_sect() != 0 ) {
3161 // found another start stab, must be really old stabs...
3162 currentAtomAddress
= sym
.n_value();
3163 currentAtom
= this->findAtomByAddress(currentAtomAddress
);
3164 if ( currentAtom
!= NULL
) {
3165 stab
.atom
= currentAtom
;
3166 stab
.string
= symString
;
3169 warning("can't find atom for stabs FUN at %08llX in %s",
3170 (uint64_t)currentAtomAddress
, _path
);
3174 // found ending stab, switch back to start state
3175 stab
.string
= symString
;
3176 stab
.atom
= currentAtom
;
3185 // adjust value to be offset in atom
3186 stab
.value
-= currentAtomAddress
;
3187 stab
.atom
= currentAtom
;
3190 stab
.string
= symString
;
3194 stab
.atom
= currentAtom
;
3195 stab
.string
= symString
;
3200 // add to list of stabs for this .o file
3202 _file
->_stabs
.push_back(stab
);
3209 // Look at the compilation unit DIE and determine
3210 // its NAME, compilation directory (in COMP_DIR) and its
3211 // line number information offset (in STMT_LIST). NAME and COMP_DIR
3212 // may be NULL (especially COMP_DIR) if they are not in the .o file;
3213 // STMT_LIST will be (uint64_t) -1.
3215 // At present this assumes that there's only one compilation unit DIE.
3217 template <typename A
>
3218 bool Parser
<A
>::read_comp_unit(const char ** name
, const char ** comp_dir
,
3219 uint64_t *stmt_list
)
3221 const uint8_t * debug_info
;
3222 const uint8_t * debug_abbrev
;
3225 const uint8_t * end
;
3226 const uint8_t * enda
;
3229 uint64_t abbrev_base
;
3231 uint8_t address_size
;
3236 *stmt_list
= (uint64_t) -1;
3238 if ( (_file
->_dwarfDebugInfoSect
== NULL
) || (_file
->_dwarfDebugAbbrevSect
== NULL
) )
3241 debug_info
= (uint8_t*)_file
->fileContent() + _file
->_dwarfDebugInfoSect
->offset();
3242 debug_abbrev
= (uint8_t*)_file
->fileContent() + _file
->_dwarfDebugAbbrevSect
->offset();
3245 if (_file
->_dwarfDebugInfoSect
->size() < 12)
3246 /* Too small to be a real debug_info section. */
3248 sz
= A::P::E::get32(*(uint32_t*)di
);
3250 dwarf64
= sz
== 0xffffffff;
3252 sz
= A::P::E::get64(*(uint64_t*)di
), di
+= 8;
3253 else if (sz
> 0xffffff00)
3254 /* Unknown dwarf format. */
3257 /* Verify claimed size. */
3258 if (sz
+ (di
- debug_info
) > _file
->_dwarfDebugInfoSect
->size() || sz
<= (dwarf64
? 23 : 11))
3261 vers
= A::P::E::get16(*(uint16_t*)di
);
3262 if (vers
< 2 || vers
> 3)
3263 /* DWARF version wrong for this code.
3264 Chances are we could continue anyway, but we don't know for sure. */
3268 /* Find the debug_abbrev section. */
3269 abbrev_base
= dwarf64
? A::P::E::get64(*(uint64_t*)di
) : A::P::E::get32(*(uint32_t*)di
);
3270 di
+= dwarf64
? 8 : 4;
3272 if (abbrev_base
> _file
->_dwarfDebugAbbrevSect
->size())
3274 da
= debug_abbrev
+ abbrev_base
;
3275 enda
= debug_abbrev
+ _file
->_dwarfDebugAbbrevSect
->size();
3277 address_size
= *di
++;
3279 /* Find the abbrev number we're looking for. */
3281 abbrev
= read_uleb128 (&di
, end
);
3282 if (abbrev
== (uint64_t) -1)
3285 /* Skip through the debug_abbrev section looking for that abbrev. */
3288 uint64_t this_abbrev
= read_uleb128 (&da
, enda
);
3291 if (this_abbrev
== abbrev
)
3292 /* This is almost always taken. */
3294 skip_leb128 (&da
, enda
); /* Skip the tag. */
3297 da
++; /* Skip the DW_CHILDREN_* value. */
3300 attr
= read_uleb128 (&da
, enda
);
3301 skip_leb128 (&da
, enda
);
3302 } while (attr
!= 0 && attr
!= (uint64_t) -1);
3307 /* Check that the abbrev is one for a DW_TAG_compile_unit. */
3308 if (read_uleb128 (&da
, enda
) != DW_TAG_compile_unit
)
3312 da
++; /* Skip the DW_CHILDREN_* value. */
3314 /* Now, go through the DIE looking for DW_AT_name,
3315 DW_AT_comp_dir, and DW_AT_stmt_list. */
3318 uint64_t attr
= read_uleb128 (&da
, enda
);
3319 uint64_t form
= read_uleb128 (&da
, enda
);
3321 if (attr
== (uint64_t) -1)
3326 if (form
== DW_FORM_indirect
)
3327 form
= read_uleb128 (&di
, end
);
3329 if (attr
== DW_AT_name
)
3330 *name
= getDwarfString(form
, di
);
3331 else if (attr
== DW_AT_comp_dir
)
3332 *comp_dir
= getDwarfString(form
, di
);
3333 else if (attr
== DW_AT_stmt_list
&& form
== DW_FORM_data4
)
3334 *stmt_list
= A::P::E::get32(*(uint32_t*)di
);
3335 else if (attr
== DW_AT_stmt_list
&& form
== DW_FORM_data8
)
3336 *stmt_list
= A::P::E::get64(*(uint64_t*)di
);
3337 if (! skip_form (&di
, end
, form
, address_size
, dwarf64
))
3344 template <typename A
>
3347 free(_sectionsArray
);
3351 template <typename A
>
3352 bool File
<A
>::translationUnitSource(const char** dir
, const char** name
) const
3354 if ( _debugInfoKind
== ld::relocatable::File::kDebugInfoDwarf
) {
3355 *dir
= _dwarfTranslationUnitDir
;
3356 *name
= _dwarfTranslationUnitFile
;
3357 return (_dwarfTranslationUnitFile
!= NULL
);
3364 template <typename A
>
3365 bool File
<A
>::forEachAtom(ld::File::AtomHandler
& handler
) const
3367 handler
.doFile(*this);
3368 uint8_t* p
= _atomsArray
;
3369 for(int i
=_atomsArrayCount
; i
> 0; --i
) {
3370 handler
.doAtom(*((Atom
<A
>*)p
));
3371 p
+= sizeof(Atom
<A
>);
3373 return (_atomsArrayCount
!= 0);
3376 template <typename A
>
3377 const char* Section
<A
>::makeSegmentName(const macho_section
<typename
A::P
>* sect
)
3379 // mach-o section record only has room for 16-byte seg/sect names
3380 // so a 16-byte name has no trailing zero
3381 const char* name
= sect
->segname();
3382 if ( strlen(name
) < 16 )
3384 char* tmp
= new char[17];
3385 strlcpy(tmp
, name
, 17);
3389 template <typename A
>
3390 const char* Section
<A
>::makeSectionName(const macho_section
<typename
A::P
>* sect
)
3392 const char* name
= sect
->sectname();
3393 if ( strlen(name
) < 16 )
3396 // special case common long section names so we don't have to malloc
3397 if ( strncmp(sect
->sectname(), "__objc_classrefs", 16) == 0 )
3398 return "__objc_classrefs";
3399 if ( strncmp(sect
->sectname(), "__objc_classlist", 16) == 0 )
3400 return "__objc_classlist";
3401 if ( strncmp(sect
->sectname(), "__objc_nlclslist", 16) == 0 )
3402 return "__objc_nlclslist";
3403 if ( strncmp(sect
->sectname(), "__objc_nlcatlist", 16) == 0 )
3404 return "__objc_nlcatlist";
3405 if ( strncmp(sect
->sectname(), "__objc_protolist", 16) == 0 )
3406 return "__objc_protolist";
3407 if ( strncmp(sect
->sectname(), "__objc_protorefs", 16) == 0 )
3408 return "__objc_protorefs";
3409 if ( strncmp(sect
->sectname(), "__objc_superrefs", 16) == 0 )
3410 return "__objc_superrefs";
3411 if ( strncmp(sect
->sectname(), "__objc_imageinfo", 16) == 0 )
3412 return "__objc_imageinfo";
3413 if ( strncmp(sect
->sectname(), "__objc_stringobj", 16) == 0 )
3414 return "__objc_stringobj";
3415 if ( strncmp(sect
->sectname(), "__gcc_except_tab", 16) == 0 )
3416 return "__gcc_except_tab";
3418 char* tmp
= new char[17];
3419 strlcpy(tmp
, name
, 17);
3423 template <typename A
>
3424 bool Section
<A
>::readable(const macho_section
<typename
A::P
>* sect
)
3429 template <typename A
>
3430 bool Section
<A
>::writable(const macho_section
<typename
A::P
>* sect
)
3432 // mach-o .o files do not contain segment permissions
3433 // we just know TEXT is special
3434 return ( strcmp(sect
->segname(), "__TEXT") != 0 );
3437 template <typename A
>
3438 bool Section
<A
>::exectuable(const macho_section
<typename
A::P
>* sect
)
3440 // mach-o .o files do not contain segment permissions
3441 // we just know TEXT is special
3442 return ( strcmp(sect
->segname(), "__TEXT") == 0 );
3446 template <typename A
>
3447 ld::Section::Type Section
<A
>::sectionType(const macho_section
<typename
A::P
>* sect
)
3449 switch ( sect
->flags() & SECTION_TYPE
) {
3451 return ld::Section::typeZeroFill
;
3452 case S_CSTRING_LITERALS
:
3453 if ( (strcmp(sect
->sectname(), "__cstring") == 0) && (strcmp(sect
->segname(), "__TEXT") == 0) )
3454 return ld::Section::typeCString
;
3456 return ld::Section::typeNonStdCString
;
3457 case S_4BYTE_LITERALS
:
3458 return ld::Section::typeLiteral4
;
3459 case S_8BYTE_LITERALS
:
3460 return ld::Section::typeLiteral8
;
3461 case S_LITERAL_POINTERS
:
3462 return ld::Section::typeCStringPointer
;
3463 case S_NON_LAZY_SYMBOL_POINTERS
:
3464 return ld::Section::typeNonLazyPointer
;
3465 case S_LAZY_SYMBOL_POINTERS
:
3466 return ld::Section::typeLazyPointer
;
3467 case S_SYMBOL_STUBS
:
3468 return ld::Section::typeStub
;
3469 case S_MOD_INIT_FUNC_POINTERS
:
3470 return ld::Section::typeInitializerPointers
;
3471 case S_MOD_TERM_FUNC_POINTERS
:
3472 return ld::Section::typeTerminatorPointers
;
3474 return ld::Section::typeUnclassified
;
3475 case S_16BYTE_LITERALS
:
3476 return ld::Section::typeLiteral16
;
3479 if ( sect
->flags() & S_ATTR_PURE_INSTRUCTIONS
) {
3480 return ld::Section::typeCode
;
3482 else if ( strcmp(sect
->segname(), "__TEXT") == 0 ) {
3483 if ( strcmp(sect
->sectname(), "__eh_frame") == 0 )
3484 return ld::Section::typeCFI
;
3485 else if ( strcmp(sect
->sectname(), "__ustring") == 0 )
3486 return ld::Section::typeUTF16Strings
;
3487 else if ( strcmp(sect
->sectname(), "__textcoal_nt") == 0 )
3488 return ld::Section::typeCode
;
3489 else if ( strcmp(sect
->sectname(), "__StaticInit") == 0 )
3490 return ld::Section::typeCode
;
3492 else if ( strcmp(sect
->segname(), "__DATA") == 0 ) {
3493 if ( strcmp(sect
->sectname(), "__cfstring") == 0 )
3494 return ld::Section::typeCFString
;
3495 else if ( strcmp(sect
->sectname(), "__dyld") == 0 )
3496 return ld::Section::typeDyldInfo
;
3497 else if ( strcmp(sect
->sectname(), "__program_vars") == 0 )
3498 return ld::Section::typeDyldInfo
;
3499 else if ( strncmp(sect
->sectname(), "__objc_classrefs", 16) == 0 )
3500 return ld::Section::typeObjCClassRefs
;
3501 else if ( strcmp(sect
->sectname(), "__objc_catlist") == 0 )
3502 return ld::Section::typeObjC2CategoryList
;
3504 else if ( strcmp(sect
->segname(), "__OBJC") == 0 ) {
3505 if ( strcmp(sect
->sectname(), "__class") == 0 )
3506 return ld::Section::typeObjC1Classes
;
3509 case S_THREAD_LOCAL_REGULAR
:
3510 return ld::Section::typeTLVInitialValues
;
3511 case S_THREAD_LOCAL_ZEROFILL
:
3512 return ld::Section::typeTLVZeroFill
;
3513 case S_THREAD_LOCAL_VARIABLES
:
3514 return ld::Section::typeTLVDefs
;
3515 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS
:
3516 return ld::Section::typeTLVInitializerPointers
;
3518 return ld::Section::typeUnclassified
;
3522 template <typename A
>
3523 Atom
<A
>* Section
<A
>::findContentAtomByAddress(pint_t addr
, class Atom
<A
>* start
, class Atom
<A
>* end
)
3525 // do a binary search of atom array
3526 uint32_t atomCount
= end
- start
;
3527 Atom
<A
>* base
= start
;
3528 for (uint32_t n
= atomCount
; n
> 0; n
/= 2) {
3529 Atom
<A
>* pivot
= &base
[n
/2];
3530 pint_t atomStartAddr
= pivot
->_objAddress
;
3531 pint_t atomEndAddr
= atomStartAddr
+ pivot
->_size
;
3532 if ( atomStartAddr
<= addr
) {
3533 // address in normal atom
3534 if (addr
< atomEndAddr
)
3536 // address in "end" label (but not in alias)
3537 if ( (pivot
->_size
== 0) && (addr
== atomEndAddr
) && !pivot
->isAlias() )
3540 if ( addr
>= atomEndAddr
) {
3542 // move base to atom after pivot
3554 template <typename A
>
3555 ld::Atom::Alignment Section
<A
>::alignmentForAddress(pint_t addr
)
3557 const uint32_t sectionAlignment
= this->_machOSection
->align();
3558 return ld::Atom::Alignment(sectionAlignment
, (addr
% (1 << sectionAlignment
)));
3561 template <typename A
>
3562 uint32_t Section
<A
>::sectionNum(class Parser
<A
>& parser
) const
3564 if ( _machOSection
== NULL
)
3567 return 1 + (this->_machOSection
- parser
.firstMachOSection());
3570 // libunwind does not support ppc64
3571 template <> uint32_t CFISection
<ppc64
>::cfiCount() { return 0; }
3572 // arm does not have zero cost exceptions
3573 template <> uint32_t CFISection
<arm
>::cfiCount() { return 0; }
3575 template <typename A
>
3576 uint32_t CFISection
<A
>::cfiCount()
3578 // create ObjectAddressSpace object for use by libunwind
3579 OAS
oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection
->offset());
3580 return libunwind::CFI_Parser
<OAS
>::getCFICount(oas
,
3581 this->_machOSection
->addr(), this->_machOSection
->size());
3584 template <typename A
>
3585 void CFISection
<A
>::warnFunc(void* ref
, uint64_t funcAddr
, const char* msg
)
3587 Parser
<A
>* parser
= (Parser
<A
>*)ref
;
3588 if ( ! parser
->convertUnwindInfo() )
3590 if ( funcAddr
!= CFI_INVALID_ADDRESS
) {
3591 // atoms are not constructed yet, so scan symbol table for labels
3592 const char* name
= parser
->scanSymbolTableForAddress(funcAddr
);
3593 warning("could not create compact unwind for %s: %s", name
, msg
);
3596 warning("could not create compact unwind: %s", msg
);
3601 bool CFISection
<x86_64
>::needsRelocating()
3606 template <typename A
>
3607 bool CFISection
<A
>::needsRelocating()
3613 void CFISection
<x86_64
>::cfiParse(class Parser
<x86_64
>& parser
, uint8_t* buffer
,
3614 libunwind::CFI_Atom_Info
<CFISection
<x86_64
>::OAS
>::CFI_Atom_Info cfiArray
[],
3617 // copy __eh_frame data to buffer
3618 memcpy(buffer
, file().fileContent() + this->_machOSection
->offset(), this->_machOSection
->size());
3620 // and apply relocations
3621 const macho_relocation_info
<P
>* relocs
= (macho_relocation_info
<P
>*)(file().fileContent() + this->_machOSection
->reloff());
3622 const macho_relocation_info
<P
>* relocsEnd
= &relocs
[this->_machOSection
->nreloc()];
3623 for (const macho_relocation_info
<P
>* reloc
= relocs
; reloc
< relocsEnd
; ++reloc
) {
3625 switch ( reloc
->r_type() ) {
3626 case X86_64_RELOC_SUBTRACTOR
:
3627 value
= 0 - parser
.symbolFromIndex(reloc
->r_symbolnum()).n_value();
3629 if ( reloc
->r_extern() )
3630 value
+= parser
.symbolFromIndex(reloc
->r_symbolnum()).n_value();
3632 case X86_64_RELOC_UNSIGNED
:
3633 value
= parser
.symbolFromIndex(reloc
->r_symbolnum()).n_value();
3635 case X86_64_RELOC_GOT
:
3636 // this is used for the reference to the personality function in CIEs
3637 // store the symbol number of the personality function for later use as a Fixup
3638 value
= reloc
->r_symbolnum();
3641 fprintf(stderr
, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc
->r_address());
3646 switch ( reloc
->r_length() ) {
3648 p64
= (uint64_t*)&buffer
[reloc
->r_address()];
3649 E::set64(*p64
, value
+ E::get64(*p64
));
3652 p32
= (uint32_t*)&buffer
[reloc
->r_address()];
3653 E::set32(*p32
, value
+ E::get32(*p32
));
3656 fprintf(stderr
, "CFISection::cfiParse() unexpected relocation size at r_address=0x%08X\n", reloc
->r_address());
3662 // create ObjectAddressSpace object for use by libunwind
3663 OAS
oas(*this, buffer
);
3665 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3667 msg
= libunwind::DwarfInstructions
<OAS
, libunwind::Registers_x86_64
>::parseCFIs(
3668 oas
, this->_machOSection
->addr(), this->_machOSection
->size(),
3669 cfiArray
, count
, (void*)&parser
, warnFunc
);
3671 throwf("malformed __eh_frame section: %s", msg
);
3675 void CFISection
<x86
>::cfiParse(class Parser
<x86
>& parser
, uint8_t* buffer
,
3676 libunwind::CFI_Atom_Info
<CFISection
<x86
>::OAS
>::CFI_Atom_Info cfiArray
[],
3679 // create ObjectAddressSpace object for use by libunwind
3680 OAS
oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection
->offset());
3682 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3684 msg
= libunwind::DwarfInstructions
<OAS
, libunwind::Registers_x86
>::parseCFIs(
3685 oas
, this->_machOSection
->addr(), this->_machOSection
->size(),
3686 cfiArray
, count
, (void*)&parser
, warnFunc
);
3688 throwf("malformed __eh_frame section: %s", msg
);
3692 // need to change libunwind parseCFIs() to work for ppc
3694 void CFISection
<ppc
>::cfiParse(class Parser
<ppc
>& parser
, uint8_t* buffer
,
3695 libunwind::CFI_Atom_Info
<CFISection
<ppc
>::OAS
>::CFI_Atom_Info cfiArray
[],
3698 // create ObjectAddressSpace object for use by libunwind
3699 OAS
oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection
->offset());
3701 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3703 msg
= libunwind::DwarfInstructions
<OAS
, libunwind::Registers_ppc
>::parseCFIs(
3704 oas
, this->_machOSection
->addr(), this->_machOSection
->size(),
3705 cfiArray
, count
, (void*)&parser
, warnFunc
);
3707 throwf("malformed __eh_frame section: %s", msg
);
3711 void CFISection
<ppc64
>::cfiParse(class Parser
<ppc64
>& parser
, uint8_t* buffer
,
3712 libunwind::CFI_Atom_Info
<CFISection
<ppc64
>::OAS
>::CFI_Atom_Info cfiArray
[],
3715 // libunwind does not support ppc64
3720 void CFISection
<arm
>::cfiParse(class Parser
<arm
>& parser
, uint8_t* buffer
,
3721 libunwind::CFI_Atom_Info
<CFISection
<arm
>::OAS
>::CFI_Atom_Info cfiArray
[],
3724 // arm does not use zero cost exceptions
3730 template <typename A
>
3731 uint32_t CFISection
<A
>::computeAtomCount(class Parser
<A
>& parser
,
3732 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
3733 const struct Parser
<A
>::CFIInfoArray
& cfis
)
3740 template <typename A
>
3741 uint32_t CFISection
<A
>::appendAtoms(class Parser
<A
>& parser
, uint8_t* p
,
3742 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
3743 const struct Parser
<A
>::CFIInfoArray
& cfis
)
3745 this->_beginAtoms
= (Atom
<A
>*)p
;
3746 // walk CFI_Atom_Info array and create atom for each entry
3747 const CFI_Atom_Info
* start
= &cfis
.array
[0];
3748 const CFI_Atom_Info
* end
= &cfis
.array
[cfis
.count
];
3749 for(const CFI_Atom_Info
* a
=start
; a
< end
; ++a
) {
3750 Atom
<A
>* space
= (Atom
<A
>*)p
;
3751 new (space
) Atom
<A
>(*this, (a
->isCIE
? "CIE" : "FDE"), a
->address
, a
->size
,
3752 ld::Atom::definitionRegular
, ld::Atom::combineNever
, ld::Atom::scopeTranslationUnit
,
3753 ld::Atom::typeCFI
, ld::Atom::symbolTableNotInFinalLinkedImages
,
3754 false, false, false, ld::Atom::Alignment(0));
3755 p
+= sizeof(Atom
<A
>);
3757 this->_endAtoms
= (Atom
<A
>*)p
;
3762 template <> bool CFISection
<x86_64
>::bigEndian() { return false; }
3763 template <> bool CFISection
<x86
>::bigEndian() { return false; }
3764 template <> bool CFISection
<arm
>::bigEndian() { return false; }
3765 template <> bool CFISection
<ppc
>::bigEndian() { return true; }
3766 template <> bool CFISection
<ppc64
>::bigEndian() { return true; }
3770 void CFISection
<x86_64
>::addCiePersonalityFixups(class Parser
<x86_64
>& parser
, const CFI_Atom_Info
* cieInfo
)
3772 uint8_t personalityEncoding
= cieInfo
->u
.cieInfo
.personality
.encodingOfTargetAddress
;
3773 if ( personalityEncoding
== 0x9B ) {
3774 // compiler always produces X86_64_RELOC_GOT with addend of 4 to personality function
3775 // CFISection<x86_64>::cfiParse() set targetAddress to be symbolIndex + 4 + addressInCIE
3776 uint32_t symbolIndex
= cieInfo
->u
.cieInfo
.personality
.targetAddress
- 4
3777 - cieInfo
->address
- cieInfo
->u
.cieInfo
.personality
.offsetInCFI
;
3778 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(symbolIndex
);
3779 const char* personalityName
= parser
.nameFromSymbol(sym
);
3781 Atom
<x86_64
>* cieAtom
= this->findAtomByAddress(cieInfo
->address
);
3782 Parser
<x86_64
>::SourceLocation
src(cieAtom
, cieInfo
->u
.cieInfo
.personality
.offsetInCFI
);
3783 parser
.addFixup(src
, ld::Fixup::k1of3
, ld::Fixup::kindSetTargetAddress
, false, personalityName
);
3784 parser
.addFixup(src
, ld::Fixup::k2of3
, ld::Fixup::kindAddAddend
, 4);
3785 parser
.addFixup(src
, ld::Fixup::k3of3
, ld::Fixup::kindStoreX86PCRel32GOT
);
3787 else if ( personalityEncoding
!= 0 ) {
3788 throwf("unsupported address encoding (%02X) of personality function in CIE",
3789 personalityEncoding
);
3794 void CFISection
<x86
>::addCiePersonalityFixups(class Parser
<x86
>& parser
, const CFI_Atom_Info
* cieInfo
)
3796 uint8_t personalityEncoding
= cieInfo
->u
.cieInfo
.personality
.encodingOfTargetAddress
;
3797 if ( (personalityEncoding
== 0x9B) || (personalityEncoding
== 0x90) ) {
3798 uint32_t offsetInCFI
= cieInfo
->u
.cieInfo
.personality
.offsetInCFI
;
3799 uint32_t nlpAddr
= cieInfo
->u
.cieInfo
.personality
.targetAddress
;
3800 Atom
<x86
>* cieAtom
= this->findAtomByAddress(cieInfo
->address
);
3801 Atom
<x86
>* nlpAtom
= parser
.findAtomByAddress(nlpAddr
);
3802 assert(nlpAtom
->contentType() == ld::Atom::typeNonLazyPointer
);
3803 Parser
<x86
>::SourceLocation
src(cieAtom
, cieInfo
->u
.cieInfo
.personality
.offsetInCFI
);
3805 parser
.addFixup(src
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, nlpAtom
);
3806 parser
.addFixup(src
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, cieAtom
);
3807 parser
.addFixup(src
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, offsetInCFI
);
3808 parser
.addFixup(src
, ld::Fixup::k4of4
, ld::Fixup::kindStoreLittleEndian32
);
3810 else if ( personalityEncoding
!= 0 ) {
3811 throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding
);
3817 void CFISection
<ppc
>::addCiePersonalityFixups(class Parser
<ppc
>& parser
, const CFI_Atom_Info
* cieInfo
)
3819 uint8_t personalityEncoding
= cieInfo
->u
.cieInfo
.personality
.encodingOfTargetAddress
;
3820 if ( (personalityEncoding
== 0x9B) || (personalityEncoding
== 0x90) ) {
3821 uint32_t offsetInCFI
= cieInfo
->u
.cieInfo
.personality
.offsetInCFI
;
3822 uint32_t nlpAddr
= cieInfo
->u
.cieInfo
.personality
.targetAddress
;
3823 Atom
<ppc
>* cieAtom
= this->findAtomByAddress(cieInfo
->address
);
3824 Atom
<ppc
>* nlpAtom
= parser
.findAtomByAddress(nlpAddr
);
3825 assert(nlpAtom
->contentType() == ld::Atom::typeNonLazyPointer
);
3826 Parser
<ppc
>::SourceLocation
src(cieAtom
, cieInfo
->u
.cieInfo
.personality
.offsetInCFI
);
3828 parser
.addFixup(src
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, nlpAtom
);
3829 parser
.addFixup(src
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, cieAtom
);
3830 parser
.addFixup(src
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, offsetInCFI
);
3831 parser
.addFixup(src
, ld::Fixup::k4of4
, ld::Fixup::kindStoreBigEndian32
);
3833 else if ( personalityEncoding
!= 0 ) {
3834 throwf("unsupported address encoding (%02X) of personality function in CIE",
3835 personalityEncoding
);
3840 template <typename A
>
3841 void CFISection
<A
>::addCiePersonalityFixups(class Parser
<A
>& parser
, const CFI_Atom_Info
* cieInfo
)
3847 template <typename A
>
3848 void CFISection
<A
>::makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
& cfis
)
3850 ld::Fixup::Kind store32
= bigEndian() ? ld::Fixup::kindStoreBigEndian32
: ld::Fixup::kindStoreLittleEndian32
;
3851 ld::Fixup::Kind store64
= bigEndian() ? ld::Fixup::kindStoreBigEndian64
: ld::Fixup::kindStoreLittleEndian64
;
3853 // add all references for FDEs, including implicit group references
3854 const CFI_Atom_Info
* end
= &cfis
.array
[cfis
.count
];
3855 for(const CFI_Atom_Info
* p
= &cfis
.array
[0]; p
< end
; ++p
) {
3857 // add reference to personality function if used
3858 if ( p
->u
.cieInfo
.personality
.targetAddress
!= CFI_INVALID_ADDRESS
) {
3859 this->addCiePersonalityFixups(parser
, p
);
3864 Atom
<A
>* fdeAtom
= this->findAtomByAddress(p
->address
);
3865 // find function Atom
3866 Atom
<A
>* functionAtom
= parser
.findAtomByAddress(p
->u
.fdeInfo
.function
.targetAddress
);
3868 Atom
<A
>* cieAtom
= this->findAtomByAddress(p
->u
.fdeInfo
.cie
.targetAddress
);
3870 Atom
<A
>* lsdaAtom
= NULL
;
3871 if ( p
->u
.fdeInfo
.lsda
.targetAddress
!= CFI_INVALID_ADDRESS
) {
3872 lsdaAtom
= parser
.findAtomByAddress(p
->u
.fdeInfo
.lsda
.targetAddress
);
3874 // add reference from FDE to CIE (always 32-bit pc-rel)
3875 typename Parser
<A
>::SourceLocation
fdeToCieSrc(fdeAtom
, p
->u
.fdeInfo
.cie
.offsetInCFI
);
3876 parser
.addFixup(fdeToCieSrc
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, fdeAtom
);
3877 parser
.addFixup(fdeToCieSrc
, ld::Fixup::k2of4
, ld::Fixup::kindAddAddend
, p
->u
.fdeInfo
.cie
.offsetInCFI
);
3878 parser
.addFixup(fdeToCieSrc
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractTargetAddress
, cieAtom
);
3879 parser
.addFixup(fdeToCieSrc
, ld::Fixup::k4of4
, store32
, cieAtom
);
3881 // add reference from FDE to function
3882 typename Parser
<A
>::SourceLocation
fdeToFuncSrc(fdeAtom
, p
->u
.fdeInfo
.function
.offsetInCFI
);
3883 switch (p
->u
.fdeInfo
.function
.encodingOfTargetAddress
) {
3884 case DW_EH_PE_pcrel
|DW_EH_PE_ptr
:
3885 if ( sizeof(typename
A::P::uint_t
) == 8 ) {
3886 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, functionAtom
);
3887 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, fdeAtom
);
3888 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, p
->u
.fdeInfo
.function
.offsetInCFI
);
3889 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k4of4
, store64
);
3892 // else fall into 32-bit case
3893 case DW_EH_PE_pcrel
|DW_EH_PE_sdata4
:
3894 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, functionAtom
);
3895 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, fdeAtom
);
3896 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, p
->u
.fdeInfo
.function
.offsetInCFI
);
3897 parser
.addFixup(fdeToFuncSrc
, ld::Fixup::k4of4
, store32
);
3900 throw "unsupported encoding in FDE of pointer to function";
3903 // add reference from FDE to LSDA
3904 typename Parser
<A
>::SourceLocation
fdeToLsdaSrc(fdeAtom
, p
->u
.fdeInfo
.lsda
.offsetInCFI
);
3905 if ( lsdaAtom
!= NULL
) {
3906 switch (p
->u
.fdeInfo
.lsda
.encodingOfTargetAddress
) {
3907 case DW_EH_PE_pcrel
|DW_EH_PE_ptr
:
3908 if ( sizeof(typename
A::P::uint_t
) == 8 ) {
3909 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, lsdaAtom
);
3910 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, fdeAtom
);
3911 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, p
->u
.fdeInfo
.lsda
.offsetInCFI
);
3912 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k4of4
, store64
);
3915 // else fall into 32-bit case
3916 case DW_EH_PE_pcrel
|DW_EH_PE_sdata4
:
3917 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, lsdaAtom
);
3918 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k2of4
, ld::Fixup::kindSubtractTargetAddress
, fdeAtom
);
3919 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractAddend
, p
->u
.fdeInfo
.lsda
.offsetInCFI
);
3920 parser
.addFixup(fdeToLsdaSrc
, ld::Fixup::k4of4
, store32
);
3923 throw "unsupported encoding in FDE of pointer to LSDA";
3927 // FDE is in group lead by function atom
3928 typename Parser
<A
>::SourceLocation
fdeSrc(functionAtom
,0);
3929 parser
.addFixup(fdeSrc
, ld::Fixup::k1of1
, ld::Fixup::kindNoneGroupSubordinateFDE
, fdeAtom
);
3931 // LSDA is in group lead by function atom
3932 if ( lsdaAtom
!= NULL
) {
3933 parser
.addFixup(fdeSrc
, ld::Fixup::k1of1
, ld::Fixup::kindNoneGroupSubordinateLSDA
, lsdaAtom
);
3942 template <typename A
>
3943 const void* CFISection
<A
>::OAS::mappedAddress(pint_t addr
)
3945 if ( (_ehFrameStartAddr
<= addr
) && (addr
< _ehFrameEndAddr
) )
3946 return &_ehFrameContent
[addr
-_ehFrameStartAddr
];
3948 // requested bytes are not in __eh_frame section
3949 // this can occur when examining the instruction bytes in the __text
3950 File
<A
>& file
= _ehFrameSection
.file();
3951 for (uint32_t i
=0; i
< file
._sectionsArrayCount
; ++i
) {
3952 const macho_section
<typename
A::P
>* sect
= file
._sectionsArray
[i
]->machoSection();
3953 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
3954 if ( sect
!= NULL
) {
3955 if ( (sect
->addr() <= addr
) && (addr
< (sect
->addr()+sect
->size())) ) {
3956 return file
.fileContent() + sect
->offset() + addr
- sect
->addr();
3960 throwf("__eh_frame parsing problem. Can't find target of reference to address 0x%08llX", (uint64_t)addr
);
3965 template <typename A
>
3966 uint64_t CFISection
<A
>::OAS::getULEB128(pint_t
& logicalAddr
, pint_t end
)
3968 uintptr_t size
= (end
- logicalAddr
);
3969 libunwind::LocalAddressSpace::pint_t laddr
= (libunwind::LocalAddressSpace::pint_t
)mappedAddress(logicalAddr
);
3970 libunwind::LocalAddressSpace::pint_t sladdr
= laddr
;
3971 uint64_t result
= libunwind::LocalAddressSpace::getULEB128(laddr
, laddr
+size
);
3972 logicalAddr
+= (laddr
-sladdr
);
3976 template <typename A
>
3977 int64_t CFISection
<A
>::OAS::getSLEB128(pint_t
& logicalAddr
, pint_t end
)
3979 uintptr_t size
= (end
- logicalAddr
);
3980 libunwind::LocalAddressSpace::pint_t laddr
= (libunwind::LocalAddressSpace::pint_t
)mappedAddress(logicalAddr
);
3981 libunwind::LocalAddressSpace::pint_t sladdr
= laddr
;
3982 int64_t result
= libunwind::LocalAddressSpace::getSLEB128(laddr
, laddr
+size
);
3983 logicalAddr
+= (laddr
-sladdr
);
3987 template <typename A
>
3988 typename
A::P::uint_t CFISection
<A
>::OAS::getEncodedP(pint_t
& addr
, pint_t end
, uint8_t encoding
)
3990 pint_t startAddr
= addr
;
3995 switch (encoding
& 0x0F) {
3997 result
= getP(addr
);
3998 p
+= sizeof(pint_t
);
4001 case DW_EH_PE_uleb128
:
4002 result
= getULEB128(addr
, end
);
4004 case DW_EH_PE_udata2
:
4005 result
= get16(addr
);
4009 case DW_EH_PE_udata4
:
4010 result
= get32(addr
);
4014 case DW_EH_PE_udata8
:
4015 result
= get64(addr
);
4019 case DW_EH_PE_sleb128
:
4020 result
= getSLEB128(addr
, end
);
4022 case DW_EH_PE_sdata2
:
4023 result
= (int16_t)get16(addr
);
4027 case DW_EH_PE_sdata4
:
4028 result
= (int32_t)get32(addr
);
4032 case DW_EH_PE_sdata8
:
4033 result
= get64(addr
);
4038 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding
);
4041 // then add relative offset
4042 switch ( encoding
& 0x70 ) {
4043 case DW_EH_PE_absptr
:
4046 case DW_EH_PE_pcrel
:
4047 result
+= startAddr
;
4049 case DW_EH_PE_textrel
:
4050 throw "DW_EH_PE_textrel pointer encoding not supported";
4052 case DW_EH_PE_datarel
:
4053 throw "DW_EH_PE_datarel pointer encoding not supported";
4055 case DW_EH_PE_funcrel
:
4056 throw "DW_EH_PE_funcrel pointer encoding not supported";
4058 case DW_EH_PE_aligned
:
4059 throw "DW_EH_PE_aligned pointer encoding not supported";
4062 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding
);
4066 // Note: DW_EH_PE_indirect is only used in CIEs to refernce the personality pointer
4067 // When parsing .o files that pointer contains zero, so we don't to return that.
4068 // Instead we skip the dereference and return the address of the pointer.
4069 // if ( encoding & DW_EH_PE_indirect )
4070 // result = getP(result);
4075 template <typename A
>
4076 SymboledSection
<A
>::SymboledSection(Parser
<A
>& parser
, File
<A
>& f
, const macho_section
<typename
A::P
>* s
)
4077 : Section
<A
>(f
, s
), _type(ld::Atom::typeUnclassified
)
4079 switch ( s
->flags() & SECTION_TYPE
) {
4081 _type
= ld::Atom::typeZeroFill
;
4083 case S_MOD_INIT_FUNC_POINTERS
:
4084 _type
= ld::Atom::typeInitializerPointers
;
4086 case S_MOD_TERM_FUNC_POINTERS
:
4087 _type
= ld::Atom::typeTerminatorPointers
;
4089 case S_THREAD_LOCAL_VARIABLES
:
4090 _type
= ld::Atom::typeTLV
;
4092 case S_THREAD_LOCAL_ZEROFILL
:
4093 _type
= ld::Atom::typeTLVZeroFill
;
4095 case S_THREAD_LOCAL_REGULAR
:
4096 _type
= ld::Atom::typeTLVInitialValue
;
4098 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS
:
4099 _type
= ld::Atom::typeTLVInitializerPointers
;
4102 if ( strncmp(s
->sectname(), "__gcc_except_tab", 16) == 0 )
4103 _type
= ld::Atom::typeLSDA
;
4109 template <typename A
>
4110 bool SymboledSection
<A
>::dontDeadStrip()
4113 case ld::Atom::typeInitializerPointers
:
4114 case ld::Atom::typeTerminatorPointers
:
4117 // model an object file without MH_SUBSECTIONS_VIA_SYMBOLS as one in which nothing can be dead stripped
4118 if ( ! this->_file
.canScatterAtoms() )
4121 return Section
<A
>::dontDeadStrip();
4127 template <typename A
>
4128 uint32_t SymboledSection
<A
>::computeAtomCount(class Parser
<A
>& parser
,
4129 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
4130 const struct Parser
<A
>::CFIInfoArray
&)
4132 const pint_t startAddr
= this->_machOSection
->addr();
4133 const pint_t endAddr
= startAddr
+ this->_machOSection
->size();
4134 const uint32_t sectNum
= this->sectionNum(parser
);
4139 const macho_nlist
<P
>* sym
;
4140 while ( it
.next(parser
, sectNum
, startAddr
, endAddr
, &addr
, &size
, &sym
) ) {
4143 //fprintf(stderr, "computeAtomCount(%s,%s) => %d\n", this->segmentName(), this->sectionName(), count);
4147 template <typename A
>
4148 uint32_t SymboledSection
<A
>::appendAtoms(class Parser
<A
>& parser
, uint8_t* p
,
4149 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
4150 const struct Parser
<A
>::CFIInfoArray
&)
4152 this->_beginAtoms
= (Atom
<A
>*)p
;
4154 //fprintf(stderr, "SymboledSection::appendAtoms() in section %s\n", this->_machOSection->sectname());
4155 const pint_t startAddr
= this->_machOSection
->addr();
4156 const pint_t endAddr
= startAddr
+ this->_machOSection
->size();
4157 const uint32_t sectNum
= this->sectionNum(parser
);
4162 const macho_nlist
<P
>* label
;
4163 while ( it
.next(parser
, sectNum
, startAddr
, endAddr
, &addr
, &size
, &label
) ) {
4164 Atom
<A
>* allocatedSpace
= (Atom
<A
>*)p
;
4165 // is break because of label or CFI?
4166 if ( label
!= NULL
) {
4167 // The size is computed based on the address of the next label (or the end of the section for the last label)
4168 // If there are two labels at the same address, we want them one to be an alias of the other.
4169 // If the label is at the end of a section, it is has zero size, but is not an alias
4170 const bool isAlias
= ( (size
== 0) && (addr
< endAddr
) );
4171 new (allocatedSpace
) Atom
<A
>(*this, parser
, *label
, size
, isAlias
);
4173 this->_hasAliases
= true;
4176 new (allocatedSpace
) Atom
<A
>(*this, "anon", addr
, size
, ld::Atom::definitionRegular
, ld::Atom::combineNever
,
4177 ld::Atom::scopeTranslationUnit
, this->contentType(), ld::Atom::symbolTableNotIn
,
4178 this->dontDeadStrip(), false, false, this->alignmentForAddress(addr
));
4180 p
+= sizeof(Atom
<A
>);
4184 this->_endAtoms
= (Atom
<A
>*)p
;
4189 template <typename A
>
4190 uint32_t ImplicitSizeSection
<A
>::computeAtomCount(class Parser
<A
>& parser
,
4191 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
4192 const struct Parser
<A
>::CFIInfoArray
&)
4195 const macho_section
<P
>* sect
= this->machoSection();
4196 const pint_t startAddr
= sect
->addr();
4197 const pint_t endAddr
= startAddr
+ sect
->size();
4198 for (pint_t addr
= startAddr
; addr
< endAddr
; addr
+= elementSizeAtAddress(addr
) ) {
4199 if ( useElementAt(parser
, it
, addr
) )
4202 if ( it
.fileHasOverlappingSymbols
&& (sect
->size() != 0) && (this->combine(parser
, startAddr
) == ld::Atom::combineByNameAndContent
) ) {
4203 // if there are multiple labels in this section for the same address, then clone them into multi atoms
4204 pint_t prevSymbolAddr
= (pint_t
)(-1);
4205 uint8_t prevSymbolSectNum
= 0;
4206 for(uint32_t i
=0; i
< it
.sortedSymbolCount
; ++i
) {
4207 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(it
.sortedSymbolIndexes
[i
]);
4208 const pint_t symbolAddr
= sym
.n_value();
4209 const pint_t symbolSectNum
= sym
.n_sect();
4210 if ( (symbolAddr
== prevSymbolAddr
) && (prevSymbolSectNum
== symbolSectNum
) && (symbolSectNum
== this->sectionNum(parser
)) ) {
4213 prevSymbolAddr
= symbolAddr
;
4214 prevSymbolSectNum
= symbolSectNum
;
4220 template <typename A
>
4221 uint32_t ImplicitSizeSection
<A
>::appendAtoms(class Parser
<A
>& parser
, uint8_t* p
,
4222 struct Parser
<A
>::LabelAndCFIBreakIterator
& it
,
4223 const struct Parser
<A
>::CFIInfoArray
&)
4225 this->_beginAtoms
= (Atom
<A
>*)p
;
4227 const macho_section
<P
>* sect
= this->machoSection();
4228 const pint_t startAddr
= sect
->addr();
4229 const pint_t endAddr
= startAddr
+ sect
->size();
4230 const uint32_t sectNum
= this->sectionNum(parser
);
4231 //fprintf(stderr, "ImplicitSizeSection::appendAtoms() in section %s\n", sect->sectname());
4235 const macho_nlist
<P
>* foundLabel
;
4236 Atom
<A
>* allocatedSpace
;
4237 while ( it
.next(parser
, sectNum
, startAddr
, endAddr
, &foundAddr
, &size
, &foundLabel
) ) {
4238 if ( foundLabel
!= NULL
) {
4239 pint_t labeledAtomSize
= this->elementSizeAtAddress(foundAddr
);
4240 allocatedSpace
= (Atom
<A
>*)p
;
4241 if ( this->ignoreLabel(parser
.nameFromSymbol(*foundLabel
)) ) {
4242 //fprintf(stderr, " 0x%08llX make annon\n", (uint64_t)foundAddr);
4243 new (allocatedSpace
) Atom
<A
>(*this, this->unlabeledAtomName(parser
, foundAddr
), foundAddr
,
4244 this->elementSizeAtAddress(foundAddr
), this->definition(),
4245 this->combine(parser
, foundAddr
), this->scopeAtAddress(parser
, foundAddr
),
4246 this->contentType(), this->symbolTableInclusion(),
4247 this->dontDeadStrip(), false, false, this->alignmentForAddress(foundAddr
));
4250 // make named atom for label
4251 //fprintf(stderr, " 0x%08llX make labeled\n", (uint64_t)foundAddr);
4252 new (allocatedSpace
) Atom
<A
>(*this, parser
, *foundLabel
, labeledAtomSize
);
4255 p
+= sizeof(Atom
<A
>);
4256 foundAddr
+= labeledAtomSize
;
4257 size
-= labeledAtomSize
;
4259 // some number of anonymous atoms
4260 for (pint_t addr
= foundAddr
; addr
< (foundAddr
+size
); addr
+= elementSizeAtAddress(addr
) ) {
4261 // make anon atoms for area before label
4262 if ( this->useElementAt(parser
, it
, addr
) ) {
4263 //fprintf(stderr, " 0x%08llX make annon\n", (uint64_t)addr);
4264 allocatedSpace
= (Atom
<A
>*)p
;
4265 new (allocatedSpace
) Atom
<A
>(*this, this->unlabeledAtomName(parser
, addr
), addr
, this->elementSizeAtAddress(addr
),
4266 this->definition(), this->combine(parser
, addr
), this->scopeAtAddress(parser
, addr
),
4267 this->contentType(), this->symbolTableInclusion(),
4268 this->dontDeadStrip(), false, false, this->alignmentForAddress(addr
));
4270 p
+= sizeof(Atom
<A
>);
4275 this->_endAtoms
= (Atom
<A
>*)p
;
4281 template <typename A
>
4282 unsigned long Literal4Section
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4284 const uint32_t* literalContent
= (uint32_t*)atom
->contentPointer();
4285 return *literalContent
;
4288 template <typename A
>
4289 bool Literal4Section
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4290 const ld::IndirectBindingTable
& ind
) const
4292 assert(this->type() == rhs
.section().type());
4293 const uint32_t* literalContent
= (uint32_t*)atom
->contentPointer();
4295 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4296 assert(rhsAtom
!= NULL
);
4297 if ( rhsAtom
!= NULL
) {
4298 const uint32_t* rhsLiteralContent
= (uint32_t*)rhsAtom
->contentPointer();
4299 return (*literalContent
== *rhsLiteralContent
);
4305 template <typename A
>
4306 unsigned long Literal8Section
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4309 const uint64_t* literalContent
= (uint64_t*)atom
->contentPointer();
4310 return *literalContent
;
4312 unsigned long hash
= 5381;
4313 const uint8_t* byteContent
= atom
->contentPointer();
4314 for (int i
=0; i
< 8; ++i
) {
4315 hash
= hash
* 33 + byteContent
[i
];
4321 template <typename A
>
4322 bool Literal8Section
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4323 const ld::IndirectBindingTable
& ind
) const
4325 if ( rhs
.section().type() != ld::Section::typeLiteral8
)
4327 assert(this->type() == rhs
.section().type());
4328 const uint64_t* literalContent
= (uint64_t*)atom
->contentPointer();
4330 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4331 assert(rhsAtom
!= NULL
);
4332 if ( rhsAtom
!= NULL
) {
4333 const uint64_t* rhsLiteralContent
= (uint64_t*)rhsAtom
->contentPointer();
4334 return (*literalContent
== *rhsLiteralContent
);
4340 template <typename A
>
4341 unsigned long Literal16Section
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4343 unsigned long hash
= 5381;
4344 const uint8_t* byteContent
= atom
->contentPointer();
4345 for (int i
=0; i
< 16; ++i
) {
4346 hash
= hash
* 33 + byteContent
[i
];
4351 template <typename A
>
4352 bool Literal16Section
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4353 const ld::IndirectBindingTable
& ind
) const
4355 if ( rhs
.section().type() != ld::Section::typeLiteral16
)
4357 assert(this->type() == rhs
.section().type());
4358 const uint64_t* literalContent
= (uint64_t*)atom
->contentPointer();
4360 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4361 assert(rhsAtom
!= NULL
);
4362 if ( rhsAtom
!= NULL
) {
4363 const uint64_t* rhsLiteralContent
= (uint64_t*)rhsAtom
->contentPointer();
4364 return ((literalContent
[0] == rhsLiteralContent
[0]) && (literalContent
[1] == rhsLiteralContent
[1]));
4371 template <typename A
>
4372 typename
A::P::uint_t CStringSection
<A
>::elementSizeAtAddress(pint_t addr
)
4374 const macho_section
<P
>* sect
= this->machoSection();
4375 const char* stringContent
= (char*)(this->file().fileContent() + sect
->offset() + addr
- sect
->addr());
4376 return strlen(stringContent
) + 1;
4379 template <typename A
>
4380 bool CStringSection
<A
>::useElementAt(Parser
<A
>& parser
, struct Parser
<A
>::LabelAndCFIBreakIterator
& it
, pint_t addr
)
4385 template <typename A
>
4386 Atom
<A
>* CStringSection
<A
>::findAtomByAddress(pint_t addr
)
4388 Atom
<A
>* result
= this->findContentAtomByAddress(addr
, this->_beginAtoms
, this->_endAtoms
);
4392 template <typename A
>
4393 unsigned long CStringSection
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4395 unsigned long hash
= 5381;
4396 const char* stringContent
= (char*)atom
->contentPointer();
4397 for (const char* s
= stringContent
; *s
!= '\0'; ++s
) {
4398 hash
= hash
* 33 + *s
;
4404 template <typename A
>
4405 bool CStringSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4406 const ld::IndirectBindingTable
& ind
) const
4408 if ( rhs
.section().type() != ld::Section::typeCString
)
4410 assert(this->type() == rhs
.section().type());
4411 assert(strcmp(this->sectionName(), rhs
.section().sectionName())== 0);
4412 assert(strcmp(this->segmentName(), rhs
.section().segmentName())== 0);
4413 const char* stringContent
= (char*)atom
->contentPointer();
4415 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4416 assert(rhsAtom
!= NULL
);
4417 if ( rhsAtom
!= NULL
) {
4418 if ( atom
->_size
!= rhsAtom
->_size
)
4420 const char* rhsStringContent
= (char*)rhsAtom
->contentPointer();
4421 return (strcmp(stringContent
, rhsStringContent
) == 0);
4428 ld::Fixup::Kind NonLazyPointerSection
<x86
>::fixupKind()
4430 return ld::Fixup::kindStoreLittleEndian32
;
4434 ld::Fixup::Kind NonLazyPointerSection
<arm
>::fixupKind()
4436 return ld::Fixup::kindStoreLittleEndian32
;
4440 ld::Fixup::Kind NonLazyPointerSection
<ppc
>::fixupKind()
4442 return ld::Fixup::kindStoreBigEndian32
;
4446 ld::Fixup::Kind NonLazyPointerSection
<ppc64
>::fixupKind()
4448 return ld::Fixup::kindStoreBigEndian64
;
4452 void NonLazyPointerSection
<x86_64
>::makeFixups(class Parser
<x86_64
>& parser
, const struct Parser
<x86_64
>::CFIInfoArray
&)
4454 assert(0 && "x86_64 should not have non-lazy-pointer sections in .o files");
4457 template <typename A
>
4458 void NonLazyPointerSection
<A
>::makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&)
4460 // add references for each NLP atom based on indirect symbol table
4461 const macho_section
<P
>* sect
= this->machoSection();
4462 const pint_t endAddr
= sect
->addr() + sect
->size();
4463 for( pint_t addr
= sect
->addr(); addr
< endAddr
; addr
+= sizeof(pint_t
)) {
4464 typename Parser
<A
>::SourceLocation src
;
4465 typename Parser
<A
>::TargetDesc target
;
4466 src
.atom
= this->findAtomByAddress(addr
);
4467 src
.offsetInAtom
= 0;
4468 uint32_t symIndex
= parser
.symbolIndexFromIndirectSectionAddress(addr
, sect
);
4471 target
.weakImport
= false;
4473 if ( symIndex
== INDIRECT_SYMBOL_LOCAL
) {
4474 // use direct reference for local symbols
4475 const pint_t
* nlpContent
= (pint_t
*)(this->file().fileContent() + sect
->offset() + addr
- sect
->addr());
4476 pint_t targetAddr
= P::getP(*nlpContent
);
4477 target
.atom
= parser
.findAtomByAddress(targetAddr
);
4478 target
.weakImport
= false;
4479 target
.addend
= (targetAddr
- target
.atom
->objectAddress());
4480 // <rdar://problem/8385011> if pointer to thumb function, mask of thumb bit (not an addend of +1)
4481 if ( target
.atom
->isThumb() )
4482 target
.addend
&= (-2);
4483 assert(src
.atom
->combine() == ld::Atom::combineNever
);
4486 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(symIndex
);
4487 // use direct reference for local symbols
4488 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && ((sym
.n_type() & N_EXT
) == 0) ) {
4489 parser
.findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), target
);
4490 assert(src
.atom
->combine() == ld::Atom::combineNever
);
4493 target
.name
= parser
.nameFromSymbol(sym
);
4494 target
.weakImport
= parser
.weakImportFromSymbol(sym
);
4495 assert(src
.atom
->combine() == ld::Atom::combineByNameAndReferences
);
4498 parser
.addFixups(src
, this->fixupKind(), target
);
4502 template <typename A
>
4503 ld::Atom::Combine NonLazyPointerSection
<A
>::combine(Parser
<A
>& parser
, pint_t addr
)
4505 const macho_section
<P
>* sect
= this->machoSection();
4506 uint32_t symIndex
= parser
.symbolIndexFromIndirectSectionAddress(addr
, sect
);
4507 if ( symIndex
== INDIRECT_SYMBOL_LOCAL
)
4508 return ld::Atom::combineNever
;
4510 // don't coalesce non-lazy-pointers to local symbols
4511 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(symIndex
);
4512 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && ((sym
.n_type() & N_EXT
) == 0) )
4513 return ld::Atom::combineNever
;
4515 return ld::Atom::combineByNameAndReferences
;
4518 template <typename A
>
4519 const char* NonLazyPointerSection
<A
>::targetName(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
)
4521 assert(atom
->combine() == ld::Atom::combineByNameAndReferences
);
4522 assert(atom
->fixupCount() == 1);
4523 ld::Fixup::iterator fit
= atom
->fixupsBegin();
4524 const char* name
= NULL
;
4525 switch ( fit
->binding
) {
4526 case ld::Fixup::bindingByNameUnbound
:
4529 case ld::Fixup::bindingByContentBound
:
4530 name
= fit
->u
.target
->name();
4532 case ld::Fixup::bindingsIndirectlyBound
:
4533 name
= ind
.indirectName(fit
->u
.bindingIndex
);
4538 assert(name
!= NULL
);
4542 template <typename A
>
4543 unsigned long NonLazyPointerSection
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4545 assert(atom
->combine() == ld::Atom::combineByNameAndReferences
);
4546 unsigned long hash
= 9508;
4547 for (const char* s
= this->targetName(atom
, ind
); *s
!= '\0'; ++s
) {
4548 hash
= hash
* 33 + *s
;
4553 template <typename A
>
4554 bool NonLazyPointerSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4555 const ld::IndirectBindingTable
& indirectBindingTable
) const
4557 if ( rhs
.section().type() != ld::Section::typeNonLazyPointer
)
4559 assert(this->type() == rhs
.section().type());
4560 // there can be many non-lazy pointer in different section names
4561 // we only want to coalesce in same section name
4562 if ( *this != rhs
.section() )
4564 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4565 assert(rhsAtom
!= NULL
);
4566 const char* thisName
= this->targetName(atom
, indirectBindingTable
);
4567 const char* rhsName
= this->targetName(rhsAtom
, indirectBindingTable
);
4568 return (strcmp(thisName
, rhsName
) == 0);
4571 template <typename A
>
4572 ld::Atom::Scope NonLazyPointerSection
<A
>::scopeAtAddress(Parser
<A
>& parser
, pint_t addr
)
4574 const macho_section
<P
>* sect
= this->machoSection();
4575 uint32_t symIndex
= parser
.symbolIndexFromIndirectSectionAddress(addr
, sect
);
4576 if ( symIndex
== INDIRECT_SYMBOL_LOCAL
)
4577 return ld::Atom::scopeTranslationUnit
;
4579 return ld::Atom::scopeLinkageUnit
;
4583 template <typename A
>
4584 const uint8_t* CFStringSection
<A
>::targetContent(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
,
4585 ContentType
* ct
, unsigned int* count
)
4587 *ct
= contentUnknown
;
4588 for (ld::Fixup::iterator fit
=atom
->fixupsBegin(), end
=atom
->fixupsEnd(); fit
!= end
; ++fit
) {
4589 const ld::Atom
* targetAtom
= NULL
;
4590 switch ( fit
->binding
) {
4591 case ld::Fixup::bindingByNameUnbound
:
4592 // ignore reference to ___CFConstantStringClassReference
4593 // we are just looking for reference to backing string data
4594 assert(fit
->offsetInAtom
== 0);
4595 assert(strcmp(fit
->u
.name
, "___CFConstantStringClassReference") == 0);
4597 case ld::Fixup::bindingDirectlyBound
:
4598 case ld::Fixup::bindingByContentBound
:
4599 targetAtom
= fit
->u
.target
;
4601 case ld::Fixup::bindingsIndirectlyBound
:
4602 targetAtom
= ind
.indirectAtom(fit
->u
.bindingIndex
);
4605 assert(0 && "bad binding type");
4607 assert(targetAtom
!= NULL
);
4608 const Atom
<A
>* target
= dynamic_cast<const Atom
<A
>*>(targetAtom
);
4609 if ( targetAtom
->section().type() == ld::Section::typeCString
) {
4611 *count
= targetAtom
->size();
4613 else if ( targetAtom
->section().type() == ld::Section::typeUTF16Strings
) {
4615 *count
= (targetAtom
->size()+1)/2; // round up incase of buggy compiler that has only one trailing zero byte
4617 assert(target
!= NULL
);
4618 return target
->contentPointer();
4624 template <typename A
>
4625 unsigned long CFStringSection
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4627 // base hash of CFString on hash of cstring it wraps
4630 unsigned int charCount
;
4631 const uint8_t* content
= this->targetContent(atom
, ind
, &cType
, &charCount
);
4635 for (const char* s
= (char*)content
; *s
!= '\0'; ++s
) {
4636 hash
= hash
* 33 + *s
;
4641 --charCount
; // don't add last 0x0000 to hash because some buggy compilers only have trailing single byte
4642 for (const uint16_t* s
= (uint16_t*)content
; charCount
> 0; ++s
, --charCount
) {
4643 hash
= hash
* 1025 + *s
;
4646 case contentUnknown
:
4653 template <typename A
>
4654 bool CFStringSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4655 const ld::IndirectBindingTable
& indirectBindingTable
) const
4659 if ( rhs
.section().type() != ld::Section::typeCFString
)
4661 assert(this->type() == rhs
.section().type());
4662 assert(strcmp(this->sectionName(), "__cfstring") == 0);
4664 ContentType thisType
;
4665 unsigned int charCount
;
4666 const uint8_t* cstringContent
= this->targetContent(atom
, indirectBindingTable
, &thisType
, &charCount
);
4667 ContentType rhsType
;
4668 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4669 assert(rhsAtom
!= NULL
);
4670 unsigned int rhsCharCount
;
4671 const uint8_t* rhsStringContent
= this->targetContent(rhsAtom
, indirectBindingTable
, &rhsType
, &rhsCharCount
);
4673 if ( thisType
!= rhsType
)
4676 // no need to compare content of pointers are already the same
4677 if ( cstringContent
== rhsStringContent
)
4680 // no need to compare content if size is different
4681 if ( charCount
!= rhsCharCount
)
4684 switch ( thisType
) {
4686 return (strcmp((char*)cstringContent
, (char*)rhsStringContent
) == 0);
4689 const uint16_t* cstringContent16
= (uint16_t*)cstringContent
;
4690 const uint16_t* rhsStringContent16
= (uint16_t*)rhsStringContent
;
4691 for (unsigned int i
= 0; i
< charCount
; ++i
) {
4692 if ( cstringContent16
[i
] != rhsStringContent16
[i
] )
4697 case contentUnknown
:
4704 template <typename A
>
4705 typename
A::P::uint_t ObjC1ClassSection
<A
>::elementSizeAtAddress(pint_t addr
)
4707 // nominal size for each class is 48 bytes, but sometimes the compiler
4708 // over aligns and there is padding after class data
4709 const macho_section
<P
>* sct
= this->machoSection();
4710 uint32_t align
= 1 << sct
->align();
4711 uint32_t size
= ((12 * sizeof(pint_t
)) + align
-1) & (-align
);
4715 template <typename A
>
4716 const char* ObjC1ClassSection
<A
>::unlabeledAtomName(Parser
<A
>& parser
, pint_t addr
)
4718 // 8-bytes into class object is pointer to class name
4719 const macho_section
<P
>* sct
= this->machoSection();
4720 uint32_t classObjcFileOffset
= sct
->offset() - sct
->addr() + addr
;
4721 const uint8_t* mappedFileContent
= this->file().fileContent();
4722 pint_t nameAddr
= P::getP(*((pint_t
*)(mappedFileContent
+classObjcFileOffset
+2*sizeof(pint_t
))));
4724 // find section containing string address to get string bytes
4725 const macho_section
<P
>* const sections
= parser
.firstMachOSection();
4726 const uint32_t sectionCount
= parser
.machOSectionCount();
4727 for (uint32_t i
=0; i
< sectionCount
; ++i
) {
4728 const macho_section
<P
>* aSect
= §ions
[i
];
4729 if ( (aSect
->addr() <= nameAddr
) && (nameAddr
< (aSect
->addr()+aSect
->size())) ) {
4730 assert((aSect
->flags() & SECTION_TYPE
) == S_CSTRING_LITERALS
);
4731 uint32_t nameFileOffset
= aSect
->offset() - aSect
->addr() + nameAddr
;
4732 const char* name
= (char*)mappedFileContent
+ nameFileOffset
;
4733 // spin through symbol table to find absolute symbol corresponding to this class
4734 for (uint32_t s
=0; s
< parser
.symbolCount(); ++s
) {
4735 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(s
);
4736 if ( (sym
.n_type() & N_TYPE
) != N_ABS
)
4738 const char* absName
= parser
.nameFromSymbol(sym
);
4739 if ( strncmp(absName
, ".objc_class_name_", 17) == 0 ) {
4740 if ( strcmp(&absName
[17], name
) == 0 )
4744 assert(0 && "obj class name not found in symbol table");
4747 assert(0 && "obj class name not found");
4748 return "unknown objc class";
4752 template <typename A
>
4753 const char* ObjC2ClassRefsSection
<A
>::targetClassName(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4755 assert(atom
->fixupCount() == 1);
4756 ld::Fixup::iterator fit
= atom
->fixupsBegin();
4757 const char* className
= NULL
;
4758 switch ( fit
->binding
) {
4759 case ld::Fixup::bindingByNameUnbound
:
4760 className
= fit
->u
.name
;
4762 case ld::Fixup::bindingDirectlyBound
:
4763 case ld::Fixup::bindingByContentBound
:
4764 className
= fit
->u
.target
->name();
4766 case ld::Fixup::bindingsIndirectlyBound
:
4767 className
= ind
.indirectName(fit
->u
.bindingIndex
);
4770 assert(0 && "unsupported binding in objc2 class ref section");
4772 assert(className
!= NULL
);
4777 template <typename A
>
4778 unsigned long ObjC2ClassRefsSection
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4780 unsigned long hash
= 978;
4781 for (const char* s
= targetClassName(atom
, ind
); *s
!= '\0'; ++s
) {
4782 hash
= hash
* 33 + *s
;
4787 template <typename A
>
4788 bool ObjC2ClassRefsSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4789 const ld::IndirectBindingTable
& indirectBindingTable
) const
4791 assert(this->type() == rhs
.section().type());
4792 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4793 assert(rhsAtom
!= NULL
);
4794 const char* thisClassName
= targetClassName(atom
, indirectBindingTable
);
4795 const char* rhsClassName
= targetClassName(rhsAtom
, indirectBindingTable
);
4796 return (strcmp(thisClassName
, rhsClassName
) == 0);
4800 template <typename A
>
4801 const char* Objc1ClassReferences
<A
>::targetCString(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4803 assert(atom
->fixupCount() == 2);
4804 ld::Fixup::iterator fit
= atom
->fixupsBegin();
4805 if ( fit
->kind
== ld::Fixup::kindSetTargetAddress
)
4807 const ld::Atom
* targetAtom
= NULL
;
4808 switch ( fit
->binding
) {
4809 case ld::Fixup::bindingByContentBound
:
4810 targetAtom
= fit
->u
.target
;
4812 case ld::Fixup::bindingsIndirectlyBound
:
4813 targetAtom
= ind
.indirectAtom(fit
->u
.bindingIndex
);
4814 if ( targetAtom
== NULL
) {
4815 fprintf(stderr
, "missing target named %s\n", ind
.indirectName(fit
->u
.bindingIndex
));
4821 assert(targetAtom
!= NULL
);
4822 const Atom
<A
>* target
= dynamic_cast<const Atom
<A
>*>(targetAtom
);
4823 assert(target
!= NULL
);
4824 return (char*)target
->contentPointer();
4828 template <typename A
>
4829 const char* PointerToCStringSection
<A
>::targetCString(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4831 assert(atom
->fixupCount() == 1);
4832 ld::Fixup::iterator fit
= atom
->fixupsBegin();
4833 const ld::Atom
* targetAtom
= NULL
;
4834 switch ( fit
->binding
) {
4835 case ld::Fixup::bindingByContentBound
:
4836 targetAtom
= fit
->u
.target
;
4838 case ld::Fixup::bindingsIndirectlyBound
:
4839 targetAtom
= ind
.indirectAtom(fit
->u
.bindingIndex
);
4844 assert(targetAtom
!= NULL
);
4845 const Atom
<A
>* target
= dynamic_cast<const Atom
<A
>*>(targetAtom
);
4846 assert(target
!= NULL
);
4847 return (char*)target
->contentPointer();
4850 template <typename A
>
4851 unsigned long PointerToCStringSection
<A
>::contentHash(const class Atom
<A
>* atom
,
4852 const ld::IndirectBindingTable
& indirectBindingTable
) const
4854 // make hash from section name and target cstring name
4855 unsigned long hash
= 123;
4856 for (const char* s
= this->sectionName(); *s
!= '\0'; ++s
) {
4857 hash
= hash
* 33 + *s
;
4859 for (const char* s
= this->targetCString(atom
, indirectBindingTable
); *s
!= '\0'; ++s
) {
4860 hash
= hash
* 33 + *s
;
4865 template <typename A
>
4866 bool PointerToCStringSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4867 const ld::IndirectBindingTable
& indirectBindingTable
) const
4869 assert(this->type() == rhs
.section().type());
4870 // there can be pointers-to-cstrings in different section names
4871 // we only want to coalesce in same section name
4872 if ( *this != rhs
.section() )
4875 // get string content for this
4876 const char* cstringContent
= this->targetCString(atom
, indirectBindingTable
);
4877 const Atom
<A
>* rhsAtom
= dynamic_cast<const Atom
<A
>*>(&rhs
);
4878 assert(rhsAtom
!= NULL
);
4879 const char* rhsCstringContent
= this->targetCString(rhsAtom
, indirectBindingTable
);
4881 assert(cstringContent
!= NULL
);
4882 assert(rhsCstringContent
!= NULL
);
4883 return (strcmp(cstringContent
, rhsCstringContent
) == 0);
4888 template <typename A
>
4889 unsigned long UTF16StringSection
<A
>::contentHash(const class Atom
<A
>* atom
, const ld::IndirectBindingTable
& ind
) const
4891 unsigned long hash
= 5381;
4892 const uint16_t* stringContent
= (uint16_t*)atom
->contentPointer();
4893 // some buggy compilers end utf16 data with single byte, so don't use last word in hash computation
4894 unsigned int count
= (atom
->size()/2) - 1;
4895 for (const uint16_t* s
= stringContent
; count
> 0; ++s
, --count
) {
4896 hash
= hash
* 33 + *s
;
4901 template <typename A
>
4902 bool UTF16StringSection
<A
>::canCoalesceWith(const class Atom
<A
>* atom
, const ld::Atom
& rhs
,
4903 const ld::IndirectBindingTable
& ind
) const
4905 if ( rhs
.section().type() != ld::Section::typeUTF16Strings
)
4918 uint32_t Section
<x86_64
>::x86_64PcRelOffset(uint8_t r_type
)
4921 case X86_64_RELOC_SIGNED
:
4923 case X86_64_RELOC_SIGNED_1
:
4925 case X86_64_RELOC_SIGNED_2
:
4927 case X86_64_RELOC_SIGNED_4
:
4935 bool Section
<x86_64
>::addRelocFixup(class Parser
<x86_64
>& parser
, const macho_relocation_info
<P
>* reloc
)
4937 const macho_section
<P
>* sect
= this->machoSection();
4938 uint64_t srcAddr
= sect
->addr() + reloc
->r_address();
4939 Parser
<x86_64
>::SourceLocation src
;
4940 Parser
<x86_64
>::TargetDesc target
;
4941 Parser
<x86_64
>::TargetDesc toTarget
;
4942 src
.atom
= this->findAtomByAddress(srcAddr
);
4943 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
4944 const uint8_t* fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
4945 uint64_t contentValue
= 0;
4946 const macho_relocation_info
<x86_64::P
>* nextReloc
= &reloc
[1];
4947 bool result
= false;
4948 bool useDirectBinding
;
4949 switch ( reloc
->r_length() ) {
4951 contentValue
= *fixUpPtr
;
4954 contentValue
= (int64_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr
));
4957 contentValue
= (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr
));
4960 contentValue
= E::get64(*((uint64_t*)fixUpPtr
));
4965 target
.weakImport
= false;
4967 if ( reloc
->r_extern() ) {
4968 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(reloc
->r_symbolnum());
4969 // use direct reference for local symbols
4970 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && (((sym
.n_type() & N_EXT
) == 0) || (parser
.nameFromSymbol(sym
)[0] == 'L')) ) {
4971 parser
.findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), target
);
4972 target
.addend
+= contentValue
;
4975 target
.name
= parser
.nameFromSymbol(sym
);
4976 target
.weakImport
= parser
.weakImportFromSymbol(sym
);
4977 target
.addend
= contentValue
;
4979 // cfstrings should always use direct reference to backing store
4980 if ( (this->type() == ld::Section::typeCFString
) && (src
.offsetInAtom
!= 0) ) {
4981 parser
.findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), target
);
4982 target
.addend
= contentValue
;
4986 if ( reloc
->r_pcrel() )
4987 contentValue
+= srcAddr
+ x86_64PcRelOffset(reloc
->r_type());
4988 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), target
);
4990 switch ( reloc
->r_type() ) {
4991 case X86_64_RELOC_UNSIGNED
:
4992 if ( reloc
->r_pcrel() )
4993 throw "pcrel and X86_64_RELOC_UNSIGNED not supported";
4994 switch ( reloc
->r_length() ) {
4997 throw "length < 2 and X86_64_RELOC_UNSIGNED not supported";
4999 parser
.addFixups(src
, ld::Fixup::kindStoreLittleEndian32
, target
);
5002 parser
.addFixups(src
, ld::Fixup::kindStoreLittleEndian64
, target
);
5006 case X86_64_RELOC_SIGNED
:
5007 case X86_64_RELOC_SIGNED_1
:
5008 case X86_64_RELOC_SIGNED_2
:
5009 case X86_64_RELOC_SIGNED_4
:
5010 if ( ! reloc
->r_pcrel() )
5011 throw "not pcrel and X86_64_RELOC_SIGNED* not supported";
5012 if ( reloc
->r_length() != 2 )
5013 throw "length != 2 and X86_64_RELOC_SIGNED* not supported";
5014 switch ( reloc
->r_type() ) {
5015 case X86_64_RELOC_SIGNED
:
5016 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32
, target
);
5018 case X86_64_RELOC_SIGNED_1
:
5019 if ( reloc
->r_extern() )
5021 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32_1
, target
);
5023 case X86_64_RELOC_SIGNED_2
:
5024 if ( reloc
->r_extern() )
5026 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32_2
, target
);
5028 case X86_64_RELOC_SIGNED_4
:
5029 if ( reloc
->r_extern() )
5031 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32_4
, target
);
5035 case X86_64_RELOC_BRANCH
:
5036 if ( ! reloc
->r_pcrel() )
5037 throw "not pcrel and X86_64_RELOC_BRANCH not supported";
5038 switch ( reloc
->r_length() ) {
5040 if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_probe$", 16) == 0) ) {
5041 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindStoreX86DtraceCallSiteNop
, false, target
.name
);
5042 parser
.addDtraceExtraInfos(src
, &target
.name
[16]);
5044 else if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_isenabled$", 20) == 0) ) {
5045 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindStoreX86DtraceIsEnableSiteClear
, false, target
.name
);
5046 parser
.addDtraceExtraInfos(src
, &target
.name
[20]);
5049 parser
.addFixups(src
, ld::Fixup::kindStoreX86BranchPCRel32
, target
);
5053 parser
.addFixups(src
, ld::Fixup::kindStoreX86BranchPCRel8
, target
);
5056 throwf("length=%d and X86_64_RELOC_BRANCH not supported", reloc
->r_length());
5059 case X86_64_RELOC_GOT
:
5060 if ( ! reloc
->r_extern() )
5061 throw "not extern and X86_64_RELOC_GOT not supported";
5062 if ( ! reloc
->r_pcrel() )
5063 throw "not pcrel and X86_64_RELOC_GOT not supported";
5064 if ( reloc
->r_length() != 2 )
5065 throw "length != 2 and X86_64_RELOC_GOT not supported";
5066 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32GOT
, target
);
5068 case X86_64_RELOC_GOT_LOAD
:
5069 if ( ! reloc
->r_extern() )
5070 throw "not extern and X86_64_RELOC_GOT_LOAD not supported";
5071 if ( ! reloc
->r_pcrel() )
5072 throw "not pcrel and X86_64_RELOC_GOT_LOAD not supported";
5073 if ( reloc
->r_length() != 2 )
5074 throw "length != 2 and X86_64_RELOC_GOT_LOAD not supported";
5075 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32GOTLoad
, target
);
5077 case X86_64_RELOC_SUBTRACTOR
:
5078 if ( reloc
->r_pcrel() )
5079 throw "X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
5080 if ( reloc
->r_length() < 2 )
5081 throw "X86_64_RELOC_SUBTRACTOR must have r_length of 2 or 3";
5082 if ( !reloc
->r_extern() )
5083 throw "X86_64_RELOC_SUBTRACTOR must have r_extern=1";
5084 if ( nextReloc
->r_type() != X86_64_RELOC_UNSIGNED
)
5085 throw "X86_64_RELOC_SUBTRACTOR must be followed by X86_64_RELOC_UNSIGNED";
5087 if ( nextReloc
->r_pcrel() )
5088 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
5089 if ( nextReloc
->r_length() != reloc
->r_length() )
5090 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR must have same r_length";
5091 if ( nextReloc
->r_extern() ) {
5092 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(nextReloc
->r_symbolnum());
5093 // use direct reference for local symbols
5094 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && (((sym
.n_type() & N_EXT
) == 0) || (parser
.nameFromSymbol(sym
)[0] == 'L')) ) {
5095 parser
.findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), toTarget
);
5096 toTarget
.addend
= contentValue
;
5097 useDirectBinding
= true;
5100 toTarget
.name
= parser
.nameFromSymbol(sym
);
5101 toTarget
.weakImport
= parser
.weakImportFromSymbol(sym
);
5102 toTarget
.addend
= contentValue
;
5103 useDirectBinding
= false;
5107 parser
.findTargetFromAddressAndSectionNum(contentValue
, nextReloc
->r_symbolnum(), toTarget
);
5108 useDirectBinding
= (toTarget
.atom
->scope() == ld::Atom::scopeTranslationUnit
);
5110 if ( useDirectBinding
)
5111 parser
.addFixup(src
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, toTarget
.atom
);
5113 parser
.addFixup(src
, ld::Fixup::k1of4
, ld::Fixup::kindSetTargetAddress
, toTarget
.weakImport
, toTarget
.name
);
5114 parser
.addFixup(src
, ld::Fixup::k2of4
, ld::Fixup::kindAddAddend
, toTarget
.addend
);
5115 if ( target
.atom
== NULL
)
5116 parser
.addFixup(src
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractTargetAddress
, false, target
.name
);
5118 parser
.addFixup(src
, ld::Fixup::k3of4
, ld::Fixup::kindSubtractTargetAddress
, target
.atom
);
5119 if ( reloc
->r_length() == 2 )
5120 parser
.addFixup(src
, ld::Fixup::k4of4
, ld::Fixup::kindStoreLittleEndian32
);
5122 parser
.addFixup(src
, ld::Fixup::k4of4
, ld::Fixup::kindStoreLittleEndian64
);
5124 case X86_64_RELOC_TLV
:
5125 if ( ! reloc
->r_extern() )
5126 throw "not extern and X86_64_RELOC_TLV not supported";
5127 if ( ! reloc
->r_pcrel() )
5128 throw "not pcrel and X86_64_RELOC_TLV not supported";
5129 if ( reloc
->r_length() != 2 )
5130 throw "length != 2 and X86_64_RELOC_TLV not supported";
5131 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32TLVLoad
, target
);
5134 throwf("unknown relocation type %d", reloc
->r_type());
5142 bool Section
<x86
>::addRelocFixup(class Parser
<x86
>& parser
, const macho_relocation_info
<P
>* reloc
)
5144 const macho_section
<P
>* sect
= this->machoSection();
5146 const uint8_t* fixUpPtr
;
5147 uint32_t contentValue
= 0;
5148 ld::Fixup::Kind kind
= ld::Fixup::kindNone
;
5149 Parser
<x86
>::SourceLocation src
;
5150 Parser
<x86
>::TargetDesc target
;
5152 if ( (reloc
->r_address() & R_SCATTERED
) == 0 ) {
5153 srcAddr
= sect
->addr() + reloc
->r_address();
5154 src
.atom
= this->findAtomByAddress(srcAddr
);
5155 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5156 fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
5157 switch ( reloc
->r_type() ) {
5158 case GENERIC_RELOC_VANILLA
:
5159 switch ( reloc
->r_length() ) {
5161 contentValue
= (int32_t)(int8_t)*fixUpPtr
;
5162 if ( reloc
->r_pcrel() ) {
5163 kind
= ld::Fixup::kindStoreX86BranchPCRel8
;
5164 contentValue
+= srcAddr
+ sizeof(uint8_t);
5167 throw "r_length=0 and r_pcrel=0 not supported";
5170 contentValue
= (int32_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr
));
5171 if ( reloc
->r_pcrel() ) {
5172 kind
= ld::Fixup::kindStoreX86PCRel16
;
5173 contentValue
+= srcAddr
+ sizeof(uint16_t);
5176 kind
= ld::Fixup::kindStoreLittleEndian16
;
5179 contentValue
= E::get32(*((uint32_t*)fixUpPtr
));
5180 if ( reloc
->r_pcrel() ) {
5181 kind
= ld::Fixup::kindStoreX86BranchPCRel32
;
5182 contentValue
+= srcAddr
+ sizeof(uint32_t);
5185 kind
= ld::Fixup::kindStoreLittleEndian32
;
5188 throw "r_length=3 not supported";
5190 if ( reloc
->r_extern() ) {
5192 const macho_nlist
<P
>& targetSymbol
= parser
.symbolFromIndex(reloc
->r_symbolnum());
5193 target
.name
= parser
.nameFromSymbol(targetSymbol
);
5194 target
.weakImport
= parser
.weakImportFromSymbol(targetSymbol
);
5195 target
.addend
= contentValue
;
5198 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), target
);
5200 if ( (kind
== ld::Fixup::kindStoreX86BranchPCRel32
) && (target
.name
!= NULL
) ) {
5201 if ( strncmp(target
.name
, "___dtrace_probe$", 16) == 0 ) {
5202 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindStoreX86DtraceCallSiteNop
, false, target
.name
);
5203 parser
.addDtraceExtraInfos(src
, &target
.name
[16]);
5206 else if ( strncmp(target
.name
, "___dtrace_isenabled$", 20) == 0 ) {
5207 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindStoreX86DtraceIsEnableSiteClear
, false, target
.name
);
5208 parser
.addDtraceExtraInfos(src
, &target
.name
[20]);
5212 parser
.addFixups(src
, kind
, target
);
5215 case GENERIC_RLEOC_TLV
:
5217 if ( !reloc
->r_extern() )
5218 throw "r_extern=0 and r_type=GENERIC_RLEOC_TLV not supported";
5219 if ( reloc
->r_length() != 2 )
5220 throw "r_length!=2 and r_type=GENERIC_RLEOC_TLV not supported";
5221 const macho_nlist
<P
>& sym
= parser
.symbolFromIndex(reloc
->r_symbolnum());
5222 // use direct reference for local symbols
5223 if ( ((sym
.n_type() & N_TYPE
) == N_SECT
) && ((sym
.n_type() & N_EXT
) == 0) ) {
5224 parser
.findTargetFromAddressAndSectionNum(sym
.n_value(), sym
.n_sect(), target
);
5228 target
.name
= parser
.nameFromSymbol(sym
);
5229 target
.weakImport
= parser
.weakImportFromSymbol(sym
);
5231 target
.addend
= (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr
));
5232 if ( reloc
->r_pcrel() ) {
5233 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32TLVLoad
, target
);
5236 parser
.addFixups(src
, ld::Fixup::kindStoreX86Abs32TLVLoad
, target
);
5242 throwf("unsupported i386 relocation type (%d)", reloc
->r_type());
5246 // scattered relocation
5247 const macho_scattered_relocation_info
<P
>* sreloc
= (macho_scattered_relocation_info
<P
>*)reloc
;
5248 srcAddr
= sect
->addr() + sreloc
->r_address();
5249 src
.atom
= this->findAtomByAddress(srcAddr
);
5250 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5251 fixUpPtr
= file().fileContent() + sect
->offset() + sreloc
->r_address();
5252 uint32_t relocValue
= sreloc
->r_value();
5253 bool result
= false;
5254 // file format allows pair to be scattered or not
5255 const macho_scattered_relocation_info
<P
>* nextSReloc
= &sreloc
[1];
5256 const macho_relocation_info
<P
>* nextReloc
= &reloc
[1];
5257 bool nextRelocIsPair
= false;
5258 uint32_t nextRelocAddress
= 0;
5259 uint32_t nextRelocValue
= 0;
5260 if ( (nextReloc
->r_address() & R_SCATTERED
) == 0 ) {
5261 if ( nextReloc
->r_type() == GENERIC_RELOC_PAIR
) {
5262 nextRelocIsPair
= true;
5263 nextRelocAddress
= nextReloc
->r_address();
5264 result
= true; // iterator should skip next reloc, since we've consumed it here
5268 if ( nextSReloc
->r_type() == GENERIC_RELOC_PAIR
) {
5269 nextRelocIsPair
= true;
5270 nextRelocAddress
= nextSReloc
->r_address();
5271 nextRelocValue
= nextSReloc
->r_value();
5274 switch (sreloc
->r_type()) {
5275 case GENERIC_RELOC_VANILLA
:
5276 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
5277 target
.atom
= parser
.findAtomByAddress(relocValue
);
5278 if ( sreloc
->r_pcrel() ) {
5279 switch ( sreloc
->r_length() ) {
5281 contentValue
= srcAddr
+ 1 + *fixUpPtr
;
5282 target
.addend
= contentValue
- relocValue
;
5283 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel8
, target
);
5286 contentValue
= srcAddr
+ 2 + LittleEndian::get16(*((uint16_t*)fixUpPtr
));
5287 target
.addend
= contentValue
- relocValue
;
5288 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel16
, target
);
5291 contentValue
= srcAddr
+ 4 + LittleEndian::get32(*((uint32_t*)fixUpPtr
));
5292 target
.addend
= contentValue
- relocValue
;
5293 parser
.addFixups(src
, ld::Fixup::kindStoreX86PCRel32
, target
);
5296 throw "unsupported r_length=3 for scattered pc-rel vanilla reloc";
5301 if ( sreloc
->r_length() != 2 )
5302 throwf("unsupported r_length=%d for scattered vanilla reloc", sreloc
->r_length());
5303 contentValue
= LittleEndian::get32(*((uint32_t*)fixUpPtr
));
5304 target
.addend
= contentValue
- target
.atom
->objectAddress();
5305 parser
.addFixups(src
, ld::Fixup::kindStoreLittleEndian32
, target
);
5308 case GENERIC_RELOC_SECTDIFF
:
5309 case GENERIC_RELOC_LOCAL_SECTDIFF
:
5311 if ( !nextRelocIsPair
)
5312 throw "GENERIC_RELOC_SECTDIFF missing following pair";
5313 switch ( sreloc
->r_length() ) {
5316 throw "bad length for GENERIC_RELOC_SECTDIFF";
5318 contentValue
= (int32_t)(int16_t)LittleEndian::get16(*((uint16_t*)fixUpPtr
));
5319 kind
= ld::Fixup::kindStoreLittleEndian16
;
5322 contentValue
= LittleEndian::get32(*((uint32_t*)fixUpPtr
));
5323 kind
= ld::Fixup::kindStoreLittleEndian32
;
5326 Atom
<x86
>* fromAtom
= parser
.findAtomByAddress(nextRelocValue
);
5327 uint32_t offsetInFrom
= nextRelocValue
- fromAtom
->_objAddress
;
5328 parser
.findTargetFromAddress(sreloc
->r_value(), target
);
5329 // check for addend encoded in the section content
5330 int32_t addend
= contentValue
- (sreloc
->r_value() - nextRelocValue
);
5332 // switch binding base on coalescing
5333 if ( target
.atom
== NULL
) {
5334 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, target
.name
);
5336 else if ( target
.atom
->scope() == ld::Atom::scopeTranslationUnit
) {
5337 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, target
.atom
);
5339 else if ( (target
.atom
->combine() == ld::Atom::combineByNameAndContent
) || (target
.atom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
5340 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, target
.atom
);
5343 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, target
.atom
->name());
5345 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, target
.addend
);
5346 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
5347 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
-addend
);
5348 parser
.addFixup(src
, ld::Fixup::k5of5
, kind
);
5351 // switch binding base on coalescing
5352 if ( target
.atom
== NULL
) {
5353 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, target
.name
);
5355 else if ( target
.atom
->scope() == ld::Atom::scopeTranslationUnit
) {
5356 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, target
.atom
);
5358 else if ( (target
.atom
->combine() == ld::Atom::combineByNameAndContent
) || (target
.atom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
5359 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, target
.atom
);
5362 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, target
.atom
->name());
5364 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, target
.addend
+addend
);
5365 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
5366 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
);
5367 parser
.addFixup(src
, ld::Fixup::k5of5
, kind
);
5379 // ppc and ppc64 both use the same relocations, so process them in one common routine
5381 template <typename A
>
5382 bool Section
<A
>::addRelocFixup_powerpc(class Parser
<A
>& parser
,
5383 const macho_relocation_info
<typename
A::P
>* reloc
)
5385 const macho_section
<P
>* sect
= this->machoSection();
5386 bool result
= false;
5390 int32_t displacement
= 0;
5391 uint32_t instruction
= 0;
5393 pint_t contentValue
= 0;
5394 typename Parser
<A
>::SourceLocation src
;
5395 typename Parser
<A
>::TargetDesc target
;
5397 if ( (reloc
->r_address() & R_SCATTERED
) == 0 ) {
5398 srcAddr
= sect
->addr() + reloc
->r_address();
5399 src
.atom
= this->findAtomByAddress(srcAddr
);
5400 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5401 const macho_relocation_info
<P
>* nextReloc
= &reloc
[1];
5402 fixUpPtr
= (uint32_t*)(file().fileContent() + sect
->offset() + reloc
->r_address());
5403 if ( reloc
->r_type() != PPC_RELOC_PAIR
)
5404 instruction
= BigEndian::get32(*fixUpPtr
);
5405 if ( reloc
->r_extern() ) {
5407 const macho_nlist
<P
>& targetSymbol
= parser
.symbolFromIndex(reloc
->r_symbolnum());
5408 target
.name
= parser
.nameFromSymbol(targetSymbol
);
5409 target
.weakImport
= parser
.weakImportFromSymbol(targetSymbol
);
5411 switch ( reloc
->r_type() ) {
5412 case PPC_RELOC_BR24
:
5413 assert((instruction
& 0x4C000000) == 0x48000000);
5414 displacement
= (instruction
& 0x03FFFFFC);
5415 if ( (displacement
& 0x02000000) != 0 )
5416 displacement
|= 0xFC000000;
5417 if ( reloc
->r_extern() ) {
5418 target
.addend
= srcAddr
+ displacement
;
5421 dstAddr
= srcAddr
+ displacement
;
5422 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5424 // special case "calls" for dtrace
5425 if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_probe$", 16) == 0) ) {
5426 parser
.addFixup(src
, ld::Fixup::k1of1
,
5427 ld::Fixup::kindStorePPCDtraceCallSiteNop
, false, target
.name
);
5428 parser
.addDtraceExtraInfos(src
, &target
.name
[16]);
5430 else if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_isenabled$", 20) == 0) ) {
5431 parser
.addFixup(src
, ld::Fixup::k1of1
,
5432 ld::Fixup::kindStorePPCDtraceIsEnableSiteClear
, false, target
.name
);
5433 parser
.addDtraceExtraInfos(src
, &target
.name
[20]);
5436 parser
.addFixups(src
, ld::Fixup::kindStorePPCBranch24
, target
);
5439 case PPC_RELOC_BR14
:
5440 displacement
= (instruction
& 0x0000FFFC);
5441 if ( (displacement
& 0x00008000) != 0 )
5442 displacement
|= 0xFFFF0000;
5443 if ( reloc
->r_extern() ) {
5444 target
.addend
= srcAddr
+ displacement
;
5447 dstAddr
= srcAddr
+ displacement
;
5448 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5450 parser
.addFixups(src
, ld::Fixup::kindStorePPCBranch14
, target
);
5452 case PPC_RELOC_PAIR
:
5453 // skip, processed by a previous look ahead
5455 case PPC_RELOC_LO16
:
5456 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
)
5457 throw "PPC_RELOC_LO16 missing following pair";
5459 lowBits
= (instruction
& 0x0000FFFF);
5460 dstAddr
= (nextReloc
->r_address() << 16) + ((uint32_t)lowBits
& 0x0000FFFF);
5461 if ( reloc
->r_extern() ) {
5462 target
.addend
= dstAddr
;
5465 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5467 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsLow16
, target
);
5469 case PPC_RELOC_LO14
:
5470 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
)
5471 throw "PPC_RELOC_LO14 missing following pair";
5473 lowBits
= (instruction
& 0xFFFC);
5474 dstAddr
= (nextReloc
->r_address() << 16) + ((uint32_t)lowBits
& 0x0000FFFF);
5475 if ( reloc
->r_extern() ) {
5476 target
.addend
= dstAddr
;
5479 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5481 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsLow14
, target
);
5483 case PPC_RELOC_HI16
:
5484 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
)
5485 throw "PPC_RELOC_HI16 missing following pair";
5487 lowBits
= (nextReloc
->r_address() & 0xFFFF);
5488 dstAddr
= ((instruction
& 0xFFFF) << 16) | (lowBits
& 0x0000FFFF);
5489 if ( reloc
->r_extern() ) {
5490 target
.addend
= dstAddr
;
5493 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5495 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsHigh16
, target
);
5497 case PPC_RELOC_HA16
:
5498 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
)
5499 throw "PPC_RELOC_HA16 missing following pair";
5501 lowBits
= (nextReloc
->r_address() & 0x0000FFFF);
5502 dstAddr
= ((instruction
& 0xFFFF) << 16) + (int32_t)lowBits
;
5503 if ( reloc
->r_extern() ) {
5504 target
.addend
= dstAddr
;
5507 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5509 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsHigh16AddLow
, target
);
5511 case PPC_RELOC_VANILLA
:
5512 contentValue
= P::getP(*((pint_t
*)fixUpPtr
));
5513 if ( reloc
->r_extern() ) {
5514 target
.addend
= contentValue
;
5517 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), target
);
5519 switch ( reloc
->r_length() ) {
5522 throw "bad r_length in PPC_RELOC_VANILLA";
5524 parser
.addFixups(src
, ld::Fixup::kindStoreBigEndian32
, target
);
5527 parser
.addFixups(src
, ld::Fixup::kindStoreBigEndian64
, target
);
5531 case PPC_RELOC_JBSR
:
5532 // this is from -mlong-branch codegen. We ignore the jump island and make reference to the real target
5533 if ( nextReloc
->r_type() != PPC_RELOC_PAIR
)
5534 throw "PPC_RELOC_JBSR missing following pair";
5535 if ( !parser
._hasLongBranchStubs
)
5536 warning("object file compiled with -mlong-branch which is no longer needed. "
5537 "To remove this warning, recompile without -mlong-branch: %s", parser
._path
);
5538 parser
._hasLongBranchStubs
= true;
5540 if ( reloc
->r_extern() ) {
5541 throw "PPC_RELOC_JBSR should not be using an external relocation";
5543 parser
.findTargetFromAddressAndSectionNum(nextReloc
->r_address(), reloc
->r_symbolnum(), target
);
5544 parser
.addFixups(src
, ld::Fixup::kindStorePPCBranch24
, target
);
5547 warning("unknown relocation type %d", reloc
->r_type());
5551 const macho_scattered_relocation_info
<P
>* sreloc
= (macho_scattered_relocation_info
<P
>*)reloc
;
5552 // file format allows pair to be scattered or not
5553 const macho_scattered_relocation_info
<P
>* nextSReloc
= &sreloc
[1];
5554 const macho_relocation_info
<P
>* nextReloc
= &reloc
[1];
5555 srcAddr
= sect
->addr() + sreloc
->r_address();
5556 dstAddr
= sreloc
->r_value();
5557 fixUpPtr
= (uint32_t*)(file().fileContent() + sect
->offset() + sreloc
->r_address());
5558 instruction
= BigEndian::get32(*fixUpPtr
);
5559 src
.atom
= this->findAtomByAddress(srcAddr
);
5560 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5561 typename Parser
<A
>::TargetDesc picBase
;
5562 bool nextRelocIsPair
= false;
5563 uint32_t nextRelocAddress
= 0;
5564 uint32_t nextRelocValue
= 0;
5565 if ( (nextReloc
->r_address() & R_SCATTERED
) == 0 ) {
5566 if ( nextReloc
->r_type() == PPC_RELOC_PAIR
) {
5567 nextRelocIsPair
= true;
5568 nextRelocAddress
= nextReloc
->r_address();
5573 if ( nextSReloc
->r_type() == PPC_RELOC_PAIR
) {
5574 nextRelocIsPair
= true;
5575 nextRelocAddress
= nextSReloc
->r_address();
5576 nextRelocValue
= nextSReloc
->r_value();
5580 switch ( sreloc
->r_type() ) {
5581 case PPC_RELOC_VANILLA
:
5582 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
5583 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
5584 switch ( sreloc
->r_length() ) {
5587 throw "unsuppored r_length < 2 for scattered PPC_RELOC_VANILLA";
5589 contentValue
= BigEndian::get32(*(uint32_t*)fixUpPtr
);
5590 target
.addend
= contentValue
- target
.atom
->_objAddress
;
5591 parser
.addFixups(src
, ld::Fixup::kindStoreBigEndian32
, target
);
5594 contentValue
= BigEndian::get64(*(uint64_t*)fixUpPtr
);
5595 target
.addend
= contentValue
- target
.atom
->_objAddress
;
5596 parser
.addFixups(src
, ld::Fixup::kindStoreBigEndian64
, target
);
5600 case PPC_RELOC_BR14
:
5601 displacement
= (instruction
& 0x0000FFFC);
5602 if ( (displacement
& 0x00008000) != 0 )
5603 displacement
|= 0xFFFF0000;
5604 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
5605 target
.addend
= (srcAddr
+ displacement
) - target
.atom
->_objAddress
;
5606 parser
.addFixups(src
, ld::Fixup::kindStorePPCBranch14
, target
);
5608 case PPC_RELOC_BR24
:
5609 assert((instruction
& 0x4C000000) == 0x48000000);
5610 displacement
= (instruction
& 0x03FFFFFC);
5611 if ( (displacement
& 0x02000000) != 0 )
5612 displacement
|= 0xFC000000;
5613 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
5614 target
.addend
= (srcAddr
+ displacement
) - target
.atom
->_objAddress
;
5615 parser
.addFixups(src
, ld::Fixup::kindStorePPCBranch24
, target
);
5617 case PPC_RELOC_LO16_SECTDIFF
:
5618 if ( ! nextRelocIsPair
)
5619 throw "PPC_RELOC_LO16_SECTDIFF missing following pair";
5620 lowBits
= (instruction
& 0xFFFF);
5621 dstAddr
= nextRelocValue
+ ((nextRelocAddress
<< 16) | ((uint32_t)lowBits
& 0x0000FFFF));
5622 parser
.findTargetFromAddress(sreloc
->r_value(), target
);
5623 if ( target
.atom
!= NULL
)
5624 target
.addend
= dstAddr
- target
.atom
->_objAddress
;
5625 picBase
.atom
= parser
.findAtomByAddress(nextRelocValue
);
5626 picBase
.addend
= nextRelocValue
- picBase
.atom
->_objAddress
;
5627 picBase
.weakImport
= false;
5628 picBase
.name
= NULL
;
5629 parser
.addFixups(src
, ld::Fixup::kindStorePPCPicLow16
, target
, picBase
);
5631 case PPC_RELOC_LO14_SECTDIFF
:
5632 if ( ! nextRelocIsPair
)
5633 throw "PPC_RELOC_LO14_SECTDIFF missing following pair";
5634 lowBits
= (instruction
& 0xFFFC);
5635 dstAddr
= nextRelocValue
+ ((nextRelocAddress
<< 16) | ((uint32_t)lowBits
& 0x0000FFFF));
5636 parser
.findTargetFromAddress(sreloc
->r_value(), target
);
5637 if ( target
.atom
!= NULL
)
5638 target
.addend
= dstAddr
- target
.atom
->_objAddress
;
5639 picBase
.atom
= parser
.findAtomByAddress(nextRelocValue
);
5640 picBase
.addend
= nextRelocValue
- picBase
.atom
->_objAddress
;
5641 picBase
.weakImport
= false;
5642 picBase
.name
= NULL
;
5643 parser
.addFixups(src
, ld::Fixup::kindStorePPCPicLow14
, target
, picBase
);
5645 case PPC_RELOC_HA16_SECTDIFF
:
5646 if ( ! nextRelocIsPair
)
5647 throw "PPC_RELOC_HA16_SECTDIFF missing following pair";
5648 lowBits
= (nextRelocAddress
& 0x0000FFFF);
5649 dstAddr
= nextRelocValue
+ (((instruction
& 0x0000FFFF) << 16) + (int32_t)lowBits
);
5650 parser
.findTargetFromAddress(sreloc
->r_value(), target
);
5651 if ( target
.atom
!= NULL
)
5652 target
.addend
= dstAddr
- target
.atom
->_objAddress
;
5653 picBase
.atom
= parser
.findAtomByAddress(nextRelocValue
);
5654 picBase
.addend
= nextRelocValue
- picBase
.atom
->_objAddress
;
5655 picBase
.weakImport
= false;
5656 picBase
.name
= NULL
;
5657 parser
.addFixups(src
, ld::Fixup::kindStorePPCPicHigh16AddLow
, target
, picBase
);
5659 case PPC_RELOC_LO14
:
5660 if ( ! nextRelocIsPair
)
5661 throw "PPC_RELOC_LO14 missing following pair";
5662 lowBits
= (instruction
& 0xFFFC);
5663 dstAddr
= ((nextRelocAddress
<< 16) + ((uint32_t)lowBits
& 0x0000FFFF));
5664 parser
.findTargetFromAddress(sreloc
->r_value(), dstAddr
, target
);
5665 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsLow14
, target
);
5667 case PPC_RELOC_LO16
:
5668 if ( ! nextRelocIsPair
)
5669 throw "PPC_RELOC_LO16 missing following pair";
5670 lowBits
= (instruction
& 0xFFFF);
5671 dstAddr
= ((nextRelocAddress
<< 16) + ((uint32_t)lowBits
& 0x0000FFFF));
5672 parser
.findTargetFromAddress(sreloc
->r_value(), dstAddr
, target
);
5673 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsLow16
, target
);
5675 case PPC_RELOC_HA16
:
5676 if ( ! nextRelocIsPair
)
5677 throw "PPC_RELOC_HA16 missing following pair";
5678 lowBits
= (nextRelocAddress
& 0xFFFF);
5679 dstAddr
= (((instruction
& 0xFFFF) << 16) + (int32_t)lowBits
);
5680 parser
.findTargetFromAddress(sreloc
->r_value(), dstAddr
, target
);
5681 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsHigh16AddLow
, target
);
5683 case PPC_RELOC_HI16
:
5684 if ( ! nextRelocIsPair
)
5685 throw "PPC_RELOC_HI16 missing following pair";
5686 lowBits
= (nextRelocAddress
& 0xFFFF);
5687 dstAddr
= ((instruction
& 0xFFFF) << 16) | (lowBits
& 0x0000FFFF);
5688 parser
.findTargetFromAddress(sreloc
->r_value(), dstAddr
, target
);
5689 parser
.addFixups(src
, ld::Fixup::kindStorePPCAbsHigh16
, target
);
5691 case PPC_RELOC_SECTDIFF
:
5692 case PPC_RELOC_LOCAL_SECTDIFF
:
5694 if ( ! nextRelocIsPair
)
5695 throw "PPC_RELOC_SECTDIFF missing following pair";
5696 ld::Fixup::Kind kind
= ld::Fixup::kindNone
;
5697 switch ( sreloc
->r_length() ) {
5699 throw "bad length for PPC_RELOC_SECTDIFF";
5701 contentValue
= (int32_t)(int16_t)BigEndian::get16(*((uint16_t*)fixUpPtr
));
5702 kind
= ld::Fixup::kindStoreBigEndian16
;
5705 contentValue
= BigEndian::get32(*((uint32_t*)fixUpPtr
));
5706 kind
= ld::Fixup::kindStoreBigEndian32
;
5709 contentValue
= BigEndian::get64(*((uint64_t*)fixUpPtr
));
5710 kind
= ld::Fixup::kindStoreBigEndian64
;
5714 Atom
<A
>* fromAtom
= parser
.findAtomByAddress(nextRelocValue
);
5715 Atom
<A
>* targetAtom
= parser
.findAtomByAddress(sreloc
->r_value());
5716 uint32_t offsetInFrom
= nextRelocValue
- fromAtom
->_objAddress
;
5717 uint32_t offsetInTarget
= sreloc
->r_value() - targetAtom
->_objAddress
;
5718 // check for addend encoded in the section content
5719 int32_t addend
= contentValue
- (sreloc
->r_value() - nextRelocValue
);
5721 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
5722 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
5724 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
5725 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
5728 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
5730 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, offsetInTarget
);
5731 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
5732 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
-addend
);
5733 parser
.addFixup(src
, ld::Fixup::k5of5
, kind
);
5736 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
5737 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
5739 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
5740 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
5743 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
5745 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, offsetInTarget
+addend
);
5746 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
5747 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
);
5748 parser
.addFixup(src
, ld::Fixup::k5of5
, kind
);
5752 case PPC_RELOC_PAIR
:
5754 case PPC_RELOC_HI16_SECTDIFF
:
5755 warning("unexpected scattered relocation type PPC_RELOC_HI16_SECTDIFF");
5758 warning("unknown scattered relocation type %d", sreloc
->r_type());
5766 bool Section
<ppc
>::addRelocFixup(class Parser
<ppc
>& parser
, const macho_relocation_info
<P
>* reloc
)
5768 return addRelocFixup_powerpc(parser
, reloc
);
5773 bool Section
<ppc64
>::addRelocFixup(class Parser
<ppc64
>& parser
, const macho_relocation_info
<P
>* reloc
)
5775 return addRelocFixup_powerpc(parser
, reloc
);
5781 bool Section
<arm
>::addRelocFixup(class Parser
<arm
>& parser
, const macho_relocation_info
<P
>* reloc
)
5783 const macho_section
<P
>* sect
= this->machoSection();
5784 bool result
= false;
5788 int32_t displacement
= 0;
5789 uint32_t instruction
= 0;
5790 pint_t contentValue
= 0;
5791 Parser
<arm
>::SourceLocation src
;
5792 Parser
<arm
>::TargetDesc target
;
5793 const macho_relocation_info
<P
>* nextReloc
;
5795 if ( (reloc
->r_address() & R_SCATTERED
) == 0 ) {
5796 bool externSymbolIsThumbDef
= false;
5797 srcAddr
= sect
->addr() + reloc
->r_address();
5798 src
.atom
= this->findAtomByAddress(srcAddr
);
5799 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5800 fixUpPtr
= (uint32_t*)(file().fileContent() + sect
->offset() + reloc
->r_address());
5801 if ( reloc
->r_type() != ARM_RELOC_PAIR
)
5802 instruction
= LittleEndian::get32(*fixUpPtr
);
5803 if ( reloc
->r_extern() ) {
5805 const macho_nlist
<P
>& targetSymbol
= parser
.symbolFromIndex(reloc
->r_symbolnum());
5806 target
.name
= parser
.nameFromSymbol(targetSymbol
);
5807 target
.weakImport
= parser
.weakImportFromSymbol(targetSymbol
);
5808 if ( ((targetSymbol
.n_type() & N_TYPE
) == N_SECT
) && (targetSymbol
.n_desc() & N_ARM_THUMB_DEF
) )
5809 externSymbolIsThumbDef
= true;
5811 switch ( reloc
->r_type() ) {
5812 case ARM_RELOC_BR24
:
5813 // Sign-extend displacement
5814 displacement
= (instruction
& 0x00FFFFFF) << 2;
5815 if ( (displacement
& 0x02000000) != 0 )
5816 displacement
|= 0xFC000000;
5817 // The pc added will be +8 from the pc
5819 // If this is BLX add H << 1
5820 if ((instruction
& 0xFE000000) == 0xFA000000)
5821 displacement
+= ((instruction
& 0x01000000) >> 23);
5822 if ( reloc
->r_extern() ) {
5823 target
.addend
= srcAddr
+ displacement
;
5824 if ( externSymbolIsThumbDef
)
5825 target
.addend
&= -2; // remove thumb bit
5828 dstAddr
= srcAddr
+ displacement
;
5829 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5831 // special case "calls" for dtrace
5832 if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_probe$", 16) == 0) ) {
5833 parser
.addFixup(src
, ld::Fixup::k1of1
,
5834 ld::Fixup::kindStoreARMDtraceCallSiteNop
, false, target
.name
);
5835 parser
.addDtraceExtraInfos(src
, &target
.name
[16]);
5837 else if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_isenabled$", 20) == 0) ) {
5838 parser
.addFixup(src
, ld::Fixup::k1of1
,
5839 ld::Fixup::kindStoreARMDtraceIsEnableSiteClear
, false, target
.name
);
5840 parser
.addDtraceExtraInfos(src
, &target
.name
[20]);
5843 parser
.addFixups(src
, ld::Fixup::kindStoreARMBranch24
, target
);
5846 case ARM_THUMB_RELOC_BR22
:
5847 // thumb2 added two more bits to displacement, complicating the displacement decoding
5849 uint32_t s
= (instruction
>> 10) & 0x1;
5850 uint32_t j1
= (instruction
>> 29) & 0x1;
5851 uint32_t j2
= (instruction
>> 27) & 0x1;
5852 uint32_t imm10
= instruction
& 0x3FF;
5853 uint32_t imm11
= (instruction
>> 16) & 0x7FF;
5854 uint32_t i1
= (j1
== s
);
5855 uint32_t i2
= (j2
== s
);
5856 uint32_t dis
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
5860 displacement
= sdis
;
5862 // The pc added will be +4 from the pc
5864 // If the instruction was blx, force the low 2 bits to be clear
5865 dstAddr
= srcAddr
+ displacement
;
5866 if ((instruction
& 0xF8000000) == 0xE8000000)
5867 dstAddr
&= 0xFFFFFFFC;
5869 if ( reloc
->r_extern() ) {
5870 target
.addend
= dstAddr
;
5873 parser
.findTargetFromAddressAndSectionNum(dstAddr
, reloc
->r_symbolnum(), target
);
5875 // special case "calls" for dtrace
5876 if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_probe$", 16) == 0) ) {
5877 parser
.addFixup(src
, ld::Fixup::k1of1
,
5878 ld::Fixup::kindStoreThumbDtraceCallSiteNop
, false, target
.name
);
5879 parser
.addDtraceExtraInfos(src
, &target
.name
[16]);
5881 else if ( (target
.name
!= NULL
) && (strncmp(target
.name
, "___dtrace_isenabled$", 20) == 0) ) {
5882 parser
.addFixup(src
, ld::Fixup::k1of1
,
5883 ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear
, false, target
.name
);
5884 parser
.addDtraceExtraInfos(src
, &target
.name
[20]);
5887 parser
.addFixups(src
, ld::Fixup::kindStoreThumbBranch22
, target
);
5890 case ARM_RELOC_VANILLA
:
5891 if ( reloc
->r_length() != 2 )
5892 throw "bad length for ARM_RELOC_VANILLA";
5893 contentValue
= LittleEndian::get32(*fixUpPtr
);
5894 if ( reloc
->r_extern() ) {
5895 target
.addend
= contentValue
;
5896 if ( externSymbolIsThumbDef
)
5897 target
.addend
&= -2; // remove thumb bit
5900 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), target
);
5901 // possible non-extern relocation turned into by-name ref because target is a weak-def
5902 if ( target
.atom
!= NULL
) {
5903 if ( target
.atom
->isThumb() )
5904 target
.addend
&= -2; // remove thumb bit
5905 // if reference to LSDA, add group subordinate fixup
5906 if ( target
.atom
->contentType() == ld::Atom::typeLSDA
) {
5907 Parser
<arm
>::SourceLocation src2
;
5908 src2
.atom
= src
.atom
;
5909 src2
.offsetInAtom
= 0;
5910 parser
.addFixup(src2
, ld::Fixup::k1of1
, ld::Fixup::kindNoneGroupSubordinateLSDA
, target
.atom
);
5914 parser
.addFixups(src
, ld::Fixup::kindStoreLittleEndian32
, target
);
5916 case ARM_THUMB_32BIT_BRANCH
:
5917 // silently ignore old unnecessary reloc
5919 case ARM_RELOC_HALF
:
5920 nextReloc
= &reloc
[1];
5921 if ( nextReloc
->r_type() == ARM_RELOC_PAIR
) {
5922 uint32_t instruction16
;
5923 uint32_t other16
= (nextReloc
->r_address() & 0xFFFF);
5925 if ( reloc
->r_length() & 2 ) {
5927 uint32_t i
= ((instruction
& 0x00000400) >> 10);
5928 uint32_t imm4
= (instruction
& 0x0000000F);
5929 uint32_t imm3
= ((instruction
& 0x70000000) >> 28);
5930 uint32_t imm8
= ((instruction
& 0x00FF0000) >> 16);
5931 instruction16
= (imm4
<< 12) | (i
<< 11) | (imm3
<< 8) | imm8
;
5935 uint32_t imm4
= ((instruction
& 0x000F0000) >> 16);
5936 uint32_t imm12
= (instruction
& 0x00000FFF);
5937 instruction16
= (imm4
<< 12) | imm12
;
5939 if ( reloc
->r_length() & 1 ) {
5941 dstAddr
= ((instruction16
<< 16) | other16
);
5942 parser
.findTargetFromAddress(dstAddr
, target
);
5943 parser
.addFixups(src
, (isThumb
? ld::Fixup::kindStoreThumbHigh16
: ld::Fixup::kindStoreARMHigh16
), target
);
5947 dstAddr
= (other16
<< 16) | instruction16
;
5948 parser
.findTargetFromAddress(dstAddr
, target
);
5949 parser
.addFixups(src
, (isThumb
? ld::Fixup::kindStoreThumbLow16
: ld::Fixup::kindStoreARMLow16
), target
);
5954 throw "for ARM_RELOC_HALF, next reloc is not ARM_RELOC_PAIR";
5957 throwf("unknown relocation type %d", reloc
->r_type());
5962 const macho_scattered_relocation_info
<P
>* sreloc
= (macho_scattered_relocation_info
<P
>*)reloc
;
5963 // file format allows pair to be scattered or not
5964 const macho_scattered_relocation_info
<P
>* nextSReloc
= &sreloc
[1];
5965 nextReloc
= &reloc
[1];
5966 srcAddr
= sect
->addr() + sreloc
->r_address();
5967 dstAddr
= sreloc
->r_value();
5968 fixUpPtr
= (uint32_t*)(file().fileContent() + sect
->offset() + sreloc
->r_address());
5969 instruction
= LittleEndian::get32(*fixUpPtr
);
5970 src
.atom
= this->findAtomByAddress(srcAddr
);
5971 src
.offsetInAtom
= srcAddr
- src
.atom
->_objAddress
;
5972 bool nextRelocIsPair
= false;
5973 uint32_t nextRelocAddress
= 0;
5974 uint32_t nextRelocValue
= 0;
5975 if ( (nextReloc
->r_address() & R_SCATTERED
) == 0 ) {
5976 if ( nextReloc
->r_type() == ARM_RELOC_PAIR
) {
5977 nextRelocIsPair
= true;
5978 nextRelocAddress
= nextReloc
->r_address();
5983 if ( nextSReloc
->r_type() == ARM_RELOC_PAIR
) {
5984 nextRelocIsPair
= true;
5985 nextRelocAddress
= nextSReloc
->r_address();
5986 nextRelocValue
= nextSReloc
->r_value();
5990 switch ( sreloc
->r_type() ) {
5991 case ARM_RELOC_VANILLA
:
5992 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
5993 if ( sreloc
->r_length() != 2 )
5994 throw "bad length for ARM_RELOC_VANILLA";
5995 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
5996 contentValue
= LittleEndian::get32(*fixUpPtr
);
5997 target
.addend
= contentValue
- target
.atom
->_objAddress
;
5998 if ( target
.atom
->isThumb() )
5999 target
.addend
&= -2; // remove thumb bit
6000 parser
.addFixups(src
, ld::Fixup::kindStoreLittleEndian32
, target
);
6002 case ARM_RELOC_BR24
:
6003 // Sign-extend displacement
6004 displacement
= (instruction
& 0x00FFFFFF) << 2;
6005 if ( (displacement
& 0x02000000) != 0 )
6006 displacement
|= 0xFC000000;
6007 // The pc added will be +8 from the pc
6009 // If this is BLX add H << 1
6010 if ((instruction
& 0xFE000000) == 0xFA000000)
6011 displacement
+= ((instruction
& 0x01000000) >> 23);
6012 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
6013 target
.addend
= (int64_t)(srcAddr
+ displacement
) - (int64_t)(target
.atom
->_objAddress
);
6014 parser
.addFixups(src
, ld::Fixup::kindStoreARMBranch24
, target
);
6016 case ARM_THUMB_RELOC_BR22
:
6017 // thumb2 added two more bits to displacement, complicating the displacement decoding
6019 uint32_t s
= (instruction
>> 10) & 0x1;
6020 uint32_t j1
= (instruction
>> 29) & 0x1;
6021 uint32_t j2
= (instruction
>> 27) & 0x1;
6022 uint32_t imm10
= instruction
& 0x3FF;
6023 uint32_t imm11
= (instruction
>> 16) & 0x7FF;
6024 uint32_t i1
= (j1
== s
);
6025 uint32_t i2
= (j2
== s
);
6026 uint32_t dis
= (s
<< 24) | (i1
<< 23) | (i2
<< 22) | (imm10
<< 12) | (imm11
<< 1);
6030 displacement
= sdis
;
6032 // The pc added will be +4 from the pc
6034 dstAddr
= srcAddr
+displacement
;
6035 // If the instruction was blx, force the low 2 bits to be clear
6036 if ((instruction
& 0xF8000000) == 0xE8000000)
6037 dstAddr
&= 0xFFFFFFFC;
6038 target
.atom
= parser
.findAtomByAddress(sreloc
->r_value());
6039 target
.addend
= dstAddr
- target
.atom
->_objAddress
;
6040 parser
.addFixups(src
, ld::Fixup::kindStoreThumbBranch22
, target
);
6042 case ARM_RELOC_SECTDIFF
:
6043 case ARM_RELOC_LOCAL_SECTDIFF
:
6045 if ( ! nextRelocIsPair
)
6046 throw "ARM_RELOC_SECTDIFF missing following pair";
6047 if ( sreloc
->r_length() != 2 )
6048 throw "bad length for ARM_RELOC_SECTDIFF";
6049 contentValue
= LittleEndian::get32(*fixUpPtr
);
6050 Atom
<arm
>* fromAtom
= parser
.findAtomByAddress(nextRelocValue
);
6051 uint32_t offsetInFrom
= nextRelocValue
- fromAtom
->_objAddress
;
6052 uint32_t offsetInTarget
;
6053 Atom
<arm
>* targetAtom
= parser
.findAtomByAddressOrLocalTargetOfStub(sreloc
->r_value(), &offsetInTarget
);
6054 // check for addend encoded in the section content
6055 int64_t addend
= contentValue
- (sreloc
->r_value() - nextRelocValue
);
6056 if ( targetAtom
->isThumb() )
6057 addend
&= -2; // remove thumb bit
6058 // if reference to LSDA, add group subordinate fixup
6059 if ( targetAtom
->contentType() == ld::Atom::typeLSDA
) {
6060 Parser
<arm
>::SourceLocation src2
;
6061 src2
.atom
= src
.atom
;
6062 src2
.offsetInAtom
= 0;
6063 parser
.addFixup(src2
, ld::Fixup::k1of1
, ld::Fixup::kindNoneGroupSubordinateLSDA
, targetAtom
);
6066 // switch binding base on coalescing
6067 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
6068 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
6070 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
6071 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
6074 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
6076 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
6077 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, offsetInTarget
);
6078 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
6079 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
-addend
);
6080 parser
.addFixup(src
, ld::Fixup::k5of5
, ld::Fixup::kindStoreLittleEndian32
);
6083 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
6084 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
6086 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
6087 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
6090 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
6092 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, (uint32_t)(offsetInTarget
+addend
));
6093 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
6094 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
);
6095 parser
.addFixup(src
, ld::Fixup::k5of5
, ld::Fixup::kindStoreLittleEndian32
);
6099 case ARM_RELOC_HALF_SECTDIFF
:
6100 if ( nextRelocIsPair
) {
6101 instruction
= LittleEndian::get32(*fixUpPtr
);
6102 Atom
<arm
>* fromAtom
= parser
.findAtomByAddress(nextRelocValue
);
6103 uint32_t offsetInFrom
= nextRelocValue
- fromAtom
->_objAddress
;
6104 Atom
<arm
>* targetAtom
= parser
.findAtomByAddress(sreloc
->r_value());
6105 uint32_t offsetInTarget
= sreloc
->r_value() - targetAtom
->_objAddress
;
6106 //if ( targetAtom->isThumb() )
6107 // addend &= -2; // remove thumb bit
6108 uint32_t instruction16
;
6109 uint32_t other16
= (nextRelocAddress
& 0xFFFF);
6111 if ( sreloc
->r_length() & 2 ) {
6113 uint32_t i
= ((instruction
& 0x00000400) >> 10);
6114 uint32_t imm4
= (instruction
& 0x0000000F);
6115 uint32_t imm3
= ((instruction
& 0x70000000) >> 28);
6116 uint32_t imm8
= ((instruction
& 0x00FF0000) >> 16);
6117 instruction16
= (imm4
<< 12) | (i
<< 11) | (imm3
<< 8) | imm8
;
6121 uint32_t imm4
= ((instruction
& 0x000F0000) >> 16);
6122 uint32_t imm12
= (instruction
& 0x00000FFF);
6123 instruction16
= (imm4
<< 12) | imm12
;
6125 if ( sreloc
->r_length() & 1 )
6126 dstAddr
= ((instruction16
<< 16) | other16
);
6128 dstAddr
= (other16
<< 16) | instruction16
;
6129 int32_t addend
= dstAddr
- (sreloc
->r_value() - nextRelocValue
);
6130 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
6131 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
6133 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
6134 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
6137 parser
.addFixup(src
, ld::Fixup::k1of5
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
6139 parser
.addFixup(src
, ld::Fixup::k2of5
, ld::Fixup::kindAddAddend
, (uint32_t)offsetInTarget
+addend
);
6140 parser
.addFixup(src
, ld::Fixup::k3of5
, ld::Fixup::kindSubtractTargetAddress
, fromAtom
);
6141 parser
.addFixup(src
, ld::Fixup::k4of5
, ld::Fixup::kindSubtractAddend
, offsetInFrom
);
6142 if ( sreloc
->r_length() & 1 ) {
6144 parser
.addFixup(src
, ld::Fixup::k5of5
, (isThumb
? ld::Fixup::kindStoreThumbHigh16
: ld::Fixup::kindStoreARMHigh16
));
6148 parser
.addFixup(src
, ld::Fixup::k5of5
, (isThumb
? ld::Fixup::kindStoreThumbLow16
: ld::Fixup::kindStoreARMLow16
));
6153 throw "ARM_RELOC_HALF_SECTDIFF reloc missing following pair";
6155 case ARM_RELOC_HALF
:
6156 if ( nextRelocIsPair
) {
6157 instruction
= LittleEndian::get32(*fixUpPtr
);
6158 Atom
<arm
>* targetAtom
= parser
.findAtomByAddress(sreloc
->r_value());
6159 uint32_t instruction16
;
6160 uint32_t other16
= (nextRelocAddress
& 0xFFFF);
6162 if ( sreloc
->r_length() & 2 ) {
6164 uint32_t i
= ((instruction
& 0x00000400) >> 10);
6165 uint32_t imm4
= (instruction
& 0x0000000F);
6166 uint32_t imm3
= ((instruction
& 0x70000000) >> 28);
6167 uint32_t imm8
= ((instruction
& 0x00FF0000) >> 16);
6168 instruction16
= (imm4
<< 12) | (i
<< 11) | (imm3
<< 8) | imm8
;
6172 uint32_t imm4
= ((instruction
& 0x000F0000) >> 16);
6173 uint32_t imm12
= (instruction
& 0x00000FFF);
6174 instruction16
= (imm4
<< 12) | imm12
;
6176 if ( sreloc
->r_length() & 1 )
6177 dstAddr
= ((instruction16
<< 16) | other16
);
6179 dstAddr
= (other16
<< 16) | instruction16
;
6180 if ( targetAtom
->scope() == ld::Atom::scopeTranslationUnit
) {
6181 parser
.addFixup(src
, ld::Fixup::k1of3
, ld::Fixup::kindSetTargetAddress
, targetAtom
);
6183 else if ( (targetAtom
->combine() == ld::Atom::combineByNameAndContent
) || (targetAtom
->combine() == ld::Atom::combineByNameAndReferences
) ) {
6184 parser
.addFixup(src
, ld::Fixup::k1of3
, ld::Fixup::kindSetTargetAddress
, ld::Fixup::bindingByContentBound
, targetAtom
);
6187 parser
.addFixup(src
, ld::Fixup::k1of3
, ld::Fixup::kindSetTargetAddress
, false, targetAtom
->name());
6189 parser
.addFixup(src
, ld::Fixup::k2of3
, ld::Fixup::kindAddAddend
, dstAddr
- targetAtom
->_objAddress
);
6190 if ( sreloc
->r_length() & 1 ) {
6192 parser
.addFixup(src
, ld::Fixup::k3of3
, (isThumb
? ld::Fixup::kindStoreThumbHigh16
: ld::Fixup::kindStoreARMHigh16
));
6196 parser
.addFixup(src
, ld::Fixup::k3of3
, (isThumb
? ld::Fixup::kindStoreThumbLow16
: ld::Fixup::kindStoreARMLow16
));
6201 throw "scattered ARM_RELOC_HALF reloc missing following pair";
6204 throwf("unknown ARM scattered relocation type %d", sreloc
->r_type());
6214 template <typename A
>
6215 bool ObjC1ClassSection
<A
>::addRelocFixup(class Parser
<A
>& parser
, const macho_relocation_info
<P
>* reloc
)
6218 FixedSizeSection
<A
>::addRelocFixup(parser
, reloc
);
6220 assert(0 && "needs template specialization");
6225 bool ObjC1ClassSection
<x86
>::addRelocFixup(class Parser
<x86
>& parser
, const macho_relocation_info
<x86::P
>* reloc
)
6227 // if this is the reloc for the super class name string, add implicit reference to super class
6228 if ( ((reloc
->r_address() & R_SCATTERED
) == 0) && (reloc
->r_type() == GENERIC_RELOC_VANILLA
) ) {
6229 assert( reloc
->r_length() == 2 );
6230 assert( ! reloc
->r_pcrel() );
6232 const macho_section
<P
>* sect
= this->machoSection();
6233 Parser
<x86
>::SourceLocation src
;
6234 uint32_t srcAddr
= sect
->addr() + reloc
->r_address();
6235 src
.atom
= this->findAtomByAddress(srcAddr
);
6236 src
.offsetInAtom
= srcAddr
- src
.atom
->objectAddress();
6237 if ( src
.offsetInAtom
== 4 ) {
6238 Parser
<x86
>::TargetDesc stringTarget
;
6239 const uint8_t* fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
6240 uint32_t contentValue
= LittleEndian::get32(*((uint32_t*)fixUpPtr
));
6241 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), stringTarget
);
6243 assert(stringTarget
.atom
!= NULL
);
6244 assert(stringTarget
.atom
->contentType() == ld::Atom::typeCString
);
6245 const char* superClassBaseName
= (char*)stringTarget
.atom
->rawContentPointer();
6246 char* superClassName
= new char[strlen(superClassBaseName
) + 20];
6247 strcpy(superClassName
, ".objc_class_name_");
6248 strcat(superClassName
, superClassBaseName
);
6250 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindSetTargetAddress
, false, superClassName
);
6254 return FixedSizeSection
<x86
>::addRelocFixup(parser
, reloc
);
6258 bool ObjC1ClassSection
<ppc
>::addRelocFixup(class Parser
<ppc
>& parser
, const macho_relocation_info
<ppc::P
>* reloc
)
6260 // if this is the reloc for the super class name string, add implicit reference to super class
6261 if ( ((reloc
->r_address() & R_SCATTERED
) == 0) && (reloc
->r_type() == PPC_RELOC_VANILLA
) ) {
6262 assert( reloc
->r_length() == 2 );
6263 assert( ! reloc
->r_pcrel() );
6265 const macho_section
<P
>* sect
= this->machoSection();
6266 Parser
<ppc
>::SourceLocation src
;
6267 uint32_t srcAddr
= sect
->addr() + reloc
->r_address();
6268 src
.atom
= this->findAtomByAddress(srcAddr
);
6269 src
.offsetInAtom
= srcAddr
- src
.atom
->objectAddress();
6270 if ( src
.offsetInAtom
== 4 ) {
6271 Parser
<ppc
>::TargetDesc stringTarget
;
6272 const uint8_t* fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
6273 uint32_t contentValue
= BigEndian::get32(*((uint32_t*)fixUpPtr
));
6274 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), stringTarget
);
6276 assert(stringTarget
.atom
!= NULL
);
6277 assert(stringTarget
.atom
->contentType() == ld::Atom::typeCString
);
6278 const char* superClassBaseName
= (char*)stringTarget
.atom
->rawContentPointer();
6279 char* superClassName
= new char[strlen(superClassBaseName
) + 20];
6280 strcpy(superClassName
, ".objc_class_name_");
6281 strcat(superClassName
, superClassBaseName
);
6283 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindSetTargetAddress
, false, superClassName
);
6288 return FixedSizeSection
<ppc
>::addRelocFixup(parser
, reloc
);
6294 template <typename A
>
6295 bool Objc1ClassReferences
<A
>::addRelocFixup(class Parser
<A
>& parser
, const macho_relocation_info
<P
>* reloc
)
6298 PointerToCStringSection
<A
>::addRelocFixup(parser
, reloc
);
6300 assert(0 && "needs template specialization");
6306 bool Objc1ClassReferences
<ppc
>::addRelocFixup(class Parser
<ppc
>& parser
, const macho_relocation_info
<ppc::P
>* reloc
)
6308 // add implict class refs, fixups not usable yet, so look at relocations
6309 assert( (reloc
->r_address() & R_SCATTERED
) == 0 );
6310 assert( reloc
->r_type() == PPC_RELOC_VANILLA
);
6311 assert( reloc
->r_length() == 2 );
6312 assert( ! reloc
->r_pcrel() );
6314 const macho_section
<P
>* sect
= this->machoSection();
6315 Parser
<ppc
>::SourceLocation src
;
6316 uint32_t srcAddr
= sect
->addr() + reloc
->r_address();
6317 src
.atom
= this->findAtomByAddress(srcAddr
);
6318 src
.offsetInAtom
= srcAddr
- src
.atom
->objectAddress();
6319 Parser
<ppc
>::TargetDesc stringTarget
;
6320 const uint8_t* fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
6321 uint32_t contentValue
= BigEndian::get32(*((uint32_t*)fixUpPtr
));
6322 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), stringTarget
);
6324 assert(stringTarget
.atom
!= NULL
);
6325 assert(stringTarget
.atom
->contentType() == ld::Atom::typeCString
);
6326 const char* baseClassName
= (char*)stringTarget
.atom
->rawContentPointer();
6327 char* objcClassName
= new char[strlen(baseClassName
) + 20];
6328 strcpy(objcClassName
, ".objc_class_name_");
6329 strcat(objcClassName
, baseClassName
);
6331 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindSetTargetAddress
, false, objcClassName
);
6334 return PointerToCStringSection
<ppc
>::addRelocFixup(parser
, reloc
);
6339 bool Objc1ClassReferences
<x86
>::addRelocFixup(class Parser
<x86
>& parser
, const macho_relocation_info
<x86::P
>* reloc
)
6341 // add implict class refs, fixups not usable yet, so look at relocations
6342 assert( (reloc
->r_address() & R_SCATTERED
) == 0 );
6343 assert( reloc
->r_type() == GENERIC_RELOC_VANILLA
);
6344 assert( reloc
->r_length() == 2 );
6345 assert( ! reloc
->r_pcrel() );
6347 const macho_section
<P
>* sect
= this->machoSection();
6348 Parser
<x86
>::SourceLocation src
;
6349 uint32_t srcAddr
= sect
->addr() + reloc
->r_address();
6350 src
.atom
= this->findAtomByAddress(srcAddr
);
6351 src
.offsetInAtom
= srcAddr
- src
.atom
->objectAddress();
6352 Parser
<x86
>::TargetDesc stringTarget
;
6353 const uint8_t* fixUpPtr
= file().fileContent() + sect
->offset() + reloc
->r_address();
6354 uint32_t contentValue
= LittleEndian::get32(*((uint32_t*)fixUpPtr
));
6355 parser
.findTargetFromAddressAndSectionNum(contentValue
, reloc
->r_symbolnum(), stringTarget
);
6357 assert(stringTarget
.atom
!= NULL
);
6358 assert(stringTarget
.atom
->contentType() == ld::Atom::typeCString
);
6359 const char* baseClassName
= (char*)stringTarget
.atom
->rawContentPointer();
6360 char* objcClassName
= new char[strlen(baseClassName
) + 20];
6361 strcpy(objcClassName
, ".objc_class_name_");
6362 strcat(objcClassName
, baseClassName
);
6364 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindSetTargetAddress
, false, objcClassName
);
6367 return PointerToCStringSection
<x86
>::addRelocFixup(parser
, reloc
);
6371 template <typename A
>
6372 void Section
<A
>::makeFixups(class Parser
<A
>& parser
, const struct Parser
<A
>::CFIInfoArray
&)
6374 const macho_section
<P
>* sect
= this->machoSection();
6375 const macho_relocation_info
<P
>* relocs
= (macho_relocation_info
<P
>*)(file().fileContent() + sect
->reloff());
6376 const uint32_t relocCount
= sect
->nreloc();
6377 for (uint32_t r
= 0; r
< relocCount
; ++r
) {
6379 if ( this->addRelocFixup(parser
, &relocs
[r
]) )
6382 catch (const char* msg
) {
6383 throwf("in section %s,%s reloc %u: %s", sect
->segname(), sect
->sectname(), r
, msg
);
6387 // add follow-on fixups if .o file is missing .subsections_via_symbols
6388 if ( this->addFollowOnFixups() ) {
6389 Atom
<A
>* end
= &_endAtoms
[-1];
6390 for(Atom
<A
>* p
= _beginAtoms
; p
< end
; ++p
) {
6391 typename Parser
<A
>::SourceLocation
src(p
, 0);
6392 Atom
<A
>* nextAtom
= &p
[1];
6393 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindNoneFollowOn
, nextAtom
);
6396 else if ( this->type() == ld::Section::typeCode
) {
6397 // if FDE broke text not at a symbol, use followOn to keep code together
6398 Atom
<A
>* end
= &_endAtoms
[-1];
6399 for(Atom
<A
>* p
= _beginAtoms
; p
< end
; ++p
) {
6400 typename Parser
<A
>::SourceLocation
src(p
, 0);
6401 Atom
<A
>* nextAtom
= &p
[1];
6402 if ( (p
->symbolTableInclusion() == ld::Atom::symbolTableIn
) && (nextAtom
->symbolTableInclusion() == ld::Atom::symbolTableNotIn
) ) {
6403 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindNoneFollowOn
, nextAtom
);
6408 // add follow-on fixups for aliases
6409 if ( _hasAliases
) {
6410 for(Atom
<A
>* p
= _beginAtoms
; p
< _endAtoms
; ++p
) {
6411 if ( p
->isAlias() && ! this->addFollowOnFixups() ) {
6412 Atom
<A
>* targetOfAlias
= &p
[1];
6413 assert(p
< &_endAtoms
[-1]);
6414 assert(p
->_objAddress
== targetOfAlias
->_objAddress
);
6415 typename Parser
<A
>::SourceLocation
src(p
, 0);
6416 parser
.addFixup(src
, ld::Fixup::k1of1
, ld::Fixup::kindNoneFollowOn
, targetOfAlias
);
6425 // main function used by linker to instantiate ld::Files
6427 ld::relocatable::File
* parse(const uint8_t* fileContent
, uint64_t fileLength
,
6428 const char* path
, time_t modTime
, uint32_t ordinal
, const ParserOptions
& opts
)
6430 switch ( opts
.architecture
) {
6431 case CPU_TYPE_X86_64
:
6432 if ( mach_o::relocatable::Parser
<x86_64
>::validFile(fileContent
) )
6433 return mach_o::relocatable::Parser
<x86_64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
);
6436 if ( mach_o::relocatable::Parser
<x86
>::validFile(fileContent
) )
6437 return mach_o::relocatable::Parser
<x86
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
);
6440 if ( mach_o::relocatable::Parser
<arm
>::validFile(fileContent
, opts
.objSubtypeMustMatch
, opts
.subType
) )
6441 return mach_o::relocatable::Parser
<arm
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
);
6443 case CPU_TYPE_POWERPC
:
6444 if ( mach_o::relocatable::Parser
<ppc
>::validFile(fileContent
) )
6445 return mach_o::relocatable::Parser
<ppc
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
);
6447 case CPU_TYPE_POWERPC64
:
6448 if ( mach_o::relocatable::Parser
<ppc64
>::validFile(fileContent
) )
6449 return mach_o::relocatable::Parser
<ppc64
>::parse(fileContent
, fileLength
, path
, modTime
, ordinal
, opts
);
6456 // used by archive reader to validate member object file
6458 bool isObjectFile(const uint8_t* fileContent
, uint64_t fileLength
, const ParserOptions
& opts
)
6460 switch ( opts
.architecture
) {
6461 case CPU_TYPE_X86_64
:
6462 return ( mach_o::relocatable::Parser
<x86_64
>::validFile(fileContent
) );
6464 return ( mach_o::relocatable::Parser
<x86
>::validFile(fileContent
) );
6466 return ( mach_o::relocatable::Parser
<arm
>::validFile(fileContent
, opts
.objSubtypeMustMatch
, opts
.subType
) );
6467 case CPU_TYPE_POWERPC
:
6468 return ( mach_o::relocatable::Parser
<ppc
>::validFile(fileContent
) );
6469 case CPU_TYPE_POWERPC64
:
6470 return ( mach_o::relocatable::Parser
<ppc64
>::validFile(fileContent
) );
6476 // used by linker to infer architecture when no -arch is on command line
6478 bool isObjectFile(const uint8_t* fileContent
, cpu_type_t
* result
, cpu_subtype_t
* subResult
)
6480 if ( mach_o::relocatable::Parser
<x86_64
>::validFile(fileContent
) ) {
6481 *result
= CPU_TYPE_X86_64
;
6482 *subResult
= CPU_SUBTYPE_X86_64_ALL
;
6485 if ( mach_o::relocatable::Parser
<x86
>::validFile(fileContent
) ) {
6486 *result
= CPU_TYPE_I386
;
6487 *subResult
= CPU_SUBTYPE_X86_ALL
;
6490 if ( mach_o::relocatable::Parser
<arm
>::validFile(fileContent
, false, 0) ) {
6491 *result
= CPU_TYPE_ARM
;
6492 const macho_header
<Pointer32
<LittleEndian
> >* header
= (const macho_header
<Pointer32
<LittleEndian
> >*)fileContent
;
6493 *subResult
= header
->cpusubtype();
6496 if ( mach_o::relocatable::Parser
<ppc
>::validFile(fileContent
) ) {
6497 *result
= CPU_TYPE_POWERPC
;
6498 const macho_header
<Pointer32
<BigEndian
> >* header
= (const macho_header
<Pointer32
<BigEndian
> >*)fileContent
;
6499 *subResult
= header
->cpusubtype();
6502 if ( mach_o::relocatable::Parser
<ppc64
>::validFile(fileContent
) ) {
6503 *result
= CPU_TYPE_POWERPC64
;
6504 *subResult
= CPU_SUBTYPE_POWERPC_ALL
;
6511 // used by linker is error messages to describe bad .o file
6513 const char* archName(const uint8_t* fileContent
)
6515 if ( mach_o::relocatable::Parser
<x86_64
>::validFile(fileContent
) ) {
6516 return mach_o::relocatable::Parser
<x86_64
>::fileKind(fileContent
);
6518 if ( mach_o::relocatable::Parser
<x86
>::validFile(fileContent
) ) {
6519 return mach_o::relocatable::Parser
<x86
>::fileKind(fileContent
);
6521 if ( mach_o::relocatable::Parser
<arm
>::validFile(fileContent
, false, 0) ) {
6522 return mach_o::relocatable::Parser
<arm
>::fileKind(fileContent
);
6524 if ( mach_o::relocatable::Parser
<ppc
>::validFile(fileContent
) ) {
6525 return mach_o::relocatable::Parser
<ppc
>::fileKind(fileContent
);
6527 if ( mach_o::relocatable::Parser
<ppc64
>::validFile(fileContent
) ) {
6528 return mach_o::relocatable::Parser
<ppc64
>::fileKind(fileContent
);
6534 // Used by archive reader when -ObjC option is specified
6536 bool hasObjC2Categories(const uint8_t* fileContent
)
6538 if ( mach_o::relocatable::Parser
<x86_64
>::validFile(fileContent
) ) {
6539 return mach_o::relocatable::Parser
<x86_64
>::hasObjC2Categories(fileContent
);
6541 else if ( mach_o::relocatable::Parser
<arm
>::validFile(fileContent
, false, 0) ) {
6542 return mach_o::relocatable::Parser
<arm
>::hasObjC2Categories(fileContent
);
6549 } // namespace relocatable
6550 } // namespace mach_o