]> git.saurik.com Git - apple/ld64.git/blob - src/ld/parsers/macho_relocatable_file.cpp
c023f37c8c893cf552197cc39a6908713ab98146
[apple/ld64.git] / src / ld / parsers / macho_relocatable_file.cpp
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 #include <type_traits>
46
47 #include "dwarf2.h"
48 #include "debugline.h"
49
50 #include "Architectures.hpp"
51 #include "Bitcode.hpp"
52 #include "ld.hpp"
53 #include "macho_relocatable_file.h"
54
55
56
57 extern void throwf(const char* format, ...) __attribute__ ((noreturn,format(printf, 1, 2)));
58 extern void warning(const char* format, ...) __attribute__((format(printf, 1, 2)));
59
60 namespace mach_o {
61 namespace relocatable {
62
63
64 // forward reference
65 template <typename A> class Parser;
66 template <typename A> class Atom;
67 template <typename A> class Section;
68 template <typename A> class CFISection;
69 template <typename A> class CUSection;
70
71 template <typename A>
72 class File : public ld::relocatable::File
73 {
74 public:
75 File(const char* p, time_t mTime, const uint8_t* content, ld::File::Ordinal ord) :
76 ld::relocatable::File(p,mTime,ord), _fileContent(content),
77 _sectionsArray(NULL), _atomsArray(NULL),
78 _sectionsArrayCount(0), _atomsArrayCount(0), _aliasAtomsArrayCount(0),
79 _debugInfoKind(ld::relocatable::File::kDebugInfoNone),
80 _dwarfTranslationUnitPath(NULL),
81 _dwarfDebugInfoSect(NULL), _dwarfDebugAbbrevSect(NULL),
82 _dwarfDebugLineSect(NULL), _dwarfDebugStringSect(NULL),
83 _objConstraint(ld::File::objcConstraintNone),
84 _swiftVersion(0),
85 _cpuSubType(0),
86 _minOSVersion(0),
87 _platform(0),
88 _canScatterAtoms(false),
89 _srcKind(kSourceUnknown) {}
90 virtual ~File();
91
92 // overrides of ld::File
93 virtual bool forEachAtom(ld::File::AtomHandler&) const;
94 virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
95 { return false; }
96 virtual uint32_t minOSVersion() const { return _minOSVersion; }
97 virtual uint32_t platformLoadCommand() const { return _platform; }
98
99 // overrides of ld::relocatable::File
100 virtual ObjcConstraint objCConstraint() const { return _objConstraint; }
101 virtual uint32_t cpuSubType() const { return _cpuSubType; }
102 virtual DebugInfoKind debugInfo() const { return _debugInfoKind; }
103 virtual const std::vector<ld::relocatable::File::Stab>* stabs() const { return &_stabs; }
104 virtual bool canScatterAtoms() const { return _canScatterAtoms; }
105 virtual const char* translationUnitSource() const;
106 virtual LinkerOptionsList* linkerOptions() const { return &_linkerOptions; }
107 virtual uint8_t swiftVersion() const { return _swiftVersion; }
108 virtual ld::Bitcode* getBitcode() const { return _bitcode.get(); }
109 virtual SourceKind sourceKind() const { return _srcKind; }
110 virtual void setSourceKind(SourceKind src) { _srcKind = src; }
111
112 const uint8_t* fileContent() { return _fileContent; }
113 private:
114 friend class Atom<A>;
115 friend class Section<A>;
116 friend class Parser<A>;
117 friend class CFISection<A>::OAS;
118
119 typedef typename A::P P;
120
121 const uint8_t* _fileContent;
122 Section<A>** _sectionsArray;
123 uint8_t* _atomsArray;
124 uint8_t* _aliasAtomsArray;
125 uint32_t _sectionsArrayCount;
126 uint32_t _atomsArrayCount;
127 uint32_t _aliasAtomsArrayCount;
128 std::vector<ld::Fixup> _fixups;
129 std::vector<ld::Atom::UnwindInfo> _unwindInfos;
130 std::vector<ld::Atom::LineInfo> _lineInfos;
131 std::vector<ld::relocatable::File::Stab>_stabs;
132 ld::relocatable::File::DebugInfoKind _debugInfoKind;
133 const char* _dwarfTranslationUnitPath;
134 const macho_section<P>* _dwarfDebugInfoSect;
135 const macho_section<P>* _dwarfDebugAbbrevSect;
136 const macho_section<P>* _dwarfDebugLineSect;
137 const macho_section<P>* _dwarfDebugStringSect;
138 ld::File::ObjcConstraint _objConstraint;
139 uint8_t _swiftVersion;
140 uint32_t _cpuSubType;
141 uint32_t _minOSVersion;
142 uint32_t _platform;
143 bool _canScatterAtoms;
144 std::vector<std::vector<const char*> > _linkerOptions;
145 std::unique_ptr<ld::Bitcode> _bitcode;
146 SourceKind _srcKind;
147 };
148
149
150 template <typename A>
151 class Section : public ld::Section
152 {
153 public:
154 typedef typename A::P::uint_t pint_t;
155 typedef typename A::P P;
156 typedef typename A::P::E E;
157
158 virtual ~Section() { }
159 class File<A>& file() const { return _file; }
160 const macho_section<P>* machoSection() const { return _machOSection; }
161 uint32_t sectionNum(class Parser<A>&) const;
162 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr);
163 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeUnclassified; }
164 virtual bool dontDeadStrip() { return (this->_machOSection->flags() & S_ATTR_NO_DEAD_STRIP); }
165 virtual bool dontDeadStripIfReferencesLive() { return ( (this->_machOSection != NULL) && (this->_machOSection->flags() & S_ATTR_LIVE_SUPPORT) ); }
166 virtual Atom<A>* findAtomByAddress(pint_t addr) { return this->findContentAtomByAddress(addr, this->_beginAtoms, this->_endAtoms); }
167 virtual bool addFollowOnFixups() const { return ! _file.canScatterAtoms(); }
168 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer,
169 struct Parser<A>::LabelAndCFIBreakIterator& it,
170 const struct Parser<A>::CFI_CU_InfoArrays&) = 0;
171 virtual uint32_t computeAtomCount(class Parser<A>& parser,
172 struct Parser<A>::LabelAndCFIBreakIterator& it,
173 const struct Parser<A>::CFI_CU_InfoArrays&) = 0;
174 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&);
175 virtual bool addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>*);
176 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const { return 0; }
177 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
178 const ld::IndirectBindingTable& ind) const { return false; }
179 virtual bool ignoreLabel(const char* label) const { return false; }
180 static const char* makeSectionName(const macho_section<typename A::P>* s);
181
182 protected:
183 Section(File<A>& f, const macho_section<typename A::P>* s)
184 : ld::Section(makeSegmentName(s), makeSectionName(s), sectionType(s)),
185 _file(f), _machOSection(s), _beginAtoms(NULL), _endAtoms(NULL), _hasAliases(false) { }
186 Section(File<A>& f, const char* segName, const char* sectName, ld::Section::Type t, bool hidden=false)
187 : ld::Section(segName, sectName, t, hidden), _file(f), _machOSection(NULL),
188 _beginAtoms(NULL), _endAtoms(NULL), _hasAliases(false) { }
189
190
191 Atom<A>* findContentAtomByAddress(pint_t addr, class Atom<A>* start, class Atom<A>* end);
192 uint32_t x86_64PcRelOffset(uint8_t r_type);
193 void addLOH(class Parser<A>& parser, int kind, int count, const uint64_t addrs[]);
194 static const char* makeSegmentName(const macho_section<typename A::P>* s);
195 static bool readable(const macho_section<typename A::P>* s);
196 static bool writable(const macho_section<typename A::P>* s);
197 static bool exectuable(const macho_section<typename A::P>* s);
198 static ld::Section::Type sectionType(const macho_section<typename A::P>* s);
199
200 File<A>& _file;
201 const macho_section<P>* _machOSection;
202 class Atom<A>* _beginAtoms;
203 class Atom<A>* _endAtoms;
204 bool _hasAliases;
205 std::set<const class Atom<A>*> _altEntries;
206 };
207
208
209 template <typename A>
210 class CFISection : public Section<A>
211 {
212 public:
213 CFISection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
214 : Section<A>(f, s) { }
215 uint32_t cfiCount(Parser<A>& parser);
216
217 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeCFI; }
218 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&);
219 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&);
220 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&);
221 virtual bool addFollowOnFixups() const { return false; }
222
223
224 ///
225 /// ObjectFileAddressSpace is used as a template parameter to UnwindCursor for parsing
226 /// dwarf CFI information in an object file.
227 ///
228 class OAS
229 {
230 public:
231 typedef typename A::P::uint_t pint_t;
232 typedef typename A::P P;
233 typedef typename A::P::E E;
234 typedef typename A::P::uint_t sint_t;
235
236 OAS(CFISection<A>& ehFrameSection, const uint8_t* ehFrameBuffer) :
237 _ehFrameSection(ehFrameSection),
238 _ehFrameContent(ehFrameBuffer),
239 _ehFrameStartAddr(ehFrameSection.machoSection()->addr()),
240 _ehFrameEndAddr(ehFrameSection.machoSection()->addr()+ehFrameSection.machoSection()->size()) {}
241
242 uint8_t get8(pint_t addr) { return *((uint8_t*)mappedAddress(addr)); }
243 uint16_t get16(pint_t addr) { return E::get16(*((uint16_t*)mappedAddress(addr))); }
244 uint32_t get32(pint_t addr) { return E::get32(*((uint32_t*)mappedAddress(addr))); }
245 uint64_t get64(pint_t addr) { return E::get64(*((uint64_t*)mappedAddress(addr))); }
246 pint_t getP(pint_t addr) { return P::getP(*((pint_t*)mappedAddress(addr))); }
247 uint64_t getULEB128(pint_t& addr, pint_t end);
248 int64_t getSLEB128(pint_t& addr, pint_t end);
249 pint_t getEncodedP(pint_t& addr, pint_t end, uint8_t encoding);
250 private:
251 const void* mappedAddress(pint_t addr);
252
253 CFISection<A>& _ehFrameSection;
254 const uint8_t* _ehFrameContent;
255 pint_t _ehFrameStartAddr;
256 pint_t _ehFrameEndAddr;
257 };
258
259
260 typedef typename A::P::uint_t pint_t;
261 typedef libunwind::CFI_Atom_Info<OAS> CFI_Atom_Info;
262
263 void cfiParse(class Parser<A>& parser, uint8_t* buffer, CFI_Atom_Info cfiArray[], uint32_t& cfiCount, const pint_t cuStarts[], uint32_t cuCount);
264 bool needsRelocating();
265
266 static bool bigEndian();
267 private:
268 void addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo);
269 static void warnFunc(void* ref, uint64_t funcAddr, const char* msg);
270 };
271
272
273 template <typename A>
274 class CUSection : public Section<A>
275 {
276 public:
277 CUSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
278 : Section<A>(f, s) { }
279
280 typedef typename A::P::uint_t pint_t;
281 typedef typename A::P P;
282 typedef typename A::P::E E;
283
284 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&) { return 0; }
285 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&) { return 0; }
286 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&);
287 virtual bool addFollowOnFixups() const { return false; }
288
289 struct Info {
290 pint_t functionStartAddress;
291 uint32_t functionSymbolIndex;
292 uint32_t rangeLength;
293 uint32_t compactUnwindInfo;
294 const char* personality;
295 pint_t lsdaAddress;
296 Atom<A>* function;
297 Atom<A>* lsda;
298 };
299
300 uint32_t count();
301 void parse(class Parser<A>& parser, uint32_t cnt, Info array[]);
302 static bool encodingMeansUseDwarf(compact_unwind_encoding_t enc);
303
304
305 private:
306
307 const char* personalityName(class Parser<A>& parser, const macho_relocation_info<P>* reloc);
308
309 static int infoSorter(const void* l, const void* r);
310
311 };
312
313
314 template <typename A>
315 class TentativeDefinitionSection : public Section<A>
316 {
317 public:
318 TentativeDefinitionSection(Parser<A>& parser, File<A>& f)
319 : Section<A>(f, "__DATA", "__comm/tent", ld::Section::typeTentativeDefs) {}
320
321 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeZeroFill; }
322 virtual bool addFollowOnFixups() const { return false; }
323 virtual Atom<A>* findAtomByAddress(typename A::P::uint_t addr) { throw "TentativeDefinitionSection::findAtomByAddress() should never be called"; }
324 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it,
325 const struct Parser<A>::CFI_CU_InfoArrays&);
326 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer,
327 struct Parser<A>::LabelAndCFIBreakIterator& it,
328 const struct Parser<A>::CFI_CU_InfoArrays&);
329 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&) {}
330 private:
331 typedef typename A::P::uint_t pint_t;
332 typedef typename A::P P;
333 };
334
335
336 template <typename A>
337 class AbsoluteSymbolSection : public Section<A>
338 {
339 public:
340 AbsoluteSymbolSection(Parser<A>& parser, File<A>& f)
341 : Section<A>(f, "__DATA", "__abs", ld::Section::typeAbsoluteSymbols, true) {}
342
343 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeUnclassified; }
344 virtual bool dontDeadStrip() { return false; }
345 virtual ld::Atom::Alignment alignmentForAddress(typename A::P::uint_t addr) { return ld::Atom::Alignment(0); }
346 virtual bool addFollowOnFixups() const { return false; }
347 virtual Atom<A>* findAtomByAddress(typename A::P::uint_t addr) { throw "AbsoluteSymbolSection::findAtomByAddress() should never be called"; }
348 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it,
349 const struct Parser<A>::CFI_CU_InfoArrays&);
350 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer,
351 struct Parser<A>::LabelAndCFIBreakIterator& it,
352 const struct Parser<A>::CFI_CU_InfoArrays&);
353 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&) {}
354 virtual Atom<A>* findAbsAtomForValue(typename A::P::uint_t);
355
356 private:
357 typedef typename A::P::uint_t pint_t;
358 typedef typename A::P P;
359 };
360
361
362 template <typename A>
363 class SymboledSection : public Section<A>
364 {
365 public:
366 SymboledSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s);
367 virtual ld::Atom::ContentType contentType() { return _type; }
368 virtual bool dontDeadStrip();
369 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it,
370 const struct Parser<A>::CFI_CU_InfoArrays&);
371 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer,
372 struct Parser<A>::LabelAndCFIBreakIterator& it,
373 const struct Parser<A>::CFI_CU_InfoArrays&);
374 protected:
375 typedef typename A::P::uint_t pint_t;
376 typedef typename A::P P;
377
378 ld::Atom::ContentType _type;
379 };
380
381
382 template <typename A>
383 class TLVDefsSection : public SymboledSection<A>
384 {
385 public:
386 TLVDefsSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s) :
387 SymboledSection<A>(parser, f, s) { }
388
389 private:
390
391 };
392
393
394 template <typename A>
395 class ImplicitSizeSection : public Section<A>
396 {
397 public:
398 ImplicitSizeSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
399 : Section<A>(f, s) { }
400 virtual uint32_t computeAtomCount(class Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&);
401 virtual uint32_t appendAtoms(class Parser<A>& parser, uint8_t* buffer, struct Parser<A>::LabelAndCFIBreakIterator& it, const struct Parser<A>::CFI_CU_InfoArrays&);
402 protected:
403 typedef typename A::P::uint_t pint_t;
404 typedef typename A::P P;
405
406 virtual bool addFollowOnFixups() const { return false; }
407 virtual const char* unlabeledAtomName(Parser<A>& parser, pint_t addr) = 0;
408 virtual ld::Atom::SymbolTableInclusion symbolTableInclusion();
409 virtual pint_t elementSizeAtAddress(pint_t addr) = 0;
410 virtual ld::Atom::Scope scopeAtAddress(Parser<A>& parser, pint_t addr) { return ld::Atom::scopeLinkageUnit; }
411 virtual bool useElementAt(Parser<A>& parser,
412 struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr) = 0;
413 virtual ld::Atom::Definition definition() { return ld::Atom::definitionRegular; }
414 virtual ld::Atom::Combine combine(Parser<A>& parser, pint_t addr) = 0;
415 virtual bool ignoreLabel(const char* label) const { return (label[0] == 'L'); }
416 };
417
418
419 template <typename A>
420 class FixedSizeSection : public ImplicitSizeSection<A>
421 {
422 public:
423 FixedSizeSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
424 : ImplicitSizeSection<A>(parser, f, s) { }
425 protected:
426 typedef typename A::P::uint_t pint_t;
427 typedef typename A::P P;
428 typedef typename A::P::E E;
429
430 virtual bool useElementAt(Parser<A>& parser,
431 struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr)
432 { return true; }
433 };
434
435
436 template <typename A>
437 class Literal4Section : public FixedSizeSection<A>
438 {
439 public:
440 Literal4Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
441 : FixedSizeSection<A>(parser, f, s) {}
442 protected:
443 typedef typename A::P::uint_t pint_t;
444 typedef typename A::P P;
445
446 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(2); }
447 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "4-byte-literal"; }
448 virtual pint_t elementSizeAtAddress(pint_t addr) { return 4; }
449 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndContent; }
450 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
451 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
452 const ld::IndirectBindingTable& ind) const;
453 virtual bool ignoreLabel(const char* label) const;
454 };
455
456 template <typename A>
457 class Literal8Section : public FixedSizeSection<A>
458 {
459 public:
460 Literal8Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
461 : FixedSizeSection<A>(parser, f, s) {}
462 protected:
463 typedef typename A::P::uint_t pint_t;
464 typedef typename A::P P;
465
466 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(3); }
467 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "8-byte-literal"; }
468 virtual pint_t elementSizeAtAddress(pint_t addr) { return 8; }
469 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndContent; }
470 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
471 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
472 const ld::IndirectBindingTable& ind) const;
473 virtual bool ignoreLabel(const char* label) const;
474 };
475
476 template <typename A>
477 class Literal16Section : public FixedSizeSection<A>
478 {
479 public:
480 Literal16Section(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
481 : FixedSizeSection<A>(parser, f, s) {}
482 protected:
483 typedef typename A::P::uint_t pint_t;
484 typedef typename A::P P;
485
486 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(4); }
487 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "16-byte-literal"; }
488 virtual pint_t elementSizeAtAddress(pint_t addr) { return 16; }
489 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndContent; }
490 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
491 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
492 const ld::IndirectBindingTable& ind) const;
493 virtual bool ignoreLabel(const char* label) const;
494 };
495
496
497 template <typename A>
498 class NonLazyPointerSection : public FixedSizeSection<A>
499 {
500 public:
501 NonLazyPointerSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
502 : FixedSizeSection<A>(parser, f, s) {}
503 protected:
504 typedef typename A::P::uint_t pint_t;
505 typedef typename A::P P;
506
507 virtual void makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&);
508 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeNonLazyPointer; }
509 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
510 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "non_lazy_ptr"; }
511 virtual pint_t elementSizeAtAddress(pint_t addr) { return sizeof(pint_t); }
512 virtual ld::Atom::Scope scopeAtAddress(Parser<A>& parser, pint_t addr);
513 virtual ld::Atom::Combine combine(Parser<A>&, pint_t);
514 virtual bool ignoreLabel(const char* label) const { return true; }
515 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
516 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
517 const ld::IndirectBindingTable& ind) const;
518
519 private:
520 static const char* targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind);
521 static ld::Fixup::Kind fixupKind();
522 };
523
524 template <typename A>
525 class TLVPointerSection : public FixedSizeSection<A>
526 {
527 public:
528 TLVPointerSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
529 : FixedSizeSection<A>(parser, f, s) {}
530 protected:
531 typedef typename A::P::uint_t pint_t;
532 typedef typename A::P P;
533
534 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeTLVPointer; }
535 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
536 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "tlv_lazy_ptr"; }
537 virtual pint_t elementSizeAtAddress(pint_t addr) { return sizeof(pint_t); }
538 virtual ld::Atom::Combine combine(Parser<A>&, pint_t);
539 virtual bool ignoreLabel(const char* label) const { return true; }
540 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
541 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
542 const ld::IndirectBindingTable& ind) const;
543
544 private:
545 static const char* targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind, bool* isStatic);
546 };
547
548
549 template <typename A>
550 class CFStringSection : public FixedSizeSection<A>
551 {
552 public:
553 CFStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
554 : FixedSizeSection<A>(parser, f, s) {}
555 protected:
556 typedef typename A::P::uint_t pint_t;
557
558 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
559 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "CFString"; }
560 virtual pint_t elementSizeAtAddress(pint_t addr) { return 4*sizeof(pint_t); }
561 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndReferences; }
562 virtual bool ignoreLabel(const char* label) const { return true; }
563 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
564 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
565 const ld::IndirectBindingTable& ind) const;
566 private:
567 enum ContentType { contentUTF8, contentUTF16, contentUnknown };
568 static const uint8_t* targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
569 ContentType* ct, unsigned int* count);
570 };
571
572
573 template <typename A>
574 class ObjC1ClassSection : public FixedSizeSection<A>
575 {
576 public:
577 ObjC1ClassSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
578 : FixedSizeSection<A>(parser, f, s) {}
579 protected:
580 typedef typename A::P::uint_t pint_t;
581 typedef typename A::P P;
582 typedef typename A::P::E E;
583
584 virtual ld::Atom::Scope scopeAtAddress(Parser<A>& , pint_t ) { return ld::Atom::scopeGlobal; }
585 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(2); }
586 virtual const char* unlabeledAtomName(Parser<A>&, pint_t);
587 virtual ld::Atom::SymbolTableInclusion symbolTableInclusion() { return ld::Atom::symbolTableIn; }
588 virtual pint_t elementSizeAtAddress(pint_t addr);
589 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineNever; }
590 virtual bool ignoreLabel(const char* label) const { return true; }
591 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
592 { return 0; }
593 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
594 const ld::IndirectBindingTable& ind) const { return false; }
595 virtual bool addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>*);
596 };
597
598
599 template <typename A>
600 class ObjC2ClassRefsSection : public FixedSizeSection<A>
601 {
602 public:
603 ObjC2ClassRefsSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
604 : FixedSizeSection<A>(parser, f, s) {}
605 protected:
606 typedef typename A::P::uint_t pint_t;
607
608 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
609 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "objc-class-ref"; }
610 virtual pint_t elementSizeAtAddress(pint_t addr) { return sizeof(pint_t); }
611 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndReferences; }
612 virtual bool ignoreLabel(const char* label) const { return true; }
613 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
614 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
615 const ld::IndirectBindingTable& ind) const;
616 private:
617 const char* targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
618 };
619
620
621 template <typename A>
622 class ObjC2CategoryListSection : public FixedSizeSection<A>
623 {
624 public:
625 ObjC2CategoryListSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
626 : FixedSizeSection<A>(parser, f, s) {}
627 protected:
628 typedef typename A::P::uint_t pint_t;
629
630 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
631 virtual ld::Atom::Scope scopeAtAddress(Parser<A>& parser, pint_t addr) { return ld::Atom::scopeTranslationUnit; }
632 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "objc-cat-list"; }
633 virtual pint_t elementSizeAtAddress(pint_t addr) { return sizeof(pint_t); }
634 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineNever; }
635 virtual bool ignoreLabel(const char* label) const { return true; }
636 private:
637 const char* targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
638 };
639
640
641 template <typename A>
642 class PointerToCStringSection : public FixedSizeSection<A>
643 {
644 public:
645 PointerToCStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
646 : FixedSizeSection<A>(parser, f, s) {}
647 protected:
648 typedef typename A::P::uint_t pint_t;
649
650 virtual ld::Atom::Alignment alignmentForAddress(pint_t addr) { return ld::Atom::Alignment(log2(sizeof(pint_t))); }
651 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "pointer-to-literal-cstring"; }
652 virtual pint_t elementSizeAtAddress(pint_t addr) { return sizeof(pint_t); }
653 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndReferences; }
654 virtual bool ignoreLabel(const char* label) const { return true; }
655 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
656 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
657 const ld::IndirectBindingTable& ind) const;
658 virtual const char* targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
659 };
660
661
662 template <typename A>
663 class Objc1ClassReferences : public PointerToCStringSection<A>
664 {
665 public:
666 Objc1ClassReferences(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
667 : PointerToCStringSection<A>(parser, f, s) {}
668
669 typedef typename A::P::uint_t pint_t;
670 typedef typename A::P P;
671
672 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "pointer-to-literal-objc-class-name"; }
673 virtual bool addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>*);
674 virtual const char* targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
675 };
676
677
678 template <typename A>
679 class CStringSection : public ImplicitSizeSection<A>
680 {
681 public:
682 CStringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
683 : ImplicitSizeSection<A>(parser, f, s) {}
684 protected:
685 typedef typename A::P::uint_t pint_t;
686 typedef typename A::P P;
687
688 virtual ld::Atom::ContentType contentType() { return ld::Atom::typeCString; }
689 virtual Atom<A>* findAtomByAddress(pint_t addr);
690 virtual const char* unlabeledAtomName(Parser<A>&, pint_t) { return "cstring"; }
691 virtual pint_t elementSizeAtAddress(pint_t addr);
692 virtual bool ignoreLabel(const char* label) const;
693 virtual bool useElementAt(Parser<A>& parser,
694 struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr);
695 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndContent; }
696 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
697 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
698 const ld::IndirectBindingTable& ind) const;
699
700 };
701
702
703 template <typename A>
704 class UTF16StringSection : public SymboledSection<A>
705 {
706 public:
707 UTF16StringSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
708 : SymboledSection<A>(parser, f, s) {}
709 protected:
710 typedef typename A::P::uint_t pint_t;
711 typedef typename A::P P;
712
713 virtual ld::Atom::Combine combine(Parser<A>&, pint_t) { return ld::Atom::combineByNameAndContent; }
714 virtual unsigned long contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const;
715 virtual bool canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
716 const ld::IndirectBindingTable& ind) const;
717 };
718
719
720 //
721 // Atoms in mach-o files
722 //
723 template <typename A>
724 class Atom : public ld::Atom
725 {
726 public:
727 // overrides of ld::Atom
728 virtual const ld::File* file() const;
729 virtual const char* translationUnitSource() const
730 { return sect().file().translationUnitSource(); }
731 virtual const char* name() const { return _name; }
732 virtual uint64_t size() const { return _size; }
733 virtual uint64_t objectAddress() const { return _objAddress; }
734 virtual void copyRawContent(uint8_t buffer[]) const;
735 virtual const uint8_t* rawContentPointer() const { return contentPointer(); }
736 virtual unsigned long contentHash(const ld::IndirectBindingTable& ind) const
737 { if ( _hash == 0 ) _hash = sect().contentHash(this, ind); return _hash; }
738 virtual bool canCoalesceWith(const ld::Atom& rhs, const ld::IndirectBindingTable& ind) const
739 { return sect().canCoalesceWith(this, rhs, ind); }
740 virtual ld::Fixup::iterator fixupsBegin() const { return &machofile()._fixups[_fixupsStartIndex]; }
741 virtual ld::Fixup::iterator fixupsEnd() const { return &machofile()._fixups[_fixupsStartIndex+_fixupsCount]; }
742 virtual ld::Atom::UnwindInfo::iterator beginUnwind() const { return &machofile()._unwindInfos[_unwindInfoStartIndex]; }
743 virtual ld::Atom::UnwindInfo::iterator endUnwind() const { return &machofile()._unwindInfos[_unwindInfoStartIndex+_unwindInfoCount]; }
744 virtual ld::Atom::LineInfo::iterator beginLineInfo() const{ return &machofile()._lineInfos[_lineInfoStartIndex]; }
745 virtual ld::Atom::LineInfo::iterator endLineInfo() const { return &machofile()._lineInfos[_lineInfoStartIndex+_lineInfoCount]; }
746 virtual void setFile(const ld::File* f);
747
748 private:
749
750 enum { kFixupStartIndexBits = 32,
751 kLineInfoStartIndexBits = 32,
752 kUnwindInfoStartIndexBits = 24,
753 kFixupCountBits = 24,
754 kLineInfoCountBits = 12,
755 kUnwindInfoCountBits = 4
756 }; // must sum to 128
757
758 public:
759 // methods for all atoms from mach-o object file
760 Section<A>& sect() const { return (Section<A>&)section(); }
761 File<A>& machofile() const { return ((Section<A>*)(this->_section))->file(); }
762 void setFixupsRange(uint32_t s, uint32_t c);
763 void setUnwindInfoRange(uint32_t s, uint32_t c);
764 void extendUnwindInfoRange();
765 void setLineInfoRange(uint32_t s, uint32_t c);
766 bool roomForMoreLineInfoCount() { return (_lineInfoCount < ((1<<kLineInfoCountBits)-1)); }
767 void incrementLineInfoCount() { assert(roomForMoreLineInfoCount()); ++_lineInfoCount; }
768 void incrementFixupCount() { if (_fixupsCount == ((1 << kFixupCountBits)-1))
769 throwf("too may fixups in %s", name()); ++_fixupsCount; }
770 const uint8_t* contentPointer() const;
771 uint32_t fixupCount() const { return _fixupsCount; }
772 void verifyAlignment(const macho_section<typename A::P>&) const;
773
774 typedef typename A::P P;
775 typedef typename A::P::E E;
776 typedef typename A::P::uint_t pint_t;
777 // constuct via all attributes
778 Atom(Section<A>& sct, const char* nm, pint_t addr, uint64_t sz,
779 ld::Atom::Definition d, ld::Atom::Combine c, ld::Atom::Scope s,
780 ld::Atom::ContentType ct, ld::Atom::SymbolTableInclusion i,
781 bool dds, bool thumb, bool al, ld::Atom::Alignment a)
782 : ld::Atom((ld::Section&)sct, d, c, s, ct, i, dds, thumb, al, a),
783 _size(sz), _objAddress(addr), _name(nm), _hash(0),
784 _fixupsStartIndex(0), _lineInfoStartIndex(0),
785 _unwindInfoStartIndex(0), _fixupsCount(0),
786 _lineInfoCount(0), _unwindInfoCount(0) { }
787 // construct via symbol table entry
788 Atom(Section<A>& sct, Parser<A>& parser, const macho_nlist<P>& sym,
789 uint64_t sz, bool alias=false)
790 : ld::Atom((ld::Section&)sct, parser.definitionFromSymbol(sym),
791 parser.combineFromSymbol(sym), parser.scopeFromSymbol(sym),
792 parser.resolverFromSymbol(sym) ? ld::Atom::typeResolver : sct.contentType(),
793 parser.inclusionFromSymbol(sym),
794 (parser.dontDeadStripFromSymbol(sym) && !sct.dontDeadStripIfReferencesLive()) || sct.dontDeadStrip(),
795 parser.isThumbFromSymbol(sym), alias,
796 sct.alignmentForAddress(sym.n_value())),
797 _size(sz), _objAddress(sym.n_value()),
798 _name(parser.nameFromSymbol(sym)), _hash(0),
799 _fixupsStartIndex(0), _lineInfoStartIndex(0),
800 _unwindInfoStartIndex(0), _fixupsCount(0),
801 _lineInfoCount(0), _unwindInfoCount(0) {
802 // <rdar://problem/6783167> support auto-hidden weak symbols
803 if ( _scope == ld::Atom::scopeGlobal &&
804 (sym.n_desc() & (N_WEAK_DEF|N_WEAK_REF)) == (N_WEAK_DEF|N_WEAK_REF) )
805 this->setAutoHide();
806 this->verifyAlignment(*sct.machoSection());
807 if ( sct.dontDeadStripIfReferencesLive() )
808 this->setDontDeadStripIfReferencesLive();
809 }
810
811 private:
812 friend class Parser<A>;
813 friend class Section<A>;
814 friend class CStringSection<A>;
815 friend class AbsoluteSymbolSection<A>;
816
817 pint_t _size;
818 pint_t _objAddress;
819 const char* _name;
820 mutable unsigned long _hash;
821
822 uint64_t _fixupsStartIndex : kFixupStartIndexBits,
823 _lineInfoStartIndex : kLineInfoStartIndexBits,
824 _unwindInfoStartIndex : kUnwindInfoStartIndexBits,
825 _fixupsCount : kFixupCountBits,
826 _lineInfoCount : kLineInfoCountBits,
827 _unwindInfoCount : kUnwindInfoCountBits;
828
829 static std::map<const ld::Atom*, const ld::File*> _s_fileOverride;
830 };
831
832 template <typename A>
833 std::map<const ld::Atom*, const ld::File*> Atom<A>::_s_fileOverride;
834
835 template <typename A>
836 void Atom<A>::setFile(const ld::File* f) {
837 _s_fileOverride[this] = f;
838 }
839
840 template <typename A>
841 const ld::File* Atom<A>::file() const
842 {
843 std::map<const ld::Atom*, const ld::File*>::iterator pos = _s_fileOverride.find(this);
844 if ( pos != _s_fileOverride.end() )
845 return pos->second;
846
847 return &sect().file();
848 }
849
850 template <typename A>
851 void Atom<A>::setFixupsRange(uint32_t startIndex, uint32_t count)
852 {
853 if ( count >= (1 << kFixupCountBits) )
854 throwf("too many fixups in function %s", this->name());
855 if ( startIndex >= (1 << kFixupStartIndexBits) )
856 throwf("too many fixups in file");
857 assert(((startIndex+count) <= sect().file()._fixups.size()) && "fixup index out of range");
858 _fixupsStartIndex = startIndex;
859 _fixupsCount = count;
860 }
861
862 template <typename A>
863 void Atom<A>::setUnwindInfoRange(uint32_t startIndex, uint32_t count)
864 {
865 if ( count >= (1 << kUnwindInfoCountBits) )
866 throwf("too many compact unwind infos in function %s", this->name());
867 if ( startIndex >= (1 << kUnwindInfoStartIndexBits) )
868 throwf("too many compact unwind infos (%d) in file", startIndex);
869 assert((startIndex+count) <= sect().file()._unwindInfos.size() && "unwindinfo index out of range");
870 _unwindInfoStartIndex = startIndex;
871 _unwindInfoCount = count;
872 }
873
874 template <typename A>
875 void Atom<A>::extendUnwindInfoRange()
876 {
877 if ( _unwindInfoCount+1 >= (1 << kUnwindInfoCountBits) )
878 throwf("too many compact unwind infos in function %s", this->name());
879 _unwindInfoCount += 1;
880 }
881
882 template <typename A>
883 void Atom<A>::setLineInfoRange(uint32_t startIndex, uint32_t count)
884 {
885 assert((count < (1 << kLineInfoCountBits)) && "too many line infos");
886 assert((startIndex+count) < sect().file()._lineInfos.size() && "line info index out of range");
887 _lineInfoStartIndex = startIndex;
888 _lineInfoCount = count;
889 }
890
891 template <typename A>
892 const uint8_t* Atom<A>::contentPointer() const
893 {
894 const macho_section<P>* sct = this->sect().machoSection();
895 if ( this->_objAddress > sct->addr() + sct->size() )
896 throwf("malformed .o file, symbol has address 0x%0llX which is outside range of its section", (uint64_t)this->_objAddress);
897 uint32_t fileOffset = sct->offset() - sct->addr() + this->_objAddress;
898 return this->sect().file().fileContent()+fileOffset;
899 }
900
901
902 template <typename A>
903 void Atom<A>::copyRawContent(uint8_t buffer[]) const
904 {
905 // copy base bytes
906 if ( this->contentType() == ld::Atom::typeZeroFill ) {
907 bzero(buffer, _size);
908 }
909 else if ( _size != 0 ) {
910 memcpy(buffer, this->contentPointer(), _size);
911 }
912 }
913
914 template <>
915 void Atom<arm>::verifyAlignment(const macho_section<P>&) const
916 {
917 if ( (this->section().type() == ld::Section::typeCode) && ! isThumb() ) {
918 if ( ((_objAddress % 4) != 0) || (this->alignment().powerOf2 < 2) )
919 warning("ARM function not 4-byte aligned: %s from %s", this->name(), this->file()->path());
920 }
921 }
922
923 #if SUPPORT_ARCH_arm64
924 template <>
925 void Atom<arm64>::verifyAlignment(const macho_section<P>& sect) const
926 {
927 if ( (this->section().type() == ld::Section::typeCode) && (sect.size() != 0) ) {
928 if ( ((_objAddress % 4) != 0) || (this->alignment().powerOf2 < 2) )
929 warning("arm64 function not 4-byte aligned: %s from %s", this->name(), this->file()->path());
930 }
931 }
932 #endif
933
934 template <typename A>
935 void Atom<A>::verifyAlignment(const macho_section<P>&) const
936 {
937 }
938
939
940 class AliasAtom : public ld::Atom
941 {
942 public:
943 AliasAtom(const char* name, bool hidden, const ld::File* file, const char* aliasOfName) :
944 ld::Atom(_s_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
945 (hidden ? ld::Atom::scopeLinkageUnit : ld::Atom::scopeGlobal),
946 ld::Atom::typeUnclassified, ld::Atom::symbolTableIn,
947 false, false, true, 0),
948 _file(file),
949 _name(name),
950 _fixup(0, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, ld::Fixup::bindingByNameUnbound, aliasOfName) { }
951
952 virtual const ld::File* file() const { return _file; }
953 virtual const char* translationUnitSource() const
954 { return NULL; }
955 virtual const char* name() const { return _name; }
956 virtual uint64_t size() const { return 0; }
957 virtual uint64_t objectAddress() const { return 0; }
958 virtual void copyRawContent(uint8_t buffer[]) const { }
959 virtual ld::Fixup::iterator fixupsBegin() const { return &((ld::Fixup*)&_fixup)[0]; }
960 virtual ld::Fixup::iterator fixupsEnd() const { return &((ld::Fixup*)&_fixup)[1]; }
961
962 private:
963 static ld::Section _s_section;
964
965 const ld::File* _file;
966 const char* _name;
967 ld::Fixup _fixup;
968 };
969
970 ld::Section AliasAtom::_s_section("__LD", "__aliases", ld::Section::typeTempAlias, true);
971
972
973 template <typename A>
974 class Parser
975 {
976 public:
977 static bool validFile(const uint8_t* fileContent, bool subtypeMustMatch=false,
978 cpu_subtype_t subtype=0);
979 static const char* fileKind(const uint8_t* fileContent);
980 static Options::Platform findPlatform(const macho_header<typename A::P>* header);
981 static bool hasObjC2Categories(const uint8_t* fileContent);
982 static bool hasObjC1Categories(const uint8_t* fileContent);
983 static bool getNonLocalSymbols(const uint8_t* fileContnet, std::vector<const char*> &syms);
984 static ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
985 const char* path, time_t modTime, ld::File::Ordinal ordinal,
986 const ParserOptions& opts) {
987 Parser p(fileContent, fileLength, path, modTime,
988 ordinal, opts.warnUnwindConversionProblems,
989 opts.keepDwarfUnwind, opts.forceDwarfConversion,
990 opts.neverConvertDwarf, opts.verboseOptimizationHints,
991 opts.ignoreMismatchPlatform);
992 return p.parse(opts);
993 }
994
995 typedef typename A::P P;
996 typedef typename A::P::E E;
997 typedef typename A::P::uint_t pint_t;
998
999 struct SourceLocation {
1000 SourceLocation() {}
1001 SourceLocation(Atom<A>* a, uint32_t o) : atom(a), offsetInAtom(o) {}
1002 Atom<A>* atom;
1003 uint32_t offsetInAtom;
1004 };
1005
1006 struct TargetDesc {
1007 Atom<A>* atom;
1008 const char* name; // only used if targetAtom is NULL
1009 int64_t addend;
1010 bool weakImport; // only used if targetAtom is NULL
1011 };
1012
1013 struct FixupInAtom {
1014 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, Atom<A>* target) :
1015 fixup(src.offsetInAtom, c, k, target), atom(src.atom) { src.atom->incrementFixupCount(); }
1016
1017 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::TargetBinding b, Atom<A>* target) :
1018 fixup(src.offsetInAtom, c, k, b, target), atom(src.atom) { src.atom->incrementFixupCount(); }
1019
1020 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, bool wi, const char* name) :
1021 fixup(src.offsetInAtom, c, k, wi, name), atom(src.atom) { src.atom->incrementFixupCount(); }
1022
1023 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::TargetBinding b, const char* name) :
1024 fixup(src.offsetInAtom, c, k, b, name), atom(src.atom) { src.atom->incrementFixupCount(); }
1025
1026 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, uint64_t addend) :
1027 fixup(src.offsetInAtom, c, k, addend), atom(src.atom) { src.atom->incrementFixupCount(); }
1028
1029 FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) :
1030 fixup(src.offsetInAtom, c, k, (uint64_t)0), atom(src.atom) { src.atom->incrementFixupCount(); }
1031
1032 ld::Fixup fixup;
1033 Atom<A>* atom;
1034 };
1035
1036 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, Atom<A>* target) {
1037 _allFixups.push_back(FixupInAtom(src, c, k, target));
1038 }
1039
1040 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::TargetBinding b, Atom<A>* target) {
1041 _allFixups.push_back(FixupInAtom(src, c, k, b, target));
1042 }
1043
1044 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, bool wi, const char* name) {
1045 _allFixups.push_back(FixupInAtom(src, c, k, wi, name));
1046 }
1047
1048 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::TargetBinding b, const char* name) {
1049 _allFixups.push_back(FixupInAtom(src, c, k, b, name));
1050 }
1051
1052 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, uint64_t addend) {
1053 _allFixups.push_back(FixupInAtom(src, c, k, addend));
1054 }
1055
1056 void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) {
1057 _allFixups.push_back(FixupInAtom(src, c, k));
1058 }
1059
1060 const char* path() { return _path; }
1061 uint32_t symbolCount() { return _symbolCount; }
1062 uint32_t indirectSymbol(uint32_t indirectIndex);
1063 const macho_nlist<P>& symbolFromIndex(uint32_t index);
1064 const char* nameFromSymbol(const macho_nlist<P>& sym);
1065 ld::Atom::Scope scopeFromSymbol(const macho_nlist<P>& sym);
1066 static ld::Atom::Definition definitionFromSymbol(const macho_nlist<P>& sym);
1067 static ld::Atom::Combine combineFromSymbol(const macho_nlist<P>& sym);
1068 ld::Atom::SymbolTableInclusion inclusionFromSymbol(const macho_nlist<P>& sym);
1069 static bool dontDeadStripFromSymbol(const macho_nlist<P>& sym);
1070 static bool isThumbFromSymbol(const macho_nlist<P>& sym);
1071 static bool weakImportFromSymbol(const macho_nlist<P>& sym);
1072 static bool resolverFromSymbol(const macho_nlist<P>& sym);
1073 static bool altEntryFromSymbol(const macho_nlist<P>& sym);
1074 uint32_t symbolIndexFromIndirectSectionAddress(pint_t,const macho_section<P>*);
1075 const macho_section<P>* firstMachOSection() { return _sectionsStart; }
1076 const macho_section<P>* machOSectionFromSectionIndex(uint32_t index);
1077 uint32_t machOSectionCount() { return _machOSectionsCount; }
1078 uint32_t undefinedStartIndex() { return _undefinedStartIndex; }
1079 uint32_t undefinedEndIndex() { return _undefinedEndIndex; }
1080 void addFixup(FixupInAtom f) { _allFixups.push_back(f); }
1081 Section<A>* sectionForNum(unsigned int sectNum);
1082 Section<A>* sectionForAddress(pint_t addr);
1083 Atom<A>* findAtomByAddress(pint_t addr);
1084 Atom<A>* findAtomByAddressOrNullIfStub(pint_t addr);
1085 Atom<A>* findAtomByAddressOrLocalTargetOfStub(pint_t addr, uint32_t* offsetInAtom);
1086 Atom<A>* findAtomByName(const char* name); // slow!
1087 void findTargetFromAddress(pint_t addr, TargetDesc& target);
1088 void findTargetFromAddress(pint_t baseAddr, pint_t addr, TargetDesc& target);
1089 void findTargetFromAddressAndSectionNum(pint_t addr, unsigned int sectNum,
1090 TargetDesc& target);
1091 uint32_t tentativeDefinitionCount() { return _tentativeDefinitionCount; }
1092 uint32_t absoluteSymbolCount() { return _absoluteSymbolCount; }
1093
1094 bool hasStubsSection() { return (_stubsSectionNum != 0); }
1095 unsigned int stubsSectionNum() { return _stubsSectionNum; }
1096 void addDtraceExtraInfos(const SourceLocation& src, const char* provider);
1097 const char* scanSymbolTableForAddress(uint64_t addr);
1098 bool warnUnwindConversionProblems() { return _warnUnwindConversionProblems; }
1099 bool hasDataInCodeLabels() { return _hasDataInCodeLabels; }
1100 bool keepDwarfUnwind() { return _keepDwarfUnwind; }
1101 bool forceDwarfConversion() { return _forceDwarfConversion; }
1102 bool verboseOptimizationHints() { return _verboseOptimizationHints; }
1103 bool neverConvertDwarf() { return _neverConvertDwarf; }
1104 bool armUsesZeroCostExceptions() { return _armUsesZeroCostExceptions; }
1105
1106 macho_data_in_code_entry<P>* dataInCodeStart() { return _dataInCodeStart; }
1107 macho_data_in_code_entry<P>* dataInCodeEnd() { return _dataInCodeEnd; }
1108 const uint8_t* optimizationHintsStart() { return _lohStart; }
1109 const uint8_t* optimizationHintsEnd() { return _lohEnd; }
1110 bool hasOptimizationHints() { return _lohStart != _lohEnd; }
1111
1112
1113 void addFixups(const SourceLocation& src, ld::Fixup::Kind kind, const TargetDesc& target);
1114 void addFixups(const SourceLocation& src, ld::Fixup::Kind kind, const TargetDesc& target, const TargetDesc& picBase);
1115
1116
1117
1118 struct LabelAndCFIBreakIterator {
1119 typedef typename CFISection<A>::CFI_Atom_Info CFI_Atom_Info;
1120 LabelAndCFIBreakIterator(const uint32_t* ssa, uint32_t ssc, const pint_t* cfisa,
1121 uint32_t cfisc, bool ols)
1122 : sortedSymbolIndexes(ssa), sortedSymbolCount(ssc), cfiStartsArray(cfisa),
1123 cfiStartsCount(cfisc), fileHasOverlappingSymbols(ols),
1124 newSection(false), cfiIndex(0), symIndex(0) {}
1125 bool next(Parser<A>& parser, const Section<A>& sect, uint32_t sectNum, pint_t startAddr, pint_t endAddr,
1126 pint_t* addr, pint_t* size, const macho_nlist<P>** sym);
1127 pint_t peek(Parser<A>& parser, pint_t startAddr, pint_t endAddr);
1128 void beginSection() { newSection = true; symIndex = 0; }
1129
1130 const uint32_t* const sortedSymbolIndexes;
1131 const uint32_t sortedSymbolCount;
1132 const pint_t* cfiStartsArray;
1133 const uint32_t cfiStartsCount;
1134 const bool fileHasOverlappingSymbols;
1135 bool newSection;
1136 uint32_t cfiIndex;
1137 uint32_t symIndex;
1138 };
1139
1140 struct CFI_CU_InfoArrays {
1141 typedef typename CFISection<A>::CFI_Atom_Info CFI_Atom_Info;
1142 typedef typename CUSection<A>::Info CU_Info;
1143 CFI_CU_InfoArrays(const CFI_Atom_Info* cfiAr, uint32_t cfiC, CU_Info* cuAr, uint32_t cuC)
1144 : cfiArray(cfiAr), cuArray(cuAr), cfiCount(cfiC), cuCount(cuC) {}
1145 const CFI_Atom_Info* const cfiArray;
1146 CU_Info* const cuArray;
1147 const uint32_t cfiCount;
1148 const uint32_t cuCount;
1149 };
1150
1151
1152
1153 private:
1154 friend class Section<A>;
1155
1156 enum SectionType { sectionTypeIgnore, sectionTypeLiteral4, sectionTypeLiteral8, sectionTypeLiteral16,
1157 sectionTypeNonLazy, sectionTypeCFI, sectionTypeCString, sectionTypeCStringPointer,
1158 sectionTypeUTF16Strings, sectionTypeCFString, sectionTypeObjC2ClassRefs, typeObjC2CategoryList,
1159 sectionTypeObjC1Classes, sectionTypeSymboled, sectionTypeObjC1ClassRefs,
1160 sectionTypeTentativeDefinitions, sectionTypeAbsoluteSymbols, sectionTypeTLVDefs,
1161 sectionTypeCompactUnwind, sectionTypeTLVPointers};
1162
1163 template <typename P>
1164 struct MachOSectionAndSectionClass
1165 {
1166 const macho_section<P>* sect;
1167 SectionType type;
1168
1169 static int sorter(const void* l, const void* r) {
1170 const MachOSectionAndSectionClass<P>* left = (MachOSectionAndSectionClass<P>*)l;
1171 const MachOSectionAndSectionClass<P>* right = (MachOSectionAndSectionClass<P>*)r;
1172 int64_t diff = left->sect->addr() - right->sect->addr();
1173 if ( diff == 0 )
1174 return 0;
1175 if ( diff < 0 )
1176 return -1;
1177 else
1178 return 1;
1179 }
1180 };
1181
1182 struct ParserAndSectionsArray { Parser* parser; const uint32_t* sortedSectionsArray; };
1183
1184
1185 Parser(const uint8_t* fileContent, uint64_t fileLength,
1186 const char* path, time_t modTime, ld::File::Ordinal ordinal,
1187 bool warnUnwindConversionProblems, bool keepDwarfUnwind,
1188 bool forceDwarfConversion, bool neverConvertDwarf,
1189 bool verboseOptimizationHints, bool ignoreMismatchPlatform);
1190 ld::relocatable::File* parse(const ParserOptions& opts);
1191 static uint8_t loadCommandSizeMask();
1192 bool parseLoadCommands(Options::Platform platform, uint32_t minOSVersion, bool simulator, bool ignoreMismatchPlatform);
1193 void makeSections();
1194 void prescanSymbolTable();
1195 void makeSortedSymbolsArray(uint32_t symArray[], const uint32_t sectionArray[]);
1196 void makeSortedSectionsArray(uint32_t array[]);
1197 static int pointerSorter(const void* l, const void* r);
1198 static int symbolIndexSorter(void* extra, const void* l, const void* r);
1199 static int sectionIndexSorter(void* extra, const void* l, const void* r);
1200
1201 void parseDebugInfo();
1202 void parseStabs();
1203 void appendAliasAtoms(uint8_t* atomBuffer);
1204 static bool isConstFunStabs(const char *stabStr);
1205 bool read_comp_unit(const char ** name, const char ** comp_dir,
1206 uint64_t *stmt_list);
1207 pint_t realAddr(pint_t addr);
1208 const char* getDwarfString(uint64_t form, const uint8_t*& p);
1209 uint64_t getDwarfOffset(uint64_t form, const uint8_t*& di, bool dwarf64);
1210 bool skip_form(const uint8_t ** offset, const uint8_t * end,
1211 uint64_t form, uint8_t addr_size, bool dwarf64);
1212
1213
1214 // filled in by constructor
1215 const uint8_t* _fileContent;
1216 uint32_t _fileLength;
1217 const char* _path;
1218 time_t _modTime;
1219 ld::File::Ordinal _ordinal;
1220
1221 // filled in by parseLoadCommands()
1222 File<A>* _file;
1223 const macho_nlist<P>* _symbols;
1224 uint32_t _symbolCount;
1225 uint32_t _indirectSymbolCount;
1226 const char* _strings;
1227 uint32_t _stringsSize;
1228 const uint32_t* _indirectTable;
1229 uint32_t _indirectTableCount;
1230 uint32_t _undefinedStartIndex;
1231 uint32_t _undefinedEndIndex;
1232 const macho_section<P>* _sectionsStart;
1233 uint32_t _machOSectionsCount;
1234 bool _hasUUID;
1235 macho_data_in_code_entry<P>* _dataInCodeStart;
1236 macho_data_in_code_entry<P>* _dataInCodeEnd;
1237 const uint8_t* _lohStart;
1238 const uint8_t* _lohEnd;
1239
1240 // filled in by parse()
1241 CFISection<A>* _EHFrameSection;
1242 CUSection<A>* _compactUnwindSection;
1243 AbsoluteSymbolSection<A>* _absoluteSection;
1244 uint32_t _tentativeDefinitionCount;
1245 uint32_t _absoluteSymbolCount;
1246 uint32_t _symbolsInSections;
1247 bool _hasLongBranchStubs;
1248 bool _AppleObjc; // FSF has objc that uses different data layout
1249 bool _overlappingSymbols;
1250 bool _warnUnwindConversionProblems;
1251 bool _hasDataInCodeLabels;
1252 bool _keepDwarfUnwind;
1253 bool _forceDwarfConversion;
1254 bool _neverConvertDwarf;
1255 bool _verboseOptimizationHints;
1256 bool _armUsesZeroCostExceptions;
1257 bool _ignoreMismatchPlatform;
1258 unsigned int _stubsSectionNum;
1259 const macho_section<P>* _stubsMachOSection;
1260 std::vector<const char*> _dtraceProviderInfo;
1261 std::vector<FixupInAtom> _allFixups;
1262 };
1263
1264
1265
1266 template <typename A>
1267 Parser<A>::Parser(const uint8_t* fileContent, uint64_t fileLength, const char* path, time_t modTime,
1268 ld::File::Ordinal ordinal, bool convertDUI, bool keepDwarfUnwind, bool forceDwarfConversion,
1269 bool neverConvertDwarf, bool verboseOptimizationHints, bool ignoreMismatchPlatform)
1270 : _fileContent(fileContent), _fileLength(fileLength), _path(path), _modTime(modTime),
1271 _ordinal(ordinal), _file(NULL),
1272 _symbols(NULL), _symbolCount(0), _indirectSymbolCount(0), _strings(NULL), _stringsSize(0),
1273 _indirectTable(NULL), _indirectTableCount(0),
1274 _undefinedStartIndex(0), _undefinedEndIndex(0),
1275 _sectionsStart(NULL), _machOSectionsCount(0), _hasUUID(false),
1276 _dataInCodeStart(NULL), _dataInCodeEnd(NULL),
1277 _lohStart(NULL), _lohEnd(NULL),
1278 _EHFrameSection(NULL), _compactUnwindSection(NULL), _absoluteSection(NULL),
1279 _tentativeDefinitionCount(0), _absoluteSymbolCount(0),
1280 _symbolsInSections(0), _hasLongBranchStubs(false), _AppleObjc(false),
1281 _overlappingSymbols(false), _warnUnwindConversionProblems(convertDUI), _hasDataInCodeLabels(false),
1282 _keepDwarfUnwind(keepDwarfUnwind), _forceDwarfConversion(forceDwarfConversion),
1283 _neverConvertDwarf(neverConvertDwarf),
1284 _verboseOptimizationHints(verboseOptimizationHints),
1285 _ignoreMismatchPlatform(ignoreMismatchPlatform),
1286 _stubsSectionNum(0), _stubsMachOSection(NULL)
1287 {
1288 }
1289
1290
1291 template <>
1292 bool Parser<x86>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1293 {
1294 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1295 if ( header->magic() != MH_MAGIC )
1296 return false;
1297 if ( header->cputype() != CPU_TYPE_I386 )
1298 return false;
1299 if ( header->filetype() != MH_OBJECT )
1300 return false;
1301 return true;
1302 }
1303
1304 template <>
1305 bool Parser<x86_64>::validFile(const uint8_t* fileContent, bool, cpu_subtype_t)
1306 {
1307 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1308 if ( header->magic() != MH_MAGIC_64 )
1309 return false;
1310 if ( header->cputype() != CPU_TYPE_X86_64 )
1311 return false;
1312 if ( header->filetype() != MH_OBJECT )
1313 return false;
1314 return true;
1315 }
1316
1317 template <>
1318 bool Parser<arm>::validFile(const uint8_t* fileContent, bool subtypeMustMatch, cpu_subtype_t subtype)
1319 {
1320 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1321 if ( header->magic() != MH_MAGIC )
1322 return false;
1323 if ( header->cputype() != CPU_TYPE_ARM )
1324 return false;
1325 if ( header->filetype() != MH_OBJECT )
1326 return false;
1327 if ( subtypeMustMatch ) {
1328 if ( (cpu_subtype_t)header->cpusubtype() == subtype )
1329 return true;
1330 // hack until libcc_kext.a is made fat
1331 if ( header->cpusubtype() == CPU_SUBTYPE_ARM_ALL )
1332 return true;
1333 return false;
1334 }
1335 return true;
1336 }
1337
1338
1339 template <>
1340 bool Parser<arm64>::validFile(const uint8_t* fileContent, bool subtypeMustMatch, cpu_subtype_t subtype)
1341 {
1342 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1343 if ( header->magic() != MH_MAGIC_64 )
1344 return false;
1345 if ( header->cputype() != CPU_TYPE_ARM64 )
1346 return false;
1347 if ( header->filetype() != MH_OBJECT )
1348 return false;
1349 return true;
1350 }
1351
1352
1353 template <>
1354 const char* Parser<x86>::fileKind(const uint8_t* fileContent)
1355 {
1356 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1357 if ( header->magic() != MH_MAGIC )
1358 return NULL;
1359 if ( header->cputype() != CPU_TYPE_I386 )
1360 return NULL;
1361 return "i386";
1362 }
1363
1364 template <>
1365 const char* Parser<x86_64>::fileKind(const uint8_t* fileContent)
1366 {
1367 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1368 if ( header->magic() != MH_MAGIC_64 )
1369 return NULL;
1370 if ( header->cputype() != CPU_TYPE_X86_64 )
1371 return NULL;
1372 return "x86_64";
1373 }
1374
1375 template <>
1376 const char* Parser<arm>::fileKind(const uint8_t* fileContent)
1377 {
1378 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1379 if ( header->magic() != MH_MAGIC )
1380 return NULL;
1381 if ( header->cputype() != CPU_TYPE_ARM )
1382 return NULL;
1383 for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
1384 if ( (t->cpuType == CPU_TYPE_ARM) && ((cpu_subtype_t)header->cpusubtype() == t->cpuSubType) ) {
1385 return t->archName;
1386 }
1387 }
1388 return "arm???";
1389 }
1390
1391 #if SUPPORT_ARCH_arm64
1392 template <>
1393 const char* Parser<arm64>::fileKind(const uint8_t* fileContent)
1394 {
1395 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1396 if ( header->magic() != MH_MAGIC_64 )
1397 return NULL;
1398 if ( header->cputype() != CPU_TYPE_ARM64 )
1399 return NULL;
1400 return "arm64";
1401 }
1402 #endif
1403
1404 template <typename A>
1405 bool Parser<A>::hasObjC2Categories(const uint8_t* fileContent)
1406 {
1407 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1408 const uint32_t cmd_count = header->ncmds();
1409 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
1410 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
1411 const macho_load_command<P>* cmd = cmds;
1412 for (uint32_t i = 0; i < cmd_count; ++i) {
1413 if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
1414 const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
1415 const macho_section<P>* sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
1416 for (uint32_t si=0; si < segment->nsects(); ++si) {
1417 const macho_section<P>* sect = &sectionsStart[si];
1418 if ( (sect->size() > 0)
1419 && (strcmp(sect->sectname(), "__objc_catlist") == 0)
1420 && (strcmp(sect->segname(), "__DATA") == 0) ) {
1421 return true;
1422 }
1423 }
1424 }
1425 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
1426 if ( cmd > cmdsEnd )
1427 throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
1428 }
1429 return false;
1430 }
1431
1432
1433 template <typename A>
1434 bool Parser<A>::hasObjC1Categories(const uint8_t* fileContent)
1435 {
1436 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1437 const uint32_t cmd_count = header->ncmds();
1438 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
1439 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
1440 const macho_load_command<P>* cmd = cmds;
1441 for (uint32_t i = 0; i < cmd_count; ++i) {
1442 if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
1443 const macho_segment_command<P>* segment = (macho_segment_command<P>*)cmd;
1444 const macho_section<P>* sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
1445 for (uint32_t si=0; si < segment->nsects(); ++si) {
1446 const macho_section<P>* sect = &sectionsStart[si];
1447 if ( (sect->size() > 0)
1448 && (strcmp(sect->sectname(), "__category") == 0)
1449 && (strcmp(sect->segname(), "__OBJC") == 0) ) {
1450 return true;
1451 }
1452 }
1453 }
1454 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
1455 if ( cmd > cmdsEnd )
1456 throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
1457 }
1458 return false;
1459 }
1460
1461
1462 template <typename A>
1463 bool Parser<A>::getNonLocalSymbols(const uint8_t* fileContent, std::vector<const char*> &syms)
1464 {
1465 const macho_header<P>* header = (const macho_header<P>*)fileContent;
1466 const uint32_t cmd_count = header->ncmds();
1467 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
1468 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
1469 const macho_load_command<P>* cmd = cmds;
1470 for (uint32_t i = 0; i < cmd_count; ++i) {
1471 if ( cmd->cmd() == LC_SYMTAB ) {
1472 const macho_symtab_command<P>* symtab = (macho_symtab_command<P>*)cmd;
1473 uint32_t symbolCount = symtab->nsyms();
1474 const macho_nlist<P>* symbols = (const macho_nlist<P>*)(fileContent + symtab->symoff());
1475 const char* strings = (char*)fileContent + symtab->stroff();
1476 for (uint32_t i = 0; i < symbolCount; ++i) {
1477 // ignore stabs and count only ext symbols
1478 if ( (symbols[i].n_type() & N_STAB) == 0 &&
1479 (symbols[i].n_type() & N_EXT) != 0 ) {
1480 const char* symName = &strings[symbols[i].n_strx()];
1481 syms.push_back(symName);
1482 }
1483 }
1484 return true;
1485 }
1486 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
1487 if ( cmd > cmdsEnd )
1488 throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
1489 }
1490 return false;
1491 }
1492
1493
1494 template <typename A>
1495 int Parser<A>::pointerSorter(const void* l, const void* r)
1496 {
1497 // sort references by address
1498 const pint_t* left = (pint_t*)l;
1499 const pint_t* right = (pint_t*)r;
1500 return (*left - *right);
1501 }
1502
1503 template <typename A>
1504 typename A::P::uint_t Parser<A>::LabelAndCFIBreakIterator::peek(Parser<A>& parser, pint_t startAddr, pint_t endAddr)
1505 {
1506 pint_t symbolAddr;
1507 if ( symIndex < sortedSymbolCount )
1508 symbolAddr = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]).n_value();
1509 else
1510 symbolAddr = endAddr;
1511 pint_t cfiAddr;
1512 if ( cfiIndex < cfiStartsCount )
1513 cfiAddr = cfiStartsArray[cfiIndex];
1514 else
1515 cfiAddr = endAddr;
1516 if ( (cfiAddr < symbolAddr) && (cfiAddr >= startAddr) ) {
1517 if ( cfiAddr < endAddr )
1518 return cfiAddr;
1519 else
1520 return endAddr;
1521 }
1522 else {
1523 if ( symbolAddr < endAddr )
1524 return symbolAddr;
1525 else
1526 return endAddr;
1527 }
1528 }
1529
1530 //
1531 // Parses up a section into chunks based on labels and CFI information.
1532 // Each call returns the next chunk address and size, and (if the break
1533 // was becuase of a label, the symbol). Returns false when no more chunks.
1534 //
1535 template <typename A>
1536 bool Parser<A>::LabelAndCFIBreakIterator::next(Parser<A>& parser, const Section<A>& sect, uint32_t sectNum, pint_t startAddr, pint_t endAddr,
1537 pint_t* addr, pint_t* size, const macho_nlist<P>** symbol)
1538 {
1539 // may not be a label on start of section, but need atom demarcation there
1540 if ( newSection ) {
1541 newSection = false;
1542 // advance symIndex until we get to the first label at or past the start of this section
1543 while ( symIndex < sortedSymbolCount ) {
1544 const macho_nlist<P>& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
1545 if ( ! sect.ignoreLabel(parser.nameFromSymbol(sym)) ) {
1546 pint_t nextSymbolAddr = sym.n_value();
1547 //fprintf(stderr, "sectNum=%d, nextSymbolAddr=0x%08llX, name=%s\n", sectNum, (uint64_t)nextSymbolAddr, parser.nameFromSymbol(sym));
1548 if ( (nextSymbolAddr > startAddr) || ((nextSymbolAddr == startAddr) && (sym.n_sect() == sectNum)) )
1549 break;
1550 }
1551 ++symIndex;
1552 }
1553 if ( symIndex < sortedSymbolCount ) {
1554 const macho_nlist<P>& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
1555 pint_t nextSymbolAddr = sym.n_value();
1556 // if next symbol found is not in this section
1557 if ( sym.n_sect() != sectNum ) {
1558 // check for CFI break instead of symbol break
1559 if ( cfiIndex < cfiStartsCount ) {
1560 pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
1561 if ( nextCfiAddr < endAddr ) {
1562 // use cfi
1563 ++cfiIndex;
1564 *addr = nextCfiAddr;
1565 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1566 *symbol = NULL;
1567 return true;
1568 }
1569 }
1570 *addr = startAddr;
1571 *size = endAddr - startAddr;
1572 *symbol = NULL;
1573 if ( startAddr == endAddr )
1574 return false; // zero size section
1575 else
1576 return true; // whole section is one atom with no label
1577 }
1578 // if also CFI break here, eat it
1579 if ( cfiIndex < cfiStartsCount ) {
1580 if ( cfiStartsArray[cfiIndex] == nextSymbolAddr )
1581 ++cfiIndex;
1582 }
1583 if ( nextSymbolAddr == startAddr ) {
1584 // label at start of section, return it as chunk
1585 ++symIndex;
1586 *addr = startAddr;
1587 *size = peek(parser, startAddr, endAddr) - startAddr;
1588 *symbol = &sym;
1589 return true;
1590 }
1591 // return chunk before first symbol
1592 *addr = startAddr;
1593 *size = nextSymbolAddr - startAddr;
1594 *symbol = NULL;
1595 return true;
1596 }
1597 // no symbols in section, check CFI
1598 if ( cfiIndex < cfiStartsCount ) {
1599 pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
1600 if ( nextCfiAddr < endAddr ) {
1601 // use cfi
1602 ++cfiIndex;
1603 *addr = nextCfiAddr;
1604 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1605 *symbol = NULL;
1606 return true;
1607 }
1608 }
1609 // no cfi, so whole section is one chunk
1610 *addr = startAddr;
1611 *size = endAddr - startAddr;
1612 *symbol = NULL;
1613 if ( startAddr == endAddr )
1614 return false; // zero size section
1615 else
1616 return true; // whole section is one atom with no label
1617 }
1618
1619 while ( (symIndex < sortedSymbolCount) && (cfiIndex < cfiStartsCount) ) {
1620 const macho_nlist<P>& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
1621 pint_t nextSymbolAddr = sym.n_value();
1622 pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
1623 if ( nextSymbolAddr < nextCfiAddr ) {
1624 if ( nextSymbolAddr >= endAddr )
1625 return false;
1626 ++symIndex;
1627 if ( nextSymbolAddr < startAddr )
1628 continue;
1629 *addr = nextSymbolAddr;
1630 *size = peek(parser, startAddr, endAddr) - nextSymbolAddr;
1631 *symbol = &sym;
1632 return true;
1633 }
1634 else if ( nextCfiAddr < nextSymbolAddr ) {
1635 if ( nextCfiAddr >= endAddr )
1636 return false;
1637 ++cfiIndex;
1638 if ( nextCfiAddr < startAddr )
1639 continue;
1640 *addr = nextCfiAddr;
1641 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1642 *symbol = NULL;
1643 return true;
1644 }
1645 else {
1646 if ( nextCfiAddr >= endAddr )
1647 return false;
1648 ++symIndex;
1649 ++cfiIndex;
1650 if ( nextCfiAddr < startAddr )
1651 continue;
1652 *addr = nextCfiAddr;
1653 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1654 *symbol = &sym;
1655 return true;
1656 }
1657 }
1658 while ( symIndex < sortedSymbolCount ) {
1659 const macho_nlist<P>& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
1660 pint_t nextSymbolAddr = sym.n_value();
1661 // if next symbol found is not in this section, then done with iteration
1662 if ( sym.n_sect() != sectNum )
1663 return false;
1664 ++symIndex;
1665 if ( nextSymbolAddr < startAddr )
1666 continue;
1667 *addr = nextSymbolAddr;
1668 *size = peek(parser, startAddr, endAddr) - nextSymbolAddr;
1669 *symbol = &sym;
1670 return true;
1671 }
1672 while ( cfiIndex < cfiStartsCount ) {
1673 pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
1674 if ( nextCfiAddr >= endAddr )
1675 return false;
1676 ++cfiIndex;
1677 if ( nextCfiAddr < startAddr )
1678 continue;
1679 *addr = nextCfiAddr;
1680 *size = peek(parser, startAddr, endAddr) - nextCfiAddr;
1681 *symbol = NULL;
1682 return true;
1683 }
1684 return false;
1685 }
1686
1687 template <>
1688 typename arm::P::uint_t Parser<arm>::realAddr(typename arm::P::uint_t addr)
1689 {
1690 return addr & (-2);
1691 }
1692
1693 template <typename A>
1694 typename A::P::uint_t Parser<A>::realAddr(typename A::P::uint_t addr)
1695 {
1696 return addr;
1697 }
1698
1699 #define STACK_ALLOC_IF_SMALL(_type, _name, _actual_count, _maxCount) \
1700 _type* _name = NULL; \
1701 uint32_t _name##_count = 1; \
1702 if ( _actual_count > _maxCount ) \
1703 _name = (_type*)malloc(sizeof(_type) * _actual_count); \
1704 else \
1705 _name##_count = _actual_count; \
1706 _type _name##_buffer[_name##_count]; \
1707 if ( _name == NULL ) \
1708 _name = _name##_buffer;
1709
1710
1711 template <typename A>
1712 ld::relocatable::File* Parser<A>::parse(const ParserOptions& opts)
1713 {
1714 // create file object
1715 _file = new File<A>(_path, _modTime, _fileContent, _ordinal);
1716
1717 // set input source
1718 _file->setSourceKind(opts.srcKind);
1719
1720 // respond to -t option
1721 if ( opts.logAllFiles )
1722 printf("%s\n", _path);
1723
1724 _armUsesZeroCostExceptions = opts.armUsesZeroCostExceptions;
1725
1726 // parse start of mach-o file
1727 if ( ! parseLoadCommands(opts.platform, opts.minOSVersion, opts.simulator, opts.ignoreMismatchPlatform) )
1728 return _file;
1729
1730 // make array of
1731 uint32_t sortedSectionIndexes[_machOSectionsCount];
1732 this->makeSortedSectionsArray(sortedSectionIndexes);
1733
1734 // make symbol table sorted by address
1735 this->prescanSymbolTable();
1736 uint32_t sortedSymbolIndexes[_symbolsInSections];
1737 this->makeSortedSymbolsArray(sortedSymbolIndexes, sortedSectionIndexes);
1738
1739 // allocate Section<A> object for each mach-o section
1740 makeSections();
1741
1742 // if it exists, do special early parsing of __compact_unwind section
1743 uint32_t countOfCUs = 0;
1744 if ( _compactUnwindSection != NULL )
1745 countOfCUs = _compactUnwindSection->count();
1746 // stack allocate (if not too large) cuInfoBuffer
1747 STACK_ALLOC_IF_SMALL(typename CUSection<A>::Info, cuInfoArray, countOfCUs, 1024);
1748 if ( countOfCUs != 0 )
1749 _compactUnwindSection->parse(*this, countOfCUs, cuInfoArray);
1750
1751 // create lists of address that already have compact unwind and thus don't need the dwarf parsed
1752 unsigned cuLsdaCount = 0;
1753 pint_t cuStarts[countOfCUs];
1754 for (uint32_t i=0; i < countOfCUs; ++i) {
1755 if ( CUSection<A>::encodingMeansUseDwarf(cuInfoArray[i].compactUnwindInfo) )
1756 cuStarts[i] = -1;
1757 else
1758 cuStarts[i] = cuInfoArray[i].functionStartAddress;
1759 if ( cuInfoArray[i].lsdaAddress != 0 )
1760 ++cuLsdaCount;
1761 }
1762
1763
1764 // if it exists, do special early parsing of __eh_frame section
1765 // stack allocate (if not too large) array of CFI_Atom_Info
1766 uint32_t countOfCFIs = 0;
1767 if ( _EHFrameSection != NULL )
1768 countOfCFIs = _EHFrameSection->cfiCount(*this);
1769 STACK_ALLOC_IF_SMALL(typename CFISection<A>::CFI_Atom_Info, cfiArray, countOfCFIs, 1024);
1770
1771 // stack allocate (if not too large) a copy of __eh_frame to apply relocations to
1772 uint32_t sectSize = 4;
1773 if ( (countOfCFIs != 0) && _EHFrameSection->needsRelocating() )
1774 sectSize = _EHFrameSection->machoSection()->size()+4;
1775 STACK_ALLOC_IF_SMALL(uint8_t, ehBuffer, sectSize, 50*1024);
1776 uint32_t cfiStartsCount = 0;
1777 if ( countOfCFIs != 0 ) {
1778 _EHFrameSection->cfiParse(*this, ehBuffer, cfiArray, countOfCFIs, cuStarts, countOfCUs);
1779 // count functions and lsdas
1780 for(uint32_t i=0; i < countOfCFIs; ++i) {
1781 if ( cfiArray[i].isCIE )
1782 continue;
1783 //fprintf(stderr, "cfiArray[i].func = 0x%08llX, cfiArray[i].lsda = 0x%08llX, encoding=0x%08X\n",
1784 // (uint64_t)cfiArray[i].u.fdeInfo.function.targetAddress,
1785 // (uint64_t)cfiArray[i].u.fdeInfo.lsda.targetAddress,
1786 // cfiArray[i].u.fdeInfo.compactUnwindInfo);
1787 if ( cfiArray[i].u.fdeInfo.function.targetAddress != CFI_INVALID_ADDRESS )
1788 ++cfiStartsCount;
1789 if ( cfiArray[i].u.fdeInfo.lsda.targetAddress != CFI_INVALID_ADDRESS )
1790 ++cfiStartsCount;
1791 }
1792 }
1793 CFI_CU_InfoArrays cfis(cfiArray, countOfCFIs, cuInfoArray, countOfCUs);
1794
1795 // create sorted array of function starts and lsda starts
1796 pint_t cfiStartsArray[cfiStartsCount+cuLsdaCount];
1797 uint32_t countOfFDEs = 0;
1798 uint32_t cfiStartsArrayCount = 0;
1799 if ( countOfCFIs != 0 ) {
1800 for(uint32_t i=0; i < countOfCFIs; ++i) {
1801 if ( cfiArray[i].isCIE )
1802 continue;
1803 if ( cfiArray[i].u.fdeInfo.function.targetAddress != CFI_INVALID_ADDRESS )
1804 cfiStartsArray[cfiStartsArrayCount++] = realAddr(cfiArray[i].u.fdeInfo.function.targetAddress);
1805 if ( cfiArray[i].u.fdeInfo.lsda.targetAddress != CFI_INVALID_ADDRESS )
1806 cfiStartsArray[cfiStartsArrayCount++] = cfiArray[i].u.fdeInfo.lsda.targetAddress;
1807 ++countOfFDEs;
1808 }
1809 }
1810 if ( cuLsdaCount != 0 ) {
1811 // merge in an lsda info from compact unwind
1812 for (uint32_t i=0; i < countOfCUs; ++i) {
1813 if ( cuInfoArray[i].lsdaAddress == 0 )
1814 continue;
1815 // append to cfiStartsArray if not already in that list
1816 bool found = false;
1817 for(uint32_t j=0; j < cfiStartsArrayCount; ++j) {
1818 if ( cfiStartsArray[j] == cuInfoArray[i].lsdaAddress )
1819 found = true;
1820 }
1821 if ( ! found ) {
1822 cfiStartsArray[cfiStartsArrayCount++] = cuInfoArray[i].lsdaAddress;
1823 }
1824 }
1825 }
1826 if ( cfiStartsArrayCount != 0 ) {
1827 ::qsort(cfiStartsArray, cfiStartsArrayCount, sizeof(pint_t), pointerSorter);
1828 #ifndef NDEBUG
1829 // scan for FDEs claming the same function
1830 for(uint32_t i=1; i < cfiStartsArrayCount; ++i) {
1831 assert( cfiStartsArray[i] != cfiStartsArray[i-1] );
1832 }
1833 #endif
1834 }
1835
1836 Section<A>** sections = _file->_sectionsArray;
1837 uint32_t sectionsCount = _file->_sectionsArrayCount;
1838
1839 // figure out how many atoms will be allocated and allocate
1840 LabelAndCFIBreakIterator breakIterator(sortedSymbolIndexes, _symbolsInSections, cfiStartsArray,
1841 cfiStartsArrayCount, _overlappingSymbols);
1842 uint32_t computedAtomCount = 0;
1843 for (uint32_t i=0; i < sectionsCount; ++i ) {
1844 breakIterator.beginSection();
1845 uint32_t count = sections[i]->computeAtomCount(*this, breakIterator, cfis);
1846 //const macho_section<P>* sect = sections[i]->machoSection();
1847 //fprintf(stderr, "computed count=%u for section %s size=%llu\n", count, sect->sectname(), (sect != NULL) ? sect->size() : 0);
1848 computedAtomCount += count;
1849 }
1850 //fprintf(stderr, "allocating %d atoms * sizeof(Atom<A>)=%ld, sizeof(ld::Atom)=%ld\n", computedAtomCount, sizeof(Atom<A>), sizeof(ld::Atom));
1851 _file->_atomsArray = new uint8_t[computedAtomCount*sizeof(Atom<A>)];
1852 _file->_atomsArrayCount = 0;
1853
1854 // have each section append atoms to _atomsArray
1855 LabelAndCFIBreakIterator breakIterator2(sortedSymbolIndexes, _symbolsInSections, cfiStartsArray,
1856 cfiStartsArrayCount, _overlappingSymbols);
1857 for (uint32_t i=0; i < sectionsCount; ++i ) {
1858 uint8_t* atoms = _file->_atomsArray + _file->_atomsArrayCount*sizeof(Atom<A>);
1859 breakIterator2.beginSection();
1860 uint32_t count = sections[i]->appendAtoms(*this, atoms, breakIterator2, cfis);
1861 //fprintf(stderr, "append count=%u for section %s/%s\n", count, sections[i]->machoSection()->segname(), sections[i]->machoSection()->sectname());
1862 _file->_atomsArrayCount += count;
1863 }
1864 assert( _file->_atomsArrayCount == computedAtomCount && "more atoms allocated than expected");
1865
1866
1867 // have each section add all fix-ups for its atoms
1868 _allFixups.reserve(computedAtomCount*5);
1869 for (uint32_t i=0; i < sectionsCount; ++i )
1870 sections[i]->makeFixups(*this, cfis);
1871
1872 // assign fixups start offset for each atom
1873 uint8_t* p = _file->_atomsArray;
1874 uint32_t fixupOffset = 0;
1875 for(int i=_file->_atomsArrayCount; i > 0; --i) {
1876 Atom<A>* atom = (Atom<A>*)p;
1877 atom->_fixupsStartIndex = fixupOffset;
1878 fixupOffset += atom->_fixupsCount;
1879 atom->_fixupsCount = 0;
1880 p += sizeof(Atom<A>);
1881 }
1882 assert(fixupOffset == _allFixups.size());
1883 _file->_fixups.resize(fixupOffset);
1884
1885 // copy each fixup for each atom
1886 for(typename std::vector<FixupInAtom>::iterator it=_allFixups.begin(); it != _allFixups.end(); ++it) {
1887 uint32_t slot = it->atom->_fixupsStartIndex + it->atom->_fixupsCount;
1888 _file->_fixups[slot] = it->fixup;
1889 it->atom->_fixupsCount++;
1890 }
1891
1892 // done with temp vector
1893 _allFixups.clear();
1894
1895 // add unwind info
1896 _file->_unwindInfos.reserve(countOfFDEs+countOfCUs);
1897 for(uint32_t i=0; i < countOfCFIs; ++i) {
1898 if ( cfiArray[i].isCIE )
1899 continue;
1900 if ( cfiArray[i].u.fdeInfo.function.targetAddress != CFI_INVALID_ADDRESS ) {
1901 ld::Atom::UnwindInfo info;
1902 info.startOffset = 0;
1903 info.unwindInfo = cfiArray[i].u.fdeInfo.compactUnwindInfo;
1904 _file->_unwindInfos.push_back(info);
1905 Atom<A>* func = findAtomByAddress(cfiArray[i].u.fdeInfo.function.targetAddress);
1906 func->setUnwindInfoRange(_file->_unwindInfos.size()-1, 1);
1907 //fprintf(stderr, "cu from dwarf =0x%08X, atom=%s\n", info.unwindInfo, func->name());
1908 }
1909 }
1910 // apply compact infos in __LD,__compact_unwind section to each function
1911 // if function also has dwarf unwind, CU will override it
1912 Atom<A>* lastFunc = NULL;
1913 uint32_t lastEnd = 0;
1914 for(uint32_t i=0; i < countOfCUs; ++i) {
1915 typename CUSection<A>::Info* info = &cuInfoArray[i];
1916 assert(info->function != NULL);
1917 ld::Atom::UnwindInfo ui;
1918 ui.startOffset = info->functionStartAddress - info->function->objectAddress();
1919 ui.unwindInfo = info->compactUnwindInfo;
1920 _file->_unwindInfos.push_back(ui);
1921 // don't override with converted cu with "use dwarf" cu, if forcing dwarf conversion
1922 if ( !_forceDwarfConversion || !CUSection<A>::encodingMeansUseDwarf(info->compactUnwindInfo) ) {
1923 //fprintf(stderr, "cu=0x%08X, atom=%s\n", ui.unwindInfo, info->function->name());
1924 // if previous is for same function, extend range
1925 if ( info->function == lastFunc ) {
1926 if ( lastEnd != ui.startOffset ) {
1927 if ( lastEnd < ui.startOffset )
1928 warning("__LD,__compact_unwind entries for %s have a gap at offset 0x%0X", info->function->name(), lastEnd);
1929 else
1930 warning("__LD,__compact_unwind entries for %s overlap at offset 0x%0X", info->function->name(), lastEnd);
1931 }
1932 lastFunc->extendUnwindInfoRange();
1933 }
1934 else
1935 info->function->setUnwindInfoRange(_file->_unwindInfos.size()-1, 1);
1936 lastFunc = info->function;
1937 lastEnd = ui.startOffset + info->rangeLength;
1938 }
1939 }
1940
1941 // process indirect symbols which become AliasAtoms
1942 _file->_aliasAtomsArray = NULL;
1943 _file->_aliasAtomsArrayCount = 0;
1944 if ( _indirectSymbolCount != 0 ) {
1945 _file->_aliasAtomsArrayCount = _indirectSymbolCount;
1946 _file->_aliasAtomsArray = new uint8_t[_file->_aliasAtomsArrayCount*sizeof(AliasAtom)];
1947 this->appendAliasAtoms(_file->_aliasAtomsArray);
1948 }
1949
1950
1951 // parse dwarf debug info to get line info
1952 this->parseDebugInfo();
1953
1954 return _file;
1955 }
1956
1957 static void versionToString(uint32_t value, char buffer[32])
1958 {
1959 if ( value & 0xFF )
1960 sprintf(buffer, "%d.%d.%d", value >> 16, (value >> 8) & 0xFF, value & 0xFF);
1961 else
1962 sprintf(buffer, "%d.%d", value >> 16, (value >> 8) & 0xFF);
1963 }
1964
1965 template <> uint8_t Parser<x86>::loadCommandSizeMask() { return 0x03; }
1966 template <> uint8_t Parser<x86_64>::loadCommandSizeMask() { return 0x07; }
1967 template <> uint8_t Parser<arm>::loadCommandSizeMask() { return 0x03; }
1968 template <> uint8_t Parser<arm64>::loadCommandSizeMask() { return 0x07; }
1969
1970 template <typename A>
1971 bool Parser<A>::parseLoadCommands(Options::Platform platform, uint32_t linkMinOSVersion, bool simulator, bool ignoreMismatchPlatform)
1972 {
1973 const macho_header<P>* header = (const macho_header<P>*)_fileContent;
1974
1975 // set File attributes
1976 _file->_canScatterAtoms = (header->flags() & MH_SUBSECTIONS_VIA_SYMBOLS);
1977 _file->_cpuSubType = header->cpusubtype();
1978
1979 const macho_segment_command<P>* segment = NULL;
1980 const uint8_t* const endOfFile = _fileContent + _fileLength;
1981 const uint32_t cmd_count = header->ncmds();
1982 // <rdar://problem/5394172> an empty .o file with zero load commands will crash linker
1983 if ( cmd_count == 0 )
1984 return false;
1985 Options::Platform lcPlatform = Options::kPlatformUnknown;
1986 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
1987 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
1988 const macho_load_command<P>* cmd = cmds;
1989 for (uint32_t i = 0; i < cmd_count; ++i) {
1990 uint32_t size = cmd->cmdsize();
1991 if ( (size & this->loadCommandSizeMask()) != 0 )
1992 throwf("load command #%d has a unaligned size", i);
1993 const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize();
1994 if ( endOfCmd > (uint8_t*)cmdsEnd )
1995 throwf("load command #%d extends beyond the end of the load commands", i);
1996 if ( endOfCmd > endOfFile )
1997 throwf("load command #%d extends beyond the end of the file", i);
1998 switch (cmd->cmd()) {
1999 case LC_SYMTAB:
2000 {
2001 const macho_symtab_command<P>* symtab = (macho_symtab_command<P>*)cmd;
2002 _symbolCount = symtab->nsyms();
2003 _symbols = (const macho_nlist<P>*)(_fileContent + symtab->symoff());
2004 _strings = (char*)_fileContent + symtab->stroff();
2005 _stringsSize = symtab->strsize();
2006 if ( (symtab->symoff() + _symbolCount*sizeof(macho_nlist<P>)) > _fileLength )
2007 throw "mach-o symbol table extends beyond end of file";
2008 if ( (_strings + _stringsSize) > (char*)endOfFile )
2009 throw "mach-o string pool extends beyond end of file";
2010 if ( _indirectTable == NULL ) {
2011 if ( _undefinedEndIndex == 0 ) {
2012 _undefinedStartIndex = 0;
2013 _undefinedEndIndex = symtab->nsyms();
2014 }
2015 }
2016 }
2017 break;
2018 case LC_DYSYMTAB:
2019 {
2020 const macho_dysymtab_command<P>* dsymtab = (macho_dysymtab_command<P>*)cmd;
2021 _indirectTable = (uint32_t*)(_fileContent + dsymtab->indirectsymoff());
2022 _indirectTableCount = dsymtab->nindirectsyms();
2023 if ( &_indirectTable[_indirectTableCount] > (uint32_t*)endOfFile )
2024 throw "indirect symbol table extends beyond end of file";
2025 _undefinedStartIndex = dsymtab->iundefsym();
2026 _undefinedEndIndex = _undefinedStartIndex + dsymtab->nundefsym();
2027 }
2028 break;
2029 case LC_UUID:
2030 _hasUUID = true;
2031 break;
2032 case LC_DATA_IN_CODE:
2033 {
2034 const macho_linkedit_data_command<P>* dc = (macho_linkedit_data_command<P>*)cmd;
2035 _dataInCodeStart = (macho_data_in_code_entry<P>*)(_fileContent + dc->dataoff());
2036 _dataInCodeEnd = (macho_data_in_code_entry<P>*)(_fileContent + dc->dataoff() + dc->datasize());
2037 if ( _dataInCodeEnd > (macho_data_in_code_entry<P>*)endOfFile )
2038 throw "LC_DATA_IN_CODE table extends beyond end of file";
2039 }
2040 break;
2041 case LC_LINKER_OPTION:
2042 {
2043 const macho_linker_option_command<P>* loc = (macho_linker_option_command<P>*)cmd;
2044 const char* buffer = loc->buffer();
2045 _file->_linkerOptions.resize(_file->_linkerOptions.size() + 1);
2046 std::vector<const char*>& vec = _file->_linkerOptions.back();
2047 for (uint32_t j=0; j < loc->count(); ++j) {
2048 vec.push_back(buffer);
2049 buffer += strlen(buffer) + 1;
2050 }
2051 if ( buffer > ((char*)cmd + loc->cmdsize()) )
2052 throw "malformed LC_LINKER_OPTION";
2053 }
2054 break;
2055 case LC_LINKER_OPTIMIZATION_HINTS:
2056 {
2057 const macho_linkedit_data_command<P>* loh = (macho_linkedit_data_command<P>*)cmd;
2058 _lohStart = _fileContent + loh->dataoff();
2059 _lohEnd = _fileContent + loh->dataoff() + loh->datasize();
2060 if ( _lohEnd > endOfFile )
2061 throw "LC_LINKER_OPTIMIZATION_HINTS table extends beyond end of file";
2062 }
2063 break;
2064 case LC_VERSION_MIN_MACOSX:
2065 case LC_VERSION_MIN_IPHONEOS:
2066 case LC_VERSION_MIN_WATCHOS:
2067 #if SUPPORT_APPLE_TV
2068 case LC_VERSION_MIN_TVOS:
2069 #endif
2070 if ( ignoreMismatchPlatform )
2071 break;
2072 _file->_platform = cmd->cmd();
2073 lcPlatform = Options::platformForLoadCommand(cmd->cmd());
2074 _file->_minOSVersion = ((macho_version_min_command<P>*)cmd)->version();
2075 break;
2076 default:
2077 if ( cmd->cmd() == macho_segment_command<P>::CMD ) {
2078 if ( segment != NULL )
2079 throw "more than one LC_SEGMENT found in object file";
2080 segment = (macho_segment_command<P>*)cmd;
2081 }
2082 break;
2083 }
2084 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
2085 if ( cmd > cmdsEnd )
2086 throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
2087 }
2088 // arm/arm64 objects are default to ios platform if not set.
2089 // rdar://problem/21746314
2090 if (lcPlatform == Options::kPlatformUnknown &&
2091 (std::is_same<A, arm>::value || std::is_same<A, arm64>::value))
2092 lcPlatform = Options::kPlatformiOS;
2093
2094 // Check platform cross-linking.
2095 if ( !ignoreMismatchPlatform ) {
2096 if ( lcPlatform != platform ) {
2097 switch (platform) {
2098 case Options::kPlatformOSX:
2099 case Options::kPlatformiOS:
2100 if ( lcPlatform == Options::kPlatformUnknown )
2101 break;
2102 // fall through if the Platform is not Unknown
2103 case Options::kPlatformWatchOS:
2104 // WatchOS errors on cross-linking all the time.
2105 throwf("building for %s%s, but linking in object file built for %s,",
2106 Options::platformName(platform), (simulator ? " simulator" : ""),
2107 Options::platformName(lcPlatform));
2108 break;
2109 #if SUPPORT_APPLE_TV
2110 case Options::kPlatform_tvOS:
2111 // tvOS is a warning temporarily. rdar://problem/21746965
2112 if (platform == Options::kPlatform_tvOS)
2113 warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. "
2114 "Note: This will be an error in the future.",
2115 Options::platformName(platform), (simulator ? " simulator" : ""), path(),
2116 Options::platformName(lcPlatform));
2117 break;
2118 #endif
2119 case Options::kPlatformUnknown:
2120 // skip if the target platform is unknown
2121 break;
2122 }
2123 }
2124 if ( linkMinOSVersion && (_file->_minOSVersion > linkMinOSVersion) ) {
2125 char t1[32];
2126 char t2[32];
2127 versionToString(_file->_minOSVersion, t1);
2128 versionToString(linkMinOSVersion, t2);
2129 warning("object file (%s) was built for newer %s version (%s) than being linked (%s)",
2130 _path, Options::platformName(lcPlatform), t1, t2);
2131 }
2132 }
2133
2134
2135 // record range of sections
2136 if ( segment == NULL )
2137 throw "missing LC_SEGMENT";
2138 _sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
2139 _machOSectionsCount = segment->nsects();
2140
2141 return true;
2142 }
2143
2144 template <typename A>
2145 Options::Platform Parser<A>::findPlatform(const macho_header<P>* header)
2146 {
2147 const uint32_t cmd_count = header->ncmds();
2148 if ( cmd_count == 0 )
2149 return Options::kPlatformUnknown;
2150 const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
2151 const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
2152 const macho_load_command<P>* cmd = cmds;
2153 for (uint32_t i = 0; i < cmd_count; ++i) {
2154 uint32_t size = cmd->cmdsize();
2155 if ( (size & loadCommandSizeMask()) != 0 )
2156 throwf("load command #%d has a unaligned size", i);
2157 const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize();
2158 if ( endOfCmd > (uint8_t*)cmdsEnd )
2159 throwf("load command #%d extends beyond the end of the load commands", i);
2160 switch (cmd->cmd()) {
2161 case LC_VERSION_MIN_MACOSX:
2162 return Options::kPlatformOSX;
2163 case LC_VERSION_MIN_IPHONEOS:
2164 return Options::kPlatformiOS;
2165 }
2166 cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
2167 if ( cmd > cmdsEnd )
2168 throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
2169 }
2170 return Options::kPlatformUnknown;
2171 }
2172
2173
2174 template <typename A>
2175 void Parser<A>::prescanSymbolTable()
2176 {
2177 _tentativeDefinitionCount = 0;
2178 _absoluteSymbolCount = 0;
2179 _symbolsInSections = 0;
2180 _hasDataInCodeLabels = false;
2181 for (uint32_t i=0; i < this->_symbolCount; ++i) {
2182 const macho_nlist<P>& sym = symbolFromIndex(i);
2183 // ignore stabs
2184 if ( (sym.n_type() & N_STAB) != 0 )
2185 continue;
2186
2187 // look at undefines
2188 const char* symbolName = this->nameFromSymbol(sym);
2189 if ( (sym.n_type() & N_TYPE) == N_UNDF ) {
2190 if ( sym.n_value() != 0 ) {
2191 // count tentative definitions
2192 ++_tentativeDefinitionCount;
2193 }
2194 else if ( strncmp(symbolName, "___dtrace_", 10) == 0 ) {
2195 // any undefined starting with __dtrace_*$ that is not ___dtrace_probe$* or ___dtrace_isenabled$*
2196 // is extra provider info
2197 if ( (strncmp(&symbolName[10], "probe$", 6) != 0) && (strncmp(&symbolName[10], "isenabled$", 10) != 0) ) {
2198 _dtraceProviderInfo.push_back(symbolName);
2199 }
2200 }
2201 continue;
2202 }
2203 else if ( ((sym.n_type() & N_TYPE) == N_INDR) && ((sym.n_type() & N_EXT) != 0) ) {
2204 _indirectSymbolCount++;
2205 continue;
2206 }
2207
2208 // count absolute symbols
2209 if ( (sym.n_type() & N_TYPE) == N_ABS ) {
2210 const char* absName = this->nameFromSymbol(sym);
2211 // ignore .objc_class_name_* symbols
2212 if ( strncmp(absName, ".objc_class_name_", 17) == 0 ) {
2213 _AppleObjc = true;
2214 continue;
2215 }
2216 // ignore .objc_class_name_* symbols
2217 if ( strncmp(absName, ".objc_category_name_", 20) == 0 )
2218 continue;
2219 // ignore empty *.eh symbols
2220 if ( strcmp(&absName[strlen(absName)-3], ".eh") == 0 )
2221 continue;
2222 ++_absoluteSymbolCount;
2223 }
2224
2225 // only look at definitions
2226 if ( (sym.n_type() & N_TYPE) != N_SECT )
2227 continue;
2228
2229 // 'L' labels do not denote atom breaks
2230 if ( symbolName[0] == 'L' ) {
2231 // <rdar://problem/9218847> Formalize data in code with L$start$ labels
2232 if ( strncmp(symbolName, "L$start$", 8) == 0 )
2233 _hasDataInCodeLabels = true;
2234 continue;
2235 }
2236 // how many def syms in each section
2237 if ( sym.n_sect() > _machOSectionsCount )
2238 throw "bad n_sect in symbol table";
2239
2240 _symbolsInSections++;
2241 }
2242 }
2243
2244 template <typename A>
2245 void Parser<A>::appendAliasAtoms(uint8_t* p)
2246 {
2247 for (uint32_t i=0; i < this->_symbolCount; ++i) {
2248 const macho_nlist<P>& sym = symbolFromIndex(i);
2249 // ignore stabs
2250 if ( (sym.n_type() & N_STAB) != 0 )
2251 continue;
2252
2253 // only look at N_INDR symbols
2254 if ( (sym.n_type() & N_TYPE) != N_INDR )
2255 continue;
2256
2257 // skip non-external aliases
2258 if ( (sym.n_type() & N_EXT) == 0 )
2259 continue;
2260
2261 const char* symbolName = this->nameFromSymbol(sym);
2262 const char* aliasOfName = &_strings[sym.n_value()];
2263 bool isHiddenVisibility = (sym.n_type() & N_PEXT);
2264 AliasAtom* allocatedSpace = (AliasAtom*)p;
2265 new (allocatedSpace) AliasAtom(symbolName, isHiddenVisibility, _file, aliasOfName);
2266 p += sizeof(AliasAtom);
2267 }
2268 }
2269
2270
2271
2272 template <typename A>
2273 int Parser<A>::sectionIndexSorter(void* extra, const void* l, const void* r)
2274 {
2275 Parser<A>* parser = (Parser<A>*)extra;
2276 const uint32_t* left = (uint32_t*)l;
2277 const uint32_t* right = (uint32_t*)r;
2278 const macho_section<P>* leftSect = parser->machOSectionFromSectionIndex(*left);
2279 const macho_section<P>* rightSect = parser->machOSectionFromSectionIndex(*right);
2280
2281 // can't just return difference because 64-bit diff does not fit in 32-bit return type
2282 int64_t result = leftSect->addr() - rightSect->addr();
2283 if ( result == 0 ) {
2284 // two sections with same start address
2285 // one with zero size goes first
2286 bool leftEmpty = ( leftSect->size() == 0 );
2287 bool rightEmpty = ( rightSect->size() == 0 );
2288 if ( leftEmpty != rightEmpty ) {
2289 return ( rightEmpty ? 1 : -1 );
2290 }
2291 if ( !leftEmpty && !rightEmpty )
2292 throwf("overlapping sections");
2293 // both empty, so chose file order
2294 return ( rightSect - leftSect );
2295 }
2296 else if ( result < 0 )
2297 return -1;
2298 else
2299 return 1;
2300 }
2301
2302 template <typename A>
2303 void Parser<A>::makeSortedSectionsArray(uint32_t array[])
2304 {
2305 const bool log = false;
2306
2307 if ( log ) {
2308 fprintf(stderr, "unsorted sections:\n");
2309 for(unsigned int i=0; i < _machOSectionsCount; ++i )
2310 fprintf(stderr, "0x%08llX %s %s\n", _sectionsStart[i].addr(), _sectionsStart[i].segname(), _sectionsStart[i].sectname());
2311 }
2312
2313 // sort by symbol table address
2314 for (uint32_t i=0; i < _machOSectionsCount; ++i)
2315 array[i] = i;
2316 ::qsort_r(array, _machOSectionsCount, sizeof(uint32_t), this, &sectionIndexSorter);
2317
2318 if ( log ) {
2319 fprintf(stderr, "sorted sections:\n");
2320 for(unsigned int i=0; i < _machOSectionsCount; ++i )
2321 fprintf(stderr, "0x%08llX %s %s\n", _sectionsStart[array[i]].addr(), _sectionsStart[array[i]].segname(), _sectionsStart[array[i]].sectname());
2322 }
2323 }
2324
2325
2326
2327 template <typename A>
2328 int Parser<A>::symbolIndexSorter(void* extra, const void* l, const void* r)
2329 {
2330 ParserAndSectionsArray* extraInfo = (ParserAndSectionsArray*)extra;
2331 Parser<A>* parser = extraInfo->parser;
2332 const uint32_t* sortedSectionsArray = extraInfo->sortedSectionsArray;
2333 const uint32_t* left = (uint32_t*)l;
2334 const uint32_t* right = (uint32_t*)r;
2335 const macho_nlist<P>& leftSym = parser->symbolFromIndex(*left);
2336 const macho_nlist<P>& rightSym = parser->symbolFromIndex(*right);
2337 // can't just return difference because 64-bit diff does not fit in 32-bit return type
2338 int64_t result = leftSym.n_value() - rightSym.n_value();
2339 if ( result == 0 ) {
2340 // two symbols with same address
2341 // if in different sections, sort earlier section first
2342 if ( leftSym.n_sect() != rightSym.n_sect() ) {
2343 for (uint32_t i=0; i < parser->machOSectionCount(); ++i) {
2344 if ( sortedSectionsArray[i]+1 == leftSym.n_sect() )
2345 return -1;
2346 if ( sortedSectionsArray[i]+1 == rightSym.n_sect() )
2347 return 1;
2348 }
2349 }
2350 // two symbols in same section, means one is an alias
2351 // if one is ltmp*, make it an alias (sort first)
2352 const char* leftName = parser->nameFromSymbol(leftSym);
2353 const char* rightName = parser->nameFromSymbol(rightSym);
2354 bool leftIsTmp = strncmp(leftName, "ltmp", 4);
2355 bool rightIsTmp = strncmp(rightName, "ltmp", 4);
2356 if ( leftIsTmp != rightIsTmp ) {
2357 return (rightIsTmp ? -1 : 1);
2358 }
2359
2360 // if only one is global, make the other an alias (sort first)
2361 if ( (leftSym.n_type() & N_EXT) != (rightSym.n_type() & N_EXT) ) {
2362 if ( (rightSym.n_type() & N_EXT) != 0 )
2363 return -1;
2364 else
2365 return 1;
2366 }
2367 // if both are global, sort alphabetically. earlier one will be the alias
2368 return ( strcmp(rightName, leftName) );
2369 }
2370 else if ( result < 0 )
2371 return -1;
2372 else
2373 return 1;
2374 }
2375
2376
2377 template <typename A>
2378 void Parser<A>::makeSortedSymbolsArray(uint32_t array[], const uint32_t sectionArray[])
2379 {
2380 const bool log = false;
2381
2382 uint32_t* p = array;
2383 for (uint32_t i=0; i < this->_symbolCount; ++i) {
2384 const macho_nlist<P>& sym = symbolFromIndex(i);
2385 // ignore stabs
2386 if ( (sym.n_type() & N_STAB) != 0 )
2387 continue;
2388
2389 // only look at definitions
2390 if ( (sym.n_type() & N_TYPE) != N_SECT )
2391 continue;
2392
2393 // 'L' labels do not denote atom breaks
2394 const char* symbolName = this->nameFromSymbol(sym);
2395 if ( symbolName[0] == 'L' )
2396 continue;
2397
2398 // how many def syms in each section
2399 if ( sym.n_sect() > _machOSectionsCount )
2400 throw "bad n_sect in symbol table";
2401
2402 // append to array
2403 *p++ = i;
2404 }
2405 assert(p == &array[_symbolsInSections] && "second pass over symbol table yield a different number of symbols");
2406
2407 // sort by symbol table address
2408 ParserAndSectionsArray extra = { this, sectionArray };
2409 ::qsort_r(array, _symbolsInSections, sizeof(uint32_t), &extra, &symbolIndexSorter);
2410
2411
2412 // look for two symbols at same address
2413 _overlappingSymbols = false;
2414 for (unsigned int i=1; i < _symbolsInSections; ++i) {
2415 if ( symbolFromIndex(array[i-1]).n_value() == symbolFromIndex(array[i]).n_value() ) {
2416 //fprintf(stderr, "overlapping symbols at 0x%08llX\n", symbolFromIndex(array[i-1]).n_value());
2417 _overlappingSymbols = true;
2418 break;
2419 }
2420 }
2421
2422 if ( log ) {
2423 fprintf(stderr, "sorted symbols:\n");
2424 for(unsigned int i=0; i < _symbolsInSections; ++i )
2425 fprintf(stderr, "0x%09llX symIndex=%d sectNum=%2d, %s\n", symbolFromIndex(array[i]).n_value(), array[i], symbolFromIndex(array[i]).n_sect(), nameFromSymbol(symbolFromIndex(array[i])) );
2426 }
2427 }
2428
2429 template <typename A>
2430 void Parser<A>::makeSections()
2431 {
2432 // classify each section by type
2433 // compute how many Section objects will be needed and total size for all
2434 unsigned int totalSectionsSize = 0;
2435 uint8_t machOSectsStorage[sizeof(MachOSectionAndSectionClass<P>)*(_machOSectionsCount+2)]; // also room for tentative-defs and absolute symbols
2436 // allocate raw storage for all section objects on stack
2437 MachOSectionAndSectionClass<P>* machOSects = (MachOSectionAndSectionClass<P>*)machOSectsStorage;
2438 unsigned int count = 0;
2439 // local variable for bitcode parsing
2440 const macho_section<P>* bitcodeSect = NULL;
2441 const macho_section<P>* cmdlineSect = NULL;
2442 const macho_section<P>* swiftCmdlineSect = NULL;
2443 const macho_section<P>* bundleSect = NULL;
2444 bool bitcodeAsm = false;
2445
2446 for (uint32_t i=0; i < _machOSectionsCount; ++i) {
2447 const macho_section<P>* sect = &_sectionsStart[i];
2448 if ( (sect->flags() & S_ATTR_DEBUG) != 0 ) {
2449 if ( strcmp(sect->segname(), "__DWARF") == 0 ) {
2450 // note that .o file has dwarf
2451 _file->_debugInfoKind = ld::relocatable::File::kDebugInfoDwarf;
2452 // save off iteresting dwarf sections
2453 if ( strcmp(sect->sectname(), "__debug_info") == 0 )
2454 _file->_dwarfDebugInfoSect = sect;
2455 else if ( strcmp(sect->sectname(), "__debug_abbrev") == 0 )
2456 _file->_dwarfDebugAbbrevSect = sect;
2457 else if ( strcmp(sect->sectname(), "__debug_line") == 0 )
2458 _file->_dwarfDebugLineSect = sect;
2459 else if ( strcmp(sect->sectname(), "__debug_str") == 0 )
2460 _file->_dwarfDebugStringSect = sect;
2461 // linker does not propagate dwarf sections to output file
2462 continue;
2463 }
2464 else if ( strcmp(sect->segname(), "__LD") == 0 ) {
2465 if ( strncmp(sect->sectname(), "__compact_unwind", 16) == 0 ) {
2466 machOSects[count].sect = sect;
2467 totalSectionsSize += sizeof(CUSection<A>);
2468 machOSects[count++].type = sectionTypeCompactUnwind;
2469 continue;
2470 }
2471 }
2472 }
2473 if ( strcmp(sect->segname(), "__LLVM") == 0 ) {
2474 if ( strncmp(sect->sectname(), "__bitcode", 9) == 0 ) {
2475 bitcodeSect = sect;
2476 } else if ( strncmp(sect->sectname(), "__cmdline", 9) == 0 ) {
2477 cmdlineSect = sect;
2478 } else if ( strncmp(sect->sectname(), "__swift_cmdline", 15) == 0 ) {
2479 swiftCmdlineSect = sect;
2480 } else if ( strncmp(sect->sectname(), "__bundle", 8) == 0 ) {
2481 bundleSect = sect;
2482 } else if ( strncmp(sect->sectname(), "__asm", 5) == 0 ) {
2483 bitcodeAsm = true;
2484 }
2485 // If it is not single input for ld -r, don't count the section
2486 // otherwise, fall through and add it to the sections.
2487 if (_file->sourceKind() != ld::relocatable::File::kSourceSingle)
2488 continue;
2489 }
2490 // ignore empty __OBJC sections
2491 if ( (sect->size() == 0) && (strcmp(sect->segname(), "__OBJC") == 0) )
2492 continue;
2493 // objc image info section is really attributes and not content
2494 if ( ((strcmp(sect->sectname(), "__image_info") == 0) && (strcmp(sect->segname(), "__OBJC") == 0))
2495 || ((strncmp(sect->sectname(), "__objc_imageinfo", 16) == 0) && (strcmp(sect->segname(), "__DATA") == 0)) ) {
2496 // struct objc_image_info {
2497 // uint32_t version; // initially 0
2498 // uint32_t flags;
2499 // };
2500 // #define OBJC_IMAGE_SUPPORTS_GC 2
2501 // #define OBJC_IMAGE_GC_ONLY 4
2502 // #define OBJC_IMAGE_IS_SIMULATED 32
2503 //
2504 const uint32_t* contents = (uint32_t*)(_file->fileContent()+sect->offset());
2505 if ( (sect->size() >= 8) && (contents[0] == 0) ) {
2506 uint32_t flags = E::get32(contents[1]);
2507 if ( (flags & 4) == 4 )
2508 _file->_objConstraint = ld::File::objcConstraintGC;
2509 else if ( (flags & 2) == 2 )
2510 _file->_objConstraint = ld::File::objcConstraintRetainReleaseOrGC;
2511 else if ( (flags & 32) == 32 )
2512 _file->_objConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
2513 else
2514 _file->_objConstraint = ld::File::objcConstraintRetainRelease;
2515 _file->_swiftVersion = ((flags >> 8) & 0xFF);
2516 if ( sect->size() > 8 ) {
2517 warning("section %s/%s has unexpectedly large size %llu in %s",
2518 sect->segname(), Section<A>::makeSectionName(sect), sect->size(), _file->path());
2519 }
2520 }
2521 else {
2522 warning("can't parse %s/%s section in %s", sect->segname(), Section<A>::makeSectionName(sect), _file->path());
2523 }
2524 continue;
2525 }
2526 machOSects[count].sect = sect;
2527 switch ( sect->flags() & SECTION_TYPE ) {
2528 case S_SYMBOL_STUBS:
2529 if ( _stubsSectionNum == 0 ) {
2530 _stubsSectionNum = i+1;
2531 _stubsMachOSection = sect;
2532 }
2533 else
2534 assert(1 && "multiple S_SYMBOL_STUBS sections");
2535 case S_LAZY_SYMBOL_POINTERS:
2536 break;
2537 case S_4BYTE_LITERALS:
2538 totalSectionsSize += sizeof(Literal4Section<A>);
2539 machOSects[count++].type = sectionTypeLiteral4;
2540 break;
2541 case S_8BYTE_LITERALS:
2542 totalSectionsSize += sizeof(Literal8Section<A>);
2543 machOSects[count++].type = sectionTypeLiteral8;
2544 break;
2545 case S_16BYTE_LITERALS:
2546 totalSectionsSize += sizeof(Literal16Section<A>);
2547 machOSects[count++].type = sectionTypeLiteral16;
2548 break;
2549 case S_NON_LAZY_SYMBOL_POINTERS:
2550 totalSectionsSize += sizeof(NonLazyPointerSection<A>);
2551 machOSects[count++].type = sectionTypeNonLazy;
2552 break;
2553 case S_THREAD_LOCAL_VARIABLE_POINTERS:
2554 totalSectionsSize += sizeof(TLVPointerSection<A>);
2555 machOSects[count++].type = sectionTypeTLVPointers;
2556 break;
2557 case S_LITERAL_POINTERS:
2558 if ( (strcmp(sect->segname(), "__OBJC") == 0) && (strcmp(sect->sectname(), "__cls_refs") == 0) ) {
2559 totalSectionsSize += sizeof(Objc1ClassReferences<A>);
2560 machOSects[count++].type = sectionTypeObjC1ClassRefs;
2561 }
2562 else {
2563 totalSectionsSize += sizeof(PointerToCStringSection<A>);
2564 machOSects[count++].type = sectionTypeCStringPointer;
2565 }
2566 break;
2567 case S_CSTRING_LITERALS:
2568 totalSectionsSize += sizeof(CStringSection<A>);
2569 machOSects[count++].type = sectionTypeCString;
2570 break;
2571 case S_MOD_INIT_FUNC_POINTERS:
2572 case S_MOD_TERM_FUNC_POINTERS:
2573 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
2574 case S_INTERPOSING:
2575 case S_ZEROFILL:
2576 case S_REGULAR:
2577 case S_COALESCED:
2578 case S_THREAD_LOCAL_REGULAR:
2579 case S_THREAD_LOCAL_ZEROFILL:
2580 if ( (strcmp(sect->segname(), "__TEXT") == 0) && (strcmp(sect->sectname(), "__eh_frame") == 0) ) {
2581 totalSectionsSize += sizeof(CFISection<A>);
2582 machOSects[count++].type = sectionTypeCFI;
2583 }
2584 else if ( (strcmp(sect->segname(), "__DATA") == 0) && (strcmp(sect->sectname(), "__cfstring") == 0) ) {
2585 totalSectionsSize += sizeof(CFStringSection<A>);
2586 machOSects[count++].type = sectionTypeCFString;
2587 }
2588 else if ( (strcmp(sect->segname(), "__TEXT") == 0) && (strcmp(sect->sectname(), "__ustring") == 0) ) {
2589 totalSectionsSize += sizeof(UTF16StringSection<A>);
2590 machOSects[count++].type = sectionTypeUTF16Strings;
2591 }
2592 else if ( (strcmp(sect->segname(), "__DATA") == 0) && (strncmp(sect->sectname(), "__objc_classrefs", 16) == 0) ) {
2593 totalSectionsSize += sizeof(ObjC2ClassRefsSection<A>);
2594 machOSects[count++].type = sectionTypeObjC2ClassRefs;
2595 }
2596 else if ( (strcmp(sect->segname(), "__DATA") == 0) && (strcmp(sect->sectname(), "__objc_catlist") == 0) ) {
2597 totalSectionsSize += sizeof(ObjC2CategoryListSection<A>);
2598 machOSects[count++].type = typeObjC2CategoryList;
2599 }
2600 else if ( _AppleObjc && (strcmp(sect->segname(), "__OBJC") == 0) && (strcmp(sect->sectname(), "__class") == 0) ) {
2601 totalSectionsSize += sizeof(ObjC1ClassSection<A>);
2602 machOSects[count++].type = sectionTypeObjC1Classes;
2603 }
2604 else {
2605 totalSectionsSize += sizeof(SymboledSection<A>);
2606 machOSects[count++].type = sectionTypeSymboled;
2607 }
2608 break;
2609 case S_THREAD_LOCAL_VARIABLES:
2610 totalSectionsSize += sizeof(TLVDefsSection<A>);
2611 machOSects[count++].type = sectionTypeTLVDefs;
2612 break;
2613 default:
2614 throwf("unknown section type %d", sect->flags() & SECTION_TYPE);
2615 }
2616 }
2617
2618 // Create bitcode
2619 if ( bitcodeSect != NULL ) {
2620 if ( cmdlineSect != NULL )
2621 _file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::ClangBitcode(&_fileContent[bitcodeSect->offset()], bitcodeSect->size(),
2622 &_fileContent[cmdlineSect->offset()], cmdlineSect->size()));
2623 else if ( swiftCmdlineSect != NULL )
2624 _file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::SwiftBitcode(&_fileContent[bitcodeSect->offset()], bitcodeSect->size(),
2625 &_fileContent[swiftCmdlineSect->offset()], swiftCmdlineSect->size()));
2626 else
2627 throwf("Object file with bitcode missing cmdline options: %s", _file->path());
2628 }
2629 else if ( bundleSect != NULL )
2630 _file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::BundleBitcode(&_fileContent[bundleSect->offset()], bundleSect->size()));
2631 else if ( bitcodeAsm )
2632 _file->_bitcode = std::unique_ptr<ld::Bitcode>(new ld::AsmBitcode(_fileContent, _fileLength));
2633
2634 // sort by address (mach-o object files don't aways have sections sorted)
2635 ::qsort(machOSects, count, sizeof(MachOSectionAndSectionClass<P>), MachOSectionAndSectionClass<P>::sorter);
2636
2637 // we will synthesize a dummy Section<A> object for tentative definitions
2638 if ( _tentativeDefinitionCount > 0 ) {
2639 totalSectionsSize += sizeof(TentativeDefinitionSection<A>);
2640 machOSects[count++].type = sectionTypeTentativeDefinitions;
2641 }
2642
2643 // we will synthesize a dummy Section<A> object for Absolute symbols
2644 if ( _absoluteSymbolCount > 0 ) {
2645 totalSectionsSize += sizeof(AbsoluteSymbolSection<A>);
2646 machOSects[count++].type = sectionTypeAbsoluteSymbols;
2647 }
2648
2649 // allocate one block for all Section objects as well as pointers to each
2650 uint8_t* space = new uint8_t[totalSectionsSize+count*sizeof(Section<A>*)];
2651 _file->_sectionsArray = (Section<A>**)space;
2652 _file->_sectionsArrayCount = count;
2653 Section<A>** objects = _file->_sectionsArray;
2654 space += count*sizeof(Section<A>*);
2655 for (uint32_t i=0; i < count; ++i) {
2656 switch ( machOSects[i].type ) {
2657 case sectionTypeIgnore:
2658 break;
2659 case sectionTypeLiteral4:
2660 *objects++ = new (space) Literal4Section<A>(*this, *_file, machOSects[i].sect);
2661 space += sizeof(Literal4Section<A>);
2662 break;
2663 case sectionTypeLiteral8:
2664 *objects++ = new (space) Literal8Section<A>(*this, *_file, machOSects[i].sect);
2665 space += sizeof(Literal8Section<A>);
2666 break;
2667 case sectionTypeLiteral16:
2668 *objects++ = new (space) Literal16Section<A>(*this, *_file, machOSects[i].sect);
2669 space += sizeof(Literal16Section<A>);
2670 break;
2671 case sectionTypeNonLazy:
2672 *objects++ = new (space) NonLazyPointerSection<A>(*this, *_file, machOSects[i].sect);
2673 space += sizeof(NonLazyPointerSection<A>);
2674 break;
2675 case sectionTypeTLVPointers:
2676 *objects++ = new (space) TLVPointerSection<A>(*this, *_file, machOSects[i].sect);
2677 space += sizeof(TLVPointerSection<A>);
2678 break;
2679 case sectionTypeCFI:
2680 _EHFrameSection = new (space) CFISection<A>(*this, *_file, machOSects[i].sect);
2681 *objects++ = _EHFrameSection;
2682 space += sizeof(CFISection<A>);
2683 break;
2684 case sectionTypeCString:
2685 *objects++ = new (space) CStringSection<A>(*this, *_file, machOSects[i].sect);
2686 space += sizeof(CStringSection<A>);
2687 break;
2688 case sectionTypeCStringPointer:
2689 *objects++ = new (space) PointerToCStringSection<A>(*this, *_file, machOSects[i].sect);
2690 space += sizeof(PointerToCStringSection<A>);
2691 break;
2692 case sectionTypeObjC1ClassRefs:
2693 *objects++ = new (space) Objc1ClassReferences<A>(*this, *_file, machOSects[i].sect);
2694 space += sizeof(Objc1ClassReferences<A>);
2695 break;
2696 case sectionTypeUTF16Strings:
2697 *objects++ = new (space) UTF16StringSection<A>(*this, *_file, machOSects[i].sect);
2698 space += sizeof(UTF16StringSection<A>);
2699 break;
2700 case sectionTypeCFString:
2701 *objects++ = new (space) CFStringSection<A>(*this, *_file, machOSects[i].sect);
2702 space += sizeof(CFStringSection<A>);
2703 break;
2704 case sectionTypeObjC2ClassRefs:
2705 *objects++ = new (space) ObjC2ClassRefsSection<A>(*this, *_file, machOSects[i].sect);
2706 space += sizeof(ObjC2ClassRefsSection<A>);
2707 break;
2708 case typeObjC2CategoryList:
2709 *objects++ = new (space) ObjC2CategoryListSection<A>(*this, *_file, machOSects[i].sect);
2710 space += sizeof(ObjC2CategoryListSection<A>);
2711 break;
2712 case sectionTypeObjC1Classes:
2713 *objects++ = new (space) ObjC1ClassSection<A>(*this, *_file, machOSects[i].sect);
2714 space += sizeof(ObjC1ClassSection<A>);
2715 break;
2716 case sectionTypeSymboled:
2717 *objects++ = new (space) SymboledSection<A>(*this, *_file, machOSects[i].sect);
2718 space += sizeof(SymboledSection<A>);
2719 break;
2720 case sectionTypeTLVDefs:
2721 *objects++ = new (space) TLVDefsSection<A>(*this, *_file, machOSects[i].sect);
2722 space += sizeof(TLVDefsSection<A>);
2723 break;
2724 case sectionTypeCompactUnwind:
2725 _compactUnwindSection = new (space) CUSection<A>(*this, *_file, machOSects[i].sect);
2726 *objects++ = _compactUnwindSection;
2727 space += sizeof(CUSection<A>);
2728 break;
2729 case sectionTypeTentativeDefinitions:
2730 *objects++ = new (space) TentativeDefinitionSection<A>(*this, *_file);
2731 space += sizeof(TentativeDefinitionSection<A>);
2732 break;
2733 case sectionTypeAbsoluteSymbols:
2734 _absoluteSection = new (space) AbsoluteSymbolSection<A>(*this, *_file);
2735 *objects++ = _absoluteSection;
2736 space += sizeof(AbsoluteSymbolSection<A>);
2737 break;
2738 default:
2739 throw "internal error uknown SectionType";
2740 }
2741 }
2742 }
2743
2744
2745 template <typename A>
2746 Section<A>* Parser<A>::sectionForAddress(typename A::P::uint_t addr)
2747 {
2748 for (uint32_t i=0; i < _file->_sectionsArrayCount; ++i ) {
2749 const macho_section<typename A::P>* sect = _file->_sectionsArray[i]->machoSection();
2750 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2751 if ( sect != NULL ) {
2752 if ( (sect->addr() <= addr) && (addr < (sect->addr()+sect->size())) ) {
2753 return _file->_sectionsArray[i];
2754 }
2755 }
2756 }
2757 // not strictly in any section
2758 // may be in a zero length section
2759 for (uint32_t i=0; i < _file->_sectionsArrayCount; ++i ) {
2760 const macho_section<typename A::P>* sect = _file->_sectionsArray[i]->machoSection();
2761 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2762 if ( sect != NULL ) {
2763 if ( (sect->addr() == addr) && (sect->size() == 0) ) {
2764 return _file->_sectionsArray[i];
2765 }
2766 }
2767 }
2768
2769 throwf("sectionForAddress(0x%llX) address not in any section", (uint64_t)addr);
2770 }
2771
2772 template <typename A>
2773 Section<A>* Parser<A>::sectionForNum(unsigned int num)
2774 {
2775 for (uint32_t i=0; i < _file->_sectionsArrayCount; ++i ) {
2776 const macho_section<typename A::P>* sect = _file->_sectionsArray[i]->machoSection();
2777 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
2778 if ( sect != NULL ) {
2779 if ( num == (unsigned int)((sect - _sectionsStart)+1) )
2780 return _file->_sectionsArray[i];
2781 }
2782 }
2783 throwf("sectionForNum(%u) section number not for any section", num);
2784 }
2785
2786 template <typename A>
2787 Atom<A>* Parser<A>::findAtomByAddress(pint_t addr)
2788 {
2789 Section<A>* section = this->sectionForAddress(addr);
2790 return section->findAtomByAddress(addr);
2791 }
2792
2793 template <typename A>
2794 Atom<A>* Parser<A>::findAtomByAddressOrNullIfStub(pint_t addr)
2795 {
2796 if ( hasStubsSection() && (_stubsMachOSection->addr() <= addr) && (addr < (_stubsMachOSection->addr()+_stubsMachOSection->size())) )
2797 return NULL;
2798 return findAtomByAddress(addr);
2799 }
2800
2801 template <typename A>
2802 Atom<A>* Parser<A>::findAtomByAddressOrLocalTargetOfStub(pint_t addr, uint32_t* offsetInAtom)
2803 {
2804 if ( hasStubsSection() && (_stubsMachOSection->addr() <= addr) && (addr < (_stubsMachOSection->addr()+_stubsMachOSection->size())) ) {
2805 // target is a stub, remove indirection
2806 uint32_t symbolIndex = this->symbolIndexFromIndirectSectionAddress(addr, _stubsMachOSection);
2807 assert(symbolIndex != INDIRECT_SYMBOL_LOCAL);
2808 const macho_nlist<P>& sym = this->symbolFromIndex(symbolIndex);
2809 // can't be to external weak symbol
2810 assert( (this->combineFromSymbol(sym) != ld::Atom::combineByName) || (this->scopeFromSymbol(sym) != ld::Atom::scopeGlobal) );
2811 *offsetInAtom = 0;
2812 return this->findAtomByName(this->nameFromSymbol(sym));
2813 }
2814 Atom<A>* target = this->findAtomByAddress(addr);
2815 *offsetInAtom = addr - target->_objAddress;
2816 return target;
2817 }
2818
2819 template <typename A>
2820 Atom<A>* Parser<A>::findAtomByName(const char* name)
2821 {
2822 uint8_t* p = _file->_atomsArray;
2823 for(int i=_file->_atomsArrayCount; i > 0; --i) {
2824 Atom<A>* atom = (Atom<A>*)p;
2825 if ( strcmp(name, atom->name()) == 0 )
2826 return atom;
2827 p += sizeof(Atom<A>);
2828 }
2829 return NULL;
2830 }
2831
2832 template <typename A>
2833 void Parser<A>::findTargetFromAddress(pint_t addr, TargetDesc& target)
2834 {
2835 if ( hasStubsSection() && (_stubsMachOSection->addr() <= addr) && (addr < (_stubsMachOSection->addr()+_stubsMachOSection->size())) ) {
2836 // target is a stub, remove indirection
2837 uint32_t symbolIndex = this->symbolIndexFromIndirectSectionAddress(addr, _stubsMachOSection);
2838 assert(symbolIndex != INDIRECT_SYMBOL_LOCAL);
2839 const macho_nlist<P>& sym = this->symbolFromIndex(symbolIndex);
2840 target.atom = NULL;
2841 target.name = this->nameFromSymbol(sym);
2842 target.weakImport = this->weakImportFromSymbol(sym);
2843 target.addend = 0;
2844 return;
2845 }
2846 Section<A>* section = this->sectionForAddress(addr);
2847 target.atom = section->findAtomByAddress(addr);
2848 target.addend = addr - target.atom->_objAddress;
2849 target.weakImport = false;
2850 target.name = NULL;
2851 }
2852
2853 template <typename A>
2854 void Parser<A>::findTargetFromAddress(pint_t baseAddr, pint_t addr, TargetDesc& target)
2855 {
2856 findTargetFromAddress(baseAddr, target);
2857 target.addend = addr - target.atom->_objAddress;
2858 }
2859
2860 template <typename A>
2861 void Parser<A>::findTargetFromAddressAndSectionNum(pint_t addr, unsigned int sectNum, TargetDesc& target)
2862 {
2863 if ( sectNum == R_ABS ) {
2864 // target is absolute symbol that corresponds to addr
2865 if ( _absoluteSection != NULL ) {
2866 target.atom = _absoluteSection->findAbsAtomForValue(addr);
2867 if ( target.atom != NULL ) {
2868 target.name = NULL;
2869 target.weakImport = false;
2870 target.addend = 0;
2871 return;
2872 }
2873 }
2874 throwf("R_ABS reloc but no absolute symbol at target address");
2875 }
2876
2877 if ( hasStubsSection() && (stubsSectionNum() == sectNum) ) {
2878 // target is a stub, remove indirection
2879 uint32_t symbolIndex = this->symbolIndexFromIndirectSectionAddress(addr, _stubsMachOSection);
2880 assert(symbolIndex != INDIRECT_SYMBOL_LOCAL);
2881 const macho_nlist<P>& sym = this->symbolFromIndex(symbolIndex);
2882 // use direct reference when stub is to a static function
2883 if ( ((sym.n_type() & N_TYPE) == N_SECT) && (((sym.n_type() & N_EXT) == 0) || (this->nameFromSymbol(sym)[0] == 'L')) ) {
2884 this->findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
2885 }
2886 else {
2887 target.atom = NULL;
2888 target.name = this->nameFromSymbol(sym);
2889 target.weakImport = this->weakImportFromSymbol(sym);
2890 target.addend = 0;
2891 }
2892 return;
2893 }
2894 Section<A>* section = this->sectionForNum(sectNum);
2895 target.atom = section->findAtomByAddress(addr);
2896 if ( target.atom == NULL ) {
2897 typedef typename A::P::sint_t sint_t;
2898 sint_t a = (sint_t)addr;
2899 sint_t sectStart = (sint_t)(section->machoSection()->addr());
2900 sint_t sectEnd = sectStart + section->machoSection()->size();
2901 if ( a < sectStart ) {
2902 // target address is before start of section, so must be negative addend
2903 target.atom = section->findAtomByAddress(sectStart);
2904 target.addend = a - sectStart;
2905 target.weakImport = false;
2906 target.name = NULL;
2907 return;
2908 }
2909 else if ( a >= sectEnd ) {
2910 target.atom = section->findAtomByAddress(sectEnd-1);
2911 target.addend = a - sectEnd;
2912 target.weakImport = false;
2913 target.name = NULL;
2914 return;
2915 }
2916 }
2917 assert(target.atom != NULL);
2918 target.addend = addr - target.atom->_objAddress;
2919 target.weakImport = false;
2920 target.name = NULL;
2921 }
2922
2923 template <typename A>
2924 void Parser<A>::addDtraceExtraInfos(const SourceLocation& src, const char* providerName)
2925 {
2926 // for every ___dtrace_stability$* and ___dtrace_typedefs$* undefine with
2927 // a matching provider name, add a by-name kDtraceTypeReference at probe site
2928 const char* dollar = strchr(providerName, '$');
2929 if ( dollar != NULL ) {
2930 int providerNameLen = dollar-providerName+1;
2931 for ( std::vector<const char*>::iterator it = _dtraceProviderInfo.begin(); it != _dtraceProviderInfo.end(); ++it) {
2932 const char* typeDollar = strchr(*it, '$');
2933 if ( typeDollar != NULL ) {
2934 if ( strncmp(typeDollar+1, providerName, providerNameLen) == 0 ) {
2935 addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindDtraceExtra,false, *it);
2936 }
2937 }
2938 }
2939 }
2940 }
2941
2942 template <typename A>
2943 const char* Parser<A>::scanSymbolTableForAddress(uint64_t addr)
2944 {
2945 uint64_t closestSymAddr = 0;
2946 const char* closestSymName = NULL;
2947 for (uint32_t i=0; i < this->_symbolCount; ++i) {
2948 const macho_nlist<P>& sym = symbolFromIndex(i);
2949 // ignore stabs
2950 if ( (sym.n_type() & N_STAB) != 0 )
2951 continue;
2952
2953 // only look at definitions
2954 if ( (sym.n_type() & N_TYPE) != N_SECT )
2955 continue;
2956
2957 // return with exact match
2958 if ( sym.n_value() == addr ) {
2959 const char* name = nameFromSymbol(sym);
2960 if ( strncmp(name, "ltmp", 4) != 0 )
2961 return name;
2962 // treat 'ltmp*' labels as close match
2963 closestSymAddr = sym.n_value();
2964 closestSymName = name;
2965 }
2966
2967 // record closest seen so far
2968 if ( (sym.n_value() < addr) && ((sym.n_value() > closestSymAddr) || (closestSymName == NULL)) )
2969 closestSymName = nameFromSymbol(sym);
2970 }
2971
2972 return (closestSymName != NULL) ? closestSymName : "unknown";
2973 }
2974
2975
2976 template <typename A>
2977 void Parser<A>::addFixups(const SourceLocation& src, ld::Fixup::Kind setKind, const TargetDesc& target)
2978 {
2979 // some fixup pairs can be combined
2980 ld::Fixup::Cluster cl = ld::Fixup::k1of3;
2981 ld::Fixup::Kind firstKind = ld::Fixup::kindSetTargetAddress;
2982 bool combined = false;
2983 if ( target.addend == 0 ) {
2984 cl = ld::Fixup::k1of1;
2985 combined = true;
2986 switch ( setKind ) {
2987 case ld::Fixup::kindStoreLittleEndian32:
2988 firstKind = ld::Fixup::kindStoreTargetAddressLittleEndian32;
2989 break;
2990 case ld::Fixup::kindStoreLittleEndian64:
2991 firstKind = ld::Fixup::kindStoreTargetAddressLittleEndian64;
2992 break;
2993 case ld::Fixup::kindStoreBigEndian32:
2994 firstKind = ld::Fixup::kindStoreTargetAddressBigEndian32;
2995 break;
2996 case ld::Fixup::kindStoreBigEndian64:
2997 firstKind = ld::Fixup::kindStoreTargetAddressBigEndian64;
2998 break;
2999 case ld::Fixup::kindStoreX86BranchPCRel32:
3000 firstKind = ld::Fixup::kindStoreTargetAddressX86BranchPCRel32;
3001 break;
3002 case ld::Fixup::kindStoreX86PCRel32:
3003 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32;
3004 break;
3005 case ld::Fixup::kindStoreX86PCRel32GOTLoad:
3006 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32GOTLoad;
3007 break;
3008 case ld::Fixup::kindStoreX86PCRel32TLVLoad:
3009 firstKind = ld::Fixup::kindStoreTargetAddressX86PCRel32TLVLoad;
3010 break;
3011 case ld::Fixup::kindStoreX86Abs32TLVLoad:
3012 firstKind = ld::Fixup::kindStoreTargetAddressX86Abs32TLVLoad;
3013 break;
3014 case ld::Fixup::kindStoreARMBranch24:
3015 firstKind = ld::Fixup::kindStoreTargetAddressARMBranch24;
3016 break;
3017 case ld::Fixup::kindStoreThumbBranch22:
3018 firstKind = ld::Fixup::kindStoreTargetAddressThumbBranch22;
3019 break;
3020 #if SUPPORT_ARCH_arm64
3021 case ld::Fixup::kindStoreARM64Branch26:
3022 firstKind = ld::Fixup::kindStoreTargetAddressARM64Branch26;
3023 break;
3024 case ld::Fixup::kindStoreARM64Page21:
3025 firstKind = ld::Fixup::kindStoreTargetAddressARM64Page21;
3026 break;
3027 case ld::Fixup::kindStoreARM64PageOff12:
3028 firstKind = ld::Fixup::kindStoreTargetAddressARM64PageOff12;
3029 break;
3030 case ld::Fixup::kindStoreARM64GOTLoadPage21:
3031 firstKind = ld::Fixup::kindStoreTargetAddressARM64GOTLoadPage21;
3032 break;
3033 case ld::Fixup::kindStoreARM64GOTLoadPageOff12:
3034 firstKind = ld::Fixup::kindStoreTargetAddressARM64GOTLoadPageOff12;
3035 break;
3036 case ld::Fixup::kindStoreARM64TLVPLoadPage21:
3037 firstKind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPage21;
3038 break;
3039 case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
3040 firstKind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12;
3041 break;
3042 #endif
3043 default:
3044 combined = false;
3045 cl = ld::Fixup::k1of2;
3046 break;
3047 }
3048 }
3049
3050 if ( target.atom != NULL ) {
3051 if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
3052 addFixup(src, cl, firstKind, target.atom);
3053 }
3054 else if ( (target.atom->combine() == ld::Atom::combineByNameAndContent) || (target.atom->combine() == ld::Atom::combineByNameAndReferences) ) {
3055 addFixup(src, cl, firstKind, ld::Fixup::bindingByContentBound, target.atom);
3056 }
3057 else if ( (src.atom->section().type() == ld::Section::typeCFString) && (src.offsetInAtom != 0) ) {
3058 // backing string in CFStrings should always be direct
3059 addFixup(src, cl, firstKind, target.atom);
3060 }
3061 else if ( (src.atom == target.atom) && (target.atom->combine() == ld::Atom::combineByName) ) {
3062 // reference to self should always be direct
3063 addFixup(src, cl, firstKind, target.atom);
3064 }
3065 else {
3066 // change direct fixup to by-name fixup
3067 addFixup(src, cl, firstKind, false, target.atom->name());
3068 }
3069 }
3070 else {
3071 addFixup(src, cl, firstKind, target.weakImport, target.name);
3072 }
3073 if ( target.addend == 0 ) {
3074 if ( ! combined )
3075 addFixup(src, ld::Fixup::k2of2, setKind);
3076 }
3077 else {
3078 addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend);
3079 addFixup(src, ld::Fixup::k3of3, setKind);
3080 }
3081 }
3082
3083 template <typename A>
3084 void Parser<A>::addFixups(const SourceLocation& src, ld::Fixup::Kind kind, const TargetDesc& target, const TargetDesc& picBase)
3085 {
3086 ld::Fixup::Cluster cl = (target.addend == 0) ? ld::Fixup::k1of4 : ld::Fixup::k1of5;
3087 if ( target.atom != NULL ) {
3088 if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
3089 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, target.atom);
3090 }
3091 else if ( (target.atom->combine() == ld::Atom::combineByNameAndContent) || (target.atom->combine() == ld::Atom::combineByNameAndReferences) ) {
3092 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, target.atom);
3093 }
3094 else {
3095 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
3096 }
3097 }
3098 else {
3099 addFixup(src, cl, ld::Fixup::kindSetTargetAddress, target.weakImport, target.name);
3100 }
3101 if ( target.addend == 0 ) {
3102 assert(picBase.atom != NULL);
3103 addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, picBase.atom);
3104 addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, picBase.addend);
3105 addFixup(src, ld::Fixup::k4of4, kind);
3106 }
3107 else {
3108 addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, target.addend);
3109 addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, picBase.atom);
3110 addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, picBase.addend);
3111 addFixup(src, ld::Fixup::k5of5, kind);
3112 }
3113 }
3114
3115
3116
3117 template <typename A>
3118 uint32_t TentativeDefinitionSection<A>::computeAtomCount(class Parser<A>& parser,
3119 struct Parser<A>::LabelAndCFIBreakIterator& it,
3120 const struct Parser<A>::CFI_CU_InfoArrays&)
3121 {
3122 return parser.tentativeDefinitionCount();
3123 }
3124
3125 template <typename A>
3126 uint32_t TentativeDefinitionSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
3127 struct Parser<A>::LabelAndCFIBreakIterator& it,
3128 const struct Parser<A>::CFI_CU_InfoArrays&)
3129 {
3130 this->_beginAtoms = (Atom<A>*)p;
3131 uint32_t count = 0;
3132 for (uint32_t i=parser.undefinedStartIndex(); i < parser.undefinedEndIndex(); ++i) {
3133 const macho_nlist<P>& sym = parser.symbolFromIndex(i);
3134 if ( ((sym.n_type() & N_TYPE) == N_UNDF) && (sym.n_value() != 0) ) {
3135 uint64_t size = sym.n_value();
3136 uint8_t alignP2 = GET_COMM_ALIGN(sym.n_desc());
3137 if ( alignP2 == 0 ) {
3138 // common symbols align to their size
3139 // that is, a 4-byte common aligns to 4-bytes
3140 // if this size is not a power of two,
3141 // then round up to the next power of two
3142 alignP2 = 63 - (uint8_t)__builtin_clzll(size);
3143 if ( size != (1ULL << alignP2) )
3144 ++alignP2;
3145 }
3146 // limit alignment of extremely large commons to 2^15 bytes (8-page)
3147 if ( alignP2 > 15 )
3148 alignP2 = 15;
3149 Atom<A>* allocatedSpace = (Atom<A>*)p;
3150 new (allocatedSpace) Atom<A>(*this, parser.nameFromSymbol(sym), (pint_t)ULLONG_MAX, size,
3151 ld::Atom::definitionTentative, ld::Atom::combineByName,
3152 parser.scopeFromSymbol(sym), ld::Atom::typeZeroFill, ld::Atom::symbolTableIn,
3153 parser.dontDeadStripFromSymbol(sym), false, false, ld::Atom::Alignment(alignP2) );
3154 p += sizeof(Atom<A>);
3155 ++count;
3156 }
3157 }
3158 this->_endAtoms = (Atom<A>*)p;
3159 return count;
3160 }
3161
3162
3163 template <typename A>
3164 uint32_t AbsoluteSymbolSection<A>::computeAtomCount(class Parser<A>& parser,
3165 struct Parser<A>::LabelAndCFIBreakIterator& it,
3166 const struct Parser<A>::CFI_CU_InfoArrays&)
3167 {
3168 return parser.absoluteSymbolCount();
3169 }
3170
3171 template <typename A>
3172 uint32_t AbsoluteSymbolSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
3173 struct Parser<A>::LabelAndCFIBreakIterator& it,
3174 const struct Parser<A>::CFI_CU_InfoArrays&)
3175 {
3176 this->_beginAtoms = (Atom<A>*)p;
3177 uint32_t count = 0;
3178 for (uint32_t i=0; i < parser.symbolCount(); ++i) {
3179 const macho_nlist<P>& sym = parser.symbolFromIndex(i);
3180 if ( (sym.n_type() & N_TYPE) != N_ABS )
3181 continue;
3182 const char* absName = parser.nameFromSymbol(sym);
3183 // ignore .objc_class_name_* symbols
3184 if ( strncmp(absName, ".objc_class_name_", 17) == 0 )
3185 continue;
3186 // ignore .objc_class_name_* symbols
3187 if ( strncmp(absName, ".objc_category_name_", 20) == 0 )
3188 continue;
3189 // ignore empty *.eh symbols
3190 if ( strcmp(&absName[strlen(absName)-3], ".eh") == 0 )
3191 continue;
3192
3193 Atom<A>* allocatedSpace = (Atom<A>*)p;
3194 new (allocatedSpace) Atom<A>(*this, parser, sym, 0);
3195 p += sizeof(Atom<A>);
3196 ++count;
3197 }
3198 this->_endAtoms = (Atom<A>*)p;
3199 return count;
3200 }
3201
3202 template <typename A>
3203 Atom<A>* AbsoluteSymbolSection<A>::findAbsAtomForValue(typename A::P::uint_t value)
3204 {
3205 Atom<A>* end = this->_endAtoms;
3206 for(Atom<A>* p = this->_beginAtoms; p < end; ++p) {
3207 if ( p->_objAddress == value )
3208 return p;
3209 }
3210 return NULL;
3211 }
3212
3213
3214 template <typename A>
3215 uint32_t Parser<A>::indirectSymbol(uint32_t indirectIndex)
3216 {
3217 if ( indirectIndex >= _indirectTableCount )
3218 throw "indirect symbol index out of range";
3219 return E::get32(_indirectTable[indirectIndex]);
3220 }
3221
3222 template <typename A>
3223 const macho_nlist<typename A::P>& Parser<A>::symbolFromIndex(uint32_t index)
3224 {
3225 if ( index > _symbolCount )
3226 throw "symbol index out of range";
3227 return _symbols[index];
3228 }
3229
3230 template <typename A>
3231 const macho_section<typename A::P>* Parser<A>::machOSectionFromSectionIndex(uint32_t index)
3232 {
3233 if ( index >= _machOSectionsCount )
3234 throw "section index out of range";
3235 return &_sectionsStart[index];
3236 }
3237
3238 template <typename A>
3239 uint32_t Parser<A>::symbolIndexFromIndirectSectionAddress(pint_t addr, const macho_section<P>* sect)
3240 {
3241 uint32_t elementSize = 0;
3242 switch ( sect->flags() & SECTION_TYPE ) {
3243 case S_SYMBOL_STUBS:
3244 elementSize = sect->reserved2();
3245 break;
3246 case S_LAZY_SYMBOL_POINTERS:
3247 case S_NON_LAZY_SYMBOL_POINTERS:
3248 elementSize = sizeof(pint_t);
3249 break;
3250 default:
3251 throw "section does not use inirect symbol table";
3252 }
3253 uint32_t indexInSection = (addr - sect->addr()) / elementSize;
3254 uint32_t indexIntoIndirectTable = sect->reserved1() + indexInSection;
3255 return this->indirectSymbol(indexIntoIndirectTable);
3256 }
3257
3258
3259
3260 template <typename A>
3261 const char* Parser<A>::nameFromSymbol(const macho_nlist<P>& sym)
3262 {
3263 return &_strings[sym.n_strx()];
3264 }
3265
3266 template <typename A>
3267 ld::Atom::Scope Parser<A>::scopeFromSymbol(const macho_nlist<P>& sym)
3268 {
3269 if ( (sym.n_type() & N_EXT) == 0 )
3270 return ld::Atom::scopeTranslationUnit;
3271 else if ( (sym.n_type() & N_PEXT) != 0 )
3272 return ld::Atom::scopeLinkageUnit;
3273 else if ( this->nameFromSymbol(sym)[0] == 'l' ) // since all 'l' symbols will be remove, don't make them global
3274 return ld::Atom::scopeLinkageUnit;
3275 else
3276 return ld::Atom::scopeGlobal;
3277 }
3278
3279 template <typename A>
3280 ld::Atom::Definition Parser<A>::definitionFromSymbol(const macho_nlist<P>& sym)
3281 {
3282 switch ( sym.n_type() & N_TYPE ) {
3283 case N_ABS:
3284 return ld::Atom::definitionAbsolute;
3285 case N_SECT:
3286 return ld::Atom::definitionRegular;
3287 case N_UNDF:
3288 if ( sym.n_value() != 0 )
3289 return ld::Atom::definitionTentative;
3290 }
3291 throw "definitionFromSymbol() bad symbol";
3292 }
3293
3294 template <typename A>
3295 ld::Atom::Combine Parser<A>::combineFromSymbol(const macho_nlist<P>& sym)
3296 {
3297 if ( sym.n_desc() & N_WEAK_DEF )
3298 return ld::Atom::combineByName;
3299 else
3300 return ld::Atom::combineNever;
3301 }
3302
3303
3304 template <typename A>
3305 ld::Atom::SymbolTableInclusion Parser<A>::inclusionFromSymbol(const macho_nlist<P>& sym)
3306 {
3307 const char* symbolName = nameFromSymbol(sym);
3308 // labels beginning with 'l' (lowercase ell) are automatically removed in final linked images <rdar://problem/4571042>
3309 // labels beginning with 'L' should have been stripped by the assembler, so are stripped now
3310 if ( sym.n_desc() & REFERENCED_DYNAMICALLY )
3311 return ld::Atom::symbolTableInAndNeverStrip;
3312 else if ( symbolName[0] == 'l' )
3313 return ld::Atom::symbolTableNotInFinalLinkedImages;
3314 else if ( symbolName[0] == 'L' )
3315 return ld::Atom::symbolTableNotIn;
3316 else
3317 return ld::Atom::symbolTableIn;
3318 }
3319
3320 template <typename A>
3321 bool Parser<A>::dontDeadStripFromSymbol(const macho_nlist<P>& sym)
3322 {
3323 return ( (sym.n_desc() & (N_NO_DEAD_STRIP|REFERENCED_DYNAMICALLY)) != 0 );
3324 }
3325
3326 template <typename A>
3327 bool Parser<A>::isThumbFromSymbol(const macho_nlist<P>& sym)
3328 {
3329 return ( sym.n_desc() & N_ARM_THUMB_DEF );
3330 }
3331
3332 template <typename A>
3333 bool Parser<A>::weakImportFromSymbol(const macho_nlist<P>& sym)
3334 {
3335 return ( ((sym.n_type() & N_TYPE) == N_UNDF) && ((sym.n_desc() & N_WEAK_REF) != 0) );
3336 }
3337
3338 template <typename A>
3339 bool Parser<A>::resolverFromSymbol(const macho_nlist<P>& sym)
3340 {
3341 return ( sym.n_desc() & N_SYMBOL_RESOLVER );
3342 }
3343
3344 template <typename A>
3345 bool Parser<A>::altEntryFromSymbol(const macho_nlist<P>& sym)
3346 {
3347 return ( sym.n_desc() & N_ALT_ENTRY );
3348 }
3349
3350
3351 /* Skip over a LEB128 value (signed or unsigned). */
3352 static void
3353 skip_leb128 (const uint8_t ** offset, const uint8_t * end)
3354 {
3355 while (*offset != end && **offset >= 0x80)
3356 (*offset)++;
3357 if (*offset != end)
3358 (*offset)++;
3359 }
3360
3361 /* Read a ULEB128 into a 64-bit word. Return (uint64_t)-1 on overflow
3362 or error. On overflow, skip past the rest of the uleb128. */
3363 static uint64_t
3364 read_uleb128 (const uint8_t ** offset, const uint8_t * end)
3365 {
3366 uint64_t result = 0;
3367 int bit = 0;
3368
3369 do {
3370 uint64_t b;
3371
3372 if (*offset == end)
3373 return (uint64_t) -1;
3374
3375 b = **offset & 0x7f;
3376
3377 if (bit >= 64 || b << bit >> bit != b)
3378 result = (uint64_t) -1;
3379 else
3380 result |= b << bit, bit += 7;
3381 } while (*(*offset)++ >= 0x80);
3382 return result;
3383 }
3384
3385
3386 /* Skip over a DWARF attribute of form FORM. */
3387 template <typename A>
3388 bool Parser<A>::skip_form(const uint8_t ** offset, const uint8_t * end, uint64_t form,
3389 uint8_t addr_size, bool dwarf64)
3390 {
3391 int64_t sz=0;
3392
3393 switch (form)
3394 {
3395 case DW_FORM_addr:
3396 sz = addr_size;
3397 break;
3398
3399 case DW_FORM_block2:
3400 if (end - *offset < 2)
3401 return false;
3402 sz = 2 + A::P::E::get16(*(uint16_t*)offset);
3403 break;
3404
3405 case DW_FORM_block4:
3406 if (end - *offset < 4)
3407 return false;
3408 sz = 2 + A::P::E::get32(*(uint32_t*)offset);
3409 break;
3410
3411 case DW_FORM_data2:
3412 case DW_FORM_ref2:
3413 sz = 2;
3414 break;
3415
3416 case DW_FORM_data4:
3417 case DW_FORM_ref4:
3418 sz = 4;
3419 break;
3420
3421 case DW_FORM_data8:
3422 case DW_FORM_ref8:
3423 sz = 8;
3424 break;
3425
3426 case DW_FORM_string:
3427 while (*offset != end && **offset)
3428 ++*offset;
3429 case DW_FORM_data1:
3430 case DW_FORM_flag:
3431 case DW_FORM_ref1:
3432 sz = 1;
3433 break;
3434
3435 case DW_FORM_block:
3436 sz = read_uleb128 (offset, end);
3437 break;
3438
3439 case DW_FORM_block1:
3440 if (*offset == end)
3441 return false;
3442 sz = 1 + **offset;
3443 break;
3444
3445 case DW_FORM_sdata:
3446 case DW_FORM_udata:
3447 case DW_FORM_ref_udata:
3448 skip_leb128 (offset, end);
3449 return true;
3450
3451 case DW_FORM_strp:
3452 case DW_FORM_ref_addr:
3453 sz = 4;
3454 break;
3455
3456 case DW_FORM_sec_offset:
3457 sz = sizeof(typename A::P::uint_t);
3458 break;
3459
3460 case DW_FORM_exprloc:
3461 sz = read_uleb128 (offset, end);
3462 break;
3463
3464 case DW_FORM_flag_present:
3465 sz = 0;
3466 break;
3467
3468 case DW_FORM_ref_sig8:
3469 sz = 8;
3470 break;
3471
3472 default:
3473 return false;
3474 }
3475 if (end - *offset < sz)
3476 return false;
3477 *offset += sz;
3478 return true;
3479 }
3480
3481
3482 template <typename A>
3483 const char* Parser<A>::getDwarfString(uint64_t form, const uint8_t*& di)
3484 {
3485 uint32_t offset;
3486 const char* dwarfStrings;
3487 const char* result = NULL;
3488 switch (form) {
3489 case DW_FORM_string:
3490 result = (const char*)di;
3491 di += strlen(result) + 1;
3492 break;
3493 case DW_FORM_strp:
3494 offset = E::get32(*((uint32_t*)di));
3495 dwarfStrings = (char*)_file->fileContent() + _file->_dwarfDebugStringSect->offset();
3496 if ( offset < _file->_dwarfDebugStringSect->size() )
3497 result = &dwarfStrings[offset];
3498 else
3499 warning("dwarf DW_FORM_strp (offset=0x%08X) is too big in %s", offset, this->_path);
3500 di += 4;
3501 break;
3502 default:
3503 warning("unknown dwarf string encoding (form=%lld) in %s", form, this->_path);
3504 break;
3505 }
3506 return result;
3507 }
3508
3509 template <typename A>
3510 uint64_t Parser<A>::getDwarfOffset(uint64_t form, const uint8_t*& di, bool dwarf64)
3511 {
3512 if ( form == DW_FORM_sec_offset )
3513 form = (dwarf64 ? DW_FORM_data8 : DW_FORM_data4);
3514 uint64_t result = -1;
3515 switch (form) {
3516 case DW_FORM_data4:
3517 result = A::P::E::get32(*(uint32_t*)di);
3518 di += 4;
3519 break;
3520 case DW_FORM_data8:
3521 result = A::P::E::get64(*(uint64_t*)di);
3522 di += 8;
3523 break;
3524 default:
3525 warning("unknown dwarf DW_FORM_ for DW_AT_stmt_list in %s", this->_path);
3526 }
3527 return result;
3528 }
3529
3530
3531 template <typename A>
3532 struct AtomAndLineInfo {
3533 Atom<A>* atom;
3534 ld::Atom::LineInfo info;
3535 };
3536
3537
3538 // <rdar://problem/5591394> Add support to ld64 for N_FUN stabs when used for symbolic constants
3539 // Returns whether a stabStr belonging to an N_FUN stab represents a
3540 // symbolic constant rather than a function
3541 template <typename A>
3542 bool Parser<A>::isConstFunStabs(const char *stabStr)
3543 {
3544 const char* colon;
3545 // N_FUN can be used for both constants and for functions. In case it's a constant,
3546 // the format of the stabs string is "symname:c=<value>;"
3547 // ':' cannot appear in the symbol name, except if it's an Objective-C method
3548 // (in which case the symbol name starts with + or -, and then it's definitely
3549 // not a constant)
3550 return (stabStr != NULL) && (stabStr[0] != '+') && (stabStr[0] != '-')
3551 && ((colon = strchr(stabStr, ':')) != NULL)
3552 && (colon[1] == 'c') && (colon[2] == '=');
3553 }
3554
3555
3556 template <typename A>
3557 void Parser<A>::parseDebugInfo()
3558 {
3559 // check for dwarf __debug_info section
3560 if ( _file->_dwarfDebugInfoSect == NULL ) {
3561 // if no DWARF debug info, look for stabs
3562 this->parseStabs();
3563 return;
3564 }
3565 if ( _file->_dwarfDebugInfoSect->size() == 0 )
3566 return;
3567
3568 uint64_t stmtList;
3569 const char* tuDir;
3570 const char* tuName;
3571 if ( !read_comp_unit(&tuName, &tuDir, &stmtList) ) {
3572 // if can't parse dwarf, warn and give up
3573 _file->_dwarfTranslationUnitPath = NULL;
3574 warning("can't parse dwarf compilation unit info in %s", _path);
3575 _file->_debugInfoKind = ld::relocatable::File::kDebugInfoNone;
3576 return;
3577 }
3578 if ( (tuName != NULL) && (tuName[0] == '/') ) {
3579 _file->_dwarfTranslationUnitPath = tuName;
3580 }
3581 else if ( (tuDir != NULL) && (tuName != NULL) ) {
3582 asprintf((char**)&(_file->_dwarfTranslationUnitPath), "%s/%s", tuDir, tuName);
3583 }
3584 else if ( tuDir == NULL ) {
3585 _file->_dwarfTranslationUnitPath = tuName;
3586 }
3587 else {
3588 _file->_dwarfTranslationUnitPath = NULL;
3589 }
3590
3591 // add line number info to atoms from dwarf
3592 std::vector<AtomAndLineInfo<A> > entries;
3593 entries.reserve(64);
3594 if ( _file->_debugInfoKind == ld::relocatable::File::kDebugInfoDwarf ) {
3595 // file with just data will have no __debug_line info
3596 if ( (_file->_dwarfDebugLineSect != NULL) && (_file->_dwarfDebugLineSect->size() != 0) ) {
3597 // validate stmt_list
3598 if ( (stmtList != (uint64_t)-1) && (stmtList < _file->_dwarfDebugLineSect->size()) ) {
3599 const uint8_t* debug_line = (uint8_t*)_file->fileContent() + _file->_dwarfDebugLineSect->offset();
3600 struct line_reader_data* lines = line_open(&debug_line[stmtList],
3601 _file->_dwarfDebugLineSect->size() - stmtList, E::little_endian);
3602 struct line_info result;
3603 Atom<A>* curAtom = NULL;
3604 uint32_t curAtomOffset = 0;
3605 uint32_t curAtomAddress = 0;
3606 uint32_t curAtomSize = 0;
3607 std::map<uint32_t,const char*> dwarfIndexToFile;
3608 if ( lines != NULL ) {
3609 while ( line_next(lines, &result, line_stop_pc) ) {
3610 //fprintf(stderr, "curAtom=%p, result.pc=0x%llX, result.line=%llu, result.end_of_sequence=%d,"
3611 // " curAtomAddress=0x%X, curAtomSize=0x%X\n",
3612 // curAtom, result.pc, result.line, result.end_of_sequence, curAtomAddress, curAtomSize);
3613 // work around weird debug line table compiler generates if no functions in __text section
3614 if ( (curAtom == NULL) && (result.pc == 0) && result.end_of_sequence && (result.file == 1))
3615 continue;
3616 // for performance, see if in next pc is in current atom
3617 if ( (curAtom != NULL) && (curAtomAddress <= result.pc) && (result.pc < (curAtomAddress+curAtomSize)) ) {
3618 curAtomOffset = result.pc - curAtomAddress;
3619 }
3620 // or pc at end of current atom
3621 else if ( result.end_of_sequence && (curAtom != NULL) && (result.pc == (curAtomAddress+curAtomSize)) ) {
3622 curAtomOffset = result.pc - curAtomAddress;
3623 }
3624 // or only one function that is a one line function
3625 else if ( result.end_of_sequence && (curAtom == NULL) && (this->findAtomByAddress(0) != NULL) && (result.pc == this->findAtomByAddress(0)->size()) ) {
3626 curAtom = this->findAtomByAddress(0);
3627 curAtomOffset = result.pc - curAtom->objectAddress();
3628 curAtomAddress = curAtom->objectAddress();
3629 curAtomSize = curAtom->size();
3630 }
3631 else {
3632 // do slow look up of atom by address
3633 try {
3634 curAtom = this->findAtomByAddress(result.pc);
3635 }
3636 catch (...) {
3637 // in case of bug in debug info, don't abort link, just limp on
3638 curAtom = NULL;
3639 }
3640 if ( curAtom == NULL )
3641 break; // file has line info but no functions
3642 if ( result.end_of_sequence && (curAtomAddress+curAtomSize < result.pc) ) {
3643 // a one line function can be returned by line_next() as one entry with pc at end of blob
3644 // look for alt atom starting at end of previous atom
3645 uint32_t previousEnd = curAtomAddress+curAtomSize;
3646 Atom<A>* alt = this->findAtomByAddressOrNullIfStub(previousEnd);
3647 if ( alt == NULL )
3648 continue; // ignore spurious debug info for stubs
3649 if ( result.pc <= alt->objectAddress() + alt->size() ) {
3650 curAtom = alt;
3651 curAtomOffset = result.pc - alt->objectAddress();
3652 curAtomAddress = alt->objectAddress();
3653 curAtomSize = alt->size();
3654 }
3655 else {
3656 curAtomOffset = result.pc - curAtom->objectAddress();
3657 curAtomAddress = curAtom->objectAddress();
3658 curAtomSize = curAtom->size();
3659 }
3660 }
3661 else {
3662 curAtomOffset = result.pc - curAtom->objectAddress();
3663 curAtomAddress = curAtom->objectAddress();
3664 curAtomSize = curAtom->size();
3665 }
3666 }
3667 const char* filename;
3668 std::map<uint32_t,const char*>::iterator pos = dwarfIndexToFile.find(result.file);
3669 if ( pos == dwarfIndexToFile.end() ) {
3670 filename = line_file(lines, result.file);
3671 dwarfIndexToFile[result.file] = filename;
3672 }
3673 else {
3674 filename = pos->second;
3675 }
3676 // only record for ~8000 line info records per function
3677 if ( curAtom->roomForMoreLineInfoCount() ) {
3678 AtomAndLineInfo<A> entry;
3679 entry.atom = curAtom;
3680 entry.info.atomOffset = curAtomOffset;
3681 entry.info.fileName = filename;
3682 entry.info.lineNumber = result.line;
3683 //fprintf(stderr, "addr=0x%08llX, line=%lld, file=%s, atom=%s, atom.size=0x%X, end=%d\n",
3684 // result.pc, result.line, filename, curAtom->name(), curAtomSize, result.end_of_sequence);
3685 entries.push_back(entry);
3686 curAtom->incrementLineInfoCount();
3687 }
3688 if ( result.end_of_sequence ) {
3689 curAtom = NULL;
3690 }
3691 }
3692 line_free(lines);
3693 }
3694 }
3695 }
3696 }
3697
3698 // assign line info start offset for each atom
3699 uint8_t* p = _file->_atomsArray;
3700 uint32_t liOffset = 0;
3701 for(int i=_file->_atomsArrayCount; i > 0; --i) {
3702 Atom<A>* atom = (Atom<A>*)p;
3703 atom->_lineInfoStartIndex = liOffset;
3704 liOffset += atom->_lineInfoCount;
3705 atom->_lineInfoCount = 0;
3706 p += sizeof(Atom<A>);
3707 }
3708 assert(liOffset == entries.size());
3709 _file->_lineInfos.resize(liOffset);
3710
3711 // copy each line info for each atom
3712 for (typename std::vector<AtomAndLineInfo<A> >::iterator it = entries.begin(); it != entries.end(); ++it) {
3713 uint32_t slot = it->atom->_lineInfoStartIndex + it->atom->_lineInfoCount;
3714 _file->_lineInfos[slot] = it->info;
3715 it->atom->_lineInfoCount++;
3716 }
3717
3718 // done with temp vector
3719 entries.clear();
3720 }
3721
3722 template <typename A>
3723 void Parser<A>::parseStabs()
3724 {
3725 // scan symbol table for stabs entries
3726 Atom<A>* currentAtom = NULL;
3727 pint_t currentAtomAddress = 0;
3728 enum { start, inBeginEnd, inFun } state = start;
3729 for (uint32_t symbolIndex = 0; symbolIndex < _symbolCount; ++symbolIndex ) {
3730 const macho_nlist<P>& sym = this->symbolFromIndex(symbolIndex);
3731 bool useStab = true;
3732 uint8_t type = sym.n_type();
3733 const char* symString = (sym.n_strx() != 0) ? this->nameFromSymbol(sym) : NULL;
3734 if ( (type & N_STAB) != 0 ) {
3735 _file->_debugInfoKind = (_hasUUID ? ld::relocatable::File::kDebugInfoStabsUUID : ld::relocatable::File::kDebugInfoStabs);
3736 ld::relocatable::File::Stab stab;
3737 stab.atom = NULL;
3738 stab.type = type;
3739 stab.other = sym.n_sect();
3740 stab.desc = sym.n_desc();
3741 stab.value = sym.n_value();
3742 stab.string = NULL;
3743 switch (state) {
3744 case start:
3745 switch (type) {
3746 case N_BNSYM:
3747 // beginning of function block
3748 state = inBeginEnd;
3749 // fall into case to lookup atom by addresss
3750 case N_LCSYM:
3751 case N_STSYM:
3752 currentAtomAddress = sym.n_value();
3753 currentAtom = this->findAtomByAddress(currentAtomAddress);
3754 if ( currentAtom != NULL ) {
3755 stab.atom = currentAtom;
3756 stab.string = symString;
3757 }
3758 else {
3759 fprintf(stderr, "can't find atom for stabs BNSYM at %08llX in %s",
3760 (uint64_t)sym.n_value(), _path);
3761 }
3762 break;
3763 case N_SO:
3764 case N_OSO:
3765 case N_OPT:
3766 case N_LSYM:
3767 case N_RSYM:
3768 case N_PSYM:
3769 case N_AST:
3770 // not associated with an atom, just copy
3771 stab.string = symString;
3772 break;
3773 case N_GSYM:
3774 {
3775 // n_value field is NOT atom address ;-(
3776 // need to find atom by name match
3777 const char* colon = strchr(symString, ':');
3778 if ( colon != NULL ) {
3779 // build underscore leading name
3780 int nameLen = colon - symString;
3781 char symName[nameLen+2];
3782 strlcpy(&symName[1], symString, nameLen+1);
3783 symName[0] = '_';
3784 symName[nameLen+1] = '\0';
3785 currentAtom = this->findAtomByName(symName);
3786 if ( currentAtom != NULL ) {
3787 stab.atom = currentAtom;
3788 stab.string = symString;
3789 }
3790 }
3791 else {
3792 // might be a debug-note without trailing :G()
3793 currentAtom = this->findAtomByName(symString);
3794 if ( currentAtom != NULL ) {
3795 stab.atom = currentAtom;
3796 stab.string = symString;
3797 }
3798 }
3799 if ( stab.atom == NULL ) {
3800 // ld_classic added bogus GSYM stabs for old style dtrace probes
3801 if ( (strncmp(symString, "__dtrace_probe$", 15) != 0) )
3802 warning("can't find atom for N_GSYM stabs %s in %s", symString, _path);
3803 useStab = false;
3804 }
3805 break;
3806 }
3807 case N_FUN:
3808 if ( isConstFunStabs(symString) ) {
3809 // constant not associated with a function
3810 stab.string = symString;
3811 }
3812 else {
3813 // old style stabs without BNSYM
3814 state = inFun;
3815 currentAtomAddress = sym.n_value();
3816 currentAtom = this->findAtomByAddress(currentAtomAddress);
3817 if ( currentAtom != NULL ) {
3818 stab.atom = currentAtom;
3819 stab.string = symString;
3820 }
3821 else {
3822 warning("can't find atom for stabs FUN at %08llX in %s",
3823 (uint64_t)currentAtomAddress, _path);
3824 }
3825 }
3826 break;
3827 case N_SOL:
3828 case N_SLINE:
3829 stab.string = symString;
3830 // old stabs
3831 break;
3832 case N_BINCL:
3833 case N_EINCL:
3834 case N_EXCL:
3835 stab.string = symString;
3836 // -gfull built .o file
3837 break;
3838 default:
3839 warning("unknown stabs type 0x%X in %s", type, _path);
3840 }
3841 break;
3842 case inBeginEnd:
3843 stab.atom = currentAtom;
3844 switch (type) {
3845 case N_ENSYM:
3846 state = start;
3847 currentAtom = NULL;
3848 break;
3849 case N_LCSYM:
3850 case N_STSYM:
3851 {
3852 Atom<A>* nestedAtom = this->findAtomByAddress(sym.n_value());
3853 if ( nestedAtom != NULL ) {
3854 stab.atom = nestedAtom;
3855 stab.string = symString;
3856 }
3857 else {
3858 warning("can't find atom for stabs 0x%X at %08llX in %s",
3859 type, (uint64_t)sym.n_value(), _path);
3860 }
3861 break;
3862 }
3863 case N_LBRAC:
3864 case N_RBRAC:
3865 case N_SLINE:
3866 // adjust value to be offset in atom
3867 stab.value -= currentAtomAddress;
3868 default:
3869 stab.string = symString;
3870 break;
3871 }
3872 break;
3873 case inFun:
3874 switch (type) {
3875 case N_FUN:
3876 if ( isConstFunStabs(symString) ) {
3877 stab.atom = currentAtom;
3878 stab.string = symString;
3879 }
3880 else {
3881 if ( sym.n_sect() != 0 ) {
3882 // found another start stab, must be really old stabs...
3883 currentAtomAddress = sym.n_value();
3884 currentAtom = this->findAtomByAddress(currentAtomAddress);
3885 if ( currentAtom != NULL ) {
3886 stab.atom = currentAtom;
3887 stab.string = symString;
3888 }
3889 else {
3890 warning("can't find atom for stabs FUN at %08llX in %s",
3891 (uint64_t)currentAtomAddress, _path);
3892 }
3893 }
3894 else {
3895 // found ending stab, switch back to start state
3896 stab.string = symString;
3897 stab.atom = currentAtom;
3898 state = start;
3899 currentAtom = NULL;
3900 }
3901 }
3902 break;
3903 case N_LBRAC:
3904 case N_RBRAC:
3905 case N_SLINE:
3906 // adjust value to be offset in atom
3907 stab.value -= currentAtomAddress;
3908 stab.atom = currentAtom;
3909 break;
3910 case N_SO:
3911 stab.string = symString;
3912 state = start;
3913 break;
3914 default:
3915 stab.atom = currentAtom;
3916 stab.string = symString;
3917 break;
3918 }
3919 break;
3920 }
3921 // add to list of stabs for this .o file
3922 if ( useStab )
3923 _file->_stabs.push_back(stab);
3924 }
3925 }
3926 }
3927
3928
3929
3930 // Look at the compilation unit DIE and determine
3931 // its NAME, compilation directory (in COMP_DIR) and its
3932 // line number information offset (in STMT_LIST). NAME and COMP_DIR
3933 // may be NULL (especially COMP_DIR) if they are not in the .o file;
3934 // STMT_LIST will be (uint64_t) -1.
3935 //
3936 // At present this assumes that there's only one compilation unit DIE.
3937 //
3938 template <typename A>
3939 bool Parser<A>::read_comp_unit(const char ** name, const char ** comp_dir,
3940 uint64_t *stmt_list)
3941 {
3942 const uint8_t * debug_info;
3943 const uint8_t * debug_abbrev;
3944 const uint8_t * di;
3945 const uint8_t * da;
3946 const uint8_t * end;
3947 const uint8_t * enda;
3948 uint64_t sz;
3949 uint16_t vers;
3950 uint64_t abbrev_base;
3951 uint64_t abbrev;
3952 uint8_t address_size;
3953 bool dwarf64;
3954
3955 *name = NULL;
3956 *comp_dir = NULL;
3957 *stmt_list = (uint64_t) -1;
3958
3959 if ( (_file->_dwarfDebugInfoSect == NULL) || (_file->_dwarfDebugAbbrevSect == NULL) )
3960 return false;
3961
3962 debug_info = (uint8_t*)_file->fileContent() + _file->_dwarfDebugInfoSect->offset();
3963 debug_abbrev = (uint8_t*)_file->fileContent() + _file->_dwarfDebugAbbrevSect->offset();
3964 di = debug_info;
3965
3966 if (_file->_dwarfDebugInfoSect->size() < 12)
3967 /* Too small to be a real debug_info section. */
3968 return false;
3969 sz = A::P::E::get32(*(uint32_t*)di);
3970 di += 4;
3971 dwarf64 = sz == 0xffffffff;
3972 if (dwarf64)
3973 sz = A::P::E::get64(*(uint64_t*)di), di += 8;
3974 else if (sz > 0xffffff00)
3975 /* Unknown dwarf format. */
3976 return false;
3977
3978 /* Verify claimed size. */
3979 if (sz + (di - debug_info) > _file->_dwarfDebugInfoSect->size() || sz <= (dwarf64 ? 23 : 11))
3980 return false;
3981
3982 vers = A::P::E::get16(*(uint16_t*)di);
3983 if (vers < 2 || vers > 4)
3984 /* DWARF version wrong for this code.
3985 Chances are we could continue anyway, but we don't know for sure. */
3986 return false;
3987 di += 2;
3988
3989 /* Find the debug_abbrev section. */
3990 abbrev_base = dwarf64 ? A::P::E::get64(*(uint64_t*)di) : A::P::E::get32(*(uint32_t*)di);
3991 di += dwarf64 ? 8 : 4;
3992
3993 if (abbrev_base > _file->_dwarfDebugAbbrevSect->size())
3994 return false;
3995 da = debug_abbrev + abbrev_base;
3996 enda = debug_abbrev + _file->_dwarfDebugAbbrevSect->size();
3997
3998 address_size = *di++;
3999
4000 /* Find the abbrev number we're looking for. */
4001 end = di + sz;
4002 abbrev = read_uleb128 (&di, end);
4003 if (abbrev == (uint64_t) -1)
4004 return false;
4005
4006 /* Skip through the debug_abbrev section looking for that abbrev. */
4007 for (;;)
4008 {
4009 uint64_t this_abbrev = read_uleb128 (&da, enda);
4010 uint64_t attr;
4011
4012 if (this_abbrev == abbrev)
4013 /* This is almost always taken. */
4014 break;
4015 skip_leb128 (&da, enda); /* Skip the tag. */
4016 if (da == enda)
4017 return false;
4018 da++; /* Skip the DW_CHILDREN_* value. */
4019
4020 do {
4021 attr = read_uleb128 (&da, enda);
4022 skip_leb128 (&da, enda);
4023 } while (attr != 0 && attr != (uint64_t) -1);
4024 if (attr != 0)
4025 return false;
4026 }
4027
4028 /* Check that the abbrev is one for a DW_TAG_compile_unit. */
4029 if (read_uleb128 (&da, enda) != DW_TAG_compile_unit)
4030 return false;
4031 if (da == enda)
4032 return false;
4033 da++; /* Skip the DW_CHILDREN_* value. */
4034
4035 /* Now, go through the DIE looking for DW_AT_name,
4036 DW_AT_comp_dir, and DW_AT_stmt_list. */
4037 for (;;)
4038 {
4039 uint64_t attr = read_uleb128 (&da, enda);
4040 uint64_t form = read_uleb128 (&da, enda);
4041
4042 if (attr == (uint64_t) -1)
4043 return false;
4044 else if (attr == 0)
4045 return true;
4046 if (form == DW_FORM_indirect)
4047 form = read_uleb128 (&di, end);
4048
4049 switch (attr) {
4050 case DW_AT_name:
4051 *name = getDwarfString(form, di);
4052 break;
4053 case DW_AT_comp_dir:
4054 *comp_dir = getDwarfString(form, di);
4055 break;
4056 case DW_AT_stmt_list:
4057 *stmt_list = getDwarfOffset(form, di, dwarf64);
4058 break;
4059 default:
4060 if (! skip_form (&di, end, form, address_size, dwarf64))
4061 return false;
4062 }
4063 }
4064 }
4065
4066
4067
4068 template <typename A>
4069 File<A>::~File()
4070 {
4071 free(_sectionsArray);
4072 free(_atomsArray);
4073 }
4074
4075 template <typename A>
4076 const char* File<A>::translationUnitSource() const
4077 {
4078 return _dwarfTranslationUnitPath;
4079 }
4080
4081 template <typename A>
4082 bool File<A>::forEachAtom(ld::File::AtomHandler& handler) const
4083 {
4084 handler.doFile(*this);
4085 uint8_t* p = _atomsArray;
4086 for(int i=_atomsArrayCount; i > 0; --i) {
4087 handler.doAtom(*((Atom<A>*)p));
4088 p += sizeof(Atom<A>);
4089 }
4090 p = _aliasAtomsArray;
4091 for(int i=_aliasAtomsArrayCount; i > 0; --i) {
4092 handler.doAtom(*((AliasAtom*)p));
4093 p += sizeof(AliasAtom);
4094 }
4095
4096 return (_atomsArrayCount != 0) || (_aliasAtomsArrayCount != 0);
4097 }
4098
4099 template <typename A>
4100 const char* Section<A>::makeSegmentName(const macho_section<typename A::P>* sect)
4101 {
4102 // mach-o section record only has room for 16-byte seg/sect names
4103 // so a 16-byte name has no trailing zero
4104 const char* name = sect->segname();
4105 if ( strlen(name) < 16 )
4106 return name;
4107 char* tmp = new char[17];
4108 strlcpy(tmp, name, 17);
4109 return tmp;
4110 }
4111
4112 template <typename A>
4113 const char* Section<A>::makeSectionName(const macho_section<typename A::P>* sect)
4114 {
4115 const char* name = sect->sectname();
4116 if ( strlen(name) < 16 )
4117 return name;
4118
4119 // special case common long section names so we don't have to malloc
4120 if ( strncmp(sect->sectname(), "__objc_classrefs", 16) == 0 )
4121 return "__objc_classrefs";
4122 if ( strncmp(sect->sectname(), "__objc_classlist", 16) == 0 )
4123 return "__objc_classlist";
4124 if ( strncmp(sect->sectname(), "__objc_nlclslist", 16) == 0 )
4125 return "__objc_nlclslist";
4126 if ( strncmp(sect->sectname(), "__objc_nlcatlist", 16) == 0 )
4127 return "__objc_nlcatlist";
4128 if ( strncmp(sect->sectname(), "__objc_protolist", 16) == 0 )
4129 return "__objc_protolist";
4130 if ( strncmp(sect->sectname(), "__objc_protorefs", 16) == 0 )
4131 return "__objc_protorefs";
4132 if ( strncmp(sect->sectname(), "__objc_superrefs", 16) == 0 )
4133 return "__objc_superrefs";
4134 if ( strncmp(sect->sectname(), "__objc_imageinfo", 16) == 0 )
4135 return "__objc_imageinfo";
4136 if ( strncmp(sect->sectname(), "__objc_stringobj", 16) == 0 )
4137 return "__objc_stringobj";
4138 if ( strncmp(sect->sectname(), "__gcc_except_tab", 16) == 0 )
4139 return "__gcc_except_tab";
4140
4141 char* tmp = new char[17];
4142 strlcpy(tmp, name, 17);
4143 return tmp;
4144 }
4145
4146 template <typename A>
4147 bool Section<A>::readable(const macho_section<typename A::P>* sect)
4148 {
4149 return true;
4150 }
4151
4152 template <typename A>
4153 bool Section<A>::writable(const macho_section<typename A::P>* sect)
4154 {
4155 // mach-o .o files do not contain segment permissions
4156 // we just know TEXT is special
4157 return ( strcmp(sect->segname(), "__TEXT") != 0 );
4158 }
4159
4160 template <typename A>
4161 bool Section<A>::exectuable(const macho_section<typename A::P>* sect)
4162 {
4163 // mach-o .o files do not contain segment permissions
4164 // we just know TEXT is special
4165 return ( strcmp(sect->segname(), "__TEXT") == 0 );
4166 }
4167
4168
4169 template <typename A>
4170 ld::Section::Type Section<A>::sectionType(const macho_section<typename A::P>* sect)
4171 {
4172 switch ( sect->flags() & SECTION_TYPE ) {
4173 case S_ZEROFILL:
4174 return ld::Section::typeZeroFill;
4175 case S_CSTRING_LITERALS:
4176 if ( (strcmp(sect->sectname(), "__cstring") == 0) && (strcmp(sect->segname(), "__TEXT") == 0) )
4177 return ld::Section::typeCString;
4178 else
4179 return ld::Section::typeNonStdCString;
4180 case S_4BYTE_LITERALS:
4181 return ld::Section::typeLiteral4;
4182 case S_8BYTE_LITERALS:
4183 return ld::Section::typeLiteral8;
4184 case S_LITERAL_POINTERS:
4185 return ld::Section::typeCStringPointer;
4186 case S_NON_LAZY_SYMBOL_POINTERS:
4187 return ld::Section::typeNonLazyPointer;
4188 case S_LAZY_SYMBOL_POINTERS:
4189 return ld::Section::typeLazyPointer;
4190 case S_SYMBOL_STUBS:
4191 return ld::Section::typeStub;
4192 case S_MOD_INIT_FUNC_POINTERS:
4193 return ld::Section::typeInitializerPointers;
4194 case S_MOD_TERM_FUNC_POINTERS:
4195 return ld::Section::typeTerminatorPointers;
4196 case S_INTERPOSING:
4197 return ld::Section::typeUnclassified;
4198 case S_16BYTE_LITERALS:
4199 return ld::Section::typeLiteral16;
4200 case S_REGULAR:
4201 case S_COALESCED:
4202 if ( sect->flags() & S_ATTR_PURE_INSTRUCTIONS ) {
4203 return ld::Section::typeCode;
4204 }
4205 else if ( strcmp(sect->segname(), "__TEXT") == 0 ) {
4206 if ( strcmp(sect->sectname(), "__eh_frame") == 0 )
4207 return ld::Section::typeCFI;
4208 else if ( strcmp(sect->sectname(), "__ustring") == 0 )
4209 return ld::Section::typeUTF16Strings;
4210 else if ( strcmp(sect->sectname(), "__textcoal_nt") == 0 )
4211 return ld::Section::typeCode;
4212 else if ( strcmp(sect->sectname(), "__StaticInit") == 0 )
4213 return ld::Section::typeCode;
4214 else if ( strcmp(sect->sectname(), "__constructor") == 0 )
4215 return ld::Section::typeInitializerPointers;
4216 }
4217 else if ( strcmp(sect->segname(), "__DATA") == 0 ) {
4218 if ( strcmp(sect->sectname(), "__cfstring") == 0 )
4219 return ld::Section::typeCFString;
4220 else if ( strcmp(sect->sectname(), "__dyld") == 0 )
4221 return ld::Section::typeDyldInfo;
4222 else if ( strcmp(sect->sectname(), "__program_vars") == 0 )
4223 return ld::Section::typeDyldInfo;
4224 else if ( strncmp(sect->sectname(), "__objc_classrefs", 16) == 0 )
4225 return ld::Section::typeObjCClassRefs;
4226 else if ( strcmp(sect->sectname(), "__objc_catlist") == 0 )
4227 return ld::Section::typeObjC2CategoryList;
4228 }
4229 else if ( strcmp(sect->segname(), "__OBJC") == 0 ) {
4230 if ( strcmp(sect->sectname(), "__class") == 0 )
4231 return ld::Section::typeObjC1Classes;
4232 }
4233 break;
4234 case S_THREAD_LOCAL_REGULAR:
4235 return ld::Section::typeTLVInitialValues;
4236 case S_THREAD_LOCAL_ZEROFILL:
4237 return ld::Section::typeTLVZeroFill;
4238 case S_THREAD_LOCAL_VARIABLES:
4239 return ld::Section::typeTLVDefs;
4240 case S_THREAD_LOCAL_VARIABLE_POINTERS:
4241 return ld::Section::typeTLVPointers;
4242 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
4243 return ld::Section::typeTLVInitializerPointers;
4244 }
4245 return ld::Section::typeUnclassified;
4246 }
4247
4248
4249 template <typename A>
4250 Atom<A>* Section<A>::findContentAtomByAddress(pint_t addr, class Atom<A>* start, class Atom<A>* end)
4251 {
4252 // do a binary search of atom array
4253 uint32_t atomCount = end - start;
4254 Atom<A>* base = start;
4255 for (uint32_t n = atomCount; n > 0; n /= 2) {
4256 Atom<A>* pivot = &base[n/2];
4257 pint_t atomStartAddr = pivot->_objAddress;
4258 pint_t atomEndAddr = atomStartAddr + pivot->_size;
4259 if ( atomStartAddr <= addr ) {
4260 // address in normal atom
4261 if (addr < atomEndAddr)
4262 return pivot;
4263 // address in "end" label (but not in alias)
4264 if ( (pivot->_size == 0) && (addr == atomEndAddr) && !pivot->isAlias() )
4265 return pivot;
4266 }
4267 if ( addr >= atomEndAddr ) {
4268 // key > pivot
4269 // move base to atom after pivot
4270 base = &pivot[1];
4271 --n;
4272 }
4273 else {
4274 // key < pivot
4275 // keep same base
4276 }
4277 }
4278 return NULL;
4279 }
4280
4281 template <typename A>
4282 ld::Atom::Alignment Section<A>::alignmentForAddress(pint_t addr)
4283 {
4284 const uint32_t sectionAlignment = this->_machOSection->align();
4285 uint32_t modulus = (addr % (1 << sectionAlignment));
4286 if ( modulus > 0xFFFF )
4287 warning("alignment for symbol at address 0x%08llX in %s exceeds 2^16", (uint64_t)addr, this->file().path());
4288 return ld::Atom::Alignment(sectionAlignment, modulus);
4289 }
4290
4291 template <typename A>
4292 uint32_t Section<A>::sectionNum(class Parser<A>& parser) const
4293 {
4294 if ( _machOSection == NULL )
4295 return 0;
4296 else
4297 return 1 + (this->_machOSection - parser.firstMachOSection());
4298 }
4299
4300 // arm does not have zero cost exceptions
4301 template <>
4302 uint32_t CFISection<arm>::cfiCount(Parser<arm>& parser)
4303 {
4304 if ( parser.armUsesZeroCostExceptions() ) {
4305 // create ObjectAddressSpace object for use by libunwind
4306 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
4307 return libunwind::CFI_Parser<OAS>::getCFICount(oas,
4308 this->_machOSection->addr(), this->_machOSection->size());
4309 }
4310 return 0;
4311 }
4312
4313 template <typename A>
4314 uint32_t CFISection<A>::cfiCount(Parser<A>& parser)
4315 {
4316 // create ObjectAddressSpace object for use by libunwind
4317 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
4318 return libunwind::CFI_Parser<OAS>::getCFICount(oas,
4319 this->_machOSection->addr(), this->_machOSection->size());
4320 }
4321
4322 template <typename A>
4323 void CFISection<A>::warnFunc(void* ref, uint64_t funcAddr, const char* msg)
4324 {
4325 Parser<A>* parser = (Parser<A>*)ref;
4326 if ( ! parser->warnUnwindConversionProblems() )
4327 return;
4328 if ( funcAddr != CFI_INVALID_ADDRESS ) {
4329 // atoms are not constructed yet, so scan symbol table for labels
4330 const char* name = parser->scanSymbolTableForAddress(funcAddr);
4331 warning("could not create compact unwind for %s: %s", name, msg);
4332 }
4333 else {
4334 warning("could not create compact unwind: %s", msg);
4335 }
4336 }
4337
4338 template <>
4339 bool CFISection<x86_64>::needsRelocating()
4340 {
4341 return true;
4342 }
4343
4344 template <>
4345 bool CFISection<arm64>::needsRelocating()
4346 {
4347 return true;
4348 }
4349
4350 template <typename A>
4351 bool CFISection<A>::needsRelocating()
4352 {
4353 return false;
4354 }
4355
4356 template <>
4357 void CFISection<x86_64>::cfiParse(class Parser<x86_64>& parser, uint8_t* buffer,
4358 libunwind::CFI_Atom_Info<CFISection<x86_64>::OAS>::CFI_Atom_Info cfiArray[],
4359 uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
4360 {
4361 // copy __eh_frame data to buffer
4362 memcpy(buffer, file().fileContent() + this->_machOSection->offset(), this->_machOSection->size());
4363
4364 // and apply relocations
4365 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + this->_machOSection->reloff());
4366 const macho_relocation_info<P>* relocsEnd = &relocs[this->_machOSection->nreloc()];
4367 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
4368 uint64_t value = 0;
4369 switch ( reloc->r_type() ) {
4370 case X86_64_RELOC_SUBTRACTOR:
4371 value = 0 - parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4372 ++reloc;
4373 if ( reloc->r_extern() )
4374 value += parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4375 break;
4376 case X86_64_RELOC_UNSIGNED:
4377 value = parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4378 break;
4379 case X86_64_RELOC_GOT:
4380 // this is used for the reference to the personality function in CIEs
4381 // store the symbol number of the personality function for later use as a Fixup
4382 value = reloc->r_symbolnum();
4383 break;
4384 default:
4385 fprintf(stderr, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc->r_address());
4386 break;
4387 }
4388 uint64_t* p64;
4389 uint32_t* p32;
4390 switch ( reloc->r_length() ) {
4391 case 3:
4392 p64 = (uint64_t*)&buffer[reloc->r_address()];
4393 E::set64(*p64, value + E::get64(*p64));
4394 break;
4395 case 2:
4396 p32 = (uint32_t*)&buffer[reloc->r_address()];
4397 E::set32(*p32, value + E::get32(*p32));
4398 break;
4399 default:
4400 fprintf(stderr, "CFISection::cfiParse() unexpected relocation size at r_address=0x%08X\n", reloc->r_address());
4401 break;
4402 }
4403 }
4404
4405 // create ObjectAddressSpace object for use by libunwind
4406 OAS oas(*this, buffer);
4407
4408 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
4409 const char* msg;
4410 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_x86_64>::parseCFIs(
4411 oas, this->_machOSection->addr(), this->_machOSection->size(),
4412 cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
4413 cfiArray, count, (void*)&parser, warnFunc);
4414 if ( msg != NULL )
4415 throwf("malformed __eh_frame section: %s", msg);
4416 }
4417
4418 template <>
4419 void CFISection<x86>::cfiParse(class Parser<x86>& parser, uint8_t* buffer,
4420 libunwind::CFI_Atom_Info<CFISection<x86>::OAS>::CFI_Atom_Info cfiArray[],
4421 uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
4422 {
4423 // create ObjectAddressSpace object for use by libunwind
4424 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
4425
4426 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
4427 const char* msg;
4428 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_x86>::parseCFIs(
4429 oas, this->_machOSection->addr(), this->_machOSection->size(),
4430 cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
4431 cfiArray, count, (void*)&parser, warnFunc);
4432 if ( msg != NULL )
4433 throwf("malformed __eh_frame section: %s", msg);
4434 }
4435
4436
4437
4438
4439 template <>
4440 void CFISection<arm>::cfiParse(class Parser<arm>& parser, uint8_t* buffer,
4441 libunwind::CFI_Atom_Info<CFISection<arm>::OAS>::CFI_Atom_Info cfiArray[],
4442 uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
4443 {
4444 if ( !parser.armUsesZeroCostExceptions() ) {
4445 // most arm do not use zero cost exceptions
4446 assert(count == 0);
4447 return;
4448 }
4449 // create ObjectAddressSpace object for use by libunwind
4450 OAS oas(*this, (uint8_t*)this->file().fileContent()+this->_machOSection->offset());
4451
4452 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
4453 const char* msg;
4454 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_arm>::parseCFIs(
4455 oas, this->_machOSection->addr(), this->_machOSection->size(),
4456 cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
4457 cfiArray, count, (void*)&parser, warnFunc);
4458 if ( msg != NULL )
4459 throwf("malformed __eh_frame section: %s", msg);
4460 }
4461
4462
4463
4464
4465 template <>
4466 void CFISection<arm64>::cfiParse(class Parser<arm64>& parser, uint8_t* buffer,
4467 libunwind::CFI_Atom_Info<CFISection<arm64>::OAS>::CFI_Atom_Info cfiArray[],
4468 uint32_t& count, const pint_t cuStarts[], uint32_t cuCount)
4469 {
4470 // copy __eh_frame data to buffer
4471 memcpy(buffer, file().fileContent() + this->_machOSection->offset(), this->_machOSection->size());
4472
4473 // and apply relocations
4474 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + this->_machOSection->reloff());
4475 const macho_relocation_info<P>* relocsEnd = &relocs[this->_machOSection->nreloc()];
4476 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
4477 uint64_t* p64 = (uint64_t*)&buffer[reloc->r_address()];
4478 uint32_t* p32 = (uint32_t*)&buffer[reloc->r_address()];
4479 uint32_t addend32 = E::get32(*p32);
4480 uint64_t addend64 = E::get64(*p64);
4481 uint64_t value = 0;
4482 switch ( reloc->r_type() ) {
4483 case ARM64_RELOC_SUBTRACTOR:
4484 value = 0 - parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4485 ++reloc;
4486 if ( reloc->r_extern() )
4487 value += parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4488 break;
4489 case ARM64_RELOC_UNSIGNED:
4490 value = parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
4491 break;
4492 case ARM64_RELOC_POINTER_TO_GOT:
4493 // this is used for the reference to the personality function in CIEs
4494 // store the symbol number of the personality function for later use as a Fixup
4495 value = reloc->r_symbolnum();
4496 addend32 = 0;
4497 addend64 = 0;
4498 break;
4499 default:
4500 fprintf(stderr, "CFISection::cfiParse() unexpected relocation type at r_address=0x%08X\n", reloc->r_address());
4501 break;
4502 }
4503 switch ( reloc->r_length() ) {
4504 case 3:
4505 E::set64(*p64, value + addend64);
4506 break;
4507 case 2:
4508 E::set32(*p32, value + addend32);
4509 break;
4510 default:
4511 fprintf(stderr, "CFISection::cfiParse() unexpected relocation size at r_address=0x%08X\n", reloc->r_address());
4512 break;
4513 }
4514 }
4515
4516
4517 // create ObjectAddressSpace object for use by libunwind
4518 OAS oas(*this, buffer);
4519
4520 // use libuwind to parse __eh_frame data into array of CFI_Atom_Info
4521 const char* msg;
4522 msg = libunwind::DwarfInstructions<OAS, libunwind::Registers_arm64>::parseCFIs(
4523 oas, this->_machOSection->addr(), this->_machOSection->size(),
4524 cuStarts, cuCount, parser.keepDwarfUnwind(), parser.forceDwarfConversion(), parser.neverConvertDwarf(),
4525 cfiArray, count, (void*)&parser, warnFunc);
4526 if ( msg != NULL )
4527 throwf("malformed __eh_frame section: %s", msg);
4528 }
4529
4530
4531 template <typename A>
4532 uint32_t CFISection<A>::computeAtomCount(class Parser<A>& parser,
4533 struct Parser<A>::LabelAndCFIBreakIterator& it,
4534 const struct Parser<A>::CFI_CU_InfoArrays& cfis)
4535 {
4536 return cfis.cfiCount;
4537 }
4538
4539
4540
4541 template <typename A>
4542 uint32_t CFISection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
4543 struct Parser<A>::LabelAndCFIBreakIterator& it,
4544 const struct Parser<A>::CFI_CU_InfoArrays& cfis)
4545 {
4546 this->_beginAtoms = (Atom<A>*)p;
4547 // walk CFI_Atom_Info array and create atom for each entry
4548 const CFI_Atom_Info* start = &cfis.cfiArray[0];
4549 const CFI_Atom_Info* end = &cfis.cfiArray[cfis.cfiCount];
4550 for(const CFI_Atom_Info* a=start; a < end; ++a) {
4551 Atom<A>* space = (Atom<A>*)p;
4552 new (space) Atom<A>(*this, (a->isCIE ? "CIE" : "FDE"), a->address, a->size,
4553 ld::Atom::definitionRegular, ld::Atom::combineNever, ld::Atom::scopeTranslationUnit,
4554 ld::Atom::typeCFI, ld::Atom::symbolTableNotInFinalLinkedImages,
4555 false, false, false, ld::Atom::Alignment(0));
4556 p += sizeof(Atom<A>);
4557 }
4558 this->_endAtoms = (Atom<A>*)p;
4559 return cfis.cfiCount;
4560 }
4561
4562
4563 template <> bool CFISection<x86_64>::bigEndian() { return false; }
4564 template <> bool CFISection<x86>::bigEndian() { return false; }
4565 template <> bool CFISection<arm>::bigEndian() { return false; }
4566 template <> bool CFISection<arm64>::bigEndian() { return false; }
4567
4568
4569 template <>
4570 void CFISection<x86_64>::addCiePersonalityFixups(class Parser<x86_64>& parser, const CFI_Atom_Info* cieInfo)
4571 {
4572 uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
4573 if ( personalityEncoding == 0x9B ) {
4574 // compiler always produces X86_64_RELOC_GOT with addend of 4 to personality function
4575 // CFISection<x86_64>::cfiParse() set targetAddress to be symbolIndex + 4 + addressInCIE
4576 uint32_t symbolIndex = cieInfo->u.cieInfo.personality.targetAddress - 4
4577 - cieInfo->address - cieInfo->u.cieInfo.personality.offsetInCFI;
4578 const macho_nlist<P>& sym = parser.symbolFromIndex(symbolIndex);
4579 const char* personalityName = parser.nameFromSymbol(sym);
4580
4581 Atom<x86_64>* cieAtom = this->findAtomByAddress(cieInfo->address);
4582 Parser<x86_64>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
4583 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, false, personalityName);
4584 parser.addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, 4);
4585 parser.addFixup(src, ld::Fixup::k3of3, ld::Fixup::kindStoreX86PCRel32GOT);
4586 }
4587 else if ( personalityEncoding != 0 ) {
4588 throwf("unsupported address encoding (%02X) of personality function in CIE",
4589 personalityEncoding);
4590 }
4591 }
4592
4593 template <>
4594 void CFISection<x86>::addCiePersonalityFixups(class Parser<x86>& parser, const CFI_Atom_Info* cieInfo)
4595 {
4596 uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
4597 if ( (personalityEncoding == 0x9B) || (personalityEncoding == 0x90) ) {
4598 uint32_t offsetInCFI = cieInfo->u.cieInfo.personality.offsetInCFI;
4599 uint32_t nlpAddr = cieInfo->u.cieInfo.personality.targetAddress;
4600 Atom<x86>* cieAtom = this->findAtomByAddress(cieInfo->address);
4601 Atom<x86>* nlpAtom = parser.findAtomByAddress(nlpAddr);
4602 assert(nlpAtom->contentType() == ld::Atom::typeNonLazyPointer);
4603 Parser<x86>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
4604
4605 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, nlpAtom);
4606 parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, cieAtom);
4607 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, offsetInCFI);
4608 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
4609 }
4610 else if ( personalityEncoding != 0 ) {
4611 throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding);
4612 }
4613 }
4614
4615 #if SUPPORT_ARCH_arm64
4616 template <>
4617 void CFISection<arm64>::addCiePersonalityFixups(class Parser<arm64>& parser, const CFI_Atom_Info* cieInfo)
4618 {
4619 uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
4620 if ( personalityEncoding == 0x9B ) {
4621 // compiler always produces ARM64_RELOC_GOT r_pcrel=1 to personality function
4622 // CFISection<arm64>::cfiParse() set targetAddress to be symbolIndex + addressInCIE
4623 uint32_t symbolIndex = cieInfo->u.cieInfo.personality.targetAddress
4624 - cieInfo->address - cieInfo->u.cieInfo.personality.offsetInCFI;
4625 const macho_nlist<P>& sym = parser.symbolFromIndex(symbolIndex);
4626 const char* personalityName = parser.nameFromSymbol(sym);
4627
4628 Atom<arm64>* cieAtom = this->findAtomByAddress(cieInfo->address);
4629 Parser<arm64>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
4630 parser.addFixup(src, ld::Fixup::k1of2, ld::Fixup::kindSetTargetAddress, false, personalityName);
4631 parser.addFixup(src, ld::Fixup::k2of2, ld::Fixup::kindStoreARM64PCRelToGOT);
4632 }
4633 else if ( personalityEncoding != 0 ) {
4634 throwf("unsupported address encoding (%02X) of personality function in CIE",
4635 personalityEncoding);
4636 }
4637 }
4638 #endif
4639
4640 template <>
4641 void CFISection<arm>::addCiePersonalityFixups(class Parser<arm>& parser, const CFI_Atom_Info* cieInfo)
4642 {
4643 uint8_t personalityEncoding = cieInfo->u.cieInfo.personality.encodingOfTargetAddress;
4644 if ( (personalityEncoding == 0x9B) || (personalityEncoding == 0x90) ) {
4645 uint32_t offsetInCFI = cieInfo->u.cieInfo.personality.offsetInCFI;
4646 uint32_t nlpAddr = cieInfo->u.cieInfo.personality.targetAddress;
4647 Atom<arm>* cieAtom = this->findAtomByAddress(cieInfo->address);
4648 Atom<arm>* nlpAtom = parser.findAtomByAddress(nlpAddr);
4649 assert(nlpAtom->contentType() == ld::Atom::typeNonLazyPointer);
4650 Parser<arm>::SourceLocation src(cieAtom, cieInfo->u.cieInfo.personality.offsetInCFI);
4651
4652 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, nlpAtom);
4653 parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, cieAtom);
4654 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, offsetInCFI);
4655 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
4656 }
4657 else if ( personalityEncoding != 0 ) {
4658 throwf("unsupported address encoding (%02X) of personality function in CIE", personalityEncoding);
4659 }
4660 }
4661
4662
4663
4664 template <typename A>
4665 void CFISection<A>::addCiePersonalityFixups(class Parser<A>& parser, const CFI_Atom_Info* cieInfo)
4666 {
4667 assert(0 && "addCiePersonalityFixups() not implemented for arch");
4668 }
4669
4670 template <typename A>
4671 void CFISection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays& cfis)
4672 {
4673 ld::Fixup::Kind store32 = bigEndian() ? ld::Fixup::kindStoreBigEndian32 : ld::Fixup::kindStoreLittleEndian32;
4674 ld::Fixup::Kind store64 = bigEndian() ? ld::Fixup::kindStoreBigEndian64 : ld::Fixup::kindStoreLittleEndian64;
4675
4676 // add all references for FDEs, including implicit group references
4677 const CFI_Atom_Info* end = &cfis.cfiArray[cfis.cfiCount];
4678 for(const CFI_Atom_Info* p = &cfis.cfiArray[0]; p < end; ++p) {
4679 if ( p->isCIE ) {
4680 // add reference to personality function if used
4681 if ( p->u.cieInfo.personality.targetAddress != CFI_INVALID_ADDRESS ) {
4682 this->addCiePersonalityFixups(parser, p);
4683 }
4684 }
4685 else {
4686 // find FDE Atom
4687 Atom<A>* fdeAtom = this->findAtomByAddress(p->address);
4688 // find function Atom
4689 Atom<A>* functionAtom = parser.findAtomByAddress(p->u.fdeInfo.function.targetAddress);
4690 // find CIE Atom
4691 Atom<A>* cieAtom = this->findAtomByAddress(p->u.fdeInfo.cie.targetAddress);
4692 // find LSDA Atom
4693 Atom<A>* lsdaAtom = NULL;
4694 if ( p->u.fdeInfo.lsda.targetAddress != CFI_INVALID_ADDRESS ) {
4695 lsdaAtom = parser.findAtomByAddress(p->u.fdeInfo.lsda.targetAddress);
4696 }
4697 // add reference from FDE to CIE (always 32-bit pc-rel)
4698 typename Parser<A>::SourceLocation fdeToCieSrc(fdeAtom, p->u.fdeInfo.cie.offsetInCFI);
4699 parser.addFixup(fdeToCieSrc, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, fdeAtom);
4700 parser.addFixup(fdeToCieSrc, ld::Fixup::k2of4, ld::Fixup::kindAddAddend, p->u.fdeInfo.cie.offsetInCFI);
4701 parser.addFixup(fdeToCieSrc, ld::Fixup::k3of4, ld::Fixup::kindSubtractTargetAddress, cieAtom);
4702 parser.addFixup(fdeToCieSrc, ld::Fixup::k4of4, store32, cieAtom);
4703
4704 // add reference from FDE to function
4705 typename Parser<A>::SourceLocation fdeToFuncSrc(fdeAtom, p->u.fdeInfo.function.offsetInCFI);
4706 switch (p->u.fdeInfo.function.encodingOfTargetAddress) {
4707 case DW_EH_PE_pcrel|DW_EH_PE_ptr:
4708 if ( sizeof(typename A::P::uint_t) == 8 ) {
4709 parser.addFixup(fdeToFuncSrc, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, functionAtom);
4710 parser.addFixup(fdeToFuncSrc, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fdeAtom);
4711 parser.addFixup(fdeToFuncSrc, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, p->u.fdeInfo.function.offsetInCFI);
4712 parser.addFixup(fdeToFuncSrc, ld::Fixup::k4of4, store64);
4713 break;
4714 }
4715 // else fall into 32-bit case
4716 case DW_EH_PE_pcrel|DW_EH_PE_sdata4:
4717 parser.addFixup(fdeToFuncSrc, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, functionAtom);
4718 parser.addFixup(fdeToFuncSrc, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fdeAtom);
4719 parser.addFixup(fdeToFuncSrc, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, p->u.fdeInfo.function.offsetInCFI);
4720 parser.addFixup(fdeToFuncSrc, ld::Fixup::k4of4, store32);
4721 break;
4722 default:
4723 throw "unsupported encoding in FDE of pointer to function";
4724 }
4725
4726 // add reference from FDE to LSDA
4727 typename Parser<A>::SourceLocation fdeToLsdaSrc(fdeAtom, p->u.fdeInfo.lsda.offsetInCFI);
4728 if ( lsdaAtom != NULL ) {
4729 switch (p->u.fdeInfo.lsda.encodingOfTargetAddress) {
4730 case DW_EH_PE_pcrel|DW_EH_PE_ptr:
4731 if ( sizeof(typename A::P::uint_t) == 8 ) {
4732 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, lsdaAtom);
4733 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fdeAtom);
4734 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, p->u.fdeInfo.lsda.offsetInCFI);
4735 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k4of4, store64);
4736 break;
4737 }
4738 // else fall into 32-bit case
4739 case DW_EH_PE_pcrel|DW_EH_PE_sdata4:
4740 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, lsdaAtom);
4741 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k2of4, ld::Fixup::kindSubtractTargetAddress, fdeAtom);
4742 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k3of4, ld::Fixup::kindSubtractAddend, p->u.fdeInfo.lsda.offsetInCFI);
4743 parser.addFixup(fdeToLsdaSrc, ld::Fixup::k4of4, store32);
4744 break;
4745 default:
4746 throw "unsupported encoding in FDE of pointer to LSDA";
4747 }
4748 }
4749
4750 // FDE is in group lead by function atom
4751 typename Parser<A>::SourceLocation fdeSrc(functionAtom,0);
4752 parser.addFixup(fdeSrc, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateFDE, fdeAtom);
4753
4754 // LSDA is in group lead by function atom
4755 if ( lsdaAtom != NULL ) {
4756 parser.addFixup(fdeSrc, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateLSDA, lsdaAtom);
4757 }
4758 }
4759 }
4760 }
4761
4762
4763
4764
4765 template <typename A>
4766 const void* CFISection<A>::OAS::mappedAddress(pint_t addr)
4767 {
4768 if ( (_ehFrameStartAddr <= addr) && (addr < _ehFrameEndAddr) )
4769 return &_ehFrameContent[addr-_ehFrameStartAddr];
4770 else {
4771 // requested bytes are not in __eh_frame section
4772 // this can occur when examining the instruction bytes in the __text
4773 File<A>& file = _ehFrameSection.file();
4774 for (uint32_t i=0; i < file._sectionsArrayCount; ++i ) {
4775 const macho_section<typename A::P>* sect = file._sectionsArray[i]->machoSection();
4776 // TentativeDefinitionSection and AbsoluteSymbolSection have no mach-o section
4777 if ( sect != NULL ) {
4778 if ( (sect->addr() <= addr) && (addr < (sect->addr()+sect->size())) ) {
4779 return file.fileContent() + sect->offset() + addr - sect->addr();
4780 }
4781 }
4782 }
4783 throwf("__eh_frame parsing problem. Can't find target of reference to address 0x%08llX", (uint64_t)addr);
4784 }
4785 }
4786
4787
4788 template <typename A>
4789 uint64_t CFISection<A>::OAS::getULEB128(pint_t& logicalAddr, pint_t end)
4790 {
4791 uintptr_t size = (end - logicalAddr);
4792 libunwind::LocalAddressSpace::pint_t laddr = (libunwind::LocalAddressSpace::pint_t)mappedAddress(logicalAddr);
4793 libunwind::LocalAddressSpace::pint_t sladdr = laddr;
4794 uint64_t result = libunwind::LocalAddressSpace::getULEB128(laddr, laddr+size);
4795 logicalAddr += (laddr-sladdr);
4796 return result;
4797 }
4798
4799 template <typename A>
4800 int64_t CFISection<A>::OAS::getSLEB128(pint_t& logicalAddr, pint_t end)
4801 {
4802 uintptr_t size = (end - logicalAddr);
4803 libunwind::LocalAddressSpace::pint_t laddr = (libunwind::LocalAddressSpace::pint_t)mappedAddress(logicalAddr);
4804 libunwind::LocalAddressSpace::pint_t sladdr = laddr;
4805 int64_t result = libunwind::LocalAddressSpace::getSLEB128(laddr, laddr+size);
4806 logicalAddr += (laddr-sladdr);
4807 return result;
4808 }
4809
4810 template <typename A>
4811 typename A::P::uint_t CFISection<A>::OAS::getEncodedP(pint_t& addr, pint_t end, uint8_t encoding)
4812 {
4813 pint_t startAddr = addr;
4814 pint_t p = addr;
4815 pint_t result;
4816
4817 // first get value
4818 switch (encoding & 0x0F) {
4819 case DW_EH_PE_ptr:
4820 result = getP(addr);
4821 p += sizeof(pint_t);
4822 addr = (pint_t)p;
4823 break;
4824 case DW_EH_PE_uleb128:
4825 result = getULEB128(addr, end);
4826 break;
4827 case DW_EH_PE_udata2:
4828 result = get16(addr);
4829 p += 2;
4830 addr = (pint_t)p;
4831 break;
4832 case DW_EH_PE_udata4:
4833 result = get32(addr);
4834 p += 4;
4835 addr = (pint_t)p;
4836 break;
4837 case DW_EH_PE_udata8:
4838 result = get64(addr);
4839 p += 8;
4840 addr = (pint_t)p;
4841 break;
4842 case DW_EH_PE_sleb128:
4843 result = getSLEB128(addr, end);
4844 break;
4845 case DW_EH_PE_sdata2:
4846 result = (int16_t)get16(addr);
4847 p += 2;
4848 addr = (pint_t)p;
4849 break;
4850 case DW_EH_PE_sdata4:
4851 result = (int32_t)get32(addr);
4852 p += 4;
4853 addr = (pint_t)p;
4854 break;
4855 case DW_EH_PE_sdata8:
4856 result = get64(addr);
4857 p += 8;
4858 addr = (pint_t)p;
4859 break;
4860 default:
4861 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
4862 }
4863
4864 // then add relative offset
4865 switch ( encoding & 0x70 ) {
4866 case DW_EH_PE_absptr:
4867 // do nothing
4868 break;
4869 case DW_EH_PE_pcrel:
4870 result += startAddr;
4871 break;
4872 case DW_EH_PE_textrel:
4873 throw "DW_EH_PE_textrel pointer encoding not supported";
4874 break;
4875 case DW_EH_PE_datarel:
4876 throw "DW_EH_PE_datarel pointer encoding not supported";
4877 break;
4878 case DW_EH_PE_funcrel:
4879 throw "DW_EH_PE_funcrel pointer encoding not supported";
4880 break;
4881 case DW_EH_PE_aligned:
4882 throw "DW_EH_PE_aligned pointer encoding not supported";
4883 break;
4884 default:
4885 throwf("ObjectFileAddressSpace<A>::getEncodedP() encoding 0x%08X not supported", encoding);
4886 break;
4887 }
4888
4889 // Note: DW_EH_PE_indirect is only used in CIEs to refernce the personality pointer
4890 // When parsing .o files that pointer contains zero, so we don't to return that.
4891 // Instead we skip the dereference and return the address of the pointer.
4892 // if ( encoding & DW_EH_PE_indirect )
4893 // result = getP(result);
4894
4895 return result;
4896 }
4897
4898 template <>
4899 const char* CUSection<x86_64>::personalityName(class Parser<x86_64>& parser, const macho_relocation_info<x86_64::P>* reloc)
4900 {
4901 if ( reloc->r_extern() ) {
4902 assert((reloc->r_type() == X86_64_RELOC_UNSIGNED) && "wrong reloc type on personality column in __compact_unwind section");
4903 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
4904 return parser.nameFromSymbol(sym);
4905 }
4906 else {
4907 const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
4908 pint_t personalityAddr = *content;
4909 assert((parser.sectionForAddress(personalityAddr)->type() == ld::Section::typeCode) && "personality column in __compact_unwind section is not pointer to function");
4910 // atoms may not be constructed yet, so scan symbol table for labels
4911 const char* name = parser.scanSymbolTableForAddress(personalityAddr);
4912 return name;
4913 }
4914 }
4915
4916 template <>
4917 const char* CUSection<x86>::personalityName(class Parser<x86>& parser, const macho_relocation_info<x86::P>* reloc)
4918 {
4919 if ( reloc->r_extern() ) {
4920 assert((reloc->r_type() == GENERIC_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
4921 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
4922 return parser.nameFromSymbol(sym);
4923 }
4924 else {
4925 // support __LD, __compact_unwind personality entries which are pointer to personality non-lazy pointer
4926 const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
4927 pint_t nlPointerAddr = *content;
4928 Section<x86>* nlSection = parser.sectionForAddress(nlPointerAddr);
4929 if ( nlSection->type() == ld::Section::typeCode ) {
4930 // personality function is defined in this .o file, so this is a direct reference to it
4931 // atoms may not be constructed yet, so scan symbol table for labels
4932 const char* name = parser.scanSymbolTableForAddress(nlPointerAddr);
4933 return name;
4934 }
4935 else {
4936 uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(nlPointerAddr, nlSection->machoSection());
4937 const macho_nlist<P>& nlSymbol = parser.symbolFromIndex(symIndex);
4938 return parser.nameFromSymbol(nlSymbol);
4939 }
4940 }
4941 }
4942
4943 #if SUPPORT_ARCH_arm64
4944 template <>
4945 const char* CUSection<arm64>::personalityName(class Parser<arm64>& parser, const macho_relocation_info<arm64::P>* reloc)
4946 {
4947 if ( reloc->r_extern() ) {
4948 assert((reloc->r_type() == ARM64_RELOC_UNSIGNED) && "wrong reloc type on personality column in __compact_unwind section");
4949 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
4950 return parser.nameFromSymbol(sym);
4951 }
4952 else {
4953 const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
4954 pint_t personalityAddr = *content;
4955 Section<arm64>* personalitySection = parser.sectionForAddress(personalityAddr);
4956 (void)personalitySection;
4957 assert((personalitySection->type() == ld::Section::typeCode) && "personality column in __compact_unwind section is not pointer to function");
4958 // atoms may not be constructed yet, so scan symbol table for labels
4959 const char* name = parser.scanSymbolTableForAddress(personalityAddr);
4960 return name;
4961 }
4962 }
4963 #endif
4964
4965 #if SUPPORT_ARCH_arm_any
4966 template <>
4967 const char* CUSection<arm>::personalityName(class Parser<arm>& parser, const macho_relocation_info<arm::P>* reloc)
4968 {
4969 if ( reloc->r_extern() ) {
4970 assert((reloc->r_type() == ARM_RELOC_VANILLA) && "wrong reloc type on personality column in __compact_unwind section");
4971 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
4972 return parser.nameFromSymbol(sym);
4973 }
4974 else {
4975 // support __LD, __compact_unwind personality entries which are pointer to personality non-lazy pointer
4976 const pint_t* content = (pint_t*)(this->file().fileContent() + this->_machOSection->offset() + reloc->r_address());
4977 pint_t nlPointerAddr = *content;
4978 Section<arm>* nlSection = parser.sectionForAddress(nlPointerAddr);
4979 if ( nlSection->type() == ld::Section::typeCode ) {
4980 // personality function is defined in this .o file, so this is a direct reference to it
4981 // atoms may not be constructed yet, so scan symbol table for labels
4982 const char* name = parser.scanSymbolTableForAddress(nlPointerAddr);
4983 return name;
4984 }
4985 else {
4986 uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(nlPointerAddr, nlSection->machoSection());
4987 const macho_nlist<P>& nlSymbol = parser.symbolFromIndex(symIndex);
4988 return parser.nameFromSymbol(nlSymbol);
4989 }
4990 }
4991 }
4992 #endif
4993
4994
4995 template <typename A>
4996 const char* CUSection<A>::personalityName(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
4997 {
4998 return NULL;
4999 }
5000
5001 template <>
5002 bool CUSection<x86>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
5003 {
5004 return ((enc & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF);
5005 }
5006
5007 template <>
5008 bool CUSection<x86_64>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
5009 {
5010 return ((enc & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF);
5011 }
5012
5013 #if SUPPORT_ARCH_arm_any
5014 template <>
5015 bool CUSection<arm>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
5016 {
5017 return ((enc & UNWIND_ARM_MODE_MASK) == UNWIND_ARM_MODE_DWARF);
5018 }
5019 #endif
5020
5021 #if SUPPORT_ARCH_arm64
5022 template <>
5023 bool CUSection<arm64>::encodingMeansUseDwarf(compact_unwind_encoding_t enc)
5024 {
5025 return ((enc & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF);
5026 }
5027 #endif
5028
5029 template <typename A>
5030 int CUSection<A>::infoSorter(const void* l, const void* r)
5031 {
5032 // sort references by symbol index, then address
5033 const Info* left = (Info*)l;
5034 const Info* right = (Info*)r;
5035 if ( left->functionSymbolIndex == right->functionSymbolIndex )
5036 return (left->functionStartAddress - right->functionStartAddress);
5037 else
5038 return (left->functionSymbolIndex - right->functionSymbolIndex);
5039 }
5040
5041 template <typename A>
5042 void CUSection<A>::parse(class Parser<A>& parser, uint32_t cnt, Info array[])
5043 {
5044 // walk section content and copy to Info array
5045 const macho_compact_unwind_entry<P>* const entries = (macho_compact_unwind_entry<P>*)(this->file().fileContent() + this->_machOSection->offset());
5046 for (uint32_t i=0; i < cnt; ++i) {
5047 Info* info = &array[i];
5048 const macho_compact_unwind_entry<P>* entry = &entries[i];
5049 info->functionStartAddress = entry->codeStart();
5050 info->functionSymbolIndex = 0xFFFFFFFF;
5051 info->rangeLength = entry->codeLen();
5052 info->compactUnwindInfo = entry->compactUnwindInfo();
5053 info->personality = NULL;
5054 info->lsdaAddress = entry->lsda();
5055 info->function = NULL;
5056 info->lsda = NULL;
5057 if ( (info->compactUnwindInfo & UNWIND_PERSONALITY_MASK) != 0 )
5058 warning("no bits should be set in UNWIND_PERSONALITY_MASK of compact unwind encoding in __LD,__compact_unwind section");
5059 if ( info->lsdaAddress != 0 ) {
5060 info->compactUnwindInfo |= UNWIND_HAS_LSDA;
5061 }
5062 }
5063
5064 // scan relocs, extern relocs are needed for personality references (possibly for function/lsda refs??)
5065 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(this->file().fileContent() + this->_machOSection->reloff());
5066 const macho_relocation_info<P>* relocsEnd = &relocs[this->_machOSection->nreloc()];
5067 for (const macho_relocation_info<P>* reloc = relocs; reloc < relocsEnd; ++reloc) {
5068 if ( reloc->r_extern() ) {
5069 // only expect external relocs on some colummns
5070 if ( (reloc->r_address() % sizeof(macho_compact_unwind_entry<P>)) == macho_compact_unwind_entry<P>::personalityFieldOffset() ) {
5071 uint32_t entryIndex = reloc->r_address() / sizeof(macho_compact_unwind_entry<P>);
5072 array[entryIndex].personality = this->personalityName(parser, reloc);
5073 }
5074 else if ( (reloc->r_address() % sizeof(macho_compact_unwind_entry<P>)) == macho_compact_unwind_entry<P>::lsdaFieldOffset() ) {
5075 uint32_t entryIndex = reloc->r_address() / sizeof(macho_compact_unwind_entry<P>);
5076 const macho_nlist<P>& lsdaSym = parser.symbolFromIndex(reloc->r_symbolnum());
5077 if ( (lsdaSym.n_type() & N_TYPE) == N_SECT )
5078 array[entryIndex].lsdaAddress = lsdaSym.n_value();
5079 else
5080 warning("unexpected extern relocation to lsda in __compact_unwind section");
5081 }
5082 else if ( (reloc->r_address() % sizeof(macho_compact_unwind_entry<P>)) == macho_compact_unwind_entry<P>::codeStartFieldOffset() ) {
5083 uint32_t entryIndex = reloc->r_address() / sizeof(macho_compact_unwind_entry<P>);
5084 array[entryIndex].functionSymbolIndex = reloc->r_symbolnum();
5085 array[entryIndex].functionStartAddress += parser.symbolFromIndex(reloc->r_symbolnum()).n_value();
5086 }
5087 else {
5088 warning("unexpected extern relocation in __compact_unwind section");
5089 }
5090 }
5091 else {
5092 if ( (reloc->r_address() % sizeof(macho_compact_unwind_entry<P>)) == macho_compact_unwind_entry<P>::personalityFieldOffset() ) {
5093 uint32_t entryIndex = reloc->r_address() / sizeof(macho_compact_unwind_entry<P>);
5094 array[entryIndex].personality = this->personalityName(parser, reloc);
5095 }
5096 }
5097 }
5098
5099 // sort array by function start address so unwind infos will be contiguous for a given function
5100 ::qsort(array, cnt, sizeof(Info), infoSorter);
5101 }
5102
5103 template <typename A>
5104 uint32_t CUSection<A>::count()
5105 {
5106 const macho_section<P>* machoSect = this->machoSection();
5107 if ( (machoSect->size() % sizeof(macho_compact_unwind_entry<P>)) != 0 )
5108 throw "malformed __LD,__compact_unwind section, bad length";
5109
5110 return machoSect->size() / sizeof(macho_compact_unwind_entry<P>);
5111 }
5112
5113 template <typename A>
5114 void CUSection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays& cus)
5115 {
5116 Info* const arrayStart = cus.cuArray;
5117 Info* const arrayEnd = &cus.cuArray[cus.cuCount];
5118 for (Info* info=arrayStart; info < arrayEnd; ++info) {
5119 // find function atom from address
5120 info->function = parser.findAtomByAddress(info->functionStartAddress);
5121 // find lsda atom from address
5122 if ( info->lsdaAddress != 0 ) {
5123 info->lsda = parser.findAtomByAddress(info->lsdaAddress);
5124 // add lsda subordinate
5125 typename Parser<A>::SourceLocation src(info->function, info->functionStartAddress - info->function->objectAddress());
5126 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateLSDA, info->lsda);
5127 }
5128 if ( info->personality != NULL ) {
5129 // add personality subordinate
5130 typename Parser<A>::SourceLocation src(info->function, info->functionStartAddress - info->function->objectAddress());
5131 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinatePersonality, false, info->personality);
5132 }
5133 }
5134
5135 }
5136
5137 template <typename A>
5138 SymboledSection<A>::SymboledSection(Parser<A>& parser, File<A>& f, const macho_section<typename A::P>* s)
5139 : Section<A>(f, s), _type(ld::Atom::typeUnclassified)
5140 {
5141 switch ( s->flags() & SECTION_TYPE ) {
5142 case S_ZEROFILL:
5143 _type = ld::Atom::typeZeroFill;
5144 break;
5145 case S_MOD_INIT_FUNC_POINTERS:
5146 _type = ld::Atom::typeInitializerPointers;
5147 break;
5148 case S_MOD_TERM_FUNC_POINTERS:
5149 _type = ld::Atom::typeTerminatorPointers;
5150 break;
5151 case S_THREAD_LOCAL_VARIABLES:
5152 _type = ld::Atom::typeTLV;
5153 break;
5154 case S_THREAD_LOCAL_ZEROFILL:
5155 _type = ld::Atom::typeTLVZeroFill;
5156 break;
5157 case S_THREAD_LOCAL_REGULAR:
5158 _type = ld::Atom::typeTLVInitialValue;
5159 break;
5160 case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS:
5161 _type = ld::Atom::typeTLVInitializerPointers;
5162 break;
5163 case S_REGULAR:
5164 if ( strncmp(s->sectname(), "__gcc_except_tab", 16) == 0 )
5165 _type = ld::Atom::typeLSDA;
5166 else if ( this->type() == ld::Section::typeInitializerPointers )
5167 _type = ld::Atom::typeInitializerPointers;
5168 break;
5169 }
5170 }
5171
5172
5173 template <typename A>
5174 bool SymboledSection<A>::dontDeadStrip()
5175 {
5176 switch ( _type ) {
5177 case ld::Atom::typeInitializerPointers:
5178 case ld::Atom::typeTerminatorPointers:
5179 return true;
5180 default:
5181 // model an object file without MH_SUBSECTIONS_VIA_SYMBOLS as one in which nothing can be dead stripped
5182 if ( ! this->_file.canScatterAtoms() )
5183 return true;
5184 // call inherited
5185 return Section<A>::dontDeadStrip();
5186 }
5187 return false;
5188 }
5189
5190
5191 template <typename A>
5192 uint32_t SymboledSection<A>::computeAtomCount(class Parser<A>& parser,
5193 struct Parser<A>::LabelAndCFIBreakIterator& it,
5194 const struct Parser<A>::CFI_CU_InfoArrays&)
5195 {
5196 const pint_t startAddr = this->_machOSection->addr();
5197 const pint_t endAddr = startAddr + this->_machOSection->size();
5198 const uint32_t sectNum = this->sectionNum(parser);
5199
5200 uint32_t count = 0;
5201 pint_t addr;
5202 pint_t size;
5203 const macho_nlist<P>* sym;
5204 while ( it.next(parser, *this, sectNum, startAddr, endAddr, &addr, &size, &sym) ) {
5205 ++count;
5206 }
5207 //fprintf(stderr, "computeAtomCount(%s,%s) => %d\n", this->segmentName(), this->sectionName(), count);
5208 return count;
5209 }
5210
5211 template <typename A>
5212 uint32_t SymboledSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
5213 struct Parser<A>::LabelAndCFIBreakIterator& it,
5214 const struct Parser<A>::CFI_CU_InfoArrays&)
5215 {
5216 this->_beginAtoms = (Atom<A>*)p;
5217
5218 //fprintf(stderr, "SymboledSection::appendAtoms() in section %s\n", this->_machOSection->sectname());
5219 const pint_t startAddr = this->_machOSection->addr();
5220 const pint_t endAddr = startAddr + this->_machOSection->size();
5221 const uint32_t sectNum = this->sectionNum(parser);
5222
5223 uint32_t count = 0;
5224 pint_t addr;
5225 pint_t size;
5226 const macho_nlist<P>* label;
5227 while ( it.next(parser, *this, sectNum, startAddr, endAddr, &addr, &size, &label) ) {
5228 Atom<A>* allocatedSpace = (Atom<A>*)p;
5229 // is break because of label or CFI?
5230 if ( label != NULL ) {
5231 // The size is computed based on the address of the next label (or the end of the section for the last label)
5232 // If there are two labels at the same address, we want them one to be an alias of the other.
5233 // If the label is at the end of a section, it is has zero size, but is not an alias
5234 const bool isAlias = ( (size == 0) && (addr < endAddr) );
5235 new (allocatedSpace) Atom<A>(*this, parser, *label, size, isAlias);
5236 if ( isAlias )
5237 this->_hasAliases = true;
5238 if ( parser.altEntryFromSymbol(*label) )
5239 this->_altEntries.insert(allocatedSpace);
5240 }
5241 else {
5242 ld::Atom::SymbolTableInclusion inclusion = ld::Atom::symbolTableNotIn;
5243 ld::Atom::ContentType ctype = this->contentType();
5244 if ( ctype == ld::Atom::typeLSDA )
5245 inclusion = ld::Atom::symbolTableInWithRandomAutoStripLabel;
5246 new (allocatedSpace) Atom<A>(*this, "anon", addr, size, ld::Atom::definitionRegular, ld::Atom::combineNever,
5247 ld::Atom::scopeTranslationUnit, ctype, inclusion,
5248 this->dontDeadStrip(), false, false, this->alignmentForAddress(addr));
5249 }
5250 p += sizeof(Atom<A>);
5251 ++count;
5252 }
5253
5254 this->_endAtoms = (Atom<A>*)p;
5255 return count;
5256 }
5257
5258
5259 template <>
5260 ld::Atom::SymbolTableInclusion ImplicitSizeSection<arm64>::symbolTableInclusion()
5261 {
5262 return ld::Atom::symbolTableInWithRandomAutoStripLabel;
5263 }
5264
5265 template <typename A>
5266 ld::Atom::SymbolTableInclusion ImplicitSizeSection<A>::symbolTableInclusion()
5267 {
5268 return ld::Atom::symbolTableNotIn;
5269 }
5270
5271
5272 template <typename A>
5273 uint32_t ImplicitSizeSection<A>::computeAtomCount(class Parser<A>& parser,
5274 struct Parser<A>::LabelAndCFIBreakIterator& it,
5275 const struct Parser<A>::CFI_CU_InfoArrays&)
5276 {
5277 uint32_t count = 0;
5278 const macho_section<P>* sect = this->machoSection();
5279 const pint_t startAddr = sect->addr();
5280 const pint_t endAddr = startAddr + sect->size();
5281 for (pint_t addr = startAddr; addr < endAddr; addr += elementSizeAtAddress(addr) ) {
5282 if ( useElementAt(parser, it, addr) )
5283 ++count;
5284 }
5285 if ( it.fileHasOverlappingSymbols && (sect->size() != 0) && (this->combine(parser, startAddr) == ld::Atom::combineByNameAndContent) ) {
5286 // if there are multiple labels in this section for the same address, then clone them into multi atoms
5287 pint_t prevSymbolAddr = (pint_t)(-1);
5288 uint8_t prevSymbolSectNum = 0;
5289 bool prevIgnore = false;
5290 for(uint32_t i=0; i < it.sortedSymbolCount; ++i) {
5291 const macho_nlist<P>& sym = parser.symbolFromIndex(it.sortedSymbolIndexes[i]);
5292 const pint_t symbolAddr = sym.n_value();
5293 const uint8_t symbolSectNum = sym.n_sect();
5294 const bool ignore = this->ignoreLabel(parser.nameFromSymbol(sym));
5295 if ( !ignore && !prevIgnore && (symbolAddr == prevSymbolAddr) && (prevSymbolSectNum == symbolSectNum) && (symbolSectNum == this->sectionNum(parser)) ) {
5296 ++count;
5297 }
5298 prevSymbolAddr = symbolAddr;
5299 prevSymbolSectNum = symbolSectNum;
5300 prevIgnore = ignore;
5301 }
5302 }
5303 return count;
5304 }
5305
5306 template <typename A>
5307 uint32_t ImplicitSizeSection<A>::appendAtoms(class Parser<A>& parser, uint8_t* p,
5308 struct Parser<A>::LabelAndCFIBreakIterator& it,
5309 const struct Parser<A>::CFI_CU_InfoArrays&)
5310 {
5311 this->_beginAtoms = (Atom<A>*)p;
5312
5313 const macho_section<P>* sect = this->machoSection();
5314 const pint_t startAddr = sect->addr();
5315 const pint_t endAddr = startAddr + sect->size();
5316 const uint32_t sectNum = this->sectionNum(parser);
5317 //fprintf(stderr, "ImplicitSizeSection::appendAtoms() in section %s\n", sect->sectname());
5318 uint32_t count = 0;
5319 pint_t foundAddr;
5320 pint_t size;
5321 const macho_nlist<P>* foundLabel;
5322 Atom<A>* allocatedSpace;
5323 while ( it.next(parser, *this, sectNum, startAddr, endAddr, &foundAddr, &size, &foundLabel) ) {
5324 if ( foundLabel != NULL ) {
5325 bool skip = false;
5326 pint_t labeledAtomSize = this->elementSizeAtAddress(foundAddr);
5327 allocatedSpace = (Atom<A>*)p;
5328 if ( this->ignoreLabel(parser.nameFromSymbol(*foundLabel)) ) {
5329 if ( size == 0 ) {
5330 // <rdar://problem/10018737>
5331 // a size of zero means there is another label at same location
5332 // and we are supposed to ignore this label
5333 skip = true;
5334 }
5335 else {
5336 //fprintf(stderr, " 0x%08llX make annon, size=%lld\n", (uint64_t)foundAddr, (uint64_t)size);
5337 new (allocatedSpace) Atom<A>(*this, this->unlabeledAtomName(parser, foundAddr), foundAddr,
5338 this->elementSizeAtAddress(foundAddr), this->definition(),
5339 this->combine(parser, foundAddr), this->scopeAtAddress(parser, foundAddr),
5340 this->contentType(), this->symbolTableInclusion(),
5341 this->dontDeadStrip(), false, false, this->alignmentForAddress(foundAddr));
5342 }
5343 }
5344 else {
5345 // make named atom for label
5346 //fprintf(stderr, " 0x%08llX make labeled\n", (uint64_t)foundAddr);
5347 new (allocatedSpace) Atom<A>(*this, parser, *foundLabel, labeledAtomSize);
5348 }
5349 if ( !skip ) {
5350 ++count;
5351 p += sizeof(Atom<A>);
5352 foundAddr += labeledAtomSize;
5353 size -= labeledAtomSize;
5354 }
5355 }
5356 // some number of anonymous atoms
5357 for (pint_t addr = foundAddr; addr < (foundAddr+size); addr += elementSizeAtAddress(addr) ) {
5358 // make anon atoms for area before label
5359 if ( this->useElementAt(parser, it, addr) ) {
5360 //fprintf(stderr, " 0x%08llX make annon, size=%lld\n", (uint64_t)addr, (uint64_t)elementSizeAtAddress(addr));
5361 allocatedSpace = (Atom<A>*)p;
5362 new (allocatedSpace) Atom<A>(*this, this->unlabeledAtomName(parser, addr), addr, this->elementSizeAtAddress(addr),
5363 this->definition(), this->combine(parser, addr), this->scopeAtAddress(parser, addr),
5364 this->contentType(), this->symbolTableInclusion(),
5365 this->dontDeadStrip(), false, false, this->alignmentForAddress(addr));
5366 ++count;
5367 p += sizeof(Atom<A>);
5368 }
5369 }
5370 }
5371
5372 this->_endAtoms = (Atom<A>*)p;
5373
5374 return count;
5375 }
5376
5377 template <typename A>
5378 bool Literal4Section<A>::ignoreLabel(const char* label) const
5379 {
5380 return (label[0] == 'L') || (label[0] == 'l');
5381 }
5382
5383 template <typename A>
5384 unsigned long Literal4Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5385 {
5386 const uint32_t* literalContent = (uint32_t*)atom->contentPointer();
5387 return *literalContent;
5388 }
5389
5390 template <typename A>
5391 bool Literal4Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5392 const ld::IndirectBindingTable& ind) const
5393 {
5394 assert(this->type() == rhs.section().type());
5395 const uint32_t* literalContent = (uint32_t*)atom->contentPointer();
5396
5397 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5398 assert(rhsAtom != NULL);
5399 if ( rhsAtom != NULL ) {
5400 const uint32_t* rhsLiteralContent = (uint32_t*)rhsAtom->contentPointer();
5401 return (*literalContent == *rhsLiteralContent);
5402 }
5403 return false;
5404 }
5405
5406
5407 template <typename A>
5408 bool Literal8Section<A>::ignoreLabel(const char* label) const
5409 {
5410 return (label[0] == 'L') || (label[0] == 'l');
5411 }
5412
5413 template <typename A>
5414 unsigned long Literal8Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5415 {
5416 #if __LP64__
5417 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
5418 return *literalContent;
5419 #else
5420 unsigned long hash = 5381;
5421 const uint8_t* byteContent = atom->contentPointer();
5422 for (int i=0; i < 8; ++i) {
5423 hash = hash * 33 + byteContent[i];
5424 }
5425 return hash;
5426 #endif
5427 }
5428
5429 template <typename A>
5430 bool Literal8Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5431 const ld::IndirectBindingTable& ind) const
5432 {
5433 if ( rhs.section().type() != ld::Section::typeLiteral8 )
5434 return false;
5435 assert(this->type() == rhs.section().type());
5436 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
5437
5438 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5439 assert(rhsAtom != NULL);
5440 if ( rhsAtom != NULL ) {
5441 const uint64_t* rhsLiteralContent = (uint64_t*)rhsAtom->contentPointer();
5442 return (*literalContent == *rhsLiteralContent);
5443 }
5444 return false;
5445 }
5446
5447 template <typename A>
5448 bool Literal16Section<A>::ignoreLabel(const char* label) const
5449 {
5450 return (label[0] == 'L') || (label[0] == 'l');
5451 }
5452
5453 template <typename A>
5454 unsigned long Literal16Section<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5455 {
5456 unsigned long hash = 5381;
5457 const uint8_t* byteContent = atom->contentPointer();
5458 for (int i=0; i < 16; ++i) {
5459 hash = hash * 33 + byteContent[i];
5460 }
5461 return hash;
5462 }
5463
5464 template <typename A>
5465 bool Literal16Section<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5466 const ld::IndirectBindingTable& ind) const
5467 {
5468 if ( rhs.section().type() != ld::Section::typeLiteral16 )
5469 return false;
5470 assert(this->type() == rhs.section().type());
5471 const uint64_t* literalContent = (uint64_t*)atom->contentPointer();
5472
5473 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5474 assert(rhsAtom != NULL);
5475 if ( rhsAtom != NULL ) {
5476 const uint64_t* rhsLiteralContent = (uint64_t*)rhsAtom->contentPointer();
5477 return ((literalContent[0] == rhsLiteralContent[0]) && (literalContent[1] == rhsLiteralContent[1]));
5478 }
5479 return false;
5480 }
5481
5482
5483
5484 template <typename A>
5485 typename A::P::uint_t CStringSection<A>::elementSizeAtAddress(pint_t addr)
5486 {
5487 const macho_section<P>* sect = this->machoSection();
5488 const char* stringContent = (char*)(this->file().fileContent() + sect->offset() + addr - sect->addr());
5489 return strlen(stringContent) + 1;
5490 }
5491
5492 template <typename A>
5493 bool CStringSection<A>::useElementAt(Parser<A>& parser, struct Parser<A>::LabelAndCFIBreakIterator& it, pint_t addr)
5494 {
5495 return true;
5496 }
5497
5498 template <typename A>
5499 bool CStringSection<A>::ignoreLabel(const char* label) const
5500 {
5501 return (label[0] == 'L') || (label[0] == 'l');
5502 }
5503
5504
5505 template <typename A>
5506 Atom<A>* CStringSection<A>::findAtomByAddress(pint_t addr)
5507 {
5508 Atom<A>* result = this->findContentAtomByAddress(addr, this->_beginAtoms, this->_endAtoms);
5509 return result;
5510 }
5511
5512 template <typename A>
5513 unsigned long CStringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5514 {
5515 unsigned long hash = 5381;
5516 const char* stringContent = (char*)atom->contentPointer();
5517 for (const char* s = stringContent; *s != '\0'; ++s) {
5518 hash = hash * 33 + *s;
5519 }
5520 return hash;
5521 }
5522
5523
5524 template <typename A>
5525 bool CStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5526 const ld::IndirectBindingTable& ind) const
5527 {
5528 if ( rhs.section().type() != ld::Section::typeCString )
5529 return false;
5530 assert(this->type() == rhs.section().type());
5531 assert(strcmp(this->sectionName(), rhs.section().sectionName())== 0);
5532 assert(strcmp(this->segmentName(), rhs.section().segmentName())== 0);
5533 const char* stringContent = (char*)atom->contentPointer();
5534
5535 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5536 assert(rhsAtom != NULL);
5537 if ( rhsAtom != NULL ) {
5538 if ( atom->_size != rhsAtom->_size )
5539 return false;
5540 const char* rhsStringContent = (char*)rhsAtom->contentPointer();
5541 return (strcmp(stringContent, rhsStringContent) == 0);
5542 }
5543 return false;
5544 }
5545
5546
5547 template <>
5548 ld::Fixup::Kind NonLazyPointerSection<x86>::fixupKind()
5549 {
5550 return ld::Fixup::kindStoreLittleEndian32;
5551 }
5552
5553 template <>
5554 ld::Fixup::Kind NonLazyPointerSection<arm>::fixupKind()
5555 {
5556 return ld::Fixup::kindStoreLittleEndian32;
5557 }
5558
5559 template <>
5560 ld::Fixup::Kind NonLazyPointerSection<arm64>::fixupKind()
5561 {
5562 return ld::Fixup::kindStoreLittleEndian64;
5563 }
5564
5565
5566 template <>
5567 void NonLazyPointerSection<x86_64>::makeFixups(class Parser<x86_64>& parser, const struct Parser<x86_64>::CFI_CU_InfoArrays&)
5568 {
5569 assert(0 && "x86_64 should not have non-lazy-pointer sections in .o files");
5570 }
5571
5572 template <typename A>
5573 void NonLazyPointerSection<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&)
5574 {
5575 // add references for each NLP atom based on indirect symbol table
5576 const macho_section<P>* sect = this->machoSection();
5577 const pint_t endAddr = sect->addr() + sect->size();
5578 for( pint_t addr = sect->addr(); addr < endAddr; addr += sizeof(pint_t)) {
5579 typename Parser<A>::SourceLocation src;
5580 typename Parser<A>::TargetDesc target;
5581 src.atom = this->findAtomByAddress(addr);
5582 src.offsetInAtom = 0;
5583 uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(addr, sect);
5584 target.atom = NULL;
5585 target.name = NULL;
5586 target.weakImport = false;
5587 target.addend = 0;
5588 if ( symIndex == INDIRECT_SYMBOL_LOCAL ) {
5589 // use direct reference for local symbols
5590 const pint_t* nlpContent = (pint_t*)(this->file().fileContent() + sect->offset() + addr - sect->addr());
5591 pint_t targetAddr = P::getP(*nlpContent);
5592 target.atom = parser.findAtomByAddress(targetAddr);
5593 target.weakImport = false;
5594 target.addend = (targetAddr - target.atom->objectAddress());
5595 // <rdar://problem/8385011> if pointer to thumb function, mask of thumb bit (not an addend of +1)
5596 if ( target.atom->isThumb() )
5597 target.addend &= (-2);
5598 assert(src.atom->combine() == ld::Atom::combineNever);
5599 }
5600 else {
5601 const macho_nlist<P>& sym = parser.symbolFromIndex(symIndex);
5602 // use direct reference for local symbols
5603 if ( ((sym.n_type() & N_TYPE) == N_SECT) && ((sym.n_type() & N_EXT) == 0) ) {
5604 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
5605 assert(src.atom->combine() == ld::Atom::combineNever);
5606 }
5607 else {
5608 target.name = parser.nameFromSymbol(sym);
5609 target.weakImport = parser.weakImportFromSymbol(sym);
5610 assert(src.atom->combine() == ld::Atom::combineByNameAndReferences);
5611 }
5612 }
5613 parser.addFixups(src, this->fixupKind(), target);
5614 }
5615 }
5616
5617 template <typename A>
5618 ld::Atom::Combine NonLazyPointerSection<A>::combine(Parser<A>& parser, pint_t addr)
5619 {
5620 const macho_section<P>* sect = this->machoSection();
5621 uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(addr, sect);
5622 if ( symIndex == INDIRECT_SYMBOL_LOCAL)
5623 return ld::Atom::combineNever;
5624
5625 // don't coalesce non-lazy-pointers to local symbols
5626 const macho_nlist<P>& sym = parser.symbolFromIndex(symIndex);
5627 if ( ((sym.n_type() & N_TYPE) == N_SECT) && ((sym.n_type() & N_EXT) == 0) )
5628 return ld::Atom::combineNever;
5629
5630 return ld::Atom::combineByNameAndReferences;
5631 }
5632
5633 template <typename A>
5634 const char* NonLazyPointerSection<A>::targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind)
5635 {
5636 assert(atom->combine() == ld::Atom::combineByNameAndReferences);
5637 assert(atom->fixupCount() == 1);
5638 ld::Fixup::iterator fit = atom->fixupsBegin();
5639 const char* name = NULL;
5640 switch ( fit->binding ) {
5641 case ld::Fixup::bindingByNameUnbound:
5642 name = fit->u.name;
5643 break;
5644 case ld::Fixup::bindingByContentBound:
5645 name = fit->u.target->name();
5646 break;
5647 case ld::Fixup::bindingsIndirectlyBound:
5648 name = ind.indirectName(fit->u.bindingIndex);
5649 break;
5650 default:
5651 assert(0);
5652 }
5653 assert(name != NULL);
5654 return name;
5655 }
5656
5657 template <typename A>
5658 unsigned long NonLazyPointerSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5659 {
5660 assert(atom->combine() == ld::Atom::combineByNameAndReferences);
5661 unsigned long hash = 9508;
5662 for (const char* s = this->targetName(atom, ind); *s != '\0'; ++s) {
5663 hash = hash * 33 + *s;
5664 }
5665 return hash;
5666 }
5667
5668 template <typename A>
5669 bool NonLazyPointerSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5670 const ld::IndirectBindingTable& indirectBindingTable) const
5671 {
5672 if ( rhs.section().type() != ld::Section::typeNonLazyPointer )
5673 return false;
5674 assert(this->type() == rhs.section().type());
5675 // there can be many non-lazy pointer in different section names
5676 // we only want to coalesce in same section name
5677 if ( *this != rhs.section() )
5678 return false;
5679 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5680 assert(rhsAtom != NULL);
5681 const char* thisName = this->targetName(atom, indirectBindingTable);
5682 const char* rhsName = this->targetName(rhsAtom, indirectBindingTable);
5683 return (strcmp(thisName, rhsName) == 0);
5684 }
5685
5686 template <typename A>
5687 ld::Atom::Scope NonLazyPointerSection<A>::scopeAtAddress(Parser<A>& parser, pint_t addr)
5688 {
5689 const macho_section<P>* sect = this->machoSection();
5690 uint32_t symIndex = parser.symbolIndexFromIndirectSectionAddress(addr, sect);
5691 if ( symIndex == INDIRECT_SYMBOL_LOCAL)
5692 return ld::Atom::scopeTranslationUnit;
5693 else
5694 return ld::Atom::scopeLinkageUnit;
5695 }
5696
5697
5698
5699 template <typename A>
5700 ld::Atom::Combine TLVPointerSection<A>::combine(Parser<A>& parser, pint_t addr)
5701 {
5702 return ld::Atom::combineByNameAndReferences;
5703 }
5704
5705
5706 template <typename A>
5707 const char* TLVPointerSection<A>::targetName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind, bool* isStatic)
5708 {
5709 assert(atom->combine() == ld::Atom::combineByNameAndReferences);
5710 assert(atom->fixupCount() == 1);
5711 *isStatic = false;
5712 ld::Fixup::iterator fit = atom->fixupsBegin();
5713 const char* name = NULL;
5714 switch ( fit->binding ) {
5715 case ld::Fixup::bindingByNameUnbound:
5716 name = fit->u.name;
5717 break;
5718 case ld::Fixup::bindingByContentBound:
5719 name = fit->u.target->name();
5720 break;
5721 case ld::Fixup::bindingsIndirectlyBound:
5722 name = ind.indirectName(fit->u.bindingIndex);
5723 break;
5724 case ld::Fixup::bindingDirectlyBound:
5725 name = fit->u.target->name();
5726 *isStatic = (fit->u.target->scope() == ld::Atom::scopeTranslationUnit);
5727 break;
5728 default:
5729 assert(0);
5730 }
5731 assert(name != NULL);
5732 return name;
5733 }
5734
5735 template <typename A>
5736 unsigned long TLVPointerSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5737 {
5738 assert(atom->combine() == ld::Atom::combineByNameAndReferences);
5739 unsigned long hash = 9508;
5740 bool isStatic;
5741 for (const char* s = this->targetName(atom, ind, &isStatic); *s != '\0'; ++s) {
5742 hash = hash * 33 + *s;
5743 }
5744 return hash;
5745 }
5746
5747 template <typename A>
5748 bool TLVPointerSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5749 const ld::IndirectBindingTable& indirectBindingTable) const
5750 {
5751 if ( rhs.section().type() != ld::Section::typeTLVPointers )
5752 return false;
5753 assert(this->type() == rhs.section().type());
5754 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5755 assert(rhsAtom != NULL);
5756 bool thisIsStatic;
5757 bool rhsIsStatic;
5758 const char* thisName = this->targetName(atom, indirectBindingTable, &thisIsStatic);
5759 const char* rhsName = this->targetName(rhsAtom, indirectBindingTable, &rhsIsStatic);
5760 return !thisIsStatic && !rhsIsStatic && (strcmp(thisName, rhsName) == 0);
5761 }
5762
5763
5764 template <typename A>
5765 const uint8_t* CFStringSection<A>::targetContent(const class Atom<A>* atom, const ld::IndirectBindingTable& ind,
5766 ContentType* ct, unsigned int* count)
5767 {
5768 *ct = contentUnknown;
5769 for (ld::Fixup::iterator fit=atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
5770 const ld::Atom* targetAtom = NULL;
5771 switch ( fit->binding ) {
5772 case ld::Fixup::bindingByNameUnbound:
5773 // ignore reference to ___CFConstantStringClassReference
5774 // we are just looking for reference to backing string data
5775 assert(fit->offsetInAtom == 0);
5776 assert(strcmp(fit->u.name, "___CFConstantStringClassReference") == 0);
5777 break;
5778 case ld::Fixup::bindingDirectlyBound:
5779 case ld::Fixup::bindingByContentBound:
5780 targetAtom = fit->u.target;
5781 break;
5782 case ld::Fixup::bindingsIndirectlyBound:
5783 targetAtom = ind.indirectAtom(fit->u.bindingIndex);
5784 break;
5785 default:
5786 assert(0 && "bad binding type");
5787 }
5788 assert(targetAtom != NULL);
5789 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
5790 if ( targetAtom->section().type() == ld::Section::typeCString ) {
5791 *ct = contentUTF8;
5792 *count = targetAtom->size();
5793 }
5794 else if ( targetAtom->section().type() == ld::Section::typeUTF16Strings ) {
5795 *ct = contentUTF16;
5796 *count = (targetAtom->size()+1)/2; // round up incase of buggy compiler that has only one trailing zero byte
5797 }
5798 else {
5799 *ct = contentUnknown;
5800 *count = 0;
5801 return NULL;
5802 }
5803 return target->contentPointer();
5804 }
5805 assert(0);
5806 return NULL;
5807 }
5808
5809 template <typename A>
5810 unsigned long CFStringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5811 {
5812 // base hash of CFString on hash of cstring it wraps
5813 ContentType cType;
5814 unsigned long hash;
5815 unsigned int charCount;
5816 const uint8_t* content = this->targetContent(atom, ind, &cType, &charCount);
5817 switch ( cType ) {
5818 case contentUTF8:
5819 hash = 9408;
5820 for (const char* s = (char*)content; *s != '\0'; ++s) {
5821 hash = hash * 33 + *s;
5822 }
5823 return hash;
5824 case contentUTF16:
5825 hash = 407955;
5826 --charCount; // don't add last 0x0000 to hash because some buggy compilers only have trailing single byte
5827 for (const uint16_t* s = (uint16_t*)content; charCount > 0; ++s, --charCount) {
5828 hash = hash * 1025 + *s;
5829 }
5830 return hash;
5831 case contentUnknown:
5832 // <rdar://problem/14134211> For malformed CFStrings, hash to address of atom so they have unique hashes
5833 return ULONG_MAX - (unsigned long)(atom);
5834 }
5835 return 0;
5836 }
5837
5838
5839 template <typename A>
5840 bool CFStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5841 const ld::IndirectBindingTable& indirectBindingTable) const
5842 {
5843 if ( atom == &rhs )
5844 return true;
5845 if ( rhs.section().type() != ld::Section::typeCFString)
5846 return false;
5847 assert(this->type() == rhs.section().type());
5848 assert(strcmp(this->sectionName(), "__cfstring") == 0);
5849
5850 ContentType thisType;
5851 unsigned int charCount;
5852 const uint8_t* cstringContent = this->targetContent(atom, indirectBindingTable, &thisType, &charCount);
5853 ContentType rhsType;
5854 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5855 assert(rhsAtom != NULL);
5856 unsigned int rhsCharCount;
5857 const uint8_t* rhsStringContent = this->targetContent(rhsAtom, indirectBindingTable, &rhsType, &rhsCharCount);
5858
5859 if ( thisType != rhsType )
5860 return false;
5861
5862 if ( thisType == contentUnknown )
5863 return false;
5864
5865 if ( rhsType == contentUnknown )
5866 return false;
5867
5868 // no need to compare content of pointers are already the same
5869 if ( cstringContent == rhsStringContent )
5870 return true;
5871
5872 // no need to compare content if size is different
5873 if ( charCount != rhsCharCount )
5874 return false;
5875
5876 switch ( thisType ) {
5877 case contentUTF8:
5878 return (strcmp((char*)cstringContent, (char*)rhsStringContent) == 0);
5879 case contentUTF16:
5880 {
5881 const uint16_t* cstringContent16 = (uint16_t*)cstringContent;
5882 const uint16_t* rhsStringContent16 = (uint16_t*)rhsStringContent;
5883 for (unsigned int i = 0; i < charCount; ++i) {
5884 if ( cstringContent16[i] != rhsStringContent16[i] )
5885 return false;
5886 }
5887 return true;
5888 }
5889 case contentUnknown:
5890 return false;
5891 }
5892 return false;
5893 }
5894
5895
5896 template <typename A>
5897 typename A::P::uint_t ObjC1ClassSection<A>::elementSizeAtAddress(pint_t addr)
5898 {
5899 // nominal size for each class is 48 bytes, but sometimes the compiler
5900 // over aligns and there is padding after class data
5901 const macho_section<P>* sct = this->machoSection();
5902 uint32_t align = 1 << sct->align();
5903 uint32_t size = ((12 * sizeof(pint_t)) + align-1) & (-align);
5904 return size;
5905 }
5906
5907 template <typename A>
5908 const char* ObjC1ClassSection<A>::unlabeledAtomName(Parser<A>& parser, pint_t addr)
5909 {
5910 // 8-bytes into class object is pointer to class name
5911 const macho_section<P>* sct = this->machoSection();
5912 uint32_t classObjcFileOffset = sct->offset() - sct->addr() + addr;
5913 const uint8_t* mappedFileContent = this->file().fileContent();
5914 pint_t nameAddr = P::getP(*((pint_t*)(mappedFileContent+classObjcFileOffset+2*sizeof(pint_t))));
5915
5916 // find section containing string address to get string bytes
5917 const macho_section<P>* const sections = parser.firstMachOSection();
5918 const uint32_t sectionCount = parser.machOSectionCount();
5919 for (uint32_t i=0; i < sectionCount; ++i) {
5920 const macho_section<P>* aSect = &sections[i];
5921 if ( (aSect->addr() <= nameAddr) && (nameAddr < (aSect->addr()+aSect->size())) ) {
5922 assert((aSect->flags() & SECTION_TYPE) == S_CSTRING_LITERALS);
5923 uint32_t nameFileOffset = aSect->offset() - aSect->addr() + nameAddr;
5924 const char* name = (char*)mappedFileContent + nameFileOffset;
5925 // spin through symbol table to find absolute symbol corresponding to this class
5926 for (uint32_t s=0; s < parser.symbolCount(); ++s) {
5927 const macho_nlist<P>& sym = parser.symbolFromIndex(s);
5928 if ( (sym.n_type() & N_TYPE) != N_ABS )
5929 continue;
5930 const char* absName = parser.nameFromSymbol(sym);
5931 if ( strncmp(absName, ".objc_class_name_", 17) == 0 ) {
5932 if ( strcmp(&absName[17], name) == 0 )
5933 return absName;
5934 }
5935 }
5936 assert(0 && "obj class name not found in symbol table");
5937 }
5938 }
5939 assert(0 && "obj class name not found");
5940 return "unknown objc class";
5941 }
5942
5943
5944 template <typename A>
5945 const char* ObjC2ClassRefsSection<A>::targetClassName(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5946 {
5947 assert(atom->fixupCount() == 1);
5948 ld::Fixup::iterator fit = atom->fixupsBegin();
5949 const char* className = NULL;
5950 switch ( fit->binding ) {
5951 case ld::Fixup::bindingByNameUnbound:
5952 className = fit->u.name;
5953 break;
5954 case ld::Fixup::bindingDirectlyBound:
5955 case ld::Fixup::bindingByContentBound:
5956 className = fit->u.target->name();
5957 break;
5958 case ld::Fixup::bindingsIndirectlyBound:
5959 className = ind.indirectName(fit->u.bindingIndex);
5960 break;
5961 default:
5962 assert(0 && "unsupported binding in objc2 class ref section");
5963 }
5964 assert(className != NULL);
5965 return className;
5966 }
5967
5968
5969 template <typename A>
5970 unsigned long ObjC2ClassRefsSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5971 {
5972 unsigned long hash = 978;
5973 for (const char* s = targetClassName(atom, ind); *s != '\0'; ++s) {
5974 hash = hash * 33 + *s;
5975 }
5976 return hash;
5977 }
5978
5979 template <typename A>
5980 bool ObjC2ClassRefsSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
5981 const ld::IndirectBindingTable& indirectBindingTable) const
5982 {
5983 assert(this->type() == rhs.section().type());
5984 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
5985 assert(rhsAtom != NULL);
5986 const char* thisClassName = targetClassName(atom, indirectBindingTable);
5987 const char* rhsClassName = targetClassName(rhsAtom, indirectBindingTable);
5988 return (strcmp(thisClassName, rhsClassName) == 0);
5989 }
5990
5991
5992 template <typename A>
5993 const char* Objc1ClassReferences<A>::targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
5994 {
5995 assert(atom->fixupCount() == 2);
5996 ld::Fixup::iterator fit = atom->fixupsBegin();
5997 if ( fit->kind == ld::Fixup::kindSetTargetAddress )
5998 ++fit;
5999 const ld::Atom* targetAtom = NULL;
6000 switch ( fit->binding ) {
6001 case ld::Fixup::bindingByContentBound:
6002 targetAtom = fit->u.target;
6003 break;
6004 case ld::Fixup::bindingsIndirectlyBound:
6005 targetAtom = ind.indirectAtom(fit->u.bindingIndex);
6006 if ( targetAtom == NULL ) {
6007 fprintf(stderr, "missing target named %s\n", ind.indirectName(fit->u.bindingIndex));
6008 }
6009 break;
6010 default:
6011 assert(0);
6012 }
6013 assert(targetAtom != NULL);
6014 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
6015 assert(target != NULL);
6016 return (char*)target->contentPointer();
6017 }
6018
6019
6020 template <typename A>
6021 const char* PointerToCStringSection<A>::targetCString(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
6022 {
6023 assert(atom->fixupCount() == 1);
6024 ld::Fixup::iterator fit = atom->fixupsBegin();
6025 const ld::Atom* targetAtom = NULL;
6026 switch ( fit->binding ) {
6027 case ld::Fixup::bindingByContentBound:
6028 targetAtom = fit->u.target;
6029 break;
6030 case ld::Fixup::bindingsIndirectlyBound:
6031 targetAtom = ind.indirectAtom(fit->u.bindingIndex);
6032 break;
6033 case ld::Fixup::bindingDirectlyBound:
6034 targetAtom = fit->u.target;
6035 break;
6036 default:
6037 assert(0 && "unsupported reference to selector");
6038 }
6039 assert(targetAtom != NULL);
6040 const Atom<A>* target = dynamic_cast<const Atom<A>*>(targetAtom);
6041 assert(target != NULL);
6042 assert(target->contentType() == ld::Atom::typeCString);
6043 return (char*)target->contentPointer();
6044 }
6045
6046 template <typename A>
6047 unsigned long PointerToCStringSection<A>::contentHash(const class Atom<A>* atom,
6048 const ld::IndirectBindingTable& indirectBindingTable) const
6049 {
6050 // make hash from section name and target cstring name
6051 unsigned long hash = 123;
6052 for (const char* s = this->sectionName(); *s != '\0'; ++s) {
6053 hash = hash * 33 + *s;
6054 }
6055 for (const char* s = this->targetCString(atom, indirectBindingTable); *s != '\0'; ++s) {
6056 hash = hash * 33 + *s;
6057 }
6058 return hash;
6059 }
6060
6061 template <typename A>
6062 bool PointerToCStringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
6063 const ld::IndirectBindingTable& indirectBindingTable) const
6064 {
6065 assert(this->type() == rhs.section().type());
6066 // there can be pointers-to-cstrings in different section names
6067 // we only want to coalesce in same section name
6068 if ( *this != rhs.section() )
6069 return false;
6070
6071 // get string content for this
6072 const char* cstringContent = this->targetCString(atom, indirectBindingTable);
6073 const Atom<A>* rhsAtom = dynamic_cast<const Atom<A>*>(&rhs);
6074 assert(rhsAtom != NULL);
6075 const char* rhsCstringContent = this->targetCString(rhsAtom, indirectBindingTable);
6076
6077 assert(cstringContent != NULL);
6078 assert(rhsCstringContent != NULL);
6079 return (strcmp(cstringContent, rhsCstringContent) == 0);
6080 }
6081
6082
6083
6084 template <typename A>
6085 unsigned long UTF16StringSection<A>::contentHash(const class Atom<A>* atom, const ld::IndirectBindingTable& ind) const
6086 {
6087 unsigned long hash = 5381;
6088 const uint16_t* stringContent = (uint16_t*)atom->contentPointer();
6089 // some buggy compilers end utf16 data with single byte, so don't use last word in hash computation
6090 unsigned int count = (atom->size()/2) - 1;
6091 for (const uint16_t* s = stringContent; count > 0; ++s, --count) {
6092 hash = hash * 33 + *s;
6093 }
6094 return hash;
6095 }
6096
6097 template <typename A>
6098 bool UTF16StringSection<A>::canCoalesceWith(const class Atom<A>* atom, const ld::Atom& rhs,
6099 const ld::IndirectBindingTable& ind) const
6100 {
6101 if ( rhs.section().type() != ld::Section::typeUTF16Strings )
6102 return false;
6103 assert(0);
6104 return false;
6105 }
6106
6107
6108
6109
6110
6111
6112
6113 template <>
6114 uint32_t Section<x86_64>::x86_64PcRelOffset(uint8_t r_type)
6115 {
6116 switch ( r_type ) {
6117 case X86_64_RELOC_SIGNED:
6118 return 4;
6119 case X86_64_RELOC_SIGNED_1:
6120 return 5;
6121 case X86_64_RELOC_SIGNED_2:
6122 return 6;
6123 case X86_64_RELOC_SIGNED_4:
6124 return 8;
6125 }
6126 return 0;
6127 }
6128
6129
6130 template <>
6131 bool Section<x86_64>::addRelocFixup(class Parser<x86_64>& parser, const macho_relocation_info<P>* reloc)
6132 {
6133 const macho_section<P>* sect = this->machoSection();
6134 uint64_t srcAddr = sect->addr() + reloc->r_address();
6135 Parser<x86_64>::SourceLocation src;
6136 Parser<x86_64>::TargetDesc target;
6137 Parser<x86_64>::TargetDesc toTarget;
6138 src.atom = this->findAtomByAddress(srcAddr);
6139 src.offsetInAtom = srcAddr - src.atom->_objAddress;
6140 const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
6141 uint64_t contentValue = 0;
6142 const macho_relocation_info<x86_64::P>* nextReloc = &reloc[1];
6143 bool result = false;
6144 bool useDirectBinding;
6145 switch ( reloc->r_length() ) {
6146 case 0:
6147 contentValue = *fixUpPtr;
6148 break;
6149 case 1:
6150 contentValue = (int64_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr));
6151 break;
6152 case 2:
6153 contentValue = (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr));
6154 break;
6155 case 3:
6156 contentValue = E::get64(*((uint64_t*)fixUpPtr));
6157 break;
6158 }
6159 target.atom = NULL;
6160 target.name = NULL;
6161 target.weakImport = false;
6162 target.addend = 0;
6163 if ( reloc->r_extern() ) {
6164 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
6165 // use direct reference for local symbols
6166 if ( ((sym.n_type() & N_TYPE) == N_SECT) && (((sym.n_type() & N_EXT) == 0) || (parser.nameFromSymbol(sym)[0] == 'L')) ) {
6167 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
6168 target.addend += contentValue;
6169 }
6170 else {
6171 target.name = parser.nameFromSymbol(sym);
6172 target.weakImport = parser.weakImportFromSymbol(sym);
6173 target.addend = contentValue;
6174 }
6175 // cfstrings should always use direct reference to backing store
6176 if ( (this->type() == ld::Section::typeCFString) && (src.offsetInAtom != 0) ) {
6177 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
6178 target.addend = contentValue;
6179 }
6180 }
6181 else {
6182 if ( reloc->r_pcrel() )
6183 contentValue += srcAddr + x86_64PcRelOffset(reloc->r_type());
6184 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
6185 }
6186 switch ( reloc->r_type() ) {
6187 case X86_64_RELOC_UNSIGNED:
6188 if ( reloc->r_pcrel() )
6189 throw "pcrel and X86_64_RELOC_UNSIGNED not supported";
6190 switch ( reloc->r_length() ) {
6191 case 0:
6192 case 1:
6193 throw "length < 2 and X86_64_RELOC_UNSIGNED not supported";
6194 case 2:
6195 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
6196 break;
6197 case 3:
6198 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian64, target);
6199 break;
6200 }
6201 break;
6202 case X86_64_RELOC_SIGNED:
6203 case X86_64_RELOC_SIGNED_1:
6204 case X86_64_RELOC_SIGNED_2:
6205 case X86_64_RELOC_SIGNED_4:
6206 if ( ! reloc->r_pcrel() )
6207 throw "not pcrel and X86_64_RELOC_SIGNED* not supported";
6208 if ( reloc->r_length() != 2 )
6209 throw "length != 2 and X86_64_RELOC_SIGNED* not supported";
6210 switch ( reloc->r_type() ) {
6211 case X86_64_RELOC_SIGNED:
6212 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32, target);
6213 break;
6214 case X86_64_RELOC_SIGNED_1:
6215 if ( reloc->r_extern() )
6216 target.addend += 1;
6217 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_1, target);
6218 break;
6219 case X86_64_RELOC_SIGNED_2:
6220 if ( reloc->r_extern() )
6221 target.addend += 2;
6222 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_2, target);
6223 break;
6224 case X86_64_RELOC_SIGNED_4:
6225 if ( reloc->r_extern() )
6226 target.addend += 4;
6227 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32_4, target);
6228 break;
6229 }
6230 break;
6231 case X86_64_RELOC_BRANCH:
6232 if ( ! reloc->r_pcrel() )
6233 throw "not pcrel and X86_64_RELOC_BRANCH not supported";
6234 switch ( reloc->r_length() ) {
6235 case 2:
6236 if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_probe$", 16) == 0) ) {
6237 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreX86DtraceCallSiteNop, false, target.name);
6238 parser.addDtraceExtraInfos(src, &target.name[16]);
6239 }
6240 else if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_isenabled$", 20) == 0) ) {
6241 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreX86DtraceIsEnableSiteClear, false, target.name);
6242 parser.addDtraceExtraInfos(src, &target.name[20]);
6243 }
6244 else {
6245 parser.addFixups(src, ld::Fixup::kindStoreX86BranchPCRel32, target);
6246 }
6247 break;
6248 case 0:
6249 parser.addFixups(src, ld::Fixup::kindStoreX86BranchPCRel8, target);
6250 break;
6251 default:
6252 throwf("length=%d and X86_64_RELOC_BRANCH not supported", reloc->r_length());
6253 }
6254 break;
6255 case X86_64_RELOC_GOT:
6256 if ( ! reloc->r_extern() )
6257 throw "not extern and X86_64_RELOC_GOT not supported";
6258 if ( ! reloc->r_pcrel() )
6259 throw "not pcrel and X86_64_RELOC_GOT not supported";
6260 if ( reloc->r_length() != 2 )
6261 throw "length != 2 and X86_64_RELOC_GOT not supported";
6262 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32GOT, target);
6263 break;
6264 case X86_64_RELOC_GOT_LOAD:
6265 if ( ! reloc->r_extern() )
6266 throw "not extern and X86_64_RELOC_GOT_LOAD not supported";
6267 if ( ! reloc->r_pcrel() )
6268 throw "not pcrel and X86_64_RELOC_GOT_LOAD not supported";
6269 if ( reloc->r_length() != 2 )
6270 throw "length != 2 and X86_64_RELOC_GOT_LOAD not supported";
6271 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32GOTLoad, target);
6272 break;
6273 case X86_64_RELOC_SUBTRACTOR:
6274 if ( reloc->r_pcrel() )
6275 throw "X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
6276 if ( reloc->r_length() < 2 )
6277 throw "X86_64_RELOC_SUBTRACTOR must have r_length of 2 or 3";
6278 if ( !reloc->r_extern() )
6279 throw "X86_64_RELOC_SUBTRACTOR must have r_extern=1";
6280 if ( nextReloc->r_type() != X86_64_RELOC_UNSIGNED )
6281 throw "X86_64_RELOC_SUBTRACTOR must be followed by X86_64_RELOC_UNSIGNED";
6282 result = true;
6283 if ( nextReloc->r_pcrel() )
6284 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR cannot be pc-relative";
6285 if ( nextReloc->r_length() != reloc->r_length() )
6286 throw "X86_64_RELOC_UNSIGNED following a X86_64_RELOC_SUBTRACTOR must have same r_length";
6287 if ( nextReloc->r_extern() ) {
6288 const macho_nlist<P>& sym = parser.symbolFromIndex(nextReloc->r_symbolnum());
6289 // use direct reference for local symbols
6290 if ( ((sym.n_type() & N_TYPE) == N_SECT) && (((sym.n_type() & N_EXT) == 0) || (parser.nameFromSymbol(sym)[0] == 'L')) ) {
6291 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), toTarget);
6292 toTarget.addend = contentValue;
6293 useDirectBinding = true;
6294 }
6295 else {
6296 toTarget.name = parser.nameFromSymbol(sym);
6297 toTarget.weakImport = parser.weakImportFromSymbol(sym);
6298 toTarget.addend = contentValue;
6299 useDirectBinding = false;
6300 }
6301 }
6302 else {
6303 parser.findTargetFromAddressAndSectionNum(contentValue, nextReloc->r_symbolnum(), toTarget);
6304 useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit);
6305 }
6306 if ( useDirectBinding )
6307 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom);
6308 else
6309 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.weakImport, toTarget.name);
6310 parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindAddAddend, toTarget.addend);
6311 if ( target.atom == NULL )
6312 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractTargetAddress, false, target.name);
6313 else
6314 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractTargetAddress, target.atom);
6315 if ( reloc->r_length() == 2 )
6316 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
6317 else
6318 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian64);
6319 break;
6320 case X86_64_RELOC_TLV:
6321 if ( ! reloc->r_extern() )
6322 throw "not extern and X86_64_RELOC_TLV not supported";
6323 if ( ! reloc->r_pcrel() )
6324 throw "not pcrel and X86_64_RELOC_TLV not supported";
6325 if ( reloc->r_length() != 2 )
6326 throw "length != 2 and X86_64_RELOC_TLV not supported";
6327 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32TLVLoad, target);
6328 break;
6329 default:
6330 throwf("unknown relocation type %d", reloc->r_type());
6331 }
6332 return result;
6333 }
6334
6335
6336
6337 template <>
6338 bool Section<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<P>* reloc)
6339 {
6340 const macho_section<P>* sect = this->machoSection();
6341 uint32_t srcAddr;
6342 const uint8_t* fixUpPtr;
6343 uint32_t contentValue = 0;
6344 ld::Fixup::Kind kind = ld::Fixup::kindNone;
6345 Parser<x86>::SourceLocation src;
6346 Parser<x86>::TargetDesc target;
6347
6348 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
6349 srcAddr = sect->addr() + reloc->r_address();
6350 src.atom = this->findAtomByAddress(srcAddr);
6351 src.offsetInAtom = srcAddr - src.atom->_objAddress;
6352 fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
6353 switch ( reloc->r_type() ) {
6354 case GENERIC_RELOC_VANILLA:
6355 switch ( reloc->r_length() ) {
6356 case 0:
6357 contentValue = (int32_t)(int8_t)*fixUpPtr;
6358 if ( reloc->r_pcrel() ) {
6359 kind = ld::Fixup::kindStoreX86BranchPCRel8;
6360 contentValue += srcAddr + sizeof(uint8_t);
6361 }
6362 else
6363 throw "r_length=0 and r_pcrel=0 not supported";
6364 break;
6365 case 1:
6366 contentValue = (int32_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr));
6367 if ( reloc->r_pcrel() ) {
6368 kind = ld::Fixup::kindStoreX86PCRel16;
6369 contentValue += srcAddr + sizeof(uint16_t);
6370 }
6371 else
6372 kind = ld::Fixup::kindStoreLittleEndian16;
6373 break;
6374 case 2:
6375 contentValue = E::get32(*((uint32_t*)fixUpPtr));
6376 if ( reloc->r_pcrel() ) {
6377 kind = ld::Fixup::kindStoreX86BranchPCRel32;
6378 contentValue += srcAddr + sizeof(uint32_t);
6379 }
6380 else
6381 kind = ld::Fixup::kindStoreLittleEndian32;
6382 break;
6383 case 3:
6384 throw "r_length=3 not supported";
6385 }
6386 if ( reloc->r_extern() ) {
6387 target.atom = NULL;
6388 const macho_nlist<P>& targetSymbol = parser.symbolFromIndex(reloc->r_symbolnum());
6389 target.name = parser.nameFromSymbol(targetSymbol);
6390 target.weakImport = parser.weakImportFromSymbol(targetSymbol);
6391 target.addend = (int32_t)contentValue;
6392 }
6393 else {
6394 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
6395 }
6396 if ( (kind == ld::Fixup::kindStoreX86BranchPCRel32) && (target.name != NULL) ) {
6397 if ( strncmp(target.name, "___dtrace_probe$", 16) == 0 ) {
6398 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreX86DtraceCallSiteNop, false, target.name);
6399 parser.addDtraceExtraInfos(src, &target.name[16]);
6400 return false;
6401 }
6402 else if ( strncmp(target.name, "___dtrace_isenabled$", 20) == 0 ) {
6403 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreX86DtraceIsEnableSiteClear, false, target.name);
6404 parser.addDtraceExtraInfos(src, &target.name[20]);
6405 return false;
6406 }
6407 }
6408 parser.addFixups(src, kind, target);
6409 return false;
6410 break;
6411 case GENERIC_RLEOC_TLV:
6412 {
6413 if ( !reloc->r_extern() )
6414 throw "r_extern=0 and r_type=GENERIC_RLEOC_TLV not supported";
6415 if ( reloc->r_length() != 2 )
6416 throw "r_length!=2 and r_type=GENERIC_RLEOC_TLV not supported";
6417 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
6418 // use direct reference for local symbols
6419 if ( ((sym.n_type() & N_TYPE) == N_SECT) && ((sym.n_type() & N_EXT) == 0) ) {
6420 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
6421 }
6422 else {
6423 target.atom = NULL;
6424 target.name = parser.nameFromSymbol(sym);
6425 target.weakImport = parser.weakImportFromSymbol(sym);
6426 }
6427 target.addend = (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr));
6428 if ( reloc->r_pcrel() ) {
6429 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32TLVLoad, target);
6430 }
6431 else {
6432 parser.addFixups(src, ld::Fixup::kindStoreX86Abs32TLVLoad, target);
6433 }
6434 return false;
6435 }
6436 break;
6437 default:
6438 throwf("unsupported i386 relocation type (%d)", reloc->r_type());
6439 }
6440 }
6441 else {
6442 // scattered relocation
6443 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
6444 srcAddr = sect->addr() + sreloc->r_address();
6445 src.atom = this->findAtomByAddress(srcAddr);
6446 assert(src.atom != NULL);
6447 src.offsetInAtom = srcAddr - src.atom->_objAddress;
6448 fixUpPtr = file().fileContent() + sect->offset() + sreloc->r_address();
6449 uint32_t relocValue = sreloc->r_value();
6450 bool result = false;
6451 // file format allows pair to be scattered or not
6452 const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
6453 const macho_relocation_info<P>* nextReloc = &reloc[1];
6454 bool nextRelocIsPair = false;
6455 uint32_t nextRelocAddress = 0;
6456 uint32_t nextRelocValue = 0;
6457 if ( (nextReloc->r_address() & R_SCATTERED) == 0 ) {
6458 if ( nextReloc->r_type() == GENERIC_RELOC_PAIR ) {
6459 nextRelocIsPair = true;
6460 nextRelocAddress = nextReloc->r_address();
6461 result = true; // iterator should skip next reloc, since we've consumed it here
6462 }
6463 }
6464 else {
6465 if ( nextSReloc->r_type() == GENERIC_RELOC_PAIR ) {
6466 nextRelocIsPair = true;
6467 nextRelocAddress = nextSReloc->r_address();
6468 nextRelocValue = nextSReloc->r_value();
6469 }
6470 }
6471 switch (sreloc->r_type()) {
6472 case GENERIC_RELOC_VANILLA:
6473 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
6474 target.atom = parser.findAtomByAddress(relocValue);
6475 if ( sreloc->r_pcrel() ) {
6476 switch ( sreloc->r_length() ) {
6477 case 0:
6478 contentValue = srcAddr + 1 + *fixUpPtr;
6479 target.addend = (int32_t)contentValue - (int32_t)relocValue;
6480 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel8, target);
6481 break;
6482 case 1:
6483 contentValue = srcAddr + 2 + LittleEndian::get16(*((uint16_t*)fixUpPtr));
6484 target.addend = (int32_t)contentValue - (int32_t)relocValue;
6485 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel16, target);
6486 break;
6487 case 2:
6488 contentValue = srcAddr + 4 + LittleEndian::get32(*((uint32_t*)fixUpPtr));
6489 target.addend = (int32_t)contentValue - (int32_t)relocValue;
6490 parser.addFixups(src, ld::Fixup::kindStoreX86PCRel32, target);
6491 break;
6492 case 3:
6493 throw "unsupported r_length=3 for scattered pc-rel vanilla reloc";
6494 break;
6495 }
6496 }
6497 else {
6498 if ( sreloc->r_length() != 2 )
6499 throwf("unsupported r_length=%d for scattered vanilla reloc", sreloc->r_length());
6500 contentValue = LittleEndian::get32(*((uint32_t*)fixUpPtr));
6501 target.addend = (int32_t)contentValue - (int32_t)(target.atom->objectAddress());
6502 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
6503 }
6504 break;
6505 case GENERIC_RELOC_SECTDIFF:
6506 case GENERIC_RELOC_LOCAL_SECTDIFF:
6507 {
6508 if ( !nextRelocIsPair )
6509 throw "GENERIC_RELOC_SECTDIFF missing following pair";
6510 switch ( sreloc->r_length() ) {
6511 case 0:
6512 case 3:
6513 throw "bad length for GENERIC_RELOC_SECTDIFF";
6514 case 1:
6515 contentValue = (int32_t)(int16_t)LittleEndian::get16(*((uint16_t*)fixUpPtr));
6516 kind = ld::Fixup::kindStoreLittleEndian16;
6517 break;
6518 case 2:
6519 contentValue = LittleEndian::get32(*((uint32_t*)fixUpPtr));
6520 kind = ld::Fixup::kindStoreLittleEndian32;
6521 break;
6522 }
6523 Atom<x86>* fromAtom = parser.findAtomByAddress(nextRelocValue);
6524 uint32_t offsetInFrom = nextRelocValue - fromAtom->_objAddress;
6525 parser.findTargetFromAddress(sreloc->r_value(), target);
6526 // check for addend encoded in the section content
6527 int64_t addend = (int32_t)contentValue - (int32_t)(sreloc->r_value() - nextRelocValue);
6528 if ( addend < 0 ) {
6529 // switch binding base on coalescing
6530 if ( target.atom == NULL ) {
6531 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.name);
6532 }
6533 else if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
6534 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, target.atom);
6535 }
6536 else if ( (target.atom->combine() == ld::Atom::combineByNameAndContent) || (target.atom->combine() == ld::Atom::combineByNameAndReferences) ) {
6537 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, target.atom);
6538 }
6539 else {
6540 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
6541 }
6542 parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, target.addend);
6543 parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
6544 parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom-addend);
6545 parser.addFixup(src, ld::Fixup::k5of5, kind);
6546 }
6547 else {
6548 // switch binding base on coalescing
6549 if ( target.atom == NULL ) {
6550 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.name);
6551 }
6552 else if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
6553 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, target.atom);
6554 }
6555 else if ( (target.atom->combine() == ld::Atom::combineByNameAndContent) || (target.atom->combine() == ld::Atom::combineByNameAndReferences) ) {
6556 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, target.atom);
6557 }
6558 else {
6559 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, target.atom->name());
6560 }
6561 parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, target.addend+addend);
6562 parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
6563 parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom);
6564 parser.addFixup(src, ld::Fixup::k5of5, kind);
6565 }
6566 }
6567 break;
6568 }
6569 return result;
6570 }
6571 }
6572
6573
6574
6575
6576
6577 #if SUPPORT_ARCH_arm_any
6578 template <>
6579 bool Section<arm>::addRelocFixup(class Parser<arm>& parser, const macho_relocation_info<P>* reloc)
6580 {
6581 const macho_section<P>* sect = this->machoSection();
6582 bool result = false;
6583 uint32_t srcAddr;
6584 uint32_t dstAddr;
6585 uint32_t* fixUpPtr;
6586 int32_t displacement = 0;
6587 uint32_t instruction = 0;
6588 pint_t contentValue = 0;
6589 Parser<arm>::SourceLocation src;
6590 Parser<arm>::TargetDesc target;
6591 const macho_relocation_info<P>* nextReloc;
6592
6593 if ( (reloc->r_address() & R_SCATTERED) == 0 ) {
6594 bool externSymbolIsThumbDef = false;
6595 srcAddr = sect->addr() + reloc->r_address();
6596 src.atom = this->findAtomByAddress(srcAddr);
6597 src.offsetInAtom = srcAddr - src.atom->_objAddress;
6598 fixUpPtr = (uint32_t*)(file().fileContent() + sect->offset() + reloc->r_address());
6599 if ( reloc->r_type() != ARM_RELOC_PAIR )
6600 instruction = LittleEndian::get32(*fixUpPtr);
6601 if ( reloc->r_extern() ) {
6602 const macho_nlist<P>& targetSymbol = parser.symbolFromIndex(reloc->r_symbolnum());
6603 // use direct reference for local symbols
6604 if ( ((targetSymbol.n_type() & N_TYPE) == N_SECT) && (((targetSymbol.n_type() & N_EXT) == 0) || (parser.nameFromSymbol(targetSymbol)[0] == 'L')) ) {
6605 parser.findTargetFromAddressAndSectionNum(targetSymbol.n_value(), targetSymbol.n_sect(), target);
6606 }
6607 else {
6608 target.atom = NULL;
6609 target.name = parser.nameFromSymbol(targetSymbol);
6610 target.weakImport = parser.weakImportFromSymbol(targetSymbol);
6611 if ( ((targetSymbol.n_type() & N_TYPE) == N_SECT) && (targetSymbol.n_desc() & N_ARM_THUMB_DEF) )
6612 externSymbolIsThumbDef = true;
6613 }
6614 }
6615 switch ( reloc->r_type() ) {
6616 case ARM_RELOC_BR24:
6617 // Sign-extend displacement
6618 displacement = (instruction & 0x00FFFFFF) << 2;
6619 if ( (displacement & 0x02000000) != 0 )
6620 displacement |= 0xFC000000;
6621 // The pc added will be +8 from the pc
6622 displacement += 8;
6623 // If this is BLX add H << 1
6624 if ((instruction & 0xFE000000) == 0xFA000000)
6625 displacement += ((instruction & 0x01000000) >> 23);
6626 if ( reloc->r_extern() ) {
6627 dstAddr = srcAddr + displacement;
6628 // <rdar://problem/16652542> support large .o files
6629 if ( srcAddr > 0x2000000 ) {
6630 dstAddr -= ((srcAddr + 0x1FFFFFF) & 0xFC000000);
6631 }
6632 target.addend = dstAddr;
6633 if ( externSymbolIsThumbDef )
6634 target.addend &= -2; // remove thumb bit
6635 }
6636 else {
6637 dstAddr = srcAddr + displacement;
6638 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
6639 }
6640 // special case "calls" for dtrace
6641 if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_probe$", 16) == 0) ) {
6642 parser.addFixup(src, ld::Fixup::k1of1,
6643 ld::Fixup::kindStoreARMDtraceCallSiteNop, false, target.name);
6644 parser.addDtraceExtraInfos(src, &target.name[16]);
6645 }
6646 else if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_isenabled$", 20) == 0) ) {
6647 parser.addFixup(src, ld::Fixup::k1of1,
6648 ld::Fixup::kindStoreARMDtraceIsEnableSiteClear, false, target.name);
6649 parser.addDtraceExtraInfos(src, &target.name[20]);
6650 }
6651 else {
6652 parser.addFixups(src, ld::Fixup::kindStoreARMBranch24, target);
6653 }
6654 break;
6655 case ARM_THUMB_RELOC_BR22:
6656 // thumb2 added two more bits to displacement, complicating the displacement decoding
6657 {
6658 uint32_t s = (instruction >> 10) & 0x1;
6659 uint32_t j1 = (instruction >> 29) & 0x1;
6660 uint32_t j2 = (instruction >> 27) & 0x1;
6661 uint32_t imm10 = instruction & 0x3FF;
6662 uint32_t imm11 = (instruction >> 16) & 0x7FF;
6663 uint32_t i1 = (j1 == s);
6664 uint32_t i2 = (j2 == s);
6665 uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
6666 int32_t sdis = dis;
6667 if ( s )
6668 sdis |= 0xFE000000;
6669 displacement = sdis;
6670 }
6671 // The pc added will be +4 from the pc
6672 displacement += 4;
6673 // If the instruction was blx, force the low 2 bits to be clear
6674 dstAddr = srcAddr + displacement;
6675 if ((instruction & 0xD0000000) == 0xC0000000)
6676 dstAddr &= 0xFFFFFFFC;
6677
6678 if ( reloc->r_extern() ) {
6679 // <rdar://problem/16652542> support large .o files
6680 if ( srcAddr > 0x1000000 ) {
6681 dstAddr -= ((srcAddr + 0xFFFFFF) & 0xFE000000);
6682 }
6683 target.addend = (int64_t)(int32_t)dstAddr;
6684 }
6685 else {
6686 parser.findTargetFromAddressAndSectionNum(dstAddr, reloc->r_symbolnum(), target);
6687 }
6688 // special case "calls" for dtrace
6689 if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_probe$", 16) == 0) ) {
6690 parser.addFixup(src, ld::Fixup::k1of1,
6691 ld::Fixup::kindStoreThumbDtraceCallSiteNop, false, target.name);
6692 parser.addDtraceExtraInfos(src, &target.name[16]);
6693 }
6694 else if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_isenabled$", 20) == 0) ) {
6695 parser.addFixup(src, ld::Fixup::k1of1,
6696 ld::Fixup::kindStoreThumbDtraceIsEnableSiteClear, false, target.name);
6697 parser.addDtraceExtraInfos(src, &target.name[20]);
6698 }
6699 else {
6700 parser.addFixups(src, ld::Fixup::kindStoreThumbBranch22, target);
6701 }
6702 break;
6703 case ARM_RELOC_VANILLA:
6704 if ( reloc->r_length() != 2 )
6705 throw "bad length for ARM_RELOC_VANILLA";
6706 contentValue = LittleEndian::get32(*fixUpPtr);
6707 if ( reloc->r_extern() ) {
6708 target.addend = (int32_t)contentValue;
6709 if ( externSymbolIsThumbDef )
6710 target.addend &= -2; // remove thumb bit
6711 }
6712 else {
6713 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
6714 // possible non-extern relocation turned into by-name ref because target is a weak-def
6715 if ( target.atom != NULL ) {
6716 if ( target.atom->isThumb() )
6717 target.addend &= -2; // remove thumb bit
6718 // if reference to LSDA, add group subordinate fixup
6719 if ( target.atom->contentType() == ld::Atom::typeLSDA ) {
6720 Parser<arm>::SourceLocation src2;
6721 src2.atom = src.atom;
6722 src2.offsetInAtom = 0;
6723 parser.addFixup(src2, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateLSDA, target.atom);
6724 }
6725 }
6726 }
6727 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
6728 break;
6729 case ARM_THUMB_32BIT_BRANCH:
6730 // silently ignore old unnecessary reloc
6731 break;
6732 case ARM_RELOC_HALF:
6733 nextReloc = &reloc[1];
6734 if ( nextReloc->r_type() == ARM_RELOC_PAIR ) {
6735 uint32_t instruction16;
6736 uint32_t other16 = (nextReloc->r_address() & 0xFFFF);
6737 bool isThumb;
6738 if ( reloc->r_length() & 2 ) {
6739 isThumb = true;
6740 uint32_t i = ((instruction & 0x00000400) >> 10);
6741 uint32_t imm4 = (instruction & 0x0000000F);
6742 uint32_t imm3 = ((instruction & 0x70000000) >> 28);
6743 uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
6744 instruction16 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
6745 }
6746 else {
6747 isThumb = false;
6748 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
6749 uint32_t imm12 = (instruction & 0x00000FFF);
6750 instruction16 = (imm4 << 12) | imm12;
6751 }
6752 if ( reloc->r_length() & 1 ) {
6753 // high 16
6754 dstAddr = ((instruction16 << 16) | other16);
6755 if ( reloc->r_extern() ) {
6756 target.addend = dstAddr;
6757 if ( externSymbolIsThumbDef )
6758 target.addend &= -2; // remove thumb bit
6759 }
6760 else {
6761 parser.findTargetFromAddress(dstAddr, target);
6762 if ( target.atom->isThumb() )
6763 target.addend &= (-2); // remove thumb bit
6764 }
6765 parser.addFixups(src, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16), target);
6766 }
6767 else {
6768 // low 16
6769 dstAddr = (other16 << 16) | instruction16;
6770 if ( reloc->r_extern() ) {
6771 target.addend = dstAddr;
6772 if ( externSymbolIsThumbDef )
6773 target.addend &= -2; // remove thumb bit
6774 }
6775 else {
6776 parser.findTargetFromAddress(dstAddr, target);
6777 if ( target.atom->isThumb() )
6778 target.addend &= (-2); // remove thumb bit
6779 }
6780 parser.addFixups(src, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16), target);
6781 }
6782 result = true;
6783 }
6784 else
6785 throw "for ARM_RELOC_HALF, next reloc is not ARM_RELOC_PAIR";
6786 break;
6787 default:
6788 throwf("unknown relocation type %d", reloc->r_type());
6789 break;
6790 }
6791 }
6792 else {
6793 const macho_scattered_relocation_info<P>* sreloc = (macho_scattered_relocation_info<P>*)reloc;
6794 // file format allows pair to be scattered or not
6795 const macho_scattered_relocation_info<P>* nextSReloc = &sreloc[1];
6796 nextReloc = &reloc[1];
6797 srcAddr = sect->addr() + sreloc->r_address();
6798 dstAddr = sreloc->r_value();
6799 fixUpPtr = (uint32_t*)(file().fileContent() + sect->offset() + sreloc->r_address());
6800 instruction = LittleEndian::get32(*fixUpPtr);
6801 src.atom = this->findAtomByAddress(srcAddr);
6802 src.offsetInAtom = srcAddr - src.atom->_objAddress;
6803 bool nextRelocIsPair = false;
6804 uint32_t nextRelocAddress = 0;
6805 uint32_t nextRelocValue = 0;
6806 if ( (nextReloc->r_address() & R_SCATTERED) == 0 ) {
6807 if ( nextReloc->r_type() == ARM_RELOC_PAIR ) {
6808 nextRelocIsPair = true;
6809 nextRelocAddress = nextReloc->r_address();
6810 result = true;
6811 }
6812 }
6813 else {
6814 if ( nextSReloc->r_type() == ARM_RELOC_PAIR ) {
6815 nextRelocIsPair = true;
6816 nextRelocAddress = nextSReloc->r_address();
6817 nextRelocValue = nextSReloc->r_value();
6818 result = true;
6819 }
6820 }
6821 switch ( sreloc->r_type() ) {
6822 case ARM_RELOC_VANILLA:
6823 // with a scattered relocation we get both the target (sreloc->r_value()) and the target+offset (*fixUpPtr)
6824 if ( sreloc->r_length() != 2 )
6825 throw "bad length for ARM_RELOC_VANILLA";
6826 target.atom = parser.findAtomByAddress(sreloc->r_value());
6827 if ( target.atom == NULL )
6828 throwf("bad r_value (0x%08X) for ARM_RELOC_VANILLA\n", sreloc->r_value());
6829 contentValue = LittleEndian::get32(*fixUpPtr);
6830 target.addend = contentValue - target.atom->_objAddress;
6831 if ( target.atom->isThumb() )
6832 target.addend &= -2; // remove thumb bit
6833 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
6834 break;
6835 case ARM_RELOC_BR24:
6836 // Sign-extend displacement
6837 displacement = (instruction & 0x00FFFFFF) << 2;
6838 if ( (displacement & 0x02000000) != 0 )
6839 displacement |= 0xFC000000;
6840 // The pc added will be +8 from the pc
6841 displacement += 8;
6842 // If this is BLX add H << 1
6843 if ((instruction & 0xFE000000) == 0xFA000000)
6844 displacement += ((instruction & 0x01000000) >> 23);
6845 target.atom = parser.findAtomByAddress(sreloc->r_value());
6846 target.addend = (int64_t)(srcAddr + displacement) - (int64_t)(target.atom->_objAddress);
6847 parser.addFixups(src, ld::Fixup::kindStoreARMBranch24, target);
6848 break;
6849 case ARM_THUMB_RELOC_BR22:
6850 // thumb2 added two more bits to displacement, complicating the displacement decoding
6851 {
6852 uint32_t s = (instruction >> 10) & 0x1;
6853 uint32_t j1 = (instruction >> 29) & 0x1;
6854 uint32_t j2 = (instruction >> 27) & 0x1;
6855 uint32_t imm10 = instruction & 0x3FF;
6856 uint32_t imm11 = (instruction >> 16) & 0x7FF;
6857 uint32_t i1 = (j1 == s);
6858 uint32_t i2 = (j2 == s);
6859 uint32_t dis = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
6860 int32_t sdis = dis;
6861 if ( s )
6862 sdis |= 0xFE000000;
6863 displacement = sdis;
6864 }
6865 // The pc added will be +4 from the pc
6866 displacement += 4;
6867 dstAddr = srcAddr+displacement;
6868 // If the instruction was blx, force the low 2 bits to be clear
6869 if ((instruction & 0xF8000000) == 0xE8000000)
6870 dstAddr &= 0xFFFFFFFC;
6871 target.atom = parser.findAtomByAddress(sreloc->r_value());
6872 target.addend = dstAddr - target.atom->_objAddress;
6873 parser.addFixups(src, ld::Fixup::kindStoreThumbBranch22, target);
6874 break;
6875 case ARM_RELOC_SECTDIFF:
6876 case ARM_RELOC_LOCAL_SECTDIFF:
6877 {
6878 if ( ! nextRelocIsPair )
6879 throw "ARM_RELOC_SECTDIFF missing following pair";
6880 if ( sreloc->r_length() != 2 )
6881 throw "bad length for ARM_RELOC_SECTDIFF";
6882 contentValue = LittleEndian::get32(*fixUpPtr);
6883 Atom<arm>* fromAtom = parser.findAtomByAddress(nextRelocValue);
6884 uint32_t offsetInFrom = nextRelocValue - fromAtom->_objAddress;
6885 uint32_t offsetInTarget;
6886 Atom<arm>* targetAtom = parser.findAtomByAddressOrLocalTargetOfStub(sreloc->r_value(), &offsetInTarget);
6887 // check for addend encoded in the section content
6888 int64_t addend = (int32_t)contentValue - (int32_t)(sreloc->r_value() - nextRelocValue);
6889 if ( targetAtom->isThumb() )
6890 addend &= -2; // remove thumb bit
6891 // if reference to LSDA, add group subordinate fixup
6892 if ( targetAtom->contentType() == ld::Atom::typeLSDA ) {
6893 Parser<arm>::SourceLocation src2;
6894 src2.atom = src.atom;
6895 src2.offsetInAtom = 0;
6896 parser.addFixup(src2, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinateLSDA, targetAtom);
6897 }
6898 if ( addend < 0 ) {
6899 // switch binding base on coalescing
6900 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6901 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
6902 }
6903 else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
6904 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
6905 }
6906 else {
6907 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6908 }
6909 parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, offsetInTarget);
6910 parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
6911 parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom-addend);
6912 parser.addFixup(src, ld::Fixup::k5of5, ld::Fixup::kindStoreLittleEndian32);
6913 }
6914 else {
6915 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6916 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
6917 }
6918 else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
6919 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
6920 }
6921 else {
6922 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6923 }
6924 parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, (uint32_t)(offsetInTarget+addend));
6925 parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
6926 parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom);
6927 parser.addFixup(src, ld::Fixup::k5of5, ld::Fixup::kindStoreLittleEndian32);
6928 }
6929 }
6930 break;
6931 case ARM_RELOC_HALF_SECTDIFF:
6932 if ( nextRelocIsPair ) {
6933 instruction = LittleEndian::get32(*fixUpPtr);
6934 Atom<arm>* fromAtom = parser.findAtomByAddress(nextRelocValue);
6935 uint32_t offsetInFrom = nextRelocValue - fromAtom->_objAddress;
6936 Atom<arm>* targetAtom = parser.findAtomByAddress(sreloc->r_value());
6937 uint32_t offsetInTarget = sreloc->r_value() - targetAtom->_objAddress;
6938 uint32_t instruction16;
6939 uint32_t other16 = (nextRelocAddress & 0xFFFF);
6940 bool isThumb;
6941 if ( sreloc->r_length() & 2 ) {
6942 isThumb = true;
6943 uint32_t i = ((instruction & 0x00000400) >> 10);
6944 uint32_t imm4 = (instruction & 0x0000000F);
6945 uint32_t imm3 = ((instruction & 0x70000000) >> 28);
6946 uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
6947 instruction16 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
6948 }
6949 else {
6950 isThumb = false;
6951 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
6952 uint32_t imm12 = (instruction & 0x00000FFF);
6953 instruction16 = (imm4 << 12) | imm12;
6954 }
6955 if ( sreloc->r_length() & 1 )
6956 dstAddr = ((instruction16 << 16) | other16);
6957 else
6958 dstAddr = (other16 << 16) | instruction16;
6959 if ( targetAtom->isThumb() )
6960 dstAddr &= (-2); // remove thumb bit
6961 int32_t addend = dstAddr - (sreloc->r_value() - nextRelocValue);
6962 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
6963 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, targetAtom);
6964 }
6965 else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
6966 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
6967 }
6968 else {
6969 parser.addFixup(src, ld::Fixup::k1of5, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
6970 }
6971 parser.addFixup(src, ld::Fixup::k2of5, ld::Fixup::kindAddAddend, (uint32_t)offsetInTarget+addend);
6972 parser.addFixup(src, ld::Fixup::k3of5, ld::Fixup::kindSubtractTargetAddress, fromAtom);
6973 parser.addFixup(src, ld::Fixup::k4of5, ld::Fixup::kindSubtractAddend, offsetInFrom);
6974 if ( sreloc->r_length() & 1 ) {
6975 // high 16
6976 parser.addFixup(src, ld::Fixup::k5of5, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16));
6977 }
6978 else {
6979 // low 16
6980 parser.addFixup(src, ld::Fixup::k5of5, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16));
6981 }
6982 result = true;
6983 }
6984 else
6985 throw "ARM_RELOC_HALF_SECTDIFF reloc missing following pair";
6986 break;
6987 case ARM_RELOC_HALF:
6988 if ( nextRelocIsPair ) {
6989 instruction = LittleEndian::get32(*fixUpPtr);
6990 Atom<arm>* targetAtom = parser.findAtomByAddress(sreloc->r_value());
6991 uint32_t instruction16;
6992 uint32_t other16 = (nextRelocAddress & 0xFFFF);
6993 bool isThumb;
6994 if ( sreloc->r_length() & 2 ) {
6995 isThumb = true;
6996 uint32_t i = ((instruction & 0x00000400) >> 10);
6997 uint32_t imm4 = (instruction & 0x0000000F);
6998 uint32_t imm3 = ((instruction & 0x70000000) >> 28);
6999 uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
7000 instruction16 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
7001 }
7002 else {
7003 isThumb = false;
7004 uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
7005 uint32_t imm12 = (instruction & 0x00000FFF);
7006 instruction16 = (imm4 << 12) | imm12;
7007 }
7008 if ( sreloc->r_length() & 1 )
7009 dstAddr = ((instruction16 << 16) | other16);
7010 else
7011 dstAddr = (other16 << 16) | instruction16;
7012 if ( targetAtom->scope() == ld::Atom::scopeTranslationUnit ) {
7013 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, targetAtom);
7014 }
7015 else if ( (targetAtom->combine() == ld::Atom::combineByNameAndContent) || (targetAtom->combine() == ld::Atom::combineByNameAndReferences) ) {
7016 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, ld::Fixup::bindingByContentBound, targetAtom);
7017 }
7018 else {
7019 parser.addFixup(src, ld::Fixup::k1of3, ld::Fixup::kindSetTargetAddress, false, targetAtom->name());
7020 }
7021 parser.addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, dstAddr - targetAtom->_objAddress);
7022 if ( sreloc->r_length() & 1 ) {
7023 // high 16
7024 parser.addFixup(src, ld::Fixup::k3of3, (isThumb ? ld::Fixup::kindStoreThumbHigh16 : ld::Fixup::kindStoreARMHigh16));
7025 }
7026 else {
7027 // low 16
7028 parser.addFixup(src, ld::Fixup::k3of3, (isThumb ? ld::Fixup::kindStoreThumbLow16 : ld::Fixup::kindStoreARMLow16));
7029 }
7030 result = true;
7031 }
7032 else
7033 throw "scattered ARM_RELOC_HALF reloc missing following pair";
7034 break;
7035 default:
7036 throwf("unknown ARM scattered relocation type %d", sreloc->r_type());
7037 }
7038 }
7039 return result;
7040 }
7041 #endif
7042
7043
7044 #if SUPPORT_ARCH_arm64
7045 template <>
7046 bool Section<arm64>::addRelocFixup(class Parser<arm64>& parser, const macho_relocation_info<P>* reloc)
7047 {
7048 bool result = false;
7049 Parser<arm64>::SourceLocation src;
7050 Parser<arm64>::TargetDesc target = { NULL, NULL, false, 0 };
7051 Parser<arm64>::TargetDesc toTarget;
7052 int32_t prefixRelocAddend = 0;
7053 if ( reloc->r_type() == ARM64_RELOC_ADDEND ) {
7054 uint32_t rawAddend = reloc->r_symbolnum();
7055 prefixRelocAddend = rawAddend;
7056 if ( rawAddend & 0x00800000 )
7057 prefixRelocAddend |= 0xFF000000; // sign extend 24-bit signed int to 32-bits
7058 uint32_t addendAddress = reloc->r_address();
7059 ++reloc; //advance to next reloc record
7060 result = true;
7061 if ( reloc->r_address() != addendAddress )
7062 throw "ARM64_RELOC_ADDEND r_address does not match next reloc's r_address";
7063 }
7064 const macho_section<P>* sect = this->machoSection();
7065 uint64_t srcAddr = sect->addr() + reloc->r_address();
7066 src.atom = this->findAtomByAddress(srcAddr);
7067 src.offsetInAtom = srcAddr - src.atom->_objAddress;
7068 const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
7069 uint64_t contentValue = 0;
7070 const macho_relocation_info<arm64::P>* nextReloc = &reloc[1];
7071 bool useDirectBinding;
7072 uint32_t instruction;
7073 uint32_t encodedAddend;
7074 switch ( reloc->r_length() ) {
7075 case 0:
7076 contentValue = *fixUpPtr;
7077 break;
7078 case 1:
7079 contentValue = (int64_t)(int16_t)E::get16(*((uint16_t*)fixUpPtr));
7080 break;
7081 case 2:
7082 contentValue = (int64_t)(int32_t)E::get32(*((uint32_t*)fixUpPtr));
7083 break;
7084 case 3:
7085 contentValue = E::get64(*((uint64_t*)fixUpPtr));
7086 break;
7087 }
7088 if ( reloc->r_extern() ) {
7089 const macho_nlist<P>& sym = parser.symbolFromIndex(reloc->r_symbolnum());
7090 const char* symbolName = parser.nameFromSymbol(sym);
7091 if ( ((sym.n_type() & N_TYPE) == N_SECT) && (((sym.n_type() & N_EXT) == 0) || (symbolName[0] == 'L') || (symbolName[0] == 'l')) ) {
7092 // use direct reference for local symbols
7093 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
7094 //target.addend += contentValue;
7095 }
7096 else if ( ((sym.n_type() & N_TYPE) == N_SECT) && (src.atom->_objAddress <= sym.n_value()) && (sym.n_value() < (src.atom->_objAddress+src.atom->size())) ) {
7097 // <rdar://problem/13700961> spurious warning when weak function has reference to itself
7098 // use direct reference when atom targets itself
7099 target.atom = src.atom;
7100 target.name = NULL;
7101 }
7102 else {
7103 target.name = symbolName;
7104 target.weakImport = parser.weakImportFromSymbol(sym);
7105 //target.addend = contentValue;
7106 }
7107 // cfstrings should always use direct reference to backing store
7108 if ( (this->type() == ld::Section::typeCFString) && (src.offsetInAtom != 0) ) {
7109 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), target);
7110 //target.addend = contentValue;
7111 }
7112 }
7113 else {
7114 if ( reloc->r_pcrel() )
7115 contentValue += srcAddr;
7116 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), target);
7117 }
7118 switch ( reloc->r_type() ) {
7119 case ARM64_RELOC_UNSIGNED:
7120 if ( reloc->r_pcrel() )
7121 throw "pcrel and ARM64_RELOC_UNSIGNED not supported";
7122 if ( reloc->r_extern() )
7123 target.addend = contentValue;
7124 switch ( reloc->r_length() ) {
7125 case 0:
7126 case 1:
7127 throw "length < 2 and ARM64_RELOC_UNSIGNED not supported";
7128 case 2:
7129 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian32, target);
7130 break;
7131 case 3:
7132 parser.addFixups(src, ld::Fixup::kindStoreLittleEndian64, target);
7133 break;
7134 }
7135 break;
7136 case ARM64_RELOC_BRANCH26:
7137 if ( ! reloc->r_pcrel() )
7138 throw "not pcrel and ARM64_RELOC_BRANCH26 not supported";
7139 if ( ! reloc->r_extern() )
7140 throw "r_extern == 0 and ARM64_RELOC_BRANCH26 not supported";
7141 if ( reloc->r_length() != 2 )
7142 throw "r_length != 2 and ARM64_RELOC_BRANCH26 not supported";
7143 if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_probe$", 16) == 0) ) {
7144 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreARM64DtraceCallSiteNop, false, target.name);
7145 parser.addDtraceExtraInfos(src, &target.name[16]);
7146 }
7147 else if ( (target.name != NULL) && (strncmp(target.name, "___dtrace_isenabled$", 20) == 0) ) {
7148 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindStoreARM64DtraceIsEnableSiteClear, false, target.name);
7149 parser.addDtraceExtraInfos(src, &target.name[20]);
7150 }
7151 else {
7152 target.addend = prefixRelocAddend;
7153 instruction = contentValue;
7154 encodedAddend = (instruction & 0x03FFFFFF) << 2;
7155 if ( encodedAddend != 0 ) {
7156 if ( prefixRelocAddend == 0 ) {
7157 warning("branch26 instruction at 0x%08X has embedded addend. ARM64_RELOC_ADDEND should be used instead", reloc->r_address());
7158 target.addend = encodedAddend;
7159 }
7160 else {
7161 throwf("branch26 instruction at 0x%08X has embedded addend and ARM64_RELOC_ADDEND also used", reloc->r_address());
7162 }
7163 }
7164 parser.addFixups(src, ld::Fixup::kindStoreARM64Branch26, target);
7165 }
7166 break;
7167 case ARM64_RELOC_PAGE21:
7168 if ( ! reloc->r_pcrel() )
7169 throw "not pcrel and ARM64_RELOC_PAGE21 not supported";
7170 if ( ! reloc->r_extern() )
7171 throw "r_extern == 0 and ARM64_RELOC_PAGE21 not supported";
7172 if ( reloc->r_length() != 2 )
7173 throw "length != 2 and ARM64_RELOC_PAGE21 not supported";
7174 target.addend = prefixRelocAddend;
7175 instruction = contentValue;
7176 encodedAddend = ((instruction & 0x60000000) >> 29) | ((instruction & 0x01FFFFE0) >> 3);
7177 encodedAddend *= 4096; // internally addend is in bytes, so scale
7178 if ( encodedAddend != 0 ) {
7179 if ( prefixRelocAddend == 0 ) {
7180 warning("adrp instruction at 0x%08X has embedded addend. ARM64_RELOC_ADDEND should be used instead", reloc->r_address());
7181 target.addend = encodedAddend;
7182 }
7183 else {
7184 throwf("adrp instruction at 0x%08X has embedded addend and ARM64_RELOC_ADDEND also used", reloc->r_address());
7185 }
7186 }
7187 parser.addFixups(src, ld::Fixup::kindStoreARM64Page21, target);
7188 break;
7189 case ARM64_RELOC_PAGEOFF12:
7190 if ( reloc->r_pcrel() )
7191 throw "pcrel and ARM64_RELOC_PAGEOFF12 not supported";
7192 if ( ! reloc->r_extern() )
7193 throw "r_extern == 0 and ARM64_RELOC_PAGEOFF12 not supported";
7194 if ( reloc->r_length() != 2 )
7195 throw "length != 2 and ARM64_RELOC_PAGEOFF12 not supported";
7196 target.addend = prefixRelocAddend;
7197 instruction = contentValue;
7198 encodedAddend = ((instruction & 0x003FFC00) >> 10);
7199 // internally addend is in bytes. Some instructions have an implicit scale factor
7200 if ( (instruction & 0x3B000000) == 0x39000000 ) {
7201 switch ( instruction & 0xC0000000 ) {
7202 case 0x00000000:
7203 break;
7204 case 0x40000000:
7205 encodedAddend *= 2;
7206 break;
7207 case 0x80000000:
7208 encodedAddend *= 4;
7209 break;
7210 case 0xC0000000:
7211 encodedAddend *= 8;
7212 break;
7213 }
7214 }
7215 if ( encodedAddend != 0 ) {
7216 if ( prefixRelocAddend == 0 ) {
7217 warning("pageoff12 instruction at 0x%08X has embedded addend. ARM64_RELOC_ADDEND should be used instead", reloc->r_address());
7218 target.addend = encodedAddend;
7219 }
7220 else {
7221 throwf("pageoff12 instruction at 0x%08X has embedded addend and ARM64_RELOC_ADDEND also used", reloc->r_address());
7222 }
7223 }
7224 parser.addFixups(src, ld::Fixup::kindStoreARM64PageOff12, target);
7225 break;
7226 case ARM64_RELOC_GOT_LOAD_PAGE21:
7227 if ( ! reloc->r_pcrel() )
7228 throw "not pcrel and ARM64_RELOC_GOT_LOAD_PAGE21 not supported";
7229 if ( ! reloc->r_extern() )
7230 throw "r_extern == 0 and ARM64_RELOC_GOT_LOAD_PAGE21 not supported";
7231 if ( reloc->r_length() != 2 )
7232 throw "length != 2 and ARM64_RELOC_GOT_LOAD_PAGE21 not supported";
7233 if ( prefixRelocAddend != 0 )
7234 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_GOT_LOAD_PAGE21 not supported";
7235 instruction = contentValue;
7236 target.addend = ((instruction & 0x60000000) >> 29) | ((instruction & 0x01FFFFE0) >> 3);
7237 if ( target.addend != 0 )
7238 throw "non-zero addend with ARM64_RELOC_GOT_LOAD_PAGE21 is not supported";
7239 parser.addFixups(src, ld::Fixup::kindStoreARM64GOTLoadPage21, target);
7240 break;
7241 case ARM64_RELOC_GOT_LOAD_PAGEOFF12:
7242 if ( reloc->r_pcrel() )
7243 throw "pcrel and ARM64_RELOC_GOT_LOAD_PAGEOFF12 not supported";
7244 if ( ! reloc->r_extern() )
7245 throw "r_extern == 0 and ARM64_RELOC_GOT_LOAD_PAGEOFF12 not supported";
7246 if ( reloc->r_length() != 2 )
7247 throw "length != 2 and ARM64_RELOC_GOT_LOAD_PAGEOFF12 not supported";
7248 if ( prefixRelocAddend != 0 )
7249 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_GOT_LOAD_PAGEOFF12 not supported";
7250 instruction = contentValue;
7251 target.addend = ((instruction & 0x003FFC00) >> 10);
7252 parser.addFixups(src, ld::Fixup::kindStoreARM64GOTLoadPageOff12, target);
7253 break;
7254 case ARM64_RELOC_TLVP_LOAD_PAGE21:
7255 if ( ! reloc->r_pcrel() )
7256 throw "not pcrel and ARM64_RELOC_TLVP_LOAD_PAGE21 not supported";
7257 if ( ! reloc->r_extern() )
7258 throw "r_extern == 0 and ARM64_RELOC_TLVP_LOAD_PAGE21 not supported";
7259 if ( reloc->r_length() != 2 )
7260 throw "length != 2 and ARM64_RELOC_TLVP_LOAD_PAGE21 not supported";
7261 if ( prefixRelocAddend != 0 )
7262 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_TLVP_LOAD_PAGE21 not supported";
7263 instruction = contentValue;
7264 target.addend = ((instruction & 0x60000000) >> 29) | ((instruction & 0x01FFFFE0) >> 3);
7265 if ( target.addend != 0 )
7266 throw "non-zero addend with ARM64_RELOC_GOT_LOAD_PAGE21 is not supported";
7267 parser.addFixups(src, ld::Fixup::kindStoreARM64TLVPLoadPage21, target);
7268 break;
7269 case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
7270 if ( reloc->r_pcrel() )
7271 throw "pcrel and ARM64_RELOC_TLVP_LOAD_PAGEOFF12 not supported";
7272 if ( ! reloc->r_extern() )
7273 throw "r_extern == 0 and ARM64_RELOC_TLVP_LOAD_PAGEOFF12 not supported";
7274 if ( reloc->r_length() != 2 )
7275 throw "length != 2 and ARM64_RELOC_TLVP_LOAD_PAGEOFF12 not supported";
7276 if ( prefixRelocAddend != 0 )
7277 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_TLVP_LOAD_PAGEOFF12 not supported";
7278 instruction = contentValue;
7279 target.addend = ((instruction & 0x003FFC00) >> 10);
7280 parser.addFixups(src, ld::Fixup::kindStoreARM64TLVPLoadPageOff12, target);
7281 break;
7282 case ARM64_RELOC_SUBTRACTOR:
7283 if ( reloc->r_pcrel() )
7284 throw "ARM64_RELOC_SUBTRACTOR cannot be pc-relative";
7285 if ( reloc->r_length() < 2 )
7286 throw "ARM64_RELOC_SUBTRACTOR must have r_length of 2 or 3";
7287 if ( !reloc->r_extern() )
7288 throw "ARM64_RELOC_SUBTRACTOR must have r_extern=1";
7289 if ( nextReloc->r_type() != ARM64_RELOC_UNSIGNED )
7290 throw "ARM64_RELOC_SUBTRACTOR must be followed by ARM64_RELOC_UNSIGNED";
7291 if ( prefixRelocAddend != 0 )
7292 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_SUBTRACTOR not supported";
7293 result = true;
7294 if ( nextReloc->r_pcrel() )
7295 throw "ARM64_RELOC_UNSIGNED following a ARM64_RELOC_SUBTRACTOR cannot be pc-relative";
7296 if ( nextReloc->r_length() != reloc->r_length() )
7297 throw "ARM64_RELOC_UNSIGNED following a ARM64_RELOC_SUBTRACTOR must have same r_length";
7298 if ( nextReloc->r_extern() ) {
7299 const macho_nlist<P>& sym = parser.symbolFromIndex(nextReloc->r_symbolnum());
7300 // use direct reference for local symbols
7301 if ( ((sym.n_type() & N_TYPE) == N_SECT) && (((sym.n_type() & N_EXT) == 0) || (parser.nameFromSymbol(sym)[0] == 'L')) ) {
7302 parser.findTargetFromAddressAndSectionNum(sym.n_value(), sym.n_sect(), toTarget);
7303 toTarget.addend = contentValue;
7304 useDirectBinding = true;
7305 }
7306 else {
7307 toTarget.name = parser.nameFromSymbol(sym);
7308 toTarget.weakImport = parser.weakImportFromSymbol(sym);
7309 toTarget.addend = contentValue;
7310 useDirectBinding = false;
7311 }
7312 }
7313 else {
7314 parser.findTargetFromAddressAndSectionNum(contentValue, nextReloc->r_symbolnum(), toTarget);
7315 useDirectBinding = (toTarget.atom->scope() == ld::Atom::scopeTranslationUnit);
7316 }
7317 if ( useDirectBinding )
7318 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.atom);
7319 else
7320 parser.addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetTargetAddress, toTarget.weakImport, toTarget.name);
7321 parser.addFixup(src, ld::Fixup::k2of4, ld::Fixup::kindAddAddend, toTarget.addend);
7322 if ( target.atom == NULL )
7323 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractTargetAddress, false, target.name);
7324 else
7325 parser.addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindSubtractTargetAddress, target.atom);
7326 if ( reloc->r_length() == 2 )
7327 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian32);
7328 else
7329 parser.addFixup(src, ld::Fixup::k4of4, ld::Fixup::kindStoreLittleEndian64);
7330 break;
7331 case ARM64_RELOC_POINTER_TO_GOT:
7332 if ( ! reloc->r_extern() )
7333 throw "r_extern == 0 and ARM64_RELOC_POINTER_TO_GOT not supported";
7334 if ( prefixRelocAddend != 0 )
7335 throw "ARM64_RELOC_ADDEND followed by ARM64_RELOC_POINTER_TO_GOT not supported";
7336 if ( reloc->r_pcrel() ) {
7337 if ( reloc->r_length() != 2 )
7338 throw "r_length != 2 and r_extern = 1 and ARM64_RELOC_POINTER_TO_GOT not supported";
7339 parser.addFixups(src, ld::Fixup::kindStoreARM64PCRelToGOT, target);
7340 }
7341 else {
7342 if ( reloc->r_length() != 3 )
7343 throw "r_length != 3 and r_extern = 0 and ARM64_RELOC_POINTER_TO_GOT not supported";
7344 parser.addFixups(src, ld::Fixup::kindStoreARM64PointerToGOT, target);
7345 }
7346 break;
7347 default:
7348 throwf("unknown relocation type %d", reloc->r_type());
7349 }
7350 return result;
7351 }
7352 #endif
7353
7354 template <typename A>
7355 bool ObjC1ClassSection<A>::addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
7356 {
7357 // inherited
7358 FixedSizeSection<A>::addRelocFixup(parser, reloc);
7359
7360 assert(0 && "needs template specialization");
7361 return false;
7362 }
7363
7364 template <>
7365 bool ObjC1ClassSection<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<x86::P>* reloc)
7366 {
7367 // if this is the reloc for the super class name string, add implicit reference to super class
7368 if ( ((reloc->r_address() & R_SCATTERED) == 0) && (reloc->r_type() == GENERIC_RELOC_VANILLA) ) {
7369 assert( reloc->r_length() == 2 );
7370 assert( ! reloc->r_pcrel() );
7371
7372 const macho_section<P>* sect = this->machoSection();
7373 Parser<x86>::SourceLocation src;
7374 uint32_t srcAddr = sect->addr() + reloc->r_address();
7375 src.atom = this->findAtomByAddress(srcAddr);
7376 src.offsetInAtom = srcAddr - src.atom->objectAddress();
7377 if ( src.offsetInAtom == 4 ) {
7378 Parser<x86>::TargetDesc stringTarget;
7379 const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
7380 uint32_t contentValue = LittleEndian::get32(*((uint32_t*)fixUpPtr));
7381 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), stringTarget);
7382
7383 assert(stringTarget.atom != NULL);
7384 assert(stringTarget.atom->contentType() == ld::Atom::typeCString);
7385 const char* superClassBaseName = (char*)stringTarget.atom->rawContentPointer();
7386 char* superClassName = new char[strlen(superClassBaseName) + 20];
7387 strcpy(superClassName, ".objc_class_name_");
7388 strcat(superClassName, superClassBaseName);
7389
7390 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, superClassName);
7391 }
7392 }
7393 // inherited
7394 return FixedSizeSection<x86>::addRelocFixup(parser, reloc);
7395 }
7396
7397
7398
7399 template <typename A>
7400 bool Objc1ClassReferences<A>::addRelocFixup(class Parser<A>& parser, const macho_relocation_info<P>* reloc)
7401 {
7402 // inherited
7403 PointerToCStringSection<A>::addRelocFixup(parser, reloc);
7404
7405 assert(0 && "needs template specialization");
7406 return false;
7407 }
7408
7409
7410
7411 template <>
7412 bool Objc1ClassReferences<x86>::addRelocFixup(class Parser<x86>& parser, const macho_relocation_info<x86::P>* reloc)
7413 {
7414 // add implict class refs, fixups not usable yet, so look at relocations
7415 assert( (reloc->r_address() & R_SCATTERED) == 0 );
7416 assert( reloc->r_type() == GENERIC_RELOC_VANILLA );
7417 assert( reloc->r_length() == 2 );
7418 assert( ! reloc->r_pcrel() );
7419
7420 const macho_section<P>* sect = this->machoSection();
7421 Parser<x86>::SourceLocation src;
7422 uint32_t srcAddr = sect->addr() + reloc->r_address();
7423 src.atom = this->findAtomByAddress(srcAddr);
7424 src.offsetInAtom = srcAddr - src.atom->objectAddress();
7425 Parser<x86>::TargetDesc stringTarget;
7426 const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
7427 uint32_t contentValue = LittleEndian::get32(*((uint32_t*)fixUpPtr));
7428 parser.findTargetFromAddressAndSectionNum(contentValue, reloc->r_symbolnum(), stringTarget);
7429
7430 assert(stringTarget.atom != NULL);
7431 assert(stringTarget.atom->contentType() == ld::Atom::typeCString);
7432 const char* baseClassName = (char*)stringTarget.atom->rawContentPointer();
7433 char* objcClassName = new char[strlen(baseClassName) + 20];
7434 strcpy(objcClassName, ".objc_class_name_");
7435 strcat(objcClassName, baseClassName);
7436
7437 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindSetTargetAddress, false, objcClassName);
7438
7439 // inherited
7440 return PointerToCStringSection<x86>::addRelocFixup(parser, reloc);
7441 }
7442
7443 #if SUPPORT_ARCH_arm64
7444 template <>
7445 void Section<arm64>::addLOH(class Parser<arm64>& parser, int kind, int count, const uint64_t addrs[]) {
7446 switch (kind) {
7447 case LOH_ARM64_ADRP_ADRP:
7448 case LOH_ARM64_ADRP_LDR:
7449 case LOH_ARM64_ADRP_ADD:
7450 case LOH_ARM64_ADRP_LDR_GOT:
7451 if ( count != 2 )
7452 warning("arm64 Linker Optimiztion Hint %d has wrong number of arguments", kind);
7453 break;
7454 case LOH_ARM64_ADRP_ADD_LDR:
7455 case LOH_ARM64_ADRP_LDR_GOT_LDR:
7456 case LOH_ARM64_ADRP_ADD_STR:
7457 case LOH_ARM64_ADRP_LDR_GOT_STR:
7458 if ( count != 3 )
7459 warning("arm64 Linker Optimiztion Hint %d has wrong number of arguments", kind);
7460 }
7461
7462 // pick lowest address in tuple for use as offsetInAtom
7463 uint64_t lowestAddress = addrs[0];
7464 for(int i=1; i < count; ++i) {
7465 if ( addrs[i] < lowestAddress )
7466 lowestAddress = addrs[i];
7467 }
7468 // verify all other address are in same atom
7469 Atom<arm64>* inAtom = parser.findAtomByAddress(lowestAddress);
7470 const uint64_t atomStartAddr = inAtom->objectAddress();
7471 const uint64_t atomEndAddr = atomStartAddr + inAtom->size();
7472 for(int i=0; i < count; ++i) {
7473 if ( (addrs[i] < atomStartAddr) || (addrs[i] >= atomEndAddr) ) {
7474 warning("arm64 Linker Optimiztion Hint addresses are not in same atom: 0x%08llX and 0x%08llX",
7475 lowestAddress, addrs[i]);
7476 return; // skip this LOH
7477 }
7478 if ( (addrs[i] & 0x3) != 0 ) {
7479 warning("arm64 Linker Optimiztion Hint address is not 4-byte aligned: 0x%08llX", addrs[i]);
7480 return; // skip this LOH
7481 }
7482 if ( (addrs[i] - lowestAddress) > 0xFFFF ) {
7483 if ( parser.verboseOptimizationHints() ) {
7484 warning("arm64 Linker Optimiztion Hint addresses are too far apart: 0x%08llX and 0x%08llX",
7485 lowestAddress, addrs[i]);
7486 }
7487 return; // skip this LOH
7488 }
7489 }
7490
7491 // encoded kind, count, and address deltas in 64-bit addend
7492 ld::Fixup::LOH_arm64 extra;
7493 extra.addend = 0;
7494 extra.info.kind = kind;
7495 extra.info.count = count-1;
7496 extra.info.delta1 = (addrs[0] - lowestAddress) >> 2;
7497 extra.info.delta2 = (count > 1) ? ((addrs[1] - lowestAddress) >> 2) : 0;
7498 extra.info.delta3 = (count > 2) ? ((addrs[2] - lowestAddress) >> 2) : 0;
7499 extra.info.delta4 = (count > 3) ? ((addrs[3] - lowestAddress) >> 2) : 0;
7500 typename Parser<arm64>::SourceLocation src(inAtom, lowestAddress- inAtom->objectAddress());
7501 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindLinkerOptimizationHint, extra.addend);
7502 }
7503 #endif
7504
7505 template <typename A>
7506 void Section<A>::addLOH(class Parser<A>& parser, int kind, int count, const uint64_t addrs[]) {
7507
7508 }
7509
7510 template <typename A>
7511 void Section<A>::makeFixups(class Parser<A>& parser, const struct Parser<A>::CFI_CU_InfoArrays&)
7512 {
7513 const macho_section<P>* sect = this->machoSection();
7514 const macho_relocation_info<P>* relocs = (macho_relocation_info<P>*)(file().fileContent() + sect->reloff());
7515 const uint32_t relocCount = sect->nreloc();
7516 for (uint32_t r = 0; r < relocCount; ++r) {
7517 try {
7518 if ( this->addRelocFixup(parser, &relocs[r]) )
7519 ++r; // skip next
7520 }
7521 catch (const char* msg) {
7522 throwf("in section %s,%s reloc %u: %s", sect->segname(), Section<A>::makeSectionName(sect), r, msg);
7523 }
7524 }
7525
7526 // add follow-on fixups if .o file is missing .subsections_via_symbols
7527 if ( this->addFollowOnFixups() ) {
7528 Atom<A>* end = &_endAtoms[-1];
7529 for(Atom<A>* p = _beginAtoms; p < end; ++p) {
7530 typename Parser<A>::SourceLocation src(p, 0);
7531 Atom<A>* nextAtom = &p[1];
7532 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, nextAtom);
7533 }
7534 }
7535 else if ( this->type() == ld::Section::typeCode ) {
7536 // if FDE broke text not at a symbol, use followOn to keep code together
7537 Atom<A>* end = &_endAtoms[-1];
7538 for(Atom<A>* p = _beginAtoms; p < end; ++p) {
7539 typename Parser<A>::SourceLocation src(p, 0);
7540 Atom<A>* nextAtom = &p[1];
7541 if ( (p->symbolTableInclusion() == ld::Atom::symbolTableIn) && (nextAtom->symbolTableInclusion() == ld::Atom::symbolTableNotIn) ) {
7542 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, nextAtom);
7543 }
7544 }
7545 }
7546 if ( !this->_altEntries.empty() && !this->addFollowOnFixups() ) {
7547 if ( _altEntries.count(_beginAtoms) != 0 )
7548 warning("N_ALT_ENTRY bit set on first atom in section %s/%s", sect->segname(), Section<A>::makeSectionName(sect));
7549
7550 Atom<A>* end = &_endAtoms[-1];
7551 for(Atom<A>* p = _beginAtoms; p < end; ++p) {
7552 Atom<A>* nextAtom = &p[1];
7553 if ( _altEntries.count(nextAtom) != 0 ) {
7554 typename Parser<A>::SourceLocation src(p, 0);
7555 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, nextAtom);
7556 typename Parser<A>::SourceLocation src2(nextAtom, 0);
7557 parser.addFixup(src2, ld::Fixup::k1of1, ld::Fixup::kindNoneGroupSubordinate, p);
7558 }
7559 }
7560 }
7561
7562 // <rdar://problem/9218847> track data-in-code
7563 if ( parser.hasDataInCodeLabels() && (this->type() == ld::Section::typeCode) ) {
7564 for (uint32_t i=0; i < parser.symbolCount(); ++i) {
7565 const macho_nlist<P>& sym = parser.symbolFromIndex(i);
7566 // ignore stabs
7567 if ( (sym.n_type() & N_STAB) != 0 )
7568 continue;
7569 // ignore non-definitions
7570 if ( (sym.n_type() & N_TYPE) != N_SECT )
7571 continue;
7572
7573 // 'L' labels do not denote atom breaks
7574 const char* symbolName = parser.nameFromSymbol(sym);
7575 if ( symbolName[0] == 'L' ) {
7576 if ( strncmp(symbolName, "L$start$", 8) == 0 ) {
7577 ld::Fixup::Kind kind = ld::Fixup::kindNone;
7578 if ( strncmp(&symbolName[8], "data$", 5) == 0 )
7579 kind = ld::Fixup::kindDataInCodeStartData;
7580 else if ( strncmp(&symbolName[8], "code$", 5) == 0 )
7581 kind = ld::Fixup::kindDataInCodeEnd;
7582 else if ( strncmp(&symbolName[8], "jt8$", 4) == 0 )
7583 kind = ld::Fixup::kindDataInCodeStartJT8;
7584 else if ( strncmp(&symbolName[8], "jt16$", 4) == 0 )
7585 kind = ld::Fixup::kindDataInCodeStartJT16;
7586 else if ( strncmp(&symbolName[8], "jt32$", 4) == 0 )
7587 kind = ld::Fixup::kindDataInCodeStartJT32;
7588 else if ( strncmp(&symbolName[8], "jta32$", 4) == 0 )
7589 kind = ld::Fixup::kindDataInCodeStartJTA32;
7590 else
7591 warning("unknown L$start$ label %s in file %s", symbolName, this->file().path());
7592 if ( kind != ld::Fixup::kindNone ) {
7593 Atom<A>* inAtom = parser.findAtomByAddress(sym.n_value());
7594 typename Parser<A>::SourceLocation src(inAtom, sym.n_value() - inAtom->objectAddress());
7595 parser.addFixup(src, ld::Fixup::k1of1, kind);
7596 }
7597 }
7598 }
7599 }
7600 }
7601
7602 // <rdar://problem/11150575> Handle LC_DATA_IN_CODE in object files
7603 if ( this->type() == ld::Section::typeCode ) {
7604 const pint_t startAddr = this->_machOSection->addr();
7605 const pint_t endAddr = startAddr + this->_machOSection->size();
7606 for ( const macho_data_in_code_entry<P>* p = parser.dataInCodeStart(); p != parser.dataInCodeEnd(); ++p ) {
7607 if ( (p->offset() >= startAddr) && (p->offset() < endAddr) ) {
7608 ld::Fixup::Kind kind = ld::Fixup::kindNone;
7609 switch ( p->kind() ) {
7610 case DICE_KIND_DATA:
7611 kind = ld::Fixup::kindDataInCodeStartData;
7612 break;
7613 case DICE_KIND_JUMP_TABLE8:
7614 kind = ld::Fixup::kindDataInCodeStartJT8;
7615 break;
7616 case DICE_KIND_JUMP_TABLE16:
7617 kind = ld::Fixup::kindDataInCodeStartJT16;
7618 break;
7619 case DICE_KIND_JUMP_TABLE32:
7620 kind = ld::Fixup::kindDataInCodeStartJT32;
7621 break;
7622 case DICE_KIND_ABS_JUMP_TABLE32:
7623 kind = ld::Fixup::kindDataInCodeStartJTA32;
7624 break;
7625 default:
7626 kind = ld::Fixup::kindDataInCodeStartData;
7627 warning("uknown LC_DATA_IN_CODE kind (%d) at offset 0x%08X", p->kind(), p->offset());
7628 break;
7629 }
7630 Atom<A>* inAtom = parser.findAtomByAddress(p->offset());
7631 typename Parser<A>::SourceLocation srcStart(inAtom, p->offset() - inAtom->objectAddress());
7632 parser.addFixup(srcStart, ld::Fixup::k1of1, kind);
7633 typename Parser<A>::SourceLocation srcEnd(inAtom, p->offset() + p->length() - inAtom->objectAddress());
7634 parser.addFixup(srcEnd, ld::Fixup::k1of1, ld::Fixup::kindDataInCodeEnd);
7635 }
7636 }
7637 }
7638
7639 // <rdar://problem/11945700> convert linker optimization hints into internal format
7640 if ( this->type() == ld::Section::typeCode && parser.hasOptimizationHints() ) {
7641 const pint_t startAddr = this->_machOSection->addr();
7642 const pint_t endAddr = startAddr + this->_machOSection->size();
7643 for (const uint8_t* p = parser.optimizationHintsStart(); p < parser.optimizationHintsEnd(); ) {
7644 uint64_t addrs[4];
7645 int32_t kind = read_uleb128(&p, parser.optimizationHintsEnd());
7646 if ( kind == 0 ) // padding at end of loh buffer
7647 break;
7648 if ( kind == -1 ) {
7649 warning("malformed uleb128 kind in LC_LINKER_OPTIMIZATION_HINTS");
7650 break;
7651 }
7652 int32_t count = read_uleb128(&p, parser.optimizationHintsEnd());
7653 if ( count == -1 ) {
7654 warning("malformed uleb128 count in LC_LINKER_OPTIMIZATION_HINTS");
7655 break;
7656 }
7657 if ( count > 3 ) {
7658 warning("address count > 3 in LC_LINKER_OPTIMIZATION_HINTS");
7659 break;
7660 }
7661 for (int32_t i=0; i < count; ++i) {
7662 addrs[i] = read_uleb128(&p, parser.optimizationHintsEnd());
7663 }
7664 if ( (startAddr <= addrs[0]) && (addrs[0] < endAddr) ) {
7665 this->addLOH(parser, kind, count, addrs);
7666 //fprintf(stderr, "kind=%d", kind);
7667 //for (int32_t i=0; i < count; ++i) {
7668 // fprintf(stderr, ", addr=0x%08llX", addrs[i]);
7669 //}
7670 //fprintf(stderr, "\n");
7671 }
7672 }
7673 }
7674
7675
7676 // add follow-on fixups for aliases
7677 if ( _hasAliases ) {
7678 for(Atom<A>* p = _beginAtoms; p < _endAtoms; ++p) {
7679 if ( p->isAlias() && ! this->addFollowOnFixups() ) {
7680 Atom<A>* targetOfAlias = &p[1];
7681 assert(p < &_endAtoms[-1]);
7682 assert(p->_objAddress == targetOfAlias->_objAddress);
7683 typename Parser<A>::SourceLocation src(p, 0);
7684 parser.addFixup(src, ld::Fixup::k1of1, ld::Fixup::kindNoneFollowOn, targetOfAlias);
7685 }
7686 }
7687 }
7688 }
7689
7690
7691
7692 //
7693 // main function used by linker to instantiate ld::Files
7694 //
7695 ld::relocatable::File* parse(const uint8_t* fileContent, uint64_t fileLength,
7696 const char* path, time_t modTime, ld::File::Ordinal ordinal, const ParserOptions& opts)
7697 {
7698 switch ( opts.architecture ) {
7699 #if SUPPORT_ARCH_x86_64
7700 case CPU_TYPE_X86_64:
7701 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) )
7702 return mach_o::relocatable::Parser<x86_64>::parse(fileContent, fileLength, path, modTime, ordinal, opts);
7703 break;
7704 #endif
7705 #if SUPPORT_ARCH_i386
7706 case CPU_TYPE_I386:
7707 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) )
7708 return mach_o::relocatable::Parser<x86>::parse(fileContent, fileLength, path, modTime, ordinal, opts);
7709 break;
7710 #endif
7711 #if SUPPORT_ARCH_arm_any
7712 case CPU_TYPE_ARM:
7713 if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, opts.objSubtypeMustMatch, opts.subType) )
7714 return mach_o::relocatable::Parser<arm>::parse(fileContent, fileLength, path, modTime, ordinal, opts);
7715 break;
7716 #endif
7717 #if SUPPORT_ARCH_arm64
7718 case CPU_TYPE_ARM64:
7719 if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, opts.objSubtypeMustMatch, opts.subType) )
7720 return mach_o::relocatable::Parser<arm64>::parse(fileContent, fileLength, path, modTime, ordinal, opts);
7721 break;
7722 #endif
7723 }
7724 return NULL;
7725 }
7726
7727 //
7728 // used by archive reader to validate member object file
7729 //
7730 bool isObjectFile(const uint8_t* fileContent, uint64_t fileLength, const ParserOptions& opts)
7731 {
7732 switch ( opts.architecture ) {
7733 case CPU_TYPE_X86_64:
7734 return ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) );
7735 case CPU_TYPE_I386:
7736 return ( mach_o::relocatable::Parser<x86>::validFile(fileContent) );
7737 case CPU_TYPE_ARM:
7738 return ( mach_o::relocatable::Parser<arm>::validFile(fileContent, opts.objSubtypeMustMatch, opts.subType) );
7739 case CPU_TYPE_ARM64:
7740 return ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, opts.objSubtypeMustMatch, opts.subType) );
7741 }
7742 return false;
7743 }
7744
7745 //
7746 // used by linker to infer architecture when no -arch is on command line
7747 //
7748 bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform)
7749 {
7750 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
7751 *result = CPU_TYPE_X86_64;
7752 const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
7753 *subResult = header->cpusubtype();
7754 *platform = Parser<x86_64>::findPlatform(header);
7755 return true;
7756 }
7757 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
7758 const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
7759 *result = CPU_TYPE_I386;
7760 *subResult = CPU_SUBTYPE_X86_ALL;
7761 *platform = Parser<x86>::findPlatform(header);
7762 return true;
7763 }
7764 if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
7765 const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
7766 *result = CPU_TYPE_ARM;
7767 *subResult = header->cpusubtype();
7768 *platform = Parser<arm>::findPlatform(header);
7769 return true;
7770 }
7771 if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
7772 const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
7773 *result = CPU_TYPE_ARM64;
7774 *subResult = CPU_SUBTYPE_ARM64_ALL;
7775 *platform = Parser<arm64>::findPlatform(header);
7776 return true;
7777 }
7778 return false;
7779 }
7780
7781 //
7782 // used by linker is error messages to describe bad .o file
7783 //
7784 const char* archName(const uint8_t* fileContent)
7785 {
7786 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
7787 return mach_o::relocatable::Parser<x86_64>::fileKind(fileContent);
7788 }
7789 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
7790 return mach_o::relocatable::Parser<x86>::fileKind(fileContent);
7791 }
7792 if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
7793 return mach_o::relocatable::Parser<arm>::fileKind(fileContent);
7794 }
7795 return NULL;
7796 }
7797
7798 //
7799 // Used by archive reader when -ObjC option is specified
7800 //
7801 bool hasObjC2Categories(const uint8_t* fileContent)
7802 {
7803 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
7804 return mach_o::relocatable::Parser<x86_64>::hasObjC2Categories(fileContent);
7805 }
7806 else if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
7807 return mach_o::relocatable::Parser<arm>::hasObjC2Categories(fileContent);
7808 }
7809 else if ( mach_o::relocatable::Parser<x86>::validFile(fileContent, false, 0) ) {
7810 return mach_o::relocatable::Parser<x86>::hasObjC2Categories(fileContent);
7811 }
7812 #if SUPPORT_ARCH_arm64
7813 else if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
7814 return mach_o::relocatable::Parser<arm64>::hasObjC2Categories(fileContent);
7815 }
7816 #endif
7817 return false;
7818 }
7819
7820 //
7821 // Used by archive reader when -ObjC option is specified
7822 //
7823 bool hasObjC1Categories(const uint8_t* fileContent)
7824 {
7825 if ( mach_o::relocatable::Parser<x86>::validFile(fileContent, false, 0) ) {
7826 return mach_o::relocatable::Parser<x86>::hasObjC1Categories(fileContent);
7827 }
7828 return false;
7829 }
7830
7831 //
7832 // Used by bitcode obfuscator to get a list of non local symbols from object file
7833 //
7834 bool getNonLocalSymbols(const uint8_t* fileContent, std::vector<const char*> &syms)
7835 {
7836 if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
7837 return mach_o::relocatable::Parser<x86_64>::getNonLocalSymbols(fileContent, syms);
7838 }
7839 else if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
7840 return mach_o::relocatable::Parser<arm>::getNonLocalSymbols(fileContent, syms);
7841 }
7842 else if ( mach_o::relocatable::Parser<x86>::validFile(fileContent, false, 0) ) {
7843 return mach_o::relocatable::Parser<x86>::getNonLocalSymbols(fileContent, syms);
7844 }
7845 else if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
7846 return mach_o::relocatable::Parser<arm64>::getNonLocalSymbols(fileContent, syms);
7847 }
7848 return false;
7849 }
7850
7851
7852
7853 } // namespace relocatable
7854 } // namespace mach_o
7855
7856