]> git.saurik.com Git - apple/ld64.git/blame - src/ld/parsers/macho_relocatable_file.cpp
ld64-123.2.1.tar.gz
[apple/ld64.git] / src / ld / parsers / macho_relocatable_file.cpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25
26#include <stdint.h>
27#include <stdlib.h>
28#include <math.h>
29#include <unistd.h>
30#include <fcntl.h>
31#include <sys/param.h>
32#include <sys/stat.h>
33#include <sys/mman.h>
34
35#include "MachOFileAbstraction.hpp"
36
37#include <libunwind/DwarfInstructions.hpp>
38#include <libunwind/AddressSpace.hpp>
39#include <libunwind/Registers.hpp>
40
41#include <vector>
42#include <set>
43#include <map>
44#include <algorithm>
45
46#include "dwarf2.h"
47#include "debugline.h"
48
49#include "Architectures.hpp"
50#include "ld.hpp"
51#include "macho_relocatable_file.h"
52
53
54
55extern void throwf(const char* format, ...) __attribute__ ((noreturn,format(printf, 1, 2)));
56extern void warning(const char* format, ...) __attribute__((format(printf, 1, 2)));
57
58namespace mach_o {
59namespace relocatable {
60
61
62// forward reference
63template <typename A> class Parser;
64template <typename A> class Atom;
65template <typename A> class Section;
66template <typename A> class CFISection;
67
68template <typename A>
69class File : public ld::relocatable::File
70{
71public:
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),
81 _cpuSubType(0),
82 _ojcReplacmentClass(false), _canScatterAtoms(false) {}
83 virtual ~File();
84
85 // overrides of ld::File
86 virtual bool forEachAtom(ld::File::AtomHandler&) const;
87 virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
88 { return false; }
89
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;
98
99 const uint8_t* fileContent() { return _fileContent; }
100private:
101 friend class Atom<A>;
102 friend class Section<A>;
103 friend class Parser<A>;
104 friend class CFISection<A>::OAS;
105
106 typedef typename A::P P;
107
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;
128};
129
130
131template <typename A>
132class Section : public ld::Section
133{
134public:
135 typedef typename A::P::uint_t pint_t;
136 typedef typename A::P P;
137 typedef typename A::P::E E;
138
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; }
159
160protected:
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) { }
167
168
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);
178
179 File<A>& _file;
180 const macho_section<P>* _machOSection;
181 class Atom<A>* _beginAtoms;
182 class Atom<A>* _endAtoms;
183 bool _hasAliases;
184};
185
186
187template <typename A>
188class CFISection : public Section<A>
189{
190public:
191 CFISection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
192 : Section<A>(f, s) { }
193 uint32_t cfiCount();
194
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; }
200
201
202 ///
203 /// ObjectFileAddressSpace is used as a template parameter to UnwindCursor for parsing
204 /// dwarf CFI information in an object file.
205 ///
206 class OAS
207 {
208 public:
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;
213
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()) {}
219
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);
228 private:
229 const void* mappedAddress(pint_t addr);
230
231 CFISection<A>& _ehFrameSection;
232 const uint8_t* _ehFrameContent;
233 pint_t _ehFrameStartAddr;
234 pint_t _ehFrameEndAddr;
235 };
236
237
238 typedef typename A::P::uint_t pint_t;
239 typedef libunwind::CFI_Atom_Info<OAS> CFI_Atom_Info;
240
241 void cfiParse(class Parser<A>& parser, uint8_t* buffer, CFI_Atom_Info cfiArray[], uint32_t cfiCount);
242 bool needsRelocating();
243
244 static bool bigEndian();
245private:
246 void addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo);
247 static void warnFunc(void* ref, uint64_t funcAddr, const char* msg);
248};
249
250
251template <typename A>
252class TentativeDefinitionSection : public Section<A>
253{
254public:
255 TentativeDefinitionSection(Parser<A>& parser, File<A>& f)
256 : Section<A>(f, "__DATA", "__comm/tent", ld::Section::typeTentativeDefs) {}
257
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&) {}
267private:
268 typedef typename A::P::uint_t pint_t;
269 typedef typename A::P P;
270};
271
272
273template <typename A>
274class AbsoluteSymbolSection : public Section<A>
275{
276public:
277 AbsoluteSymbolSection(Parser<A>& parser, File<A>& f)
278 : Section<A>(f, "__DATA", "__abs", ld::Section::typeAbsoluteSymbols, true) {}
279
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);
292
293private:
294 typedef typename A::P::uint_t pint_t;
295 typedef typename A::P P;
296};
297
298
299template <typename A>
300class SymboledSection : public Section<A>
301{
302public:
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&);
311protected:
312 typedef typename A::P::uint_t pint_t;
313 typedef typename A::P P;
314
315 ld::Atom::ContentType _type;
316};
317
318
319template <typename A>
320class TLVDefsSection : public SymboledSection<A>
321{
322public:
323 TLVDefsSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s) :
324 SymboledSection<A>(parser, f, s) { }
325
326private:
327
328};
329
330
331template <typename A>
332class ImplicitSizeSection : public Section<A>
333{
334public:
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&);
339protected:
340 typedef typename A::P::uint_t pint_t;
341 typedef typename A::P P;
342
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'); }
353};
354
355template <typename A>
356class FixedSizeSection : public ImplicitSizeSection<A>
357{
358public:
359 FixedSizeSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
360 : ImplicitSizeSection<A>(parser, f, s) { }
361protected:
362 typedef typename A::P::uint_t pint_t;
363 typedef typename A::P P;
364 typedef typename A::P::E E;
365
366 virtual bool useElementAt(Parser<A>& parser,
367 struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr)
368 { return true; }
369};
370
371
372template <typename A>
373class Literal4Section : public FixedSizeSection<A>
374{
375public:
376 Literal4Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
377 : FixedSizeSection<A>(parser, f, s) {}
378protected:
379 typedef typename A::P::uint_t pint_t;
380 typedef typename A::P P;
381
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;
389};
390
391template <typename A>
392class Literal8Section : public FixedSizeSection<A>
393{
394public:
395 Literal8Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
396 : FixedSizeSection<A>(parser, f, s) {}
397protected:
398 typedef typename A::P::uint_t pint_t;
399 typedef typename A::P P;
400
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;
408};
409
410template <typename A>
411class Literal16Section : public FixedSizeSection<A>
412{
413public:
414 Literal16Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
415 : FixedSizeSection<A>(parser, f, s) {}
416protected:
417 typedef typename A::P::uint_t pint_t;
418 typedef typename A::P P;
419
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;
427};
428
429
430template <typename A>
431class NonLazyPointerSection : public FixedSizeSection<A>
432{
433public:
434 NonLazyPointerSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
435 : FixedSizeSection<A>(parser, f, s) {}
436protected:
437 typedef typename A::P::uint_t pint_t;
438 typedef typename A::P P;
439
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;
451
452private:
453 static const char* targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind);
454 static ld::Fixup::Kind fixupKind();
455};
456
457
458template <typename A>
459class CFStringSection : public FixedSizeSection<A>
460{
461public:
462 CFStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
463 : FixedSizeSection<A>(parser, f, s) {}
464protected:
465 typedef typename A::P::uint_t pint_t;
466
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;
475private:
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);
479};
480
481
482template <typename A>
483class ObjC1ClassSection : public FixedSizeSection<A>
484{
485public:
486 ObjC1ClassSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
487 : FixedSizeSection<A>(parser, f, s) {}
488protected:
489 typedef typename A::P::uint_t pint_t;
490 typedef typename A::P P;
491 typedef typename A::P::E E;
492
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
501 { return 0; }
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>*);
505};
506
507
508template <typename A>
509class ObjC2ClassRefsSection : public FixedSizeSection<A>
510{
511public:
512 ObjC2ClassRefsSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
513 : FixedSizeSection<A>(parser, f, s) {}
514protected:
515 typedef typename A::P::uint_t pint_t;
516
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;
525private:
526 const char* targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
527};
528
529
530template <typename A>
531class ObjC2CategoryListSection : public FixedSizeSection<A>
532{
533public:
534 ObjC2CategoryListSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
535 : FixedSizeSection<A>(parser, f, s) {}
536protected:
537 typedef typename A::P::uint_t pint_t;
538
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; }
545private:
546 const char* targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
547};
548
549
550template <typename A>
551class PointerToCStringSection : public FixedSizeSection<A>
552{
553public:
554 PointerToCStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
555 : FixedSizeSection<A>(parser, f, s) {}
556protected:
557 typedef typename A::P::uint_t pint_t;
558
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;
568};
569
570
571template <typename A>
572class Objc1ClassReferences : public PointerToCStringSection<A>
573{
574public:
575 Objc1ClassReferences(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
576 : PointerToCStringSection<A>(parser, f, s) {}
577
578 typedef typename A::P::uint_t pint_t;
579 typedef typename A::P P;
580
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;
584};
585
586
587template <typename A>
588class CStringSection : public ImplicitSizeSection<A>
589{
590public:
591 CStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
592 : ImplicitSizeSection<A>(parser, f, s) {}
593protected:
594 typedef typename A::P::uint_t pint_t;
595 typedef typename A::P P;
596
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;
607
608};
609
610
611template <typename A>
612class UTF16StringSection : public SymboledSection<A>
613{
614public:
615 UTF16StringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
616 : SymboledSection<A>(parser, f, s) {}
617protected:
618 typedef typename A::P::uint_t pint_t;
619 typedef typename A::P P;
620
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;
625};
626
627
628//
629// Atoms in mach-o files
630//
631template <typename A>
632class Atom : public ld::Atom
633{
634public:
635 // overrides of ld::Atom
636 virtual ld::File* file() const { return &sect().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]; }
654
655private:
656
657 enum { kFixupStartIndexBits = 32,
658 kLineInfoStartIndexBits = 32,
659 kUnwindInfoStartIndexBits = 24,
660 kFixupCountBits = 24,
661 kLineInfoCountBits = 12,
662 kUnwindInfoCountBits = 4
663 }; // must sum to 128
664
665public:
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;
679
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) )
711 this->setAutoHide();
712 this->verifyAlignment();
713 }
714
715private:
716 friend class Parser<A>;
717 friend class Section<A>;
718 friend class CStringSection<A>;
719 friend class AbsoluteSymbolSection<A>;
720
721 pint_t _size;
722 pint_t _objAddress;
723 const char* _name;
724 mutable unsigned long _hash;
725
726 uint64_t _fixupsStartIndex : kFixupStartIndexBits,
727 _lineInfoStartIndex : kLineInfoStartIndexBits,
728 _unwindInfoStartIndex : kUnwindInfoStartIndexBits,
729 _fixupsCount : kFixupCountBits,
730 _lineInfoCount : kLineInfoCountBits,
731 _unwindInfoCount : kUnwindInfoCountBits;
732
733};
734
735
736
737template <typename A>
738void Atom<A>::setFixupsRange(uint32_t startIndex, uint32_t count)
739{
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;
747}
748
749template <typename A>
750void Atom<A>::setUnwindInfoRange(uint32_t startIndex, uint32_t count)
751{
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;
759}
760
761template <typename A>
762void Atom<A>::setLineInfoRange(uint32_t startIndex, uint32_t count)
763{
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;
768}
769
770template <typename A>
771const uint8_t* Atom<A>::contentPointer() const
772{
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;
776}
777
778
779template <typename A>
780void Atom<A>::copyRawContent(uint8_t buffer[]) const
781{
782 // copy base bytes
783 if ( this->contentType() == ld::Atom::typeZeroFill ) {
784 bzero(buffer, _size);
785 }
786 else if ( _size != 0 ) {
787 memcpy(buffer, this->contentPointer(), _size);
788 }
789}
790
791template <>
792void Atom<arm>::verifyAlignment() const
793{
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());
797 }
798}
799
800template <typename A>
801void Atom<A>::verifyAlignment() const
802{
803}
804
805
806template <typename A>
807class Parser
808{
809public:
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);
820 }
821
822 typedef typename A::P P;
823 typedef typename A::P::E E;
824 typedef typename A::P::uint_t pint_t;
825
826 struct SourceLocation {
827 SourceLocation() {}
828 SourceLocation(Atom<A>* a, uint32_t o) : atom(a), offsetInAtom(o) {}
829 Atom<A>* atom;
830 uint32_t offsetInAtom;
831 };
832
833 struct TargetDesc {
834 Atom<A>* atom;
835 const char* name; // only used if targetAtom is NULL
836 int64_t addend;
837 bool weakImport; // only used if targetAtom is NULL
838 };
839
840 struct FixupInAtom {
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(); }
843
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(); }
846
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(); }
849
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(); }
852
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(); }
855
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(); }
858
859 ld::Fixup fixup;
860 Atom<A>* atom;
861 };
862
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));
865 }
866
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));
869 }
870
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));
873 }
874
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));
877 }
878
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));
881 }
882
883 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) {
884 _allFixups.push_back(FixupInAtom(src, c, k));
885 }
886
887
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,
916 TargetDesc& target);
917 uint32_t tentativeDefinitionCount() { return _tentativeDefinitionCount; }
918 uint32_t absoluteSymbolCount() { return _absoluteSymbolCount; }
919
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; }
925
926
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);
929
930
931
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; }
943
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;
949 bool newSection;
950 uint32_t cfiIndex;
951 uint32_t symIndex;
952 };
953
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;
959 };
960
961
962private:
963 friend class Section<A>;
964
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 };
970
971 template <typename P>
972 struct MachOSectionAndSectionClass
973 {
974 const macho_section<P>* sect;
975 SectionType type;
976
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();
981 if ( diff == 0 )
982 return 0;
983 if ( diff < 0 )
984 return -1;
985 else
986 return 1;
987 }
988 };
989
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();
996 void makeSections();
997 void checkForLSDA();
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();
1003 void parseStabs();
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);
1010
1011
1012 // filled in by constructor
1013 const uint8_t* _fileContent;
1014 uint32_t _fileLength;
1015 const char* _path;
1016 time_t _modTime;
1017 uint32_t _ordinal;
1018
1019 // filled in by parseLoadCommands()
1020 File<A>* _file;
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;
1031 bool _hasUUID;
1032
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;
1049};
1050
1051
1052
1053template <typename A>
1054Parser<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)
1068{
1069}
1070
1071template <>
1072bool Parser<ppc>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1073{
1074 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1075 if ( header->magic() != MH_MAGIC )
1076 return false;
1077 if ( header->cputype() != CPU_TYPE_POWERPC )
1078 return false;
1079 if ( header->filetype() != MH_OBJECT )
1080 return false;
1081 return true;
1082}
1083
1084template <>
1085bool Parser<ppc64>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1086{
1087 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1088 if ( header->magic() != MH_MAGIC_64 )
1089 return false;
1090 if ( header->cputype() != CPU_TYPE_POWERPC64 )
1091 return false;
1092 if ( header->filetype() != MH_OBJECT )
1093 return false;
1094 return true;
1095}
1096
1097template <>
1098bool Parser<x86>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1099{
1100 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1101 if ( header->magic() != MH_MAGIC )
1102 return false;
1103 if ( header->cputype() != CPU_TYPE_I386 )
1104 return false;
1105 if ( header->filetype() != MH_OBJECT )
1106 return false;
1107 return true;
1108}
1109
1110template <>
1111bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1112{
1113 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1114 if ( header->magic() != MH_MAGIC_64 )
1115 return false;
1116 if ( header->cputype() != CPU_TYPE_X86_64 )
1117 return false;
1118 if ( header->filetype() != MH_OBJECT )
1119 return false;
1120 return true;
1121}
1122
1123template <>
1124bool Parser<arm>::validFile(const uint8_t* fileContent, bool subtypeMustMatch, cpu_subtype_t subtype)
1125{
1126 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1127 if ( header->magic() != MH_MAGIC )
1128 return false;
1129 if ( header->cputype() != CPU_TYPE_ARM )
1130 return false;
1131 if ( header->filetype() != MH_OBJECT )
1132 return false;
1133 if ( subtypeMustMatch ) {
1134 if ( (cpu_subtype_t)header->cpusubtype() == subtype )
1135 return true;
1136 // hack until libcc_kext.a is made fat
1137 if ( header->cpusubtype() == CPU_SUBTYPE_ARM_ALL )
1138 return true;
1139 return false;
1140 }
1141 return true;
1142}
1143
1144
1145template <>
1146const char* Parser<ppc>::fileKind(const uint8_t* fileContent)
1147{
1148 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1149 if ( header->magic() != MH_MAGIC )
1150 return NULL;
1151 if ( header->cputype() != CPU_TYPE_POWERPC )
1152 return NULL;
1153 switch ( header->cpusubtype() ) {
1154 case CPU_SUBTYPE_POWERPC_750:
1155 return "ppc750";
1156 case CPU_SUBTYPE_POWERPC_7400:
1157 return "ppc7400";
1158 case CPU_SUBTYPE_POWERPC_7450:
1159 return "ppc7450";
1160 case CPU_SUBTYPE_POWERPC_970:
1161 return "ppc970";
1162 case CPU_SUBTYPE_POWERPC_ALL:
1163 return "ppc";
1164 }
1165 return "ppc???";
1166}
1167
1168template <>
1169const char* Parser<ppc64>::fileKind(const uint8_t* fileContent)
1170{
1171 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1172 if ( header->magic() != MH_MAGIC )
1173 return NULL;
1174 if ( header->cputype() != CPU_TYPE_POWERPC64 )
1175 return NULL;
1176 return "ppc64";
1177}
1178
1179template <>
1180const char* Parser<x86>::fileKind(const uint8_t* fileContent)
1181{
1182 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1183 if ( header->magic() != MH_MAGIC )
1184 return NULL;
1185 if ( header->cputype() != CPU_TYPE_I386 )
1186 return NULL;
1187 return "i386";
1188}
1189
1190template <>
1191const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
1192{
1193 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1194 if ( header->magic() != MH_MAGIC )
1195 return NULL;
1196 if ( header->cputype() != CPU_TYPE_X86_64 )
1197 return NULL;
1198 return "x86_64";
1199}
1200
1201template <>
1202const char* Parser<arm>::fileKind(const uint8_t* fileContent)
1203{
1204 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1205 if ( header->magic() != MH_MAGIC )
1206 return NULL;
1207 if ( header->cputype() != CPU_TYPE_ARM )
1208 return NULL;
1209 switch ( header->cpusubtype() ) {
1210 case CPU_SUBTYPE_ARM_V4T:
1211 return "armv4t";
1212 case CPU_SUBTYPE_ARM_V5TEJ:
1213 return "armv5";
1214 case CPU_SUBTYPE_ARM_V6:
1215 return "armv6";
1216 case CPU_SUBTYPE_ARM_V7:
1217 return "armv7";
1218 case CPU_SUBTYPE_ARM_ALL:
1219 return "arm-ALL";
1220 }
1221 return "arm???";
1222}
1223
1224
1225template <typename A>
1226bool Parser<A>::hasObjC2Categories(const uint8_t* fileContent)
1227{
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 = &sectionsStart[si];
1239 if ( (sect->size() > 0)
1240 && (strcmp(sect->sectname(), "__objc_catlist") == 0)
1241 && (strcmp(sect->segname(), "__DATA") == 0) ) {
1242 return true;
1243 }
1244 }
1245 }
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);
1249 }
1250 return false;
1251}
1252
1253template <typename A>
1254int Parser<A>::pointerSorter(const void* l, const void* r)
1255{
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);
1260}
1261
1262template <typename A>
1263typename A::P::uint_t Parser<A>::LabelAndCFIBreakIterator::peek(Parser<A>& parser, pint_t startAddr, pint_t endAddr)
1264{
1265 pint_t symbolAddr;
1266 if ( symIndex < sortedSymbolCount )
1267 symbolAddr = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]).n_value();
1268 else
1269 symbolAddr = endAddr;
1270 pint_t cfiAddr;
1271 if ( cfiIndex < cfiStartsCount )
1272 cfiAddr = cfiStartsArray[cfiIndex];
1273 else
1274 cfiAddr = endAddr;
1275 if ( (cfiAddr < symbolAddr) && (cfiAddr >= startAddr) ) {
1276 if ( cfiAddr < endAddr )
1277 return cfiAddr;
1278 else
1279 return endAddr;
1280 }
1281 else {
1282 if ( symbolAddr < endAddr )
1283 return symbolAddr;
1284 else
1285 return endAddr;
1286 }
1287}
1288
1289//
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.
1293//
1294template <typename A>
1295bool 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)
1297{
1298 // may not be a label on start of section, but need atom demarcation there
1299 if ( newSection ) {
1300 newSection = false;
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) )
1306 break;
1307 ++symIndex;
1308 }
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 ) {
1318 // use cfi
1319 ++cfiIndex;
1320 *addr = nextCfiAddr;
1321 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1322 *symbol = NULL;
1323 return true;
1324 }
1325 }
1326 *addr = startAddr;
1327 *size = endAddr - startAddr;
1328 *symbol = NULL;
1329 if ( startAddr == endAddr )
1330 return false; // zero size section
1331 else
1332 return true; // whole section is one atom with no label
1333 }
1334 // if also CFI break here, eat it
1335 if ( cfiIndex < cfiStartsCount ) {
1336 if ( cfiStartsArray[cfiIndex] == nextSymbolAddr )
1337 ++cfiIndex;
1338 }
1339 if ( nextSymbolAddr == startAddr ) {
1340 // label at start of section, return it as chunk
1341 ++symIndex;
1342 *addr = startAddr;
1343 *size = peek(parser, startAddr, endAddr) - startAddr;
1344 *symbol = &sym;
1345 return true;
1346 }
1347 // return chunk before first symbol
1348 *addr = startAddr;
1349 *size = nextSymbolAddr - startAddr;
1350 *symbol = NULL;
1351 return true;
1352 }
1353 // no symbols left in whole file, so entire section is one chunk
1354 *addr = startAddr;
1355 *size = endAddr - startAddr;
1356 *symbol = NULL;
1357 if ( startAddr == endAddr )
1358 return false; // zero size section
1359 else
1360 return true; // whole section is one atom with no label
1361 }
1362
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 )
1369 return false;
1370 ++symIndex;
1371 if ( nextSymbolAddr < startAddr )
1372 continue;
1373 *addr = nextSymbolAddr;
1374 *size = peek(parser, startAddr, endAddr) - nextSymbolAddr;
1375 *symbol = &sym;
1376 return true;
1377 }
1378 else if ( nextCfiAddr < nextSymbolAddr ) {
1379 if ( nextCfiAddr >= endAddr )
1380 return false;
1381 ++cfiIndex;
1382 if ( nextCfiAddr < startAddr )
1383 continue;
1384 *addr = nextCfiAddr;
1385 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1386 *symbol = NULL;
1387 return true;
1388 }
1389 else {
1390 if ( nextCfiAddr >= endAddr )
1391 return false;
1392 ++symIndex;
1393 ++cfiIndex;
1394 if ( nextCfiAddr < startAddr )
1395 continue;
1396 *addr = nextCfiAddr;
1397 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1398 *symbol = &sym;
1399 return true;
1400 }
1401 }
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 )
1407 return false;
1408 ++symIndex;
1409 if ( nextSymbolAddr < startAddr )
1410 continue;
1411 *addr = nextSymbolAddr;
1412 *size = peek(parser, startAddr, endAddr) - nextSymbolAddr;
1413 *symbol = &sym;
1414 return true;
1415 }
1416 while ( cfiIndex < cfiStartsCount ) {
1417 pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
1418 if ( nextCfiAddr >= endAddr )
1419 return false;
1420 ++cfiIndex;
1421 if ( nextCfiAddr < startAddr )
1422 continue;
1423 *addr = nextCfiAddr;
1424 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1425 *symbol = NULL;
1426 return true;
1427 }
1428 return false;
1429}
1430
1431
1432
1433template <typename A>
1434ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
1435{
1436 // create file object
1437 _file = new File<A>(_path, _modTime, _fileContent, _ordinal);
1438
1439 // respond to -t option
1440 if ( opts.logAllFiles )
1441 printf("%s\n", _path);
1442
1443 // parse start of mach-o file
1444 if ( ! parseLoadCommands() )
1445 return _file;
1446
1447 // make symbol table sorted by address
1448 this->checkForLSDA();
1449 this->prescanSymbolTable();
1450 uint32_t sortedSymbolIndexes[_symbolsInSections];
1451 this->makeSortedSymbolsArray(sortedSymbolIndexes);
1452
1453 // allocate Section<A> object for each mach-o section
1454 makeSections();
1455
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);
1469 else
1470 stackAllocSize = sectSize;
1471 }
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 )
1481 continue;
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 )
1487 ++cfiStartsCount;
1488 if ( cfiArray[i].u.fdeInfo.lsda.targetAddress != CFI_INVALID_ADDRESS )
1489 ++cfiStartsCount;
1490 }
1491 }
1492 CFIInfoArray cfis(cfiArray, countOfCFIs);
1493
1494 // create sorted array of function starts and lsda starts
1495 pint_t cfiStartsArray[cfiStartsCount];
1496 uint32_t countOfFDEs = 0;
1497 if ( countOfCFIs != 0 ) {
1498 int index = 0;
1499 for(uint32_t i=0; i < countOfCFIs; ++i) {
1500 if ( cfiArray[i].isCIE )
1501 continue;
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;
1506 ++countOfFDEs;
1507 }
1508 ::qsort(cfiStartsArray, cfiStartsCount, sizeof(pint_t), pointerSorter);
1509 #ifndef NDEBUG
1510 // scan for FDEs claming the same function
1511 for(int i=1; i < index; ++i) {
1512 assert( cfiStartsArray[i] != cfiStartsArray[i-1] );
1513 }
1514 #endif
1515 }
1516
1517 Section<A>** sections = _file->_sectionsArray;
1518 uint32_t sectionsCount = _file->_sectionsArrayCount;
1519
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;
1530 }
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;
1534
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;
1544 }
1545 assert( _file->_atomsArrayCount == computedAtomCount && "more atoms allocated than expected");
1546
1547
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);
1552
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>);
1562 }
1563 assert(fixupOffset == _allFixups.size());
1564 _file->_fixups.reserve(fixupOffset);
1565
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++;
1571 }
1572
1573 // done with temp vector
1574 _allFixups.clear();
1575
1576 // add unwind info
1577 _file->_unwindInfos.reserve(countOfFDEs);
1578 for(uint32_t i=0; i < countOfCFIs; ++i) {
1579 if ( cfiArray[i].isCIE )
1580 continue;
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);
1588 }
1589 }
1590
1591 // parse dwarf debug info to get line info
1592 this->parseDebugInfo();
1593
1594 return _file;
1595}
1596
1597
1598
1599template <> uint8_t Parser<ppc>::loadCommandSizeMask() { return 0x03; }
1600template <> uint8_t Parser<ppc64>::loadCommandSizeMask() { return 0x07; }
1601template <> uint8_t Parser<x86>::loadCommandSizeMask() { return 0x03; }
1602template <> uint8_t Parser<x86_64>::loadCommandSizeMask() { return 0x07; }
1603template <> uint8_t Parser<arm>::loadCommandSizeMask() { return 0x03; }
1604
1605template <typename A>
1606bool Parser<A>::parseLoadCommands()
1607{
1608 const macho_header<P>* header = (const macho_header<P>*)_fileContent;
1609
1610 // set File attributes
1611 _file->_canScatterAtoms = (header->flags() & MH_SUBSECTIONS_VIA_SYMBOLS);
1612 _file->_cpuSubType = header->cpusubtype();
1613
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 )
1619 return false;
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()) {
1633 case LC_SYMTAB:
1634 {
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();
1648 }
1649 }
1650 }
1651 break;
1652 case LC_DYSYMTAB:
1653 {
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();
1661 }
1662 break;
1663 case LC_UUID:
1664 _hasUUID = true;
1665 break;
1666
1667 default:
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;
1672 }
1673 break;
1674 }
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);
1678 }
1679
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();
1685
1686 return true;
1687}
1688
1689template <>
1690void Parser<arm>::checkForLSDA()
1691{
1692 // ARM has no FDEs, so need labels to break up section into atoms
1693}
1694
1695template <typename A>
1696void Parser<A>::checkForLSDA()
1697{
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;
1705 }
1706 else if ( strcmp(sect->segname(), "__DATA") == 0 ) {
1707 assert(_lsdaDataSectionNum == 0);
1708 _lsdaDataSectionNum = i+1;
1709 }
1710 }
1711 }
1712}
1713
1714
1715template <typename A>
1716void Parser<A>::prescanSymbolTable()
1717{
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);
1723 // ignore stabs
1724 if ( (sym.n_type() & N_STAB) != 0 )
1725 continue;
1726
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;
1733 }
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);
1739 }
1740 }
1741 continue;
1742 }
1743
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 ) {
1749 _AppleObjc = true;
1750 continue;
1751 }
1752 // ignore .objc_class_name_* symbols
1753 if ( strncmp(absName, ".objc_category_name_", 20) == 0 )
1754 continue;
1755 // ignore empty *.eh symbols
1756 if ( strcmp(&absName[strlen(absName)-3], ".eh") == 0 )
1757 continue;
1758 ++_absoluteSymbolCount;
1759 }
1760
1761 // only look at definitions
1762 if ( (sym.n_type() & N_TYPE) != N_SECT )
1763 continue;
1764
1765 // 'L' labels do not denote atom breaks
1766 if ( symbolName[0] == 'L' )
1767 continue;
1768
1769 // ignore labels in __gcc_except_tab section
1770 if ( (_lsdaTextSectionNum != 0) && (sym.n_sect() == _lsdaTextSectionNum) )
1771 continue;
1772 if ( (_lsdaDataSectionNum != 0) && (sym.n_sect() == _lsdaDataSectionNum) )
1773 continue;
1774
1775 // how many def syms in each section
1776 if ( sym.n_sect() > _machOSectionsCount )
1777 throw "bad n_sect in symbol table";
1778
1779 _symbolsInSections++;
1780 }
1781}
1782
1783template <typename A>
1784int Parser<A>::symbolIndexSorter(void* extra, const void* l, const void* r)
1785{
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 )
1802 return -1;
1803 else
1804 return 1;
1805 }
1806 // if both are global, make alphabetically last one be the alias
1807 return ( strcmp(parser->nameFromSymbol(rightSym), parser->nameFromSymbol(leftSym)) );
1808 }
1809 else if ( result < 0 )
1810 return -1;
1811 else
1812 return 1;
1813}
1814
1815template <typename A>
1816void Parser<A>::makeSortedSymbolsArray(uint32_t array[])
1817{
1818 uint32_t* p = array;
1819 for (uint32_t i=0; i < this->_symbolCount; ++i) {
1820 const macho_nlist<P>& sym = symbolFromIndex(i);
1821 // ignore stabs
1822 if ( (sym.n_type() & N_STAB) != 0 )
1823 continue;
1824
1825 // only look at definitions
1826 if ( (sym.n_type() & N_TYPE) != N_SECT )
1827 continue;
1828
1829 // 'L' labels do not denote atom breaks
1830 const char* symbolName = this->nameFromSymbol(sym);
1831 if ( symbolName[0] == 'L' )
1832 continue;
1833
1834 // ignore labels in __gcc_except_tab section
1835 if ( (_lsdaTextSectionNum != 0) && (sym.n_sect() == _lsdaTextSectionNum) )
1836 continue;
1837 if ( (_lsdaDataSectionNum != 0) && (sym.n_sect() == _lsdaDataSectionNum) )
1838 continue;
1839
1840 // how many def syms in each section
1841 if ( sym.n_sect() > _machOSectionsCount )
1842 throw "bad n_sect in symbol table";
1843
1844 // append to array
1845 *p++ = i;
1846 }
1847 assert(p == &array[_symbolsInSections] && "second pass over symbol table yield a different number of symbols");
1848
1849 // sort by symbol table address
1850 ::qsort_r(array, _symbolsInSections, sizeof(uint32_t), this, &symbolIndexSorter);
1851
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;
1858 }
1859 }
1860
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])) );
1864}
1865
1866
1867template <typename A>
1868void Parser<A>::makeSections()
1869{
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
1893 continue;
1894 }
1895 // ignore empty __OBJC sections
1896 if ( (sect->size() == 0) && (strcmp(sect->segname(), "__OBJC") == 0) )
1897 continue;
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
1903 // uint32_t flags;
1904 // };
1905 // #define OBJC_IMAGE_SUPPORTS_GC 2
1906 // #define OBJC_IMAGE_GC_ONLY 4
1907 //
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;
1915 else
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());
1922 }
1923 }
1924 else {
1925 warning("can't parse %s/%s section in %s", sect->segname(), sect->sectname(), _file->path());
1926 }
1927 continue;
1928 }
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;
1935 }
1936 else
1937 assert(1 && "multiple S_SYMBOL_STUBS sections");
1938 case S_LAZY_SYMBOL_POINTERS:
1939 break;
1940 case S_4BYTE_LITERALS:
1941 totalSectionsSize += sizeof(Literal4Section<A>);
1942 machOSects[count++].type = sectionTypeLiteral4;
1943 break;
1944 case S_8BYTE_LITERALS:
1945 totalSectionsSize += sizeof(Literal8Section<A>);
1946 machOSects[count++].type = sectionTypeLiteral8;
1947 break;
1948 case S_16BYTE_LITERALS:
1949 totalSectionsSize += sizeof(Literal16Section<A>);
1950 machOSects[count++].type = sectionTypeLiteral16;
1951 break;
1952 case S_NON_LAZY_SYMBOL_POINTERS:
1953 totalSectionsSize += sizeof(NonLazyPointerSection<A>);
1954 machOSects[count++].type = sectionTypeNonLazy;
1955 break;
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;
1960 }
1961 else {
1962 totalSectionsSize += sizeof(PointerToCStringSection<A>);
1963 machOSects[count++].type = sectionTypeCStringPointer;
1964 }
1965 break;
1966 case S_CSTRING_LITERALS:
1967 totalSectionsSize += sizeof(CStringSection<A>);
1968 machOSects[count++].type = sectionTypeCString;
1969 break;
1970 case S_MOD_INIT_FUNC_POINTERS:
1971 case S_MOD_TERM_FUNC_POINTERS:
1972 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
1973 case S_INTERPOSING:
1974 case S_ZEROFILL:
1975 case S_REGULAR:
1976 case S_COALESCED:
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;
1982 }
1983 else if ( (strcmp(sect->segname(), "__DATA") == 0) && (strcmp(sect->sectname(), "__cfstring") == 0) ) {
1984 totalSectionsSize += sizeof(CFStringSection<A>);
1985 machOSects[count++].type = sectionTypeCFString;
1986 }
1987 else if ( (strcmp(sect->segname(), "__TEXT") == 0) && (strcmp(sect->sectname(), "__ustring") == 0) ) {
1988 totalSectionsSize += sizeof(UTF16StringSection<A>);
1989 machOSects[count++].type = sectionTypeUTF16Strings;
1990 }
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;
1994 }
1995 else if ( (strcmp(sect->segname(), "__DATA") == 0) && (strcmp(sect->sectname(), "__objc_catlist") == 0) ) {
1996 totalSectionsSize += sizeof(ObjC2CategoryListSection<A>);
1997 machOSects[count++].type = typeObjC2CategoryList;
1998 }
1999 else if ( _AppleObjc && (strcmp(sect->segname(), "__OBJC") == 0) && (strcmp(sect->sectname(), "__class") == 0) ) {
2000 totalSectionsSize += sizeof(ObjC1ClassSection<A>);
2001 machOSects[count++].type = sectionTypeObjC1Classes;
2002 }
2003 else {
2004 totalSectionsSize += sizeof(SymboledSection<A>);
2005 machOSects[count++].type = sectionTypeSymboled;
2006 }
2007 break;
2008 case S_THREAD_LOCAL_VARIABLES:
2009 totalSectionsSize += sizeof(TLVDefsSection<A>);
2010 machOSects[count++].type = sectionTypeTLVDefs;
2011 break;
2012 case S_THREAD_LOCAL_VARIABLE_POINTERS:
2013 default:
2014 throwf("unknown section type %d", sect->flags() & SECTION_TYPE);
2015 }
2016 }
2017
2018 // sort by address (mach-o object files don't aways have sections sorted)
2019 ::qsort(machOSects, count, sizeof(MachOSectionAndSectionClass<P>), MachOSectionAndSectionClass<P>::sorter);
2020
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;
2025 }
2026
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;
2031 }
2032
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:
2042 break;
2043 case sectionTypeLiteral4:
2044 *objects++ = new (space) Literal4Section<A>(*this, *_file, machOSects[i].sect);
2045 space += sizeof(Literal4Section<A>);
2046 break;
2047 case sectionTypeLiteral8:
2048 *objects++ = new (space) Literal8Section<A>(*this, *_file, machOSects[i].sect);
2049 space += sizeof(Literal8Section<A>);
2050 break;
2051 case sectionTypeLiteral16:
2052 *objects++ = new (space) Literal16Section<A>(*this, *_file, machOSects[i].sect);
2053 space += sizeof(Literal16Section<A>);
2054 break;
2055 case sectionTypeNonLazy:
2056 *objects++ = new (space) NonLazyPointerSection<A>(*this, *_file, machOSects[i].sect);
2057 space += sizeof(NonLazyPointerSection<A>);
2058 break;
2059 case sectionTypeCFI:
2060 _EHFrameSection = new (space) CFISection<A>(*this, *_file, machOSects[i].sect);
2061 *objects++ = _EHFrameSection;
2062 space += sizeof(CFISection<A>);
2063 break;
2064 case sectionTypeCString:
2065 *objects++ = new (space) CStringSection<A>(*this, *_file, machOSects[i].sect);
2066 space += sizeof(CStringSection<A>);
2067 break;
2068 case sectionTypeCStringPointer:
2069 *objects++ = new (space) PointerToCStringSection<A>(*this, *_file, machOSects[i].sect);
2070 space += sizeof(PointerToCStringSection<A>);
2071 break;
2072 case sectionTypeObjC1ClassRefs:
2073 *objects++ = new (space) Objc1ClassReferences<A>(*this, *_file, machOSects[i].sect);
2074 space += sizeof(Objc1ClassReferences<A>);
2075 break;
2076 case sectionTypeUTF16Strings:
2077 *objects++ = new (space) UTF16StringSection<A>(*this, *_file, machOSects[i].sect);
2078 space += sizeof(UTF16StringSection<A>);
2079 break;
2080 case sectionTypeCFString:
2081 *objects++ = new (space) CFStringSection<A>(*this, *_file, machOSects[i].sect);
2082 space += sizeof(CFStringSection<A>);
2083 break;
2084 case sectionTypeObjC2ClassRefs:
2085 *objects++ = new (space) ObjC2ClassRefsSection<A>(*this, *_file, machOSects[i].sect);
2086 space += sizeof(ObjC2ClassRefsSection<A>);
2087 break;
2088 case typeObjC2CategoryList:
2089 *objects++ = new (space) ObjC2CategoryListSection<A>(*this, *_file, machOSects[i].sect);
2090 space += sizeof(ObjC2CategoryListSection<A>);
2091 break;
2092 case sectionTypeObjC1Classes:
2093 *objects++ = new (space) ObjC1ClassSection<A>(*this, *_file, machOSects[i].sect);
2094 space += sizeof(ObjC1ClassSection<A>);
2095 break;
2096 case sectionTypeSymboled:
2097 *objects++ = new (space) SymboledSection<A>(*this, *_file, machOSects[i].sect);
2098 space += sizeof(SymboledSection<A>);
2099 break;
2100 case sectionTypeTLVDefs:
2101 *objects++ = new (space) TLVDefsSection<A>(*this, *_file, machOSects[i].sect);
2102 space += sizeof(TLVDefsSection<A>);
2103 break;
2104 case sectionTypeTentativeDefinitions:
2105 *objects++ = new (space) TentativeDefinitionSection<A>(*this, *_file);
2106 space += sizeof(TentativeDefinitionSection<A>);
2107 break;
2108 case sectionTypeAbsoluteSymbols:
2109 _absoluteSection = new (space) AbsoluteSymbolSection<A>(*this, *_file);
2110 *objects++ = _absoluteSection;
2111 space += sizeof(AbsoluteSymbolSection<A>);
2112 break;
2113 default:
2114 throw "internal error uknown SectionType";
2115 }
2116 }
2117}
2118
2119
2120template <typename A>
2121Section<A>* Parser<A>::sectionForAddress(typename A::P::uint_t addr)
2122{
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];
2129 }
2130 }
2131 }
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];
2140 }
2141 }
2142 }
2143
2144 throwf("sectionForAddress(0x%llX) address not in any section", (uint64_t)addr);
2145}
2146
2147template <typename A>
2148Section<A>* Parser<A>::sectionForNum(unsigned int num)
2149{
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];
2156 }
2157 }
2158 throwf("sectionForNum(%u) section number not for any section", num);
2159}
2160
2161template <typename A>
2162Atom<A>* Parser<A>::findAtomByAddress(pint_t addr)
2163{
2164 Section<A>* section = this->sectionForAddress(addr);
2165 return section->findAtomByAddress(addr);
2166}
2167
2168template <typename A>
2169Atom<A>* Parser<A>::findAtomByAddressOrNullIfStub(pint_t addr)
2170{
2171 if ( hasStubsSection() && (_stubsMachOSection->addr() <= addr) && (addr < (_stubsMachOSection->addr()+_stubsMachOSection->size())) )
2172 return NULL;
2173 return findAtomByAddress(addr);
2174}
2175
2176template <typename A>
2177Atom<A>* Parser<A>::findAtomByAddressOrLocalTargetOfStub(pint_t addr, uint32_t* offsetInAtom)
2178{
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) );
2186 *offsetInAtom = 0;
2187 return this->findAtomByName(this->nameFromSymbol(sym));
2188 }
2189 Atom<A>* target = this->findAtomByAddress(addr);
2190 *offsetInAtom = addr - target->_objAddress;
2191 return target;
2192}
2193
2194template <typename A>
2195Atom<A>* Parser<A>::findAtomByName(const char* name)
2196{
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 )
2201 return atom;
2202 p += sizeof(Atom<A>);
2203 }
2204 return NULL;
2205}
2206
2207template <typename A>
2208void Parser<A>::findTargetFromAddress(pint_t addr, TargetDesc& target)
2209{
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);
2215 target.atom = NULL;
2216 target.name = this->nameFromSymbol(sym);
2217 target.weakImport = this->weakImportFromSymbol(sym);
2218 target.addend = 0;
2219 return;
2220 }
2221 Section<A>* section = this->sectionForAddress(addr);
2222 target.atom = section->findAtomByAddress(addr);
2223 target.addend = addr - target.atom->_objAddress;
2224 target.weakImport = false;
2225 target.name = NULL;
2226}
2227
2228template <typename A>
2229void Parser<A>::findTargetFromAddress(pint_t baseAddr, pint_t addr, TargetDesc& target)
2230{
2231 findTargetFromAddress(baseAddr, target);
2232 target.addend = addr - target.atom->_objAddress;
2233}
2234
2235template <typename A>
2236void Parser<A>::findTargetFromAddressAndSectionNum(pint_t addr, unsigned int sectNum, TargetDesc& target)
2237{
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 ) {
2243 target.name = NULL;
2244 target.weakImport = false;
2245 target.addend = 0;
2246 return;
2247 }
2248 }
2249 throwf("R_ABS reloc but no absolute symbol at target address");
2250 }
2251
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);
2260 }
2261 else {
2262 target.atom = NULL;
2263 target.name = this->nameFromSymbol(sym);
2264 target.weakImport = this->weakImportFromSymbol(sym);
2265 target.addend = 0;
2266 }
2267 return;
2268 }
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;
2281 target.name = NULL;
2282 return;
2283 }
2284 else if ( a >= sectEnd ) {
2285 target.atom = section->findAtomByAddress(sectEnd-1);
2286 target.addend = a - sectEnd;
2287 target.weakImport = false;
2288 target.name = NULL;
2289 return;
2290 }
2291 }
2292 assert(target.atom != NULL);
2293 target.addend = addr - target.atom->_objAddress;
2294 target.weakImport = false;
2295 target.name = NULL;
2296}
2297
2298template <typename A>
2299void Parser<A>::addDtraceExtraInfos(const SourceLocation& src, const char* providerName)
2300{
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);
2311 }
2312 }
2313 }
2314 }
2315}
2316
2317template <typename A>
2318const char* Parser<A>::scanSymbolTableForAddress(uint64_t addr)
2319{
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);
2324 // ignore stabs
2325 if ( (sym.n_type() & N_STAB) != 0 )
2326 continue;
2327
2328 // only look at definitions
2329 if ( (sym.n_type() & N_TYPE) != N_SECT )
2330 continue;
2331
2332 // return with exact match
2333 if ( sym.n_value() == addr )
2334 return nameFromSymbol(sym);
2335
2336 // record closest seen so far
2337 if ( (sym.n_value() < addr) && ((sym.n_value() > closestSymAddr) || (closestSymName == NULL)) )
2338 closestSymName = nameFromSymbol(sym);
2339 }
2340
2341 return (closestSymName != NULL) ? closestSymName : "unknown";
2342}
2343
2344
2345template <typename A>
2346void Parser<A>::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, const TargetDesc& target)
2347{
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;
2354 combined = true;
2355 switch ( setKind ) {
2356 case ld::Fixup::kindStoreLittleEndian32:
2357 firstKind = ld::Fixup::kindStoreTargetAddressLittleEndian32;
2358 break;
2359 case ld::Fixup::kindStoreLittleEndian64:
2360 firstKind = ld::Fixup::kindStoreTargetAddressLittleEndian64;
2361 break;
2362 case ld::Fixup::kindStoreBigEndian32:
2363 firstKind = ld::Fixup::kindStoreTargetAddressBigEndian32;
2364 break;
2365 case ld::Fixup::kindStoreBigEndian64:
2366 firstKind = ld::Fixup::kindStoreTargetAddressBigEndian64;
2367 break;
2368 case ld::Fixup::kindStoreX86BranchPCRel32:
2369 firstKind = ld::Fixup::kindStoreTargetAddressX86BranchPCRel32;
2370 break;
2371 case ld::Fixup::kindStoreX86PCRel32:
2372 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32;
2373 break;
2374 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
2375 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad;
2376 break;
2377 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
2378 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad;
2379 break;
2380 case ld::Fixup::kindStoreX86Abs32TLVLoad:
2381 firstKind = ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad;
2382 break;
2383 case ld::Fixup::kindStoreARMBranch24:
2384 firstKind = ld::Fixup::kindStoreTargetAddressARMBranch24;
2385 break;
2386 case ld::Fixup::kindStoreThumbBranch22:
2387 firstKind = ld::Fixup::kindStoreTargetAddressThumbBranch22;
2388 break;
2389 case ld::Fixup::kindStorePPCBranch24:
2390 firstKind = ld::Fixup::kindStoreTargetAddressPPCBranch24;
2391 break;
2392 default:
2393 combined = false;
2394 cl = ld::Fixup::k1of2;
2395 break;
2396 }
2397 }
2398
2399 if ( target.atom != NULL ) {
2400 if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
2401 addFixup(src, cl, firstKind, target.atom);
2402 }
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);
2405 }
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);
2409 }
2410 else {
2411 // change direct fixup to by-name fixup
2412 addFixup(src, cl, firstKind, false, target.atom->name());
2413 }
2414 }
2415 else {
2416 addFixup(src, cl, firstKind, target.weakImport, target.name);
2417 }
2418 if ( target.addend == 0 ) {
2419 if ( ! combined )
2420 addFixup(src, ld::Fixup::k2of2, setKind);
2421 }
2422 else {
2423 addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend);
2424 addFixup(src, ld::Fixup::k3of3, setKind);
2425 }
2426}
2427
2428template <typename A>
2429void Parser<A>::addFixups(const SourceLocation& src, ld::Fixup::Kind kind, const TargetDesc& target, const TargetDesc& picBase)
2430{
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);
2435 }
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);
2438 }
2439 else {
2440 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
2441 }
2442 }
2443 else {
2444 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, target.weakImport, target.name);
2445 }
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);
2451 }
2452 else {
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);
2457 }
2458}
2459
2460
2461
2462template <typename A>
2463uint32_t TentativeDefinitionSection<A>::computeAtomCount(class Parser<A>& parser,
2464 struct Parser<A>::LabelAndCFIBreakIterator& it,
2465 const struct Parser<A>::CFIInfoArray&)
2466{
2467 return parser.tentativeDefinitionCount();
2468}
2469
2470template <typename A>
2471uint32_t TentativeDefinitionSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
2472 struct Parser<A>::LabelAndCFIBreakIterator& it,
2473 const struct Parser<A>::CFIInfoArray&)
2474{
2475 this->_beginAtoms = (Atom<A>*)p;
2476 uint32_t count = 0;
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) )
2489 ++alignP2;
2490 }
2491 // limit alignment of extremely large commons to 2^15 bytes (8-page)
2492 if ( alignP2 > 12 )
2493 alignP2 = 12;
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>);
2500 ++count;
2501 }
2502 }
2503 this->_endAtoms = (Atom<A>*)p;
2504 return count;
2505}
2506
2507
2508template <typename A>
2509uint32_t AbsoluteSymbolSection<A>::computeAtomCount(class Parser<A>& parser,
2510 struct Parser<A>::LabelAndCFIBreakIterator& it,
2511 const struct Parser<A>::CFIInfoArray&)
2512{
2513 return parser.absoluteSymbolCount();
2514}
2515
2516template <typename A>
2517uint32_t AbsoluteSymbolSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
2518 struct Parser<A>::LabelAndCFIBreakIterator& it,
2519 const struct Parser<A>::CFIInfoArray&)
2520{
2521 this->_beginAtoms = (Atom<A>*)p;
2522 uint32_t count = 0;
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 )
2526 continue;
2527 const char* absName = parser.nameFromSymbol(sym);
2528 // ignore .objc_class_name_* symbols
2529 if ( strncmp(absName, ".objc_class_name_", 17) == 0 )
2530 continue;
2531 // ignore .objc_class_name_* symbols
2532 if ( strncmp(absName, ".objc_category_name_", 20) == 0 )
2533 continue;
2534 // ignore empty *.eh symbols
2535 if ( strcmp(&absName[strlen(absName)-3], ".eh") == 0 )
2536 continue;
2537
2538 Atom<A>* allocatedSpace = (Atom<A>*)p;
2539 new (allocatedSpace) Atom<A>(*this, parser, sym, 0);
2540 p += sizeof(Atom<A>);
2541 ++count;
2542 }
2543 this->_endAtoms = (Atom<A>*)p;
2544 return count;
2545}
2546
2547template <typename A>
2548Atom<A>* AbsoluteSymbolSection<A>::findAbsAtomForValue(typename A::P::uint_t value)
2549{
2550 Atom<A>* end = this->_endAtoms;
2551 for(Atom<A>* p = this->_beginAtoms; p < end; ++p) {
2552 if ( p->_objAddress == value )
2553 return p;
2554 }
2555 return NULL;
2556}
2557
2558
2559template <typename A>
2560uint32_t Parser<A>::indirectSymbol(uint32_t indirectIndex)
2561{
2562 if ( indirectIndex >= _indirectTableCount )
2563 throw "indirect symbol index out of range";
2564 return E::get32(_indirectTable[indirectIndex]);
2565}
2566
2567template <typename A>
2568const macho_nlist<typename A::P>& Parser<A>::symbolFromIndex(uint32_t index)
2569{
2570 if ( index > _symbolCount )
2571 throw "symbol index out of range";
2572 return _symbols[index];
2573}
2574
2575template <typename A>
2576const macho_section<typename A::P>* Parser<A>::machOSectionFromSectionIndex(uint32_t index)
2577{
2578 if ( index >= _machOSectionsCount )
2579 throw "section index out of range";
2580 return &_sectionsStart[index];
2581}
2582
2583template <typename A>
2584uint32_t Parser<A>::symbolIndexFromIndirectSectionAddress(pint_t addr, const macho_section<P>* sect)
2585{
2586 uint32_t elementSize = 0;
2587 switch ( sect->flags() & SECTION_TYPE ) {
2588 case S_SYMBOL_STUBS:
2589 elementSize = sect->reserved2();
2590 break;
2591 case S_LAZY_SYMBOL_POINTERS:
2592 case S_NON_LAZY_SYMBOL_POINTERS:
2593 elementSize = sizeof(pint_t);
2594 break;
2595 default:
2596 throw "section does not use inirect symbol table";
2597 }
2598 uint32_t indexInSection = (addr - sect->addr()) / elementSize;
2599 uint32_t indexIntoIndirectTable = sect->reserved1() + indexInSection;
2600 return this->indirectSymbol(indexIntoIndirectTable);
2601}
2602
2603
2604
2605template <typename A>
2606const char* Parser<A>::nameFromSymbol(const macho_nlist<P>& sym)
2607{
2608 return &_strings[sym.n_strx()];
2609}
2610
2611template <typename A>
2612ld::Atom::Scope Parser<A>::scopeFromSymbol(const macho_nlist<P>& sym)
2613{
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;
2620 else
2621 return ld::Atom::scopeGlobal;
2622}
2623
2624template <typename A>
2625ld::Atom::Definition Parser<A>::definitionFromSymbol(const macho_nlist<P>& sym)
2626{
2627 switch ( sym.n_type() & N_TYPE ) {
2628 case N_ABS:
2629 return ld::Atom::definitionAbsolute;
2630 case N_SECT:
2631 return ld::Atom::definitionRegular;
2632 case N_UNDF:
2633 if ( sym.n_value() != 0 )
2634 return ld::Atom::definitionTentative;
2635 }
2636 throw "definitionFromSymbol() bad symbol";
2637}
2638
2639template <typename A>
2640ld::Atom::Combine Parser<A>::combineFromSymbol(const macho_nlist<P>& sym)
2641{
2642 if ( sym.n_desc() & N_WEAK_DEF )
2643 return ld::Atom::combineByName;
2644 else
2645 return ld::Atom::combineNever;
2646}
2647
2648
2649template <typename A>
2650ld::Atom::SymbolTableInclusion Parser<A>::inclusionFromSymbol(const macho_nlist<P>& sym)
2651{
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;
2661 else
2662 return ld::Atom::symbolTableIn;
2663}
2664
2665template <typename A>
2666bool Parser<A>::dontDeadStripFromSymbol(const macho_nlist<P>& sym)
2667{
2668 return ( (sym.n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0 );
2669}
2670
2671template <typename A>
2672bool Parser<A>::isThumbFromSymbol(const macho_nlist<P>& sym)
2673{
2674 return ( sym.n_desc() & N_ARM_THUMB_DEF );
2675}
2676
2677template <typename A>
2678bool Parser<A>::weakImportFromSymbol(const macho_nlist<P>& sym)
2679{
2680 return ( ((sym.n_type() & N_TYPE) == N_UNDF) && ((sym.n_desc() & N_WEAK_REF) != 0) );
2681}
2682
2683template <typename A>
2684bool Parser<A>::resolverFromSymbol(const macho_nlist<P>& sym)
2685{
2686 return ( sym.n_desc() & N_SYMBOL_RESOLVER );
2687}
2688
2689
2690/* Skip over a LEB128 value (signed or unsigned). */
2691static void
2692skip_leb128 (const uint8_t ** offset, const uint8_t * end)
2693{
2694 while (*offset != end && **offset >= 0x80)
2695 (*offset)++;
2696 if (*offset != end)
2697 (*offset)++;
2698}
2699
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. */
2702static uint64_t
2703read_uleb128 (const uint8_t ** offset, const uint8_t * end)
2704{
2705 uint64_t result = 0;
2706 int bit = 0;
2707
2708 do {
2709 uint64_t b;
2710
2711 if (*offset == end)
2712 return (uint64_t) -1;
2713
2714 b = **offset & 0x7f;
2715
2716 if (bit >= 64 || b << bit >> bit != b)
2717 result = (uint64_t) -1;
2718 else
2719 result |= b << bit, bit += 7;
2720 } while (*(*offset)++ >= 0x80);
2721 return result;
2722}
2723
2724
2725/* Skip over a DWARF attribute of form FORM. */
2726template <typename A>
2727bool Parser<A>::skip_form(const uint8_t ** offset, const uint8_t * end, uint64_t form,
2728 uint8_t addr_size, bool dwarf64)
2729{
2730 int64_t sz=0;
2731
2732 switch (form)
2733 {
2734 case DW_FORM_addr:
2735 sz = addr_size;
2736 break;
2737
2738 case DW_FORM_block2:
2739 if (end - *offset < 2)
2740 return false;
2741 sz = 2 + A::P::E::get16(*(uint16_t*)offset);
2742 break;
2743
2744 case DW_FORM_block4:
2745 if (end - *offset < 4)
2746 return false;
2747 sz = 2 + A::P::E::get32(*(uint32_t*)offset);
2748 break;
2749
2750 case DW_FORM_data2:
2751 case DW_FORM_ref2:
2752 sz = 2;
2753 break;
2754
2755 case DW_FORM_data4:
2756 case DW_FORM_ref4:
2757 sz = 4;
2758 break;
2759
2760 case DW_FORM_data8:
2761 case DW_FORM_ref8:
2762 sz = 8;
2763 break;
2764
2765 case DW_FORM_string:
2766 while (*offset != end && **offset)
2767 ++*offset;
2768 case DW_FORM_data1:
2769 case DW_FORM_flag:
2770 case DW_FORM_ref1:
2771 sz = 1;
2772 break;
2773
2774 case DW_FORM_block:
2775 sz = read_uleb128 (offset, end);
2776 break;
2777
2778 case DW_FORM_block1:
2779 if (*offset == end)
2780 return false;
2781 sz = 1 + **offset;
2782 break;
2783
2784 case DW_FORM_sdata:
2785 case DW_FORM_udata:
2786 case DW_FORM_ref_udata:
2787 skip_leb128 (offset, end);
2788 return true;
2789
2790 case DW_FORM_strp:
2791 case DW_FORM_ref_addr:
2792 sz = 4;
2793 break;
2794
2795 default:
2796 return false;
2797 }
2798 if (end - *offset < sz)
2799 return false;
2800 *offset += sz;
2801 return true;
2802}
2803
2804
2805template <typename A>
2806const char* Parser<A>::getDwarfString(uint64_t form, const uint8_t* p)
2807{
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);
2815 return NULL;
2816 }
2817 return &dwarfStrings[offset];
2818 }
2819 warning("unknown dwarf string encoding (form=%lld) in %s\n", form, this->_path);
2820 return NULL;
2821}
2822
2823
2824template <typename A>
2825struct AtomAndLineInfo {
2826 Atom<A>* atom;
2827 ld::Atom::LineInfo info;
2828};
2829
2830
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
2834template <typename A>
2835bool Parser<A>::isConstFunStabs(const char *stabStr)
2836{
2837 const char* colon;
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
2842 // not a constant)
2843 return (stabStr != NULL) && (stabStr[0] != '+') && (stabStr[0] != '-')
2844 && ((colon = strchr(stabStr, ':')) != NULL)
2845 && (colon[1] == 'c') && (colon[2] == '=');
2846}
2847
2848
2849template <typename A>
2850void Parser<A>::parseDebugInfo()
2851{
2852 // check for dwarf __debug_info section
2853 if ( _file->_dwarfDebugInfoSect == NULL ) {
2854 // if no DWARF debug info, look for stabs
2855 this->parseStabs();
2856 return;
2857 }
2858 if ( _file->_dwarfDebugInfoSect->size() == 0 )
2859 return;
2860
2861 uint64_t stmtList;
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;
2868 return;
2869 }
2870
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))
2895 continue;
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;
2899 }
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;
2903 }
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();
2910 }
2911 else {
2912 // do slow look up of atom by address
2913 try {
2914 curAtom = this->findAtomByAddress(result.pc);
2915 }
2916 catch (...) {
2917 // in case of bug in debug info, don't abort link, just limp on
2918 curAtom = NULL;
2919 }
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);
2927 if ( alt == NULL )
2928 continue; // ignore spurious debug info for stubs
2929 if ( result.pc <= alt->objectAddress() + alt->size() ) {
2930 curAtom = alt;
2931 curAtomOffset = result.pc - alt->objectAddress();
2932 curAtomAddress = alt->objectAddress();
2933 curAtomSize = alt->size();
2934 }
2935 else {
2936 curAtomOffset = result.pc - curAtom->objectAddress();
2937 curAtomAddress = curAtom->objectAddress();
2938 curAtomSize = curAtom->size();
2939 }
2940 }
2941 else {
2942 curAtomOffset = result.pc - curAtom->objectAddress();
2943 curAtomAddress = curAtom->objectAddress();
2944 curAtomSize = curAtom->size();
2945 }
2946 }
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;
2952 }
2953 else {
2954 filename = pos->second;
2955 }
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();
2967 }
2968 if ( result.end_of_sequence ) {
2969 curAtom = NULL;
2970 }
2971 }
2972 line_free(lines);
2973 }
2974 }
2975 }
2976 }
2977
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>);
2987 }
2988 assert(liOffset == entries.size());
2989 _file->_lineInfos.reserve(liOffset);
2990
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++;
2996 }
2997
2998 // done with temp vector
2999 entries.clear();
3000}
3001
3002template <typename A>
3003void Parser<A>::parseStabs()
3004{
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;
3017 stab.atom = NULL;
3018 stab.type = type;
3019 stab.other = sym.n_sect();
3020 stab.desc = sym.n_desc();
3021 stab.value = sym.n_value();
3022 stab.string = NULL;
3023 switch (state) {
3024 case start:
3025 switch (type) {
3026 case N_BNSYM:
3027 // beginning of function block
3028 state = inBeginEnd;
3029 // fall into case to lookup atom by addresss
3030 case N_LCSYM:
3031 case N_STSYM:
3032 currentAtomAddress = sym.n_value();
3033 currentAtom = this->findAtomByAddress(currentAtomAddress);
3034 if ( currentAtom != NULL ) {
3035 stab.atom = currentAtom;
3036 stab.string = symString;
3037 }
3038 else {
3039 fprintf(stderr, "can't find atom for stabs BNSYM at %08llX in %s",
3040 (uint64_t)sym.n_value(), _path);
3041 }
3042 break;
3043 case N_SO:
3044 case N_OSO:
3045 case N_OPT:
3046 case N_LSYM:
3047 case N_RSYM:
3048 case N_PSYM:
3049 // not associated with an atom, just copy
3050 stab.string = symString;
3051 break;
3052 case N_GSYM:
3053 {
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);
3062 symName[0] = '_';
3063 symName[nameLen+1] = '\0';
3064 currentAtom = this->findAtomByName(symName);
3065 if ( currentAtom != NULL ) {
3066 stab.atom = currentAtom;
3067 stab.string = symString;
3068 }
3069 }
3070 else {
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;
3076 }
3077 }
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);
3082 useStab = false;
3083 }
3084 break;
3085 }
3086 case N_FUN:
3087 if ( isConstFunStabs(symString) ) {
3088 // constant not associated with a function
3089 stab.string = symString;
3090 }
3091 else {
3092 // old style stabs without BNSYM
3093 state = inFun;
3094 currentAtomAddress = sym.n_value();
3095 currentAtom = this->findAtomByAddress(currentAtomAddress);
3096 if ( currentAtom != NULL ) {
3097 stab.atom = currentAtom;
3098 stab.string = symString;
3099 }
3100 else {
3101 warning("can't find atom for stabs FUN at %08llX in %s",
3102 (uint64_t)currentAtomAddress, _path);
3103 }
3104 }
3105 break;
3106 case N_SOL:
3107 case N_SLINE:
3108 stab.string = symString;
3109 // old stabs
3110 break;
3111 case N_BINCL:
3112 case N_EINCL:
3113 case N_EXCL:
3114 stab.string = symString;
3115 // -gfull built .o file
3116 break;
3117 default:
3118 warning("unknown stabs type 0x%X in %s", type, _path);
3119 }
3120 break;
3121 case inBeginEnd:
3122 stab.atom = currentAtom;
3123 switch (type) {
3124 case N_ENSYM:
3125 state = start;
3126 currentAtom = NULL;
3127 break;
3128 case N_LCSYM:
3129 case N_STSYM:
3130 {
3131 Atom<A>* nestedAtom = this->findAtomByAddress(sym.n_value());
3132 if ( nestedAtom != NULL ) {
3133 stab.atom = nestedAtom;
3134 stab.string = symString;
3135 }
3136 else {
3137 warning("can't find atom for stabs 0x%X at %08llX in %s",
3138 type, (uint64_t)sym.n_value(), _path);
3139 }
3140 break;
3141 }
3142 case N_LBRAC:
3143 case N_RBRAC:
3144 case N_SLINE:
3145 // adjust value to be offset in atom
3146 stab.value -= currentAtomAddress;
3147 default:
3148 stab.string = symString;
3149 break;
3150 }
3151 break;
3152 case inFun:
3153 switch (type) {
3154 case N_FUN:
3155 if ( isConstFunStabs(symString) ) {
3156 stab.atom = currentAtom;
3157 stab.string = symString;
3158 }
3159 else {
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;
3167 }
3168 else {
3169 warning("can't find atom for stabs FUN at %08llX in %s",
3170 (uint64_t)currentAtomAddress, _path);
3171 }
3172 }
3173 else {
3174 // found ending stab, switch back to start state
3175 stab.string = symString;
3176 stab.atom = currentAtom;
3177 state = start;
3178 currentAtom = NULL;
3179 }
3180 }
3181 break;
3182 case N_LBRAC:
3183 case N_RBRAC:
3184 case N_SLINE:
3185 // adjust value to be offset in atom
3186 stab.value -= currentAtomAddress;
3187 stab.atom = currentAtom;
3188 break;
3189 case N_SO:
3190 stab.string = symString;
3191 state = start;
3192 break;
3193 default:
3194 stab.atom = currentAtom;
3195 stab.string = symString;
3196 break;
3197 }
3198 break;
3199 }
3200 // add to list of stabs for this .o file
3201 if ( useStab )
3202 _file->_stabs.push_back(stab);
3203 }
3204 }
3205}
3206
3207
3208
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.
3214//
3215// At present this assumes that there's only one compilation unit DIE.
3216//
3217template <typename A>
3218bool Parser<A>::read_comp_unit(const char ** name, const char ** comp_dir,
3219 uint64_t *stmt_list)
3220{
3221 const uint8_t * debug_info;
3222 const uint8_t * debug_abbrev;
3223 const uint8_t * di;
3224 const uint8_t * da;
3225 const uint8_t * end;
3226 const uint8_t * enda;
3227 uint64_t sz;
3228 uint16_t vers;
3229 uint64_t abbrev_base;
3230 uint64_t abbrev;
3231 uint8_t address_size;
3232 bool dwarf64;
3233
3234 *name = NULL;
3235 *comp_dir = NULL;
3236 *stmt_list = (uint64_t) -1;
3237
3238 if ( (_file->_dwarfDebugInfoSect == NULL) || (_file->_dwarfDebugAbbrevSect == NULL) )
3239 return false;
3240
3241 debug_info = (uint8_t*)_file->fileContent() + _file->_dwarfDebugInfoSect->offset();
3242 debug_abbrev = (uint8_t*)_file->fileContent() + _file->_dwarfDebugAbbrevSect->offset();
3243 di = debug_info;
3244
3245 if (_file->_dwarfDebugInfoSect->size() < 12)
3246 /* Too small to be a real debug_info section. */
3247 return false;
3248 sz = A::P::E::get32(*(uint32_t*)di);
3249 di += 4;
3250 dwarf64 = sz == 0xffffffff;
3251 if (dwarf64)
3252 sz = A::P::E::get64(*(uint64_t*)di), di += 8;
3253 else if (sz > 0xffffff00)
3254 /* Unknown dwarf format. */
3255 return false;
3256
3257 /* Verify claimed size. */
3258 if (sz + (di - debug_info) > _file->_dwarfDebugInfoSect->size() || sz <= (dwarf64 ? 23 : 11))
3259 return false;
3260
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. */
3265 return false;
3266 di += 2;
3267
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;
3271
3272 if (abbrev_base > _file->_dwarfDebugAbbrevSect->size())
3273 return false;
3274 da = debug_abbrev + abbrev_base;
3275 enda = debug_abbrev + _file->_dwarfDebugAbbrevSect->size();
3276
3277 address_size = *di++;
3278
3279 /* Find the abbrev number we're looking for. */
3280 end = di + sz;
3281 abbrev = read_uleb128 (&di, end);
3282 if (abbrev == (uint64_t) -1)
3283 return false;
3284
3285 /* Skip through the debug_abbrev section looking for that abbrev. */
3286 for (;;)
3287 {
3288 uint64_t this_abbrev = read_uleb128 (&da, enda);
3289 uint64_t attr;
3290
3291 if (this_abbrev == abbrev)
3292 /* This is almost always taken. */
3293 break;
3294 skip_leb128 (&da, enda); /* Skip the tag. */
3295 if (da == enda)
3296 return false;
3297 da++; /* Skip the DW_CHILDREN_* value. */
3298
3299 do {
3300 attr = read_uleb128 (&da, enda);
3301 skip_leb128 (&da, enda);
3302 } while (attr != 0 && attr != (uint64_t) -1);
3303 if (attr != 0)
3304 return false;
3305 }
3306
3307 /* Check that the abbrev is one for a DW_TAG_compile_unit. */
3308 if (read_uleb128 (&da, enda) != DW_TAG_compile_unit)
3309 return false;
3310 if (da == enda)
3311 return false;
3312 da++; /* Skip the DW_CHILDREN_* value. */
3313
3314 /* Now, go through the DIE looking for DW_AT_name,
3315 DW_AT_comp_dir, and DW_AT_stmt_list. */
3316 for (;;)
3317 {
3318 uint64_t attr = read_uleb128 (&da, enda);
3319 uint64_t form = read_uleb128 (&da, enda);
3320
3321 if (attr == (uint64_t) -1)
3322 return false;
3323 else if (attr == 0)
3324 return true;
3325
3326 if (form == DW_FORM_indirect)
3327 form = read_uleb128 (&di, end);
3328
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))
3338 return false;
3339 }
3340}
3341
3342
3343
3344template <typename A>
3345File<A>::~File()
3346{
3347 free(_sectionsArray);
3348 free(_atomsArray);
3349}
3350
3351template <typename A>
3352bool File<A>::translationUnitSource(const char** dir, const char** name) const
3353{
3354 if ( _debugInfoKind == ld::relocatable::File::kDebugInfoDwarf ) {
3355 *dir = _dwarfTranslationUnitDir;
3356 *name = _dwarfTranslationUnitFile;
3357 return (_dwarfTranslationUnitFile != NULL);
3358 }
3359 return false;
3360}
3361
3362
3363
3364template <typename A>
3365bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
3366{
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>);
3372 }
3373 return (_atomsArrayCount != 0);
3374}
3375
3376template <typename A>
3377const char* Section<A>::makeSegmentName(const macho_section<typename A::P>* sect)
3378{
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 )
3383 return name;
3384 char* tmp = new char[17];
3385 strlcpy(tmp, name, 17);
3386 return tmp;
3387}
3388
3389template <typename A>
3390const char* Section<A>::makeSectionName(const macho_section<typename A::P>* sect)
3391{
3392 const char* name = sect->sectname();
3393 if ( strlen(name) < 16 )
3394 return name;
3395
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";
3417
3418 char* tmp = new char[17];
3419 strlcpy(tmp, name, 17);
3420 return tmp;
3421}
3422
3423template <typename A>
3424bool Section<A>::readable(const macho_section<typename A::P>* sect)
3425{
3426 return true;
3427}
3428
3429template <typename A>
3430bool Section<A>::writable(const macho_section<typename A::P>* sect)
3431{
3432 // mach-o .o files do not contain segment permissions
3433 // we just know TEXT is special
3434 return ( strcmp(sect->segname(), "__TEXT") != 0 );
3435}
3436
3437template <typename A>
3438bool Section<A>::exectuable(const macho_section<typename A::P>* sect)
3439{
3440 // mach-o .o files do not contain segment permissions
3441 // we just know TEXT is special
3442 return ( strcmp(sect->segname(), "__TEXT") == 0 );
3443}
3444
3445
3446template <typename A>
3447ld::Section::Type Section<A>::sectionType(const macho_section<typename A::P>* sect)
3448{
3449 switch ( sect->flags() & SECTION_TYPE ) {
3450 case S_ZEROFILL:
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;
3455 else
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;
3473 case S_INTERPOSING:
3474 return ld::Section::typeUnclassified;
3475 case S_16BYTE_LITERALS:
3476 return ld::Section::typeLiteral16;
3477 case S_REGULAR:
3478 case S_COALESCED:
3479 if ( sect->flags() & S_ATTR_PURE_INSTRUCTIONS ) {
3480 return ld::Section::typeCode;
3481 }
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;
3491 }
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;
3503 }
3504 else if ( strcmp(sect->segname(), "__OBJC") == 0 ) {
3505 if ( strcmp(sect->sectname(), "__class") == 0 )
3506 return ld::Section::typeObjC1Classes;
3507 }
3508 break;
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;
3517 }
3518 return ld::Section::typeUnclassified;
3519}
3520
3521
3522template <typename A>
3523Atom<A>* Section<A>::findContentAtomByAddress(pint_t addr, class Atom<A>* start, class Atom<A>* end)
3524{
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)
3535 return pivot;
3536 // address in "end" label (but not in alias)
3537 if ( (pivot->_size == 0) && (addr == atomEndAddr) && !pivot->isAlias() )
3538 return pivot;
3539 }
3540 if ( addr >= atomEndAddr ) {
3541 // key > pivot
3542 // move base to atom after pivot
3543 base = &pivot[1];
3544 --n;
3545 }
3546 else {
3547 // key < pivot
3548 // keep same base
3549 }
3550 }
3551 return NULL;
3552}
3553
3554template <typename A>
3555ld::Atom::Alignment Section<A>::alignmentForAddress(pint_t addr)
3556{
3557 const uint32_t sectionAlignment = this->_machOSection->align();
3558 return ld::Atom::Alignment(sectionAlignment, (addr % (1 << sectionAlignment)));
3559}
3560
3561template <typename A>
3562uint32_t Section<A>::sectionNum(class Parser<A>& parser) const
3563{
3564 if ( _machOSection == NULL )
3565 return 0;
3566 else
3567 return 1 + (this->_machOSection - parser.firstMachOSection());
3568}
3569
3570// libunwind does not support ppc64
3571template <> uint32_t CFISection<ppc64>::cfiCount() { return 0; }
3572// arm does not have zero cost exceptions
3573template <> uint32_t CFISection<arm>::cfiCount() { return 0; }
3574
3575template <typename A>
3576uint32_t CFISection<A>::cfiCount()
3577{
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());
3582}
3583
3584template <typename A>
3585void CFISection<A>::warnFunc(void* ref, uint64_t funcAddr, const char* msg)
3586{
3587 Parser<A>* parser = (Parser<A>*)ref;
3588 if ( ! parser->convertUnwindInfo() )
3589 return;
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);
3594 }
3595 else {
3596 warning("could not create compact unwind: %s", msg);
3597 }
3598}
3599
3600template <>
3601bool CFISection<x86_64>::needsRelocating()
3602{
3603 return true;
3604}
3605
3606template <typename A>
3607bool CFISection<A>::needsRelocating()
3608{
3609 return false;
3610}
3611
3612template <>
3613void 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[],
3615 uint32_t count)
3616{
3617 // copy __eh_frame data to buffer
3618 memcpy(buffer, file().fileContent() + this->_machOSection->offset(), this->_machOSection->size());
3619
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) {
3624 uint64_t value = 0;
3625 switch ( reloc->r_type() ) {
3626 case X86_64_RELOC_SUBTRACTOR:
3627 value = 0 - parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
3628 ++reloc;
3629 if ( reloc->r_extern() )
3630 value += parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
3631 break;
3632 case X86_64_RELOC_UNSIGNED:
3633 value = parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
3634 break;
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();
3639 break;
3640 default:
3641 fprintf(stderr, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc->r_address());
3642 break;
3643 }
3644 uint64_t* p64;
3645 uint32_t* p32;
3646 switch ( reloc->r_length() ) {
3647 case 3:
3648 p64 = (uint64_t*)&buffer[reloc->r_address()];
3649 E::set64(*p64, value + E::get64(*p64));
3650 break;
3651 case 2:
3652 p32 = (uint32_t*)&buffer[reloc->r_address()];
3653 E::set32(*p32, value + E::get32(*p32));
3654 break;
3655 default:
3656 fprintf(stderr, "CFISection::cfiParse() unexpected relocation size at r_address=0x%08X\n", reloc->r_address());
3657 break;
3658 }
3659 }
3660
3661
3662 // create ObjectAddressSpace object for use by libunwind
3663 OAS oas(*this, buffer);
3664
3665 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3666 const char* msg;
3667 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_x86_64>::parseCFIs(
3668 oas, this->_machOSection->addr(), this->_machOSection->size(),
3669 cfiArray, count, (void*)&parser, warnFunc);
3670 if ( msg != NULL )
3671 throwf("malformed __eh_frame section: %s", msg);
3672}
3673
3674template <>
3675void CFISection<x86>::cfiParse(class Parser<x86>& parser, uint8_t* buffer,
3676 libunwind::CFI_Atom_Info<CFISection<x86>::OAS>::CFI_Atom_Info cfiArray[],
3677 uint32_t count)
3678{
3679 // create ObjectAddressSpace object for use by libunwind
3680 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
3681
3682 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3683 const char* msg;
3684 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_x86>::parseCFIs(
3685 oas, this->_machOSection->addr(), this->_machOSection->size(),
3686 cfiArray, count, (void*)&parser, warnFunc);
3687 if ( msg != NULL )
3688 throwf("malformed __eh_frame section: %s", msg);
3689}
3690
3691
3692// need to change libunwind parseCFIs() to work for ppc
3693template <>
3694void CFISection<ppc>::cfiParse(class Parser<ppc>& parser, uint8_t* buffer,
3695 libunwind::CFI_Atom_Info<CFISection<ppc>::OAS>::CFI_Atom_Info cfiArray[],
3696 uint32_t count)
3697{
3698 // create ObjectAddressSpace object for use by libunwind
3699 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
3700
3701 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
3702 const char* msg;
3703 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_ppc>::parseCFIs(
3704 oas, this->_machOSection->addr(), this->_machOSection->size(),
3705 cfiArray, count, (void*)&parser, warnFunc);
3706 if ( msg != NULL )
3707 throwf("malformed __eh_frame section: %s", msg);
3708}
3709
3710template <>
3711void CFISection<ppc64>::cfiParse(class Parser<ppc64>& parser, uint8_t* buffer,
3712 libunwind::CFI_Atom_Info<CFISection<ppc64>::OAS>::CFI_Atom_Info cfiArray[],
3713 uint32_t count)
3714{
3715 // libunwind does not support ppc64
3716 assert(count == 0);
3717}
3718
3719template <>
3720void CFISection<arm>::cfiParse(class Parser<arm>& parser, uint8_t* buffer,
3721 libunwind::CFI_Atom_Info<CFISection<arm>::OAS>::CFI_Atom_Info cfiArray[],
3722 uint32_t count)
3723{
3724 // arm does not use zero cost exceptions
3725 assert(count == 0);
3726}
3727
3728
3729
3730template <typename A>
3731uint32_t CFISection<A>::computeAtomCount(class Parser<A>& parser,
3732 struct Parser<A>::LabelAndCFIBreakIterator& it,
3733 const struct Parser<A>::CFIInfoArray& cfis)
3734{
3735 return cfis.count;
3736}
3737
3738
3739
3740template <typename A>
3741uint32_t CFISection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
3742 struct Parser<A>::LabelAndCFIBreakIterator& it,
3743 const struct Parser<A>::CFIInfoArray& cfis)
3744{
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>);
3756 }
3757 this->_endAtoms = (Atom<A>*)p;
3758 return cfis.count;
3759}
3760
3761
3762template <> bool CFISection<x86_64>::bigEndian() { return false; }
3763template <> bool CFISection<x86>::bigEndian() { return false; }
3764template <> bool CFISection<arm>::bigEndian() { return false; }
3765template <> bool CFISection<ppc>::bigEndian() { return true; }
3766template <> bool CFISection<ppc64>::bigEndian() { return true; }
3767
3768
3769template <>
3770void CFISection<x86_64>::addCiePersonalityFixups(class Parser<x86_64>& parser, const CFI_Atom_Info* cieInfo)
3771{
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);
3780
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);
3786 }
3787 else if ( personalityEncoding != 0 ) {
3788 throwf("unsupported address encoding (%02X) of personality function in CIE",
3789 personalityEncoding);
3790 }
3791}
3792
3793template <>
3794void CFISection<x86>::addCiePersonalityFixups(class Parser<x86>& parser, const CFI_Atom_Info* cieInfo)
3795{
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);
3804
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);
3809 }
3810 else if ( personalityEncoding != 0 ) {
3811 throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding);
3812 }
3813}
3814
3815
3816template <>
3817void CFISection<ppc>::addCiePersonalityFixups(class Parser<ppc>& parser, const CFI_Atom_Info* cieInfo)
3818{
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);
3827
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);
3832 }
3833 else if ( personalityEncoding != 0 ) {
3834 throwf("unsupported address encoding (%02X) of personality function in CIE",
3835 personalityEncoding);
3836 }
3837}
3838
3839
3840template <typename A>
3841void CFISection<A>::addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo)
3842{
3843 // FIX ME
3844 assert(0);
3845}
3846
3847template <typename A>
3848void CFISection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFIInfoArray& cfis)
3849{
3850 ld::Fixup::Kind store32 = bigEndian() ? ld::Fixup::kindStoreBigEndian32 : ld::Fixup::kindStoreLittleEndian32;
3851 ld::Fixup::Kind store64 = bigEndian() ? ld::Fixup::kindStoreBigEndian64 : ld::Fixup::kindStoreLittleEndian64;
3852
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) {
3856 if ( p->isCIE ) {
3857 // add reference to personality function if used
3858 if ( p->u.cieInfo.personality.targetAddress != CFI_INVALID_ADDRESS ) {
3859 this->addCiePersonalityFixups(parser, p);
3860 }
3861 }
3862 else {
3863 // find FDE Atom
3864 Atom<A>* fdeAtom = this->findAtomByAddress(p->address);
3865 // find function Atom
3866 Atom<A>* functionAtom = parser.findAtomByAddress(p->u.fdeInfo.function.targetAddress);
3867 // find CIE Atom
3868 Atom<A>* cieAtom = this->findAtomByAddress(p->u.fdeInfo.cie.targetAddress);
3869 // find LSDA Atom
3870 Atom<A>* lsdaAtom = NULL;
3871 if ( p->u.fdeInfo.lsda.targetAddress != CFI_INVALID_ADDRESS ) {
3872 lsdaAtom = parser.findAtomByAddress(p->u.fdeInfo.lsda.targetAddress);
3873 }
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);
3880
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);
3890 break;
3891 }
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);
3898 break;
3899 default:
3900 throw "unsupported encoding in FDE of pointer to function";
3901 }
3902
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);
3913 break;
3914 }
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);
3921 break;
3922 default:
3923 throw "unsupported encoding in FDE of pointer to LSDA";
3924 }
3925 }
3926
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);
3930
3931 // LSDA is in group lead by function atom
3932 if ( lsdaAtom != NULL ) {
3933 parser.addFixup(fdeSrc, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateLSDA, lsdaAtom);
3934 }
3935 }
3936 }
3937}
3938
3939
3940
3941
3942template <typename A>
3943const void* CFISection<A>::OAS::mappedAddress(pint_t addr)
3944{
3945 if ( (_ehFrameStartAddr <= addr) && (addr < _ehFrameEndAddr) )
3946 return &_ehFrameContent[addr-_ehFrameStartAddr];
3947 else {
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();
3957 }
3958 }
3959 }
3960 throwf("__eh_frame parsing problem. Can't find target of reference to address 0x%08llX", (uint64_t)addr);
3961 }
3962}
3963
3964
3965template <typename A>
3966uint64_t CFISection<A>::OAS::getULEB128(pint_t& logicalAddr, pint_t end)
3967{
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);
3973 return result;
3974}
3975
3976template <typename A>
3977int64_t CFISection<A>::OAS::getSLEB128(pint_t& logicalAddr, pint_t end)
3978{
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);
3984 return result;
3985}
3986
3987template <typename A>
3988typename A::P::uint_t CFISection<A>::OAS::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
3989{
3990 pint_t startAddr = addr;
3991 pint_t p = addr;
3992 pint_t result;
3993
3994 // first get value
3995 switch (encoding & 0x0F) {
3996 case DW_EH_PE_ptr:
3997 result = getP(addr);
3998 p += sizeof(pint_t);
3999 addr = (pint_t)p;
4000 break;
4001 case DW_EH_PE_uleb128:
4002 result = getULEB128(addr, end);
4003 break;
4004 case DW_EH_PE_udata2:
4005 result = get16(addr);
4006 p += 2;
4007 addr = (pint_t)p;
4008 break;
4009 case DW_EH_PE_udata4:
4010 result = get32(addr);
4011 p += 4;
4012 addr = (pint_t)p;
4013 break;
4014 case DW_EH_PE_udata8:
4015 result = get64(addr);
4016 p += 8;
4017 addr = (pint_t)p;
4018 break;
4019 case DW_EH_PE_sleb128:
4020 result = getSLEB128(addr, end);
4021 break;
4022 case DW_EH_PE_sdata2:
4023 result = (int16_t)get16(addr);
4024 p += 2;
4025 addr = (pint_t)p;
4026 break;
4027 case DW_EH_PE_sdata4:
4028 result = (int32_t)get32(addr);
4029 p += 4;
4030 addr = (pint_t)p;
4031 break;
4032 case DW_EH_PE_sdata8:
4033 result = get64(addr);
4034 p += 8;
4035 addr = (pint_t)p;
4036 break;
4037 default:
4038 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
4039 }
4040
4041 // then add relative offset
4042 switch ( encoding & 0x70 ) {
4043 case DW_EH_PE_absptr:
4044 // do nothing
4045 break;
4046 case DW_EH_PE_pcrel:
4047 result += startAddr;
4048 break;
4049 case DW_EH_PE_textrel:
4050 throw "DW_EH_PE_textrel pointer encoding not supported";
4051 break;
4052 case DW_EH_PE_datarel:
4053 throw "DW_EH_PE_datarel pointer encoding not supported";
4054 break;
4055 case DW_EH_PE_funcrel:
4056 throw "DW_EH_PE_funcrel pointer encoding not supported";
4057 break;
4058 case DW_EH_PE_aligned:
4059 throw "DW_EH_PE_aligned pointer encoding not supported";
4060 break;
4061 default:
4062 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
4063 break;
4064 }
4065
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);
4071
4072 return result;
4073}
4074
4075template <typename A>
4076SymboledSection<A>::SymboledSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
4077 : Section<A>(f, s), _type(ld::Atom::typeUnclassified)
4078{
4079 switch ( s->flags() & SECTION_TYPE ) {
4080 case S_ZEROFILL:
4081 _type = ld::Atom::typeZeroFill;
4082 break;
4083 case S_MOD_INIT_FUNC_POINTERS:
4084 _type = ld::Atom::typeInitializerPointers;
4085 break;
4086 case S_MOD_TERM_FUNC_POINTERS:
4087 _type = ld::Atom::typeTerminatorPointers;
4088 break;
4089 case S_THREAD_LOCAL_VARIABLES:
4090 _type = ld::Atom::typeTLV;
4091 break;
4092 case S_THREAD_LOCAL_ZEROFILL:
4093 _type = ld::Atom::typeTLVZeroFill;
4094 break;
4095 case S_THREAD_LOCAL_REGULAR:
4096 _type = ld::Atom::typeTLVInitialValue;
4097 break;
4098 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
4099 _type = ld::Atom::typeTLVInitializerPointers;
4100 break;
4101 case S_REGULAR:
4102 if ( strncmp(s->sectname(), "__gcc_except_tab", 16) == 0 )
4103 _type = ld::Atom::typeLSDA;
4104 break;
4105 }
4106}
4107
4108
4109template <typename A>
4110bool SymboledSection<A>::dontDeadStrip()
4111{
4112 switch ( _type ) {
4113 case ld::Atom::typeInitializerPointers:
4114 case ld::Atom::typeTerminatorPointers:
4115 return true;
4116 default:
4117 // model an object file without MH_SUBSECTIONS_VIA_SYMBOLS as one in which nothing can be dead stripped
4118 if ( ! this->_file.canScatterAtoms() )
4119 return true;
4120 // call inherited
4121 return Section<A>::dontDeadStrip();
4122 }
4123 return false;
4124}
4125
4126
4127template <typename A>
4128uint32_t SymboledSection<A>::computeAtomCount(class Parser<A>& parser,
4129 struct Parser<A>::LabelAndCFIBreakIterator& it,
4130 const struct Parser<A>::CFIInfoArray&)
4131{
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);
4135
4136 uint32_t count = 0;
4137 pint_t addr;
4138 pint_t size;
4139 const macho_nlist<P>* sym;
4140 while ( it.next(parser, sectNum, startAddr, endAddr, &addr, &size, &sym) ) {
4141 ++count;
4142 }
4143 //fprintf(stderr, "computeAtomCount(%s,%s) => %d\n", this->segmentName(), this->sectionName(), count);
4144 return count;
4145}
4146
4147template <typename A>
4148uint32_t SymboledSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
4149 struct Parser<A>::LabelAndCFIBreakIterator& it,
4150 const struct Parser<A>::CFIInfoArray&)
4151{
4152 this->_beginAtoms = (Atom<A>*)p;
4153
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);
4158
4159 uint32_t count = 0;
4160 pint_t addr;
4161 pint_t size;
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);
4172 if ( isAlias )
4173 this->_hasAliases = true;
4174 }
4175 else {
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));
4179 }
4180 p += sizeof(Atom<A>);
4181 ++count;
4182 }
4183
4184 this->_endAtoms = (Atom<A>*)p;
4185 return count;
4186}
4187
4188
4189template <typename A>
4190uint32_t ImplicitSizeSection<A>::computeAtomCount(class Parser<A>& parser,
4191 struct Parser<A>::LabelAndCFIBreakIterator& it,
4192 const struct Parser<A>::CFIInfoArray&)
4193{
4194 uint32_t count = 0;
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) )
4200 ++count;
4201 }
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)) ) {
4211 ++count;
4212 }
4213 prevSymbolAddr = symbolAddr;
4214 prevSymbolSectNum = symbolSectNum;
4215 }
4216 }
4217 return count;
4218}
4219
4220template <typename A>
4221uint32_t ImplicitSizeSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
4222 struct Parser<A>::LabelAndCFIBreakIterator& it,
4223 const struct Parser<A>::CFIInfoArray&)
4224{
4225 this->_beginAtoms = (Atom<A>*)p;
4226
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());
4232 uint32_t count = 0;
4233 pint_t foundAddr;
4234 pint_t size;
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));
4248 }
4249 else {
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);
4253 }
4254 ++count;
4255 p += sizeof(Atom<A>);
4256 foundAddr += labeledAtomSize;
4257 size -= labeledAtomSize;
4258 }
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));
4269 ++count;
4270 p += sizeof(Atom<A>);
4271 }
4272 }
4273 }
4274
4275 this->_endAtoms = (Atom<A>*)p;
4276
4277 return count;
4278}
4279
4280
4281template <typename A>
4282unsigned long Literal4Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4283{
4284 const uint32_t* literalContent = (uint32_t*)atom->contentPointer();
4285 return *literalContent;
4286}
4287
4288template <typename A>
4289bool Literal4Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4290 const ld::IndirectBindingTable& ind) const
4291{
4292 assert(this->type() == rhs.section().type());
4293 const uint32_t* literalContent = (uint32_t*)atom->contentPointer();
4294
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);
4300 }
4301 return false;
4302}
4303
4304
4305template <typename A>
4306unsigned long Literal8Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4307{
4308#if __LP64__
4309 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
4310 return *literalContent;
4311#else
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];
4316 }
4317 return hash;
4318#endif
4319}
4320
4321template <typename A>
4322bool Literal8Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4323 const ld::IndirectBindingTable& ind) const
4324{
4325 if ( rhs.section().type() != ld::Section::typeLiteral8 )
4326 return false;
4327 assert(this->type() == rhs.section().type());
4328 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
4329
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);
4335 }
4336 return false;
4337}
4338
4339
4340template <typename A>
4341unsigned long Literal16Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4342{
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];
4347 }
4348 return hash;
4349}
4350
4351template <typename A>
4352bool Literal16Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4353 const ld::IndirectBindingTable& ind) const
4354{
4355 if ( rhs.section().type() != ld::Section::typeLiteral16 )
4356 return false;
4357 assert(this->type() == rhs.section().type());
4358 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
4359
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]));
4365 }
4366 return false;
4367}
4368
4369
4370
4371template <typename A>
4372typename A::P::uint_t CStringSection<A>::elementSizeAtAddress(pint_t addr)
4373{
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;
4377}
4378
4379template <typename A>
4380bool CStringSection<A>::useElementAt(Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr)
4381{
4382 return true;
4383}
4384
4385template <typename A>
4386Atom<A>* CStringSection<A>::findAtomByAddress(pint_t addr)
4387{
4388 Atom<A>* result = this->findContentAtomByAddress(addr, this->_beginAtoms, this->_endAtoms);
4389 return result;
4390}
4391
4392template <typename A>
4393unsigned long CStringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4394{
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;
4399 }
4400 return hash;
4401}
4402
4403
4404template <typename A>
4405bool CStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4406 const ld::IndirectBindingTable& ind) const
4407{
4408 if ( rhs.section().type() != ld::Section::typeCString )
4409 return false;
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();
4414
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 )
4419 return false;
4420 const char* rhsStringContent = (char*)rhsAtom->contentPointer();
4421 return (strcmp(stringContent, rhsStringContent) == 0);
4422 }
4423 return false;
4424}
4425
4426
4427template <>
4428ld::Fixup::Kind NonLazyPointerSection<x86>::fixupKind()
4429{
4430 return ld::Fixup::kindStoreLittleEndian32;
4431}
4432
4433template <>
4434ld::Fixup::Kind NonLazyPointerSection<arm>::fixupKind()
4435{
4436 return ld::Fixup::kindStoreLittleEndian32;
4437}
4438
4439template <>
4440ld::Fixup::Kind NonLazyPointerSection<ppc>::fixupKind()
4441{
4442 return ld::Fixup::kindStoreBigEndian32;
4443}
4444
4445template <>
4446ld::Fixup::Kind NonLazyPointerSection<ppc64>::fixupKind()
4447{
4448 return ld::Fixup::kindStoreBigEndian64;
4449}
4450
4451template <>
4452void NonLazyPointerSection<x86_64>::makeFixups(class Parser<x86_64>& parser, const struct Parser<x86_64>::CFIInfoArray&)
4453{
4454 assert(0 && "x86_64 should not have non-lazy-pointer sections in .o files");
4455}
4456
4457template <typename A>
4458void NonLazyPointerSection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFIInfoArray&)
4459{
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);
4469 target.atom = NULL;
4470 target.name = NULL;
4471 target.weakImport = false;
4472 target.addend = 0;
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);
4484 }
4485 else {
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);
4491 }
4492 else {
4493 target.name = parser.nameFromSymbol(sym);
4494 target.weakImport = parser.weakImportFromSymbol(sym);
4495 assert(src.atom->combine() == ld::Atom::combineByNameAndReferences);
4496 }
4497 }
4498 parser.addFixups(src, this->fixupKind(), target);
4499 }
4500}
4501
4502template <typename A>
4503ld::Atom::Combine NonLazyPointerSection<A>::combine(Parser<A>& parser, pint_t addr)
4504{
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;
4509
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;
4514
4515 return ld::Atom::combineByNameAndReferences;
4516}
4517
4518template <typename A>
4519const char* NonLazyPointerSection<A>::targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind)
4520{
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:
4527 name = fit->u.name;
4528 break;
4529 case ld::Fixup::bindingByContentBound:
4530 name = fit->u.target->name();
4531 break;
4532 case ld::Fixup::bindingsIndirectlyBound:
4533 name = ind.indirectName(fit->u.bindingIndex);
4534 break;
4535 default:
4536 assert(0);
4537 }
4538 assert(name != NULL);
4539 return name;
4540}
4541
4542template <typename A>
4543unsigned long NonLazyPointerSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4544{
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;
4549 }
4550 return hash;
4551}
4552
4553template <typename A>
4554bool NonLazyPointerSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4555 const ld::IndirectBindingTable& indirectBindingTable) const
4556{
4557 if ( rhs.section().type() != ld::Section::typeNonLazyPointer )
4558 return false;
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() )
4563 return false;
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);
4569}
4570
4571template <typename A>
4572ld::Atom::Scope NonLazyPointerSection<A>::scopeAtAddress(Parser<A>& parser, pint_t addr)
4573{
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;
4578 else
4579 return ld::Atom::scopeLinkageUnit;
4580}
4581
4582
4583template <typename A>
4584const uint8_t* CFStringSection<A>::targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
4585 ContentType* ct, unsigned int* count)
4586{
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);
4596 break;
4597 case ld::Fixup::bindingDirectlyBound:
4598 case ld::Fixup::bindingByContentBound:
4599 targetAtom = fit->u.target;
4600 break;
4601 case ld::Fixup::bindingsIndirectlyBound:
4602 targetAtom = ind.indirectAtom(fit->u.bindingIndex);
4603 break;
4604 default:
4605 assert(0 && "bad binding type");
4606 }
4607 assert(targetAtom != NULL);
4608 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
4609 if ( targetAtom->section().type() == ld::Section::typeCString ) {
4610 *ct = contentUTF8;
4611 *count = targetAtom->size();
4612 }
4613 else if ( targetAtom->section().type() == ld::Section::typeUTF16Strings ) {
4614 *ct = contentUTF16;
4615 *count = (targetAtom->size()+1)/2; // round up incase of buggy compiler that has only one trailing zero byte
4616 }
4617 assert(target != NULL);
4618 return target->contentPointer();
4619 }
4620 assert(0);
4621 return NULL;
4622}
4623
4624template <typename A>
4625unsigned long CFStringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4626{
4627 // base hash of CFString on hash of cstring it wraps
4628 ContentType cType;
4629 unsigned long hash;
4630 unsigned int charCount;
4631 const uint8_t* content = this->targetContent(atom, ind, &cType, &charCount);
4632 switch ( cType ) {
4633 case contentUTF8:
4634 hash = 9408;
4635 for (const char* s = (char*)content; *s != '\0'; ++s) {
4636 hash = hash * 33 + *s;
4637 }
4638 return hash;
4639 case contentUTF16:
4640 hash = 407955;
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;
4644 }
4645 return hash;
4646 case contentUnknown:
4647 return 0;
4648 }
4649 return 0;
4650}
4651
4652
4653template <typename A>
4654bool CFStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4655 const ld::IndirectBindingTable& indirectBindingTable) const
4656{
4657 if ( atom == &rhs )
4658 return true;
4659 if ( rhs.section().type() != ld::Section::typeCFString)
4660 return false;
4661 assert(this->type() == rhs.section().type());
4662 assert(strcmp(this->sectionName(), "__cfstring") == 0);
4663
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);
4672
4673 if ( thisType != rhsType )
4674 return false;
4675
4676 // no need to compare content of pointers are already the same
4677 if ( cstringContent == rhsStringContent )
4678 return true;
4679
4680 // no need to compare content if size is different
4681 if ( charCount != rhsCharCount )
4682 return false;
4683
4684 switch ( thisType ) {
4685 case contentUTF8:
4686 return (strcmp((char*)cstringContent, (char*)rhsStringContent) == 0);
4687 case contentUTF16:
4688 {
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] )
4693 return false;
4694 }
4695 return true;
4696 }
4697 case contentUnknown:
4698 return false;
4699 }
4700 return false;
4701}
4702
4703
4704template <typename A>
4705typename A::P::uint_t ObjC1ClassSection<A>::elementSizeAtAddress(pint_t addr)
4706{
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);
4712 return size;
4713}
4714
4715template <typename A>
4716const char* ObjC1ClassSection<A>::unlabeledAtomName(Parser<A>& parser, pint_t addr)
4717{
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))));
4723
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 = &sections[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 )
4737 continue;
4738 const char* absName = parser.nameFromSymbol(sym);
4739 if ( strncmp(absName, ".objc_class_name_", 17) == 0 ) {
4740 if ( strcmp(&absName[17], name) == 0 )
4741 return absName;
4742 }
4743 }
4744 assert(0 && "obj class name not found in symbol table");
4745 }
4746 }
4747 assert(0 && "obj class name not found");
4748 return "unknown objc class";
4749}
4750
4751
4752template <typename A>
4753const char* ObjC2ClassRefsSection<A>::targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4754{
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;
4761 break;
4762 case ld::Fixup::bindingDirectlyBound:
4763 case ld::Fixup::bindingByContentBound:
4764 className = fit->u.target->name();
4765 break;
4766 case ld::Fixup::bindingsIndirectlyBound:
4767 className = ind.indirectName(fit->u.bindingIndex);
4768 break;
4769 default:
4770 assert(0 && "unsupported binding in objc2 class ref section");
4771 }
4772 assert(className != NULL);
4773 return className;
4774}
4775
4776
4777template <typename A>
4778unsigned long ObjC2ClassRefsSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4779{
4780 unsigned long hash = 978;
4781 for (const char* s = targetClassName(atom, ind); *s != '\0'; ++s) {
4782 hash = hash * 33 + *s;
4783 }
4784 return hash;
4785}
4786
4787template <typename A>
4788bool ObjC2ClassRefsSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4789 const ld::IndirectBindingTable& indirectBindingTable) const
4790{
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);
4797}
4798
4799
4800template <typename A>
4801const char* Objc1ClassReferences<A>::targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4802{
4803 assert(atom->fixupCount() == 2);
4804 ld::Fixup::iterator fit = atom->fixupsBegin();
4805 if ( fit->kind == ld::Fixup::kindSetTargetAddress )
4806 ++fit;
4807 const ld::Atom* targetAtom = NULL;
4808 switch ( fit->binding ) {
4809 case ld::Fixup::bindingByContentBound:
4810 targetAtom = fit->u.target;
4811 break;
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));
4816 }
4817 break;
4818 default:
4819 assert(0);
4820 }
4821 assert(targetAtom != NULL);
4822 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
4823 assert(target != NULL);
4824 return (char*)target->contentPointer();
4825}
4826
4827
4828template <typename A>
4829const char* PointerToCStringSection<A>::targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4830{
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;
4837 break;
4838 case ld::Fixup::bindingsIndirectlyBound:
4839 targetAtom = ind.indirectAtom(fit->u.bindingIndex);
4840 break;
4841 default:
4842 assert(0);
4843 }
4844 assert(targetAtom != NULL);
4845 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
4846 assert(target != NULL);
4847 return (char*)target->contentPointer();
4848}
4849
4850template <typename A>
4851unsigned long PointerToCStringSection<A>::contentHash(const class Atom<A>* atom,
4852 const ld::IndirectBindingTable& indirectBindingTable) const
4853{
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;
4858 }
4859 for (const char* s = this->targetCString(atom, indirectBindingTable); *s != '\0'; ++s) {
4860 hash = hash * 33 + *s;
4861 }
4862 return hash;
4863}
4864
4865template <typename A>
4866bool PointerToCStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4867 const ld::IndirectBindingTable& indirectBindingTable) const
4868{
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() )
4873 return false;
4874
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);
4880
4881 assert(cstringContent != NULL);
4882 assert(rhsCstringContent != NULL);
4883 return (strcmp(cstringContent, rhsCstringContent) == 0);
4884}
4885
4886
4887
4888template <typename A>
4889unsigned long UTF16StringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
4890{
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;
4897 }
4898 return hash;
4899}
4900
4901template <typename A>
4902bool UTF16StringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
4903 const ld::IndirectBindingTable& ind) const
4904{
4905 if ( rhs.section().type() != ld::Section::typeUTF16Strings )
4906 return false;
4907 assert(0);
4908 return false;
4909}
4910
4911
4912
4913
4914
4915
4916
4917template <>
4918uint32_t Section<x86_64>::x86_64PcRelOffset(uint8_t r_type)
4919{
4920 switch ( r_type ) {
4921 case X86_64_RELOC_SIGNED:
4922 return 4;
4923 case X86_64_RELOC_SIGNED_1:
4924 return 5;
4925 case X86_64_RELOC_SIGNED_2:
4926 return 6;
4927 case X86_64_RELOC_SIGNED_4:
4928 return 8;
4929 }
4930 return 0;
4931}
4932
4933
4934template <>
4935bool Section<x86_64>::addRelocFixup(class Parser<x86_64>& parser, const macho_relocation_info<P>* reloc)
4936{
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() ) {
4950 case 0:
4951 contentValue = *fixUpPtr;
4952 break;
4953 case 1:
4954 contentValue = (int64_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr));
4955 break;
4956 case 2:
4957 contentValue = (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr));
4958 break;
4959 case 3:
4960 contentValue = E::get64(*((uint64_t*)fixUpPtr));
4961 break;
4962 }
4963 target.atom = NULL;
4964 target.name = NULL;
4965 target.weakImport = false;
4966 target.addend = 0;
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;
4973 }
4974 else {
4975 target.name = parser.nameFromSymbol(sym);
4976 target.weakImport = parser.weakImportFromSymbol(sym);
4977 target.addend = contentValue;
4978 }
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;
4983 }
4984 }
4985 else {
4986 if ( reloc->r_pcrel() )
4987 contentValue += srcAddr + x86_64PcRelOffset(reloc->r_type());
4988 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
4989 }
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() ) {
4995 case 0:
4996 case 1:
4997 throw "length < 2 and X86_64_RELOC_UNSIGNED not supported";
4998 case 2:
4999 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
5000 break;
5001 case 3:
5002 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian64, target);
5003 break;
5004 }
5005 break;
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);
5017 break;
5018 case X86_64_RELOC_SIGNED_1:
5019 if ( reloc->r_extern() )
5020 target.addend += 1;
5021 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_1, target);
5022 break;
5023 case X86_64_RELOC_SIGNED_2:
5024 if ( reloc->r_extern() )
5025 target.addend += 2;
5026 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_2, target);
5027 break;
5028 case X86_64_RELOC_SIGNED_4:
5029 if ( reloc->r_extern() )
5030 target.addend += 4;
5031 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_4, target);
5032 break;
5033 }
5034 break;
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() ) {
5039 case 2:
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]);
5043 }
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]);
5047 }
5048 else {
5049 parser.addFixups(src, ld::Fixup::kindStoreX86BranchPCRel32, target);
5050 }
5051 break;
5052 case 0:
5053 parser.addFixups(src, ld::Fixup::kindStoreX86BranchPCRel8, target);
5054 break;
5055 default:
5056 throwf("length=%d and X86_64_RELOC_BRANCH not supported", reloc->r_length());
5057 }
5058 break;
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);
5067 break;
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);
5076 break;
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";
5086 result = true;
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;
5098 }
5099 else {
5100 toTarget.name = parser.nameFromSymbol(sym);
5101 toTarget.weakImport = parser.weakImportFromSymbol(sym);
5102 toTarget.addend = contentValue;
5103 useDirectBinding = false;
5104 }
5105 }
5106 else {
5107 parser.findTargetFromAddressAndSectionNum(contentValue, nextReloc->r_symbolnum(), toTarget);
5108 useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit);
5109 }
5110 if ( useDirectBinding )
5111 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom);
5112 else
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);
5117 else
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);
5121 else
5122 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian64);
5123 break;
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);
5132 break;
5133 default:
5134 throwf("unknown relocation type %d", reloc->r_type());
5135 }
5136 return result;
5137}
5138
5139
5140
5141template <>
5142bool Section<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<P>* reloc)
5143{
5144 const macho_section<P>* sect = this->machoSection();
5145 uint32_t srcAddr;
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;
5151
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() ) {
5160 case 0:
5161 contentValue = (int32_t)(int8_t)*fixUpPtr;
5162 if ( reloc->r_pcrel() ) {
5163 kind = ld::Fixup::kindStoreX86BranchPCRel8;
5164 contentValue += srcAddr + sizeof(uint8_t);
5165 }
5166 else
5167 throw "r_length=0 and r_pcrel=0 not supported";
5168 break;
5169 case 1:
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);
5174 }
5175 else
5176 kind = ld::Fixup::kindStoreLittleEndian16;
5177 break;
5178 case 2:
5179 contentValue = E::get32(*((uint32_t*)fixUpPtr));
5180 if ( reloc->r_pcrel() ) {
5181 kind = ld::Fixup::kindStoreX86BranchPCRel32;
5182 contentValue += srcAddr + sizeof(uint32_t);
5183 }
5184 else
5185 kind = ld::Fixup::kindStoreLittleEndian32;
5186 break;
5187 case 3:
5188 throw "r_length=3 not supported";
5189 }
5190 if ( reloc->r_extern() ) {
5191 target.atom = NULL;
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;
5196 }
5197 else {
5198 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
5199 }
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]);
5204 return false;
5205 }
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]);
5209 return false;
5210 }
5211 }
5212 parser.addFixups(src, kind, target);
5213 return false;
5214 break;
5215 case GENERIC_RLEOC_TLV:
5216 {
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);
5225 }
5226 else {
5227 target.atom = NULL;
5228 target.name = parser.nameFromSymbol(sym);
5229 target.weakImport = parser.weakImportFromSymbol(sym);
5230 }
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);
5234 }
5235 else {
5236 parser.addFixups(src, ld::Fixup::kindStoreX86Abs32TLVLoad, target);
5237 }
5238 return false;
5239 }
5240 break;
5241 default:
5242 throwf("unsupported i386 relocation type (%d)", reloc->r_type());
5243 }
5244 }
5245 else {
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
5265 }
5266 }
5267 else {
5268 if ( nextSReloc->r_type() == GENERIC_RELOC_PAIR ) {
5269 nextRelocIsPair = true;
5270 nextRelocAddress = nextSReloc->r_address();
5271 nextRelocValue = nextSReloc->r_value();
5272 }
5273 }
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() ) {
5280 case 0:
5281 contentValue = srcAddr + 1 + *fixUpPtr;
5282 target.addend = contentValue - relocValue;
5283 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel8, target);
5284 break;
5285 case 1:
5286 contentValue = srcAddr + 2 + LittleEndian::get16(*((uint16_t*)fixUpPtr));
5287 target.addend = contentValue - relocValue;
5288 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel16, target);
5289 break;
5290 case 2:
5291 contentValue = srcAddr + 4 + LittleEndian::get32(*((uint32_t*)fixUpPtr));
5292 target.addend = contentValue - relocValue;
5293 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32, target);
5294 break;
5295 case 3:
5296 throw "unsupported r_length=3 for scattered pc-rel vanilla reloc";
5297 break;
5298 }
5299 }
5300 else {
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);
5306 }
5307 break;
5308 case GENERIC_RELOC_SECTDIFF:
5309 case GENERIC_RELOC_LOCAL_SECTDIFF:
5310 {
5311 if ( !nextRelocIsPair )
5312 throw "GENERIC_RELOC_SECTDIFF missing following pair";
5313 switch ( sreloc->r_length() ) {
5314 case 0:
5315 case 3:
5316 throw "bad length for GENERIC_RELOC_SECTDIFF";
5317 case 1:
5318 contentValue = (int32_t)(int16_t)LittleEndian::get16(*((uint16_t*)fixUpPtr));
5319 kind = ld::Fixup::kindStoreLittleEndian16;
5320 break;
5321 case 2:
5322 contentValue = LittleEndian::get32(*((uint32_t*)fixUpPtr));
5323 kind = ld::Fixup::kindStoreLittleEndian32;
5324 break;
5325 }
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);
5331 if ( addend < 0 ) {
5332 // switch binding base on coalescing
5333 if ( target.atom == NULL ) {
5334 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.name);
5335 }
5336 else if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
5337 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, target.atom);
5338 }
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);
5341 }
5342 else {
5343 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
5344 }
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);
5349 }
5350 else {
5351 // switch binding base on coalescing
5352 if ( target.atom == NULL ) {
5353 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.name);
5354 }
5355 else if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
5356 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, target.atom);
5357 }
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);
5360 }
5361 else {
5362 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
5363 }
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);
5368 }
5369 }
5370 break;
5371 }
5372 return result;
5373 }
5374}
5375
5376
5377
5378//
5379// ppc and ppc64 both use the same relocations, so process them in one common routine
5380//
5381template <typename A>
5382bool Section<A>::addRelocFixup_powerpc(class Parser<A>& parser,
5383 const macho_relocation_info<typename A::P>* reloc)
5384{
5385 const macho_section<P>* sect = this->machoSection();
5386 bool result = false;
5387 uint32_t srcAddr;
5388 uint32_t dstAddr;
5389 uint32_t* fixUpPtr;
5390 int32_t displacement = 0;
5391 uint32_t instruction = 0;
5392 int16_t lowBits;
5393 pint_t contentValue = 0;
5394 typename Parser<A>::SourceLocation src;
5395 typename Parser<A>::TargetDesc target;
5396
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() ) {
5406 target.atom = NULL;
5407 const macho_nlist<P>& targetSymbol = parser.symbolFromIndex(reloc->r_symbolnum());
5408 target.name = parser.nameFromSymbol(targetSymbol);
5409 target.weakImport = parser.weakImportFromSymbol(targetSymbol);
5410 }
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;
5419 }
5420 else {
5421 dstAddr = srcAddr + displacement;
5422 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5423 }
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]);
5429 }
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]);
5434 }
5435 else {
5436 parser.addFixups(src, ld::Fixup::kindStorePPCBranch24, target);
5437 }
5438 break;
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;
5445 }
5446 else {
5447 dstAddr = srcAddr + displacement;
5448 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5449 }
5450 parser.addFixups(src, ld::Fixup::kindStorePPCBranch14, target);
5451 break;
5452 case PPC_RELOC_PAIR:
5453 // skip, processed by a previous look ahead
5454 break;
5455 case PPC_RELOC_LO16:
5456 if ( nextReloc->r_type() != PPC_RELOC_PAIR )
5457 throw "PPC_RELOC_LO16 missing following pair";
5458 result = true;
5459 lowBits = (instruction & 0x0000FFFF);
5460 dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
5461 if ( reloc->r_extern() ) {
5462 target.addend = dstAddr;
5463 }
5464 else {
5465 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5466 }
5467 parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow16, target);
5468 break;
5469 case PPC_RELOC_LO14:
5470 if ( nextReloc->r_type() != PPC_RELOC_PAIR )
5471 throw "PPC_RELOC_LO14 missing following pair";
5472 result = true;
5473 lowBits = (instruction & 0xFFFC);
5474 dstAddr = (nextReloc->r_address() << 16) + ((uint32_t)lowBits & 0x0000FFFF);
5475 if ( reloc->r_extern() ) {
5476 target.addend = dstAddr;
5477 }
5478 else {
5479 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5480 }
5481 parser.addFixups(src, ld::Fixup::kindStorePPCAbsLow14, target);
5482 break;
5483 case PPC_RELOC_HI16:
5484 if ( nextReloc->r_type() != PPC_RELOC_PAIR )
5485 throw "PPC_RELOC_HI16 missing following pair";
5486 result = true;
5487 lowBits = (nextReloc->r_address() & 0xFFFF);
5488 dstAddr = ((instruction & 0xFFFF) << 16) | (lowBits & 0x0000FFFF);
5489 if ( reloc->r_extern() ) {
5490 target.addend = dstAddr;
5491 }
5492 else {
5493 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5494 }
5495 parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16, target);
5496 break;
5497 case PPC_RELOC_HA16:
5498 if ( nextReloc->r_type() != PPC_RELOC_PAIR )
5499 throw "PPC_RELOC_HA16 missing following pair";
5500 result = true;
5501 lowBits = (nextReloc->r_address() & 0x0000FFFF);
5502 dstAddr = ((instruction & 0xFFFF) << 16) + (int32_t)lowBits;
5503 if ( reloc->r_extern() ) {
5504 target.addend = dstAddr;
5505 }
5506 else {
5507 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5508 }
5509 parser.addFixups(src, ld::Fixup::kindStorePPCAbsHigh16AddLow, target);
5510 break;
5511 case PPC_RELOC_VANILLA:
5512 contentValue = P::getP(*((pint_t*)fixUpPtr));
5513 if ( reloc->r_extern() ) {
5514 target.addend = contentValue;
5515 }
5516 else {
5517 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
5518 }
5519 switch ( reloc->r_length() ) {
5520 case 0:
5521 case 1:
5522 throw "bad r_length in PPC_RELOC_VANILLA";
5523 case 2:
5524 parser.addFixups(src, ld::Fixup::kindStoreBigEndian32, target);
5525 break;
5526 case 3:
5527 parser.addFixups(src, ld::Fixup::kindStoreBigEndian64, target);
5528 break;
5529 }
5530 break;
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;
5539 result = true;
5540 if ( reloc->r_extern() ) {
5541 throw "PPC_RELOC_JBSR should not be using an external relocation";
5542 }
5543 parser.findTargetFromAddressAndSectionNum(nextReloc->r_address(), reloc->r_symbolnum(), target);
5544 parser.addFixups(src, ld::Fixup::kindStorePPCBranch24, target);
5545 break;
5546 default:
5547 warning("unknown relocation type %d", reloc->r_type());
5548 }
5549 }
5550 else {
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();
5569 result = true;
5570 }
5571 }
5572 else {
5573 if ( nextSReloc->r_type() == PPC_RELOC_PAIR ) {
5574 nextRelocIsPair = true;
5575 nextRelocAddress = nextSReloc->r_address();
5576 nextRelocValue = nextSReloc->r_value();
5577 result = true;
5578 }
5579 }
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() ) {
5585 case 0:
5586 case 1:
5587 throw "unsuppored r_length < 2 for scattered PPC_RELOC_VANILLA";
5588 case 2:
5589 contentValue = BigEndian::get32(*(uint32_t*)fixUpPtr);
5590 target.addend = contentValue - target.atom->_objAddress;
5591 parser.addFixups(src, ld::Fixup::kindStoreBigEndian32, target);
5592 break;
5593 case 3:
5594 contentValue = BigEndian::get64(*(uint64_t*)fixUpPtr);
5595 target.addend = contentValue - target.atom->_objAddress;
5596 parser.addFixups(src, ld::Fixup::kindStoreBigEndian64, target);
5597 break;
5598 }
5599 break;
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);
5607 break;
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);
5616 break;
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);
5630 break;
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);
5644 break;
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);
5658 break;
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);
5666 break;
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);
5674 break;
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);
5682 break;
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);
5690 break;
5691 case PPC_RELOC_SECTDIFF:
5692 case PPC_RELOC_LOCAL_SECTDIFF:
5693 {
5694 if ( ! nextRelocIsPair )
5695 throw "PPC_RELOC_SECTDIFF missing following pair";
5696 ld::Fixup::Kind kind = ld::Fixup::kindNone;
5697 switch ( sreloc->r_length() ) {
5698 case 0:
5699 throw "bad length for PPC_RELOC_SECTDIFF";
5700 case 1:
5701 contentValue = (int32_t)(int16_t)BigEndian::get16(*((uint16_t*)fixUpPtr));
5702 kind = ld::Fixup::kindStoreBigEndian16;
5703 break;
5704 case 2:
5705 contentValue = BigEndian::get32(*((uint32_t*)fixUpPtr));
5706 kind = ld::Fixup::kindStoreBigEndian32;
5707 break;
5708 case 3:
5709 contentValue = BigEndian::get64(*((uint64_t*)fixUpPtr));
5710 kind = ld::Fixup::kindStoreBigEndian64;
5711 break;
5712 break;
5713 }
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);
5720 if ( addend < 0 ) {
5721 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
5722 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
5723 }
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);
5726 }
5727 else {
5728 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
5729 }
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);
5734 }
5735 else {
5736 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
5737 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
5738 }
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);
5741 }
5742 else {
5743 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
5744 }
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);
5749 }
5750 }
5751 break;
5752 case PPC_RELOC_PAIR:
5753 break;
5754 case PPC_RELOC_HI16_SECTDIFF:
5755 warning("unexpected scattered relocation type PPC_RELOC_HI16_SECTDIFF");
5756 break;
5757 default:
5758 warning("unknown scattered relocation type %d", sreloc->r_type());
5759 }
5760 }
5761 return result;
5762}
5763
5764
5765template <>
5766bool Section<ppc>::addRelocFixup(class Parser<ppc>& parser, const macho_relocation_info<P>* reloc)
5767{
5768 return addRelocFixup_powerpc(parser, reloc);
5769}
5770
5771
5772template <>
5773bool Section<ppc64>::addRelocFixup(class Parser<ppc64>& parser, const macho_relocation_info<P>* reloc)
5774{
5775 return addRelocFixup_powerpc(parser, reloc);
5776}
5777
5778
5779
5780template <>
5781bool Section<arm>::addRelocFixup(class Parser<arm>& parser, const macho_relocation_info<P>* reloc)
5782{
5783 const macho_section<P>* sect = this->machoSection();
5784 bool result = false;
5785 uint32_t srcAddr;
5786 uint32_t dstAddr;
5787 uint32_t* fixUpPtr;
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;
5794
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() ) {
5804 target.atom = NULL;
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;
5810 }
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
5818 displacement += 8;
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
5826 }
5827 else {
5828 dstAddr = srcAddr + displacement;
5829 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5830 }
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]);
5836 }
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]);
5841 }
5842 else {
5843 parser.addFixups(src, ld::Fixup::kindStoreARMBranch24, target);
5844 }
5845 break;
5846 case ARM_THUMB_RELOC_BR22:
5847 // thumb2 added two more bits to displacement, complicating the displacement decoding
5848 {
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);
5857 int32_t sdis = dis;
5858 if ( s )
5859 sdis |= 0xFE000000;
5860 displacement = sdis;
5861 }
5862 // The pc added will be +4 from the pc
5863 displacement += 4;
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;
5868
5869 if ( reloc->r_extern() ) {
5870 target.addend = dstAddr;
5871 }
5872 else {
5873 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
5874 }
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]);
5880 }
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]);
5885 }
5886 else {
5887 parser.addFixups(src, ld::Fixup::kindStoreThumbBranch22, target);
5888 }
5889 break;
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
5898 }
5899 else {
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);
5911 }
5912 }
5913 }
5914 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
5915 break;
5916 case ARM_THUMB_32BIT_BRANCH:
5917 // silently ignore old unnecessary reloc
5918 break;
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);
5924 bool isThumb;
5925 if ( reloc->r_length() & 2 ) {
5926 isThumb = true;
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;
5932 }
5933 else {
5934 isThumb = false;
5935 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
5936 uint32_t imm12 = (instruction & 0x00000FFF);
5937 instruction16 = (imm4 << 12) | imm12;
5938 }
5939 if ( reloc->r_length() & 1 ) {
5940 // high 16
5941 dstAddr = ((instruction16 << 16) | other16);
5942 parser.findTargetFromAddress(dstAddr, target);
5943 parser.addFixups(src, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16), target);
5944 }
5945 else {
5946 // low 16
5947 dstAddr = (other16 << 16) | instruction16;
5948 parser.findTargetFromAddress(dstAddr, target);
5949 parser.addFixups(src, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16), target);
5950 }
5951 result = true;
5952 }
5953 else
5954 throw "for ARM_RELOC_HALF, next reloc is not ARM_RELOC_PAIR";
5955 break;
5956 default:
5957 throwf("unknown relocation type %d", reloc->r_type());
5958 break;
5959 }
5960 }
5961 else {
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();
5979 result = true;
5980 }
5981 }
5982 else {
5983 if ( nextSReloc->r_type() == ARM_RELOC_PAIR ) {
5984 nextRelocIsPair = true;
5985 nextRelocAddress = nextSReloc->r_address();
5986 nextRelocValue = nextSReloc->r_value();
5987 result = true;
5988 }
5989 }
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);
6001 break;
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
6008 displacement += 8;
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);
6015 break;
6016 case ARM_THUMB_RELOC_BR22:
6017 // thumb2 added two more bits to displacement, complicating the displacement decoding
6018 {
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);
6027 int32_t sdis = dis;
6028 if ( s )
6029 sdis |= 0xFE000000;
6030 displacement = sdis;
6031 }
6032 // The pc added will be +4 from the pc
6033 displacement += 4;
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);
6041 break;
6042 case ARM_RELOC_SECTDIFF:
6043 case ARM_RELOC_LOCAL_SECTDIFF:
6044 {
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);
6064 }
6065 if ( addend < 0 ) {
6066 // switch binding base on coalescing
6067 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6068 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
6069 }
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);
6072 }
6073 else {
6074 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6075 }
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);
6081 }
6082 else {
6083 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6084 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
6085 }
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);
6088 }
6089 else {
6090 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6091 }
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);
6096 }
6097 }
6098 break;
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);
6110 bool isThumb;
6111 if ( sreloc->r_length() & 2 ) {
6112 isThumb = true;
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;
6118 }
6119 else {
6120 isThumb = false;
6121 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
6122 uint32_t imm12 = (instruction & 0x00000FFF);
6123 instruction16 = (imm4 << 12) | imm12;
6124 }
6125 if ( sreloc->r_length() & 1 )
6126 dstAddr = ((instruction16 << 16) | other16);
6127 else
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);
6132 }
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);
6135 }
6136 else {
6137 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6138 }
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 ) {
6143 // high 16
6144 parser.addFixup(src, ld::Fixup::k5of5, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16));
6145 }
6146 else {
6147 // low 16
6148 parser.addFixup(src, ld::Fixup::k5of5, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16));
6149 }
6150 result = true;
6151 }
6152 else
6153 throw "ARM_RELOC_HALF_SECTDIFF reloc missing following pair";
6154 break;
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);
6161 bool isThumb;
6162 if ( sreloc->r_length() & 2 ) {
6163 isThumb = true;
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;
6169 }
6170 else {
6171 isThumb = false;
6172 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
6173 uint32_t imm12 = (instruction & 0x00000FFF);
6174 instruction16 = (imm4 << 12) | imm12;
6175 }
6176 if ( sreloc->r_length() & 1 )
6177 dstAddr = ((instruction16 << 16) | other16);
6178 else
6179 dstAddr = (other16 << 16) | instruction16;
6180 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6181 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, targetAtom);
6182 }
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);
6185 }
6186 else {
6187 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6188 }
6189 parser.addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, dstAddr - targetAtom->_objAddress);
6190 if ( sreloc->r_length() & 1 ) {
6191 // high 16
6192 parser.addFixup(src, ld::Fixup::k3of3, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16));
6193 }
6194 else {
6195 // low 16
6196 parser.addFixup(src, ld::Fixup::k3of3, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16));
6197 }
6198 result = true;
6199 }
6200 else
6201 throw "scattered ARM_RELOC_HALF reloc missing following pair";
6202 break;
6203 default:
6204 throwf("unknown ARM scattered relocation type %d", sreloc->r_type());
6205 }
6206 }
6207 return result;
6208}
6209
6210
6211
6212
6213
6214template <typename A>
6215bool ObjC1ClassSection<A>::addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
6216{
6217 // inherited
6218 FixedSizeSection<A>::addRelocFixup(parser, reloc);
6219
6220 assert(0 && "needs template specialization");
6221 return false;
6222}
6223
6224template <>
6225bool ObjC1ClassSection<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<x86::P>* reloc)
6226{
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() );
6231
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);
6242
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);
6249
6250 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, superClassName);
6251 }
6252 }
6253 // inherited
6254 return FixedSizeSection<x86>::addRelocFixup(parser, reloc);
6255}
6256
6257template <>
6258bool ObjC1ClassSection<ppc>::addRelocFixup(class Parser<ppc>& parser, const macho_relocation_info<ppc::P>* reloc)
6259{
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() );
6264
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);
6275
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);
6282
6283 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, superClassName);
6284 }
6285 }
6286
6287 // inherited
6288 return FixedSizeSection<ppc>::addRelocFixup(parser, reloc);
6289}
6290
6291
6292
6293
6294template <typename A>
6295bool Objc1ClassReferences<A>::addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
6296{
6297 // inherited
6298 PointerToCStringSection<A>::addRelocFixup(parser, reloc);
6299
6300 assert(0 && "needs template specialization");
6301 return false;
6302}
6303
6304
6305template <>
6306bool Objc1ClassReferences<ppc>::addRelocFixup(class Parser<ppc>& parser, const macho_relocation_info<ppc::P>* reloc)
6307{
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() );
6313
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);
6323
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);
6330
6331 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, objcClassName);
6332
6333 // inherited
6334 return PointerToCStringSection<ppc>::addRelocFixup(parser, reloc);
6335}
6336
6337
6338template <>
6339bool Objc1ClassReferences<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<x86::P>* reloc)
6340{
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() );
6346
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);
6356
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);
6363
6364 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, objcClassName);
6365
6366 // inherited
6367 return PointerToCStringSection<x86>::addRelocFixup(parser, reloc);
6368}
6369
6370
6371template <typename A>
6372void Section<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFIInfoArray&)
6373{
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) {
6378 try {
6379 if ( this->addRelocFixup(parser, &relocs[r]) )
6380 ++r; // skip next
6381 }
6382 catch (const char* msg) {
6383 throwf("in section %s,%s reloc %u: %s", sect->segname(), sect->sectname(), r, msg);
6384 }
6385 }
6386
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);
6394 }
6395 }
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);
6404 }
6405 }
6406 }
6407
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);
6417 }
6418 }
6419 }
6420}
6421
6422
6423
6424//
6425// main function used by linker to instantiate ld::Files
6426//
6427ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
6428 const char* path, time_t modTime, uint32_t ordinal, const ParserOptions& opts)
6429{
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);
6434 break;
6435 case CPU_TYPE_I386:
6436 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) )
6437 return mach_o::relocatable::Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts);
6438 break;
6439 case CPU_TYPE_ARM:
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);
6442 break;
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);
6446 break;
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);
6450 break;
6451 }
6452 return NULL;
6453}
6454
6455//
6456// used by archive reader to validate member object file
6457//
6458bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserOptions& opts)
6459{
6460 switch ( opts.architecture ) {
6461 case CPU_TYPE_X86_64:
6462 return ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) );
6463 case CPU_TYPE_I386:
6464 return ( mach_o::relocatable::Parser<x86>::validFile(fileContent) );
6465 case CPU_TYPE_ARM:
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) );
6471 }
6472 return false;
6473}
6474
6475//
6476// used by linker to infer architecture when no -arch is on command line
6477//
6478bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult)
6479{
6480 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
6481 *result = CPU_TYPE_X86_64;
6482 *subResult = CPU_SUBTYPE_X86_64_ALL;
6483 return true;
6484 }
6485 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
6486 *result = CPU_TYPE_I386;
6487 *subResult = CPU_SUBTYPE_X86_ALL;
6488 return true;
6489 }
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();
6494 return true;
6495 }
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();
6500 return true;
6501 }
6502 if ( mach_o::relocatable::Parser<ppc64>::validFile(fileContent) ) {
6503 *result = CPU_TYPE_POWERPC64;
6504 *subResult = CPU_SUBTYPE_POWERPC_ALL;
6505 return true;
6506 }
6507 return false;
6508}
6509
6510//
6511// used by linker is error messages to describe bad .o file
6512//
6513const char* archName(const uint8_t* fileContent)
6514{
6515 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
6516 return mach_o::relocatable::Parser<x86_64>::fileKind(fileContent);
6517 }
6518 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
6519 return mach_o::relocatable::Parser<x86>::fileKind(fileContent);
6520 }
6521 if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
6522 return mach_o::relocatable::Parser<arm>::fileKind(fileContent);
6523 }
6524 if ( mach_o::relocatable::Parser<ppc>::validFile(fileContent) ) {
6525 return mach_o::relocatable::Parser<ppc>::fileKind(fileContent);
6526 }
6527 if ( mach_o::relocatable::Parser<ppc64>::validFile(fileContent) ) {
6528 return mach_o::relocatable::Parser<ppc64>::fileKind(fileContent);
6529 }
6530 return NULL;
6531}
6532
6533//
6534// Used by archive reader when -ObjC option is specified
6535//
6536bool hasObjC2Categories(const uint8_t* fileContent)
6537{
6538 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
6539 return mach_o::relocatable::Parser<x86_64>::hasObjC2Categories(fileContent);
6540 }
6541 else if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
6542 return mach_o::relocatable::Parser<arm>::hasObjC2Categories(fileContent);
6543 }
6544 return false;
6545}
6546
6547
6548
6549} // namespace relocatable
6550} // namespace mach_o
6551
6552