]> git.saurik.com Git - apple/ld64.git/blame - src/ld/passes/order.cpp
ld64-242.tar.gz
[apple/ld64.git] / src / ld / passes / order.cpp
CommitLineData
a645023d
A
1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
b2fa67a8 3 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
a645023d
A
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 <math.h>
28#include <unistd.h>
29#include <dlfcn.h>
30#include <mach/machine.h>
31
32#include <vector>
33#include <map>
f80fe69f 34#include <set>
d425e388 35#include <unordered_map>
a645023d
A
36
37#include "ld.hpp"
b2fa67a8 38#include "order.h"
a645023d
A
39
40namespace ld {
41namespace passes {
b2fa67a8 42namespace order {
a645023d
A
43
44//
45// The purpose of this pass is to take the graph of all Atoms and produce an ordered
46// sequence of atoms. The constraints are that: 1) all Atoms of the same Segment must
47// be contiguous, 2) all Atoms of the same Section must be contigous, 3) Atoms specified
b2fa67a8 48// in an order are sequenced as in the order file and before Atoms not specified,
a645023d
A
49// 4) Atoms in the same section from the same .o file should be contiguous and sequenced
50// in the same order they were in the .o file, 5) Atoms in the same Section but which came
51// from different .o files should be sequenced in the same order that the .o files
52// were passed to the linker (i.e. command line order).
53//
54// The way this is implemented is that the linker passes a "base ordinal" to each File
55// as it is constructed. Add each atom has an objectAddress() method. Then
56// sorting is just sorting by section, then by file ordinal, then by object address.
57//
b2fa67a8 58// If an -order_file is specified, it gets more complicated. First, an override-ordinal map
a645023d 59// is created. It causes the sort routine to ignore the value returned by ordinal() and objectAddress()
b2fa67a8 60// and use the override value instead. Next some Atoms must be laid out consecutively
a645023d
A
61// (e.g. hand written assembly that does not end with return, but rather falls into
62// the next label). This is modeled in via a kindNoneFollowOn fixup. The use of
63// kindNoneFollowOn fixups produces "clusters" of atoms that must stay together.
64// If an order_file tries to move one atom, it may need to move a whole cluster. The
65// algorithm to do this models clusters using two maps. The "starts" maps maps any
66// atom in a cluster to the first Atom in the cluster. The "nexts" maps an Atom in a
67// cluster to the next Atom in the cluster. With this in place, while processing an
68// order_file, if any entry is in a cluster (in "starts" map), then the entire cluster is
69// given ordinal overrides.
70//
71
72class Layout
73{
74public:
75 Layout(const Options& opts, ld::Internal& state);
76 void doPass();
77private:
78
79 class Comparer {
80 public:
599556ff 81 Comparer(const Layout& l, ld::Internal& s) : _layout(l), _state(s) {}
a645023d
A
82 bool operator()(const ld::Atom* left, const ld::Atom* right);
83 private:
84 const Layout& _layout;
599556ff 85 ld::Internal& _state;
a645023d
A
86 };
87
d425e388 88 typedef std::unordered_map<const char*, const ld::Atom*, CStringHash, CStringEquals> NameToAtom;
a645023d
A
89
90 typedef std::map<const ld::Atom*, const ld::Atom*> AtomToAtom;
91
92 typedef std::map<const ld::Atom*, uint32_t> AtomToOrdinal;
93
94 const ld::Atom* findAtom(const Options::OrderedSymbol& orderedSymbol);
95 void buildNameTable();
96 void buildFollowOnTables();
97 void buildOrdinalOverrideMap();
98 const ld::Atom* follower(const ld::Atom* atom);
99 static bool matchesObjectFile(const ld::Atom* atom, const char* objectFileLeafName);
b2fa67a8 100 bool possibleToOrder(const ld::Internal::FinalSection*);
a645023d
A
101
102 const Options& _options;
103 ld::Internal& _state;
104 AtomToAtom _followOnStarts;
105 AtomToAtom _followOnNexts;
106 NameToAtom _nameTable;
107 std::vector<const ld::Atom*> _nameCollisionAtoms;
108 AtomToOrdinal _ordinalOverrideMap;
109 Comparer _comparer;
110 bool _haveOrderFile;
111
112 static bool _s_log;
113};
114
115bool Layout::_s_log = false;
116
117Layout::Layout(const Options& opts, ld::Internal& state)
599556ff 118 : _options(opts), _state(state), _comparer(*this, state), _haveOrderFile(opts.orderedSymbolsCount() != 0)
a645023d
A
119{
120}
121
122
123bool Layout::Comparer::operator()(const ld::Atom* left, const ld::Atom* right)
124{
125 if ( left == right )
126 return false;
f80fe69f 127
a645023d
A
128 // magic section$start symbol always sorts to the start of its section
129 if ( left->contentType() == ld::Atom::typeSectionStart )
130 return true;
131 if ( right->contentType() == ld::Atom::typeSectionStart )
132 return false;
133
b2fa67a8 134 // if an -order_file is specified, then sorting is altered to sort those symbols first
a645023d
A
135 if ( _layout._haveOrderFile ) {
136 AtomToOrdinal::const_iterator leftPos = _layout._ordinalOverrideMap.find(left);
137 AtomToOrdinal::const_iterator rightPos = _layout._ordinalOverrideMap.find(right);
138 AtomToOrdinal::const_iterator end = _layout._ordinalOverrideMap.end();
139 if ( leftPos != end ) {
140 if ( rightPos != end ) {
141 // both left and right are overridden, so compare overridden ordinals
142 return leftPos->second < rightPos->second;
143 }
144 else {
145 // left is overridden and right is not, so left < right
146 return true;
147 }
148 }
149 else {
150 if ( rightPos != end ) {
151 // right is overridden and left is not, so right < left
152 return false;
153 }
154 else {
155 // neither are overridden,
156 // fall into default sorting below
157 }
158 }
159 }
160
161 // magic section$end symbol always sorts to the end of its section
162 if ( left->contentType() == ld::Atom::typeSectionEnd )
163 return false;
164 if ( right->contentType() == ld::Atom::typeSectionEnd )
165 return true;
166
f80fe69f
A
167 // aliases sort before their target
168 bool leftIsAlias = left->isAlias();
169 if ( leftIsAlias ) {
170 for (ld::Fixup::iterator fit=left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
599556ff 171 const ld::Atom* target = NULL;
f80fe69f 172 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
599556ff
A
173 switch ( fit->binding ) {
174 case ld::Fixup::bindingsIndirectlyBound:
175 target = _state.indirectBindingTable[fit->u.bindingIndex];
176 break;
177 case ld::Fixup::bindingDirectlyBound:
178 target = fit->u.target;
179 break;
180 default:
181 break;
182 }
183 if ( target == right )
f80fe69f 184 return true; // left already before right
599556ff 185 left = target; // sort as if alias was its target
f80fe69f
A
186 break;
187 }
188 }
189 }
190 bool rightIsAlias = right->isAlias();
191 if ( rightIsAlias ) {
192 for (ld::Fixup::iterator fit=right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
599556ff 193 const ld::Atom* target = NULL;
f80fe69f 194 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
599556ff
A
195 switch ( fit->binding ) {
196 case ld::Fixup::bindingsIndirectlyBound:
197 target = _state.indirectBindingTable[fit->u.bindingIndex];
198 break;
199 case ld::Fixup::bindingDirectlyBound:
200 target = fit->u.target;
201 break;
202 default:
203 break;
204 }
205 if ( target == left )
f80fe69f 206 return false; // need to swap, alias is after target
599556ff 207 right = target; // continue with sort as if right was target
f80fe69f
A
208 break;
209 }
210 }
211 }
212
a645023d
A
213 // the __common section can have real or tentative definitions
214 // we want the real ones to sort before tentative ones
215 bool leftIsTent = (left->definition() == ld::Atom::definitionTentative);
216 bool rightIsTent = (right->definition() == ld::Atom::definitionTentative);
217 if ( leftIsTent != rightIsTent )
218 return rightIsTent;
219
220#if 0
221 // initializers are auto sorted to start of section
222 if ( !fInitializerSet.empty() ) {
223 bool leftFirst = (fInitializerSet.count(left) != 0);
224 bool rightFirst = (fInitializerSet.count(right) != 0);
225 if ( leftFirst != rightFirst )
226 return leftFirst;
227 }
228
229 // terminators are auto sorted to end of section
230 if ( !fTerminatorSet.empty() ) {
231 bool leftLast = (fTerminatorSet.count(left) != 0);
232 bool rightLast = (fTerminatorSet.count(right) != 0);
233 if ( leftLast != rightLast )
234 return rightLast;
235 }
236#endif
237
238 // sort by .o order
b2fa67a8
A
239 const ld::File* leftFile = left->file();
240 const ld::File* rightFile = right->file();
ebf6f434
A
241 // <rdar://problem/10830126> properly sort if on file is NULL and the other is not
242 ld::File::Ordinal leftFileOrdinal = (leftFile != NULL) ? leftFile->ordinal() : ld::File::Ordinal::NullOrdinal();
243 ld::File::Ordinal rightFileOrdinal = (rightFile != NULL) ? rightFile->ordinal() : ld::File::Ordinal::NullOrdinal();
a645023d
A
244 if ( leftFileOrdinal != rightFileOrdinal )
245 return leftFileOrdinal< rightFileOrdinal;
246
247 // tentative defintions have no address in .o file, they are traditionally laid out by name
248 if ( leftIsTent && rightIsTent )
249 return (strcmp(left->name(), right->name()) < 0);
250
251 // lastly sort by atom address
252 int64_t addrDiff = left->objectAddress() - right->objectAddress();
253 if ( addrDiff == 0 ) {
254 // have same address so one might be an alias, and aliases need to sort before target
a645023d
A
255 if ( leftIsAlias != rightIsAlias )
256 return leftIsAlias;
257
258 // both at same address, sort by name
259 return (strcmp(left->name(), right->name()) < 0);
260 }
261 return (addrDiff < 0);
262}
263
264bool Layout::matchesObjectFile(const ld::Atom* atom, const char* objectFileLeafName)
265{
266 if ( objectFileLeafName == NULL )
267 return true;
268 const char* atomFullPath = atom->file()->path();
269 const char* lastSlash = strrchr(atomFullPath, '/');
270 if ( lastSlash != NULL ) {
271 if ( strcmp(&lastSlash[1], objectFileLeafName) == 0 )
272 return true;
273 }
274 else {
275 if ( strcmp(atomFullPath, objectFileLeafName) == 0 )
276 return true;
277 }
278 return false;
279}
280
281
b2fa67a8 282bool Layout::possibleToOrder(const ld::Internal::FinalSection* sect)
a645023d 283{
b2fa67a8 284 // atoms in only some sections can have order_file applied
a645023d
A
285 switch ( sect->type() ) {
286 case ld::Section::typeUnclassified:
287 case ld::Section::typeCode:
288 case ld::Section::typeZeroFill:
289 return true;
290 case ld::Section::typeImportProxies:
291 return false;
292 default:
293 // if section has command line aliases, then we must apply ordering so aliases layout before targets
294 if ( _options.haveCmdLineAliases() ) {
295 for (std::vector<const ld::Atom*>::const_iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
296 const ld::Atom* atom = *ait;
297 if ( atom->isAlias() )
298 return true;
299 }
300 }
301 break;
302 }
303 return false;
304}
305
306void Layout::buildNameTable()
307{
308 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
309 ld::Internal::FinalSection* sect = *sit;
b2fa67a8
A
310 // some sections are not worth scanning for names
311 if ( ! possibleToOrder(sect) )
a645023d
A
312 continue;
313 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
314 const ld::Atom* atom = *ait;
315 if ( atom->symbolTableInclusion() == ld::Atom::symbolTableIn ) {
316 const char* name = atom->name();
317 if ( name != NULL) {
318 // static function or data
319 NameToAtom::iterator pos = _nameTable.find(name);
320 if ( pos == _nameTable.end() )
321 _nameTable[name] = atom;
322 else {
afe874b1
A
323 const ld::Atom* existing = _nameTable[name];
324 if ( existing != NULL ) {
325 _nameCollisionAtoms.push_back(existing);
326 _nameTable[name] = NULL; // collision, denote with NULL
327 }
a645023d
A
328 _nameCollisionAtoms.push_back(atom);
329 }
330 }
331 }
332 }
333 }
afe874b1
A
334 if ( _s_log ) {
335 fprintf(stderr, "buildNameTable() _nameTable:\n");
336 for(NameToAtom::iterator it=_nameTable.begin(); it != _nameTable.end(); ++it)
337 fprintf(stderr, " %p <- %s\n", it->second, it->first);
338 fprintf(stderr, "buildNameTable() _nameCollisionAtoms:\n");
339 for(std::vector<const ld::Atom*>::iterator it=_nameCollisionAtoms.begin(); it != _nameCollisionAtoms.end(); ++it)
340 fprintf(stderr, " %p, %s\n", *it, (*it)->name());
341 }
a645023d
A
342}
343
344
345const ld::Atom* Layout::findAtom(const Options::OrderedSymbol& orderedSymbol)
346{
347 // look for name in _nameTable
348 NameToAtom::iterator pos = _nameTable.find(orderedSymbol.symbolName);
349 if ( pos != _nameTable.end() ) {
350 if ( (pos->second != NULL) && matchesObjectFile(pos->second, orderedSymbol.objectFileName) ) {
351 //fprintf(stderr, "found %s in hash table\n", orderedSymbol.symbolName);
352 return pos->second;
353 }
354 if ( pos->second == NULL ) {
355 // name is in hash table, but atom is NULL, so that means there are duplicates, so we use super slow way
afe874b1
A
356 if ( ( orderedSymbol.objectFileName == NULL) && _options.printOrderFileStatistics() ) {
357 warning("%s specified in order_file but it exists in multiple .o files. "
358 "Prefix symbol with .o filename in order_file to disambiguate", orderedSymbol.symbolName);
359 }
a645023d
A
360 for (std::vector<const ld::Atom*>::iterator it=_nameCollisionAtoms.begin(); it != _nameCollisionAtoms.end(); it++) {
361 const ld::Atom* atom = *it;
362 if ( strcmp(atom->name(), orderedSymbol.symbolName) == 0 ) {
363 if ( matchesObjectFile(atom, orderedSymbol.objectFileName) ) {
a645023d
A
364 return atom;
365 }
366 }
367 }
368 }
369 }
370
371 return NULL;
372}
373
374const ld::Atom* Layout::follower(const ld::Atom* atom)
375{
376 for (const ld::Atom* a = _followOnStarts[atom]; a != NULL; a = _followOnNexts[a]) {
377 assert(a != NULL);
378 if ( _followOnNexts[a] == atom ) {
379 return a;
380 }
381 }
382 // no follower, first in chain
383 return NULL;
384}
385
386void Layout::buildFollowOnTables()
387{
b2fa67a8
A
388 // if no -order_file, then skip building follow on table
389 if ( ! _haveOrderFile )
390 return;
391
a645023d
A
392 // first make a pass to find all follow-on references and build start/next maps
393 // which are a way to represent clusters of atoms that must layout together
394 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
395 ld::Internal::FinalSection* sect = *sit;
b2fa67a8 396 if ( !possibleToOrder(sect) )
a645023d
A
397 continue;
398 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
399 const ld::Atom* atom = *ait;
400 for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
401 if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
402 assert(fit->binding == ld::Fixup::bindingDirectlyBound);
403 const ld::Atom* followOnAtom = fit->u.target;
404 if ( _s_log ) fprintf(stderr, "ref %p %s -> %p %s\n", atom, atom->name(), followOnAtom, followOnAtom->name());
405 assert(_followOnNexts.count(atom) == 0);
406 _followOnNexts[atom] = followOnAtom;
407 if ( _followOnStarts.count(atom) == 0 ) {
408 // first time atom has been seen, make it start of chain
409 _followOnStarts[atom] = atom;
410 if ( _s_log ) fprintf(stderr, " start %s -> %s\n", atom->name(), atom->name());
411 }
412 if ( _followOnStarts.count(followOnAtom) == 0 ) {
413 // first time followOnAtom has been seen, make atom start of chain
414 _followOnStarts[followOnAtom] = _followOnStarts[atom];
415 if ( _s_log ) fprintf(stderr, " start %s -> %s\n", followOnAtom->name(), _followOnStarts[atom]->name());
416 }
417 else {
418 if ( _followOnStarts[followOnAtom] == followOnAtom ) {
419 // followOnAtom atom already start of another chain, hook together
420 // and change all to use atom as start
421 const ld::Atom* a = followOnAtom;
422 while ( true ) {
423 assert(_followOnStarts[a] == followOnAtom);
424 _followOnStarts[a] = _followOnStarts[atom];
425 if ( _s_log ) fprintf(stderr, " adjust start for %s -> %s\n", a->name(), _followOnStarts[atom]->name());
426 AtomToAtom::iterator pos = _followOnNexts.find(a);
427 if ( pos != _followOnNexts.end() )
428 a = pos->second;
429 else
430 break;
431 }
432 }
433 else {
434 // attempt to insert atom into existing followOn chain
435 const ld::Atom* curPrevToFollowOnAtom = this->follower(followOnAtom);
436 assert(curPrevToFollowOnAtom != NULL);
437 assert((atom->size() == 0) || (curPrevToFollowOnAtom->size() == 0));
438 if ( atom->size() == 0 ) {
439 // insert alias into existing chain right before followOnAtom
440 _followOnNexts[curPrevToFollowOnAtom] = atom;
441 _followOnNexts[atom] = followOnAtom;
442 _followOnStarts[atom] = _followOnStarts[followOnAtom];
443 }
444 else {
445 // insert real atom into existing chain right before alias of followOnAtom
446 const ld::Atom* curPrevPrevToFollowOn = this->follower(curPrevToFollowOnAtom);
447 if ( curPrevPrevToFollowOn == NULL ) {
448 // nothing previous, so make this a start of a new chain
449 _followOnNexts[atom] = curPrevToFollowOnAtom;
450 for (const ld::Atom* a = atom; a != NULL; a = _followOnNexts[a]) {
451 if ( _s_log ) fprintf(stderr, " adjust start for %s -> %s\n", a->name(), atom->name());
452 _followOnStarts[a] = atom;
453 }
454 }
455 else {
456 // is previous, insert into existing chain before previous
457 _followOnNexts[curPrevPrevToFollowOn] = atom;
458 _followOnNexts[atom] = curPrevToFollowOnAtom;
459 _followOnStarts[atom] = _followOnStarts[curPrevToFollowOnAtom];
460 }
461 }
462 }
463 }
464 }
465 }
466 }
467 }
468
469 if ( _s_log ) {
470 for(AtomToAtom::iterator it = _followOnStarts.begin(); it != _followOnStarts.end(); ++it)
471 fprintf(stderr, "start %s -> %s\n", it->first->name(), it->second->name());
472
473 for(AtomToAtom::iterator it = _followOnNexts.begin(); it != _followOnNexts.end(); ++it)
474 fprintf(stderr, "next %s -> %s\n", it->first->name(), (it->second != NULL) ? it->second->name() : "null");
475 }
476}
477
b2fa67a8
A
478
479class InSet
480{
481public:
482 InSet(const std::set<const ld::Atom*>& theSet) : _set(theSet) {}
483
484 bool operator()(const ld::Atom* atom) const {
485 return ( _set.count(atom) != 0 );
486 }
487private:
488 const std::set<const ld::Atom*>& _set;
489};
490
491
a645023d
A
492void Layout::buildOrdinalOverrideMap()
493{
494 // if no -order_file, then skip building override map
495 if ( ! _haveOrderFile )
496 return;
497
498 // build fast name->atom table
499 this->buildNameTable();
500
501 // handle .o files that cannot have their atoms rearranged
502 // with the start/next maps of follow-on atoms we can process the order file and produce override ordinals
503 uint32_t index = 0;
504 uint32_t matchCount = 0;
b2fa67a8 505 std::set<const ld::Atom*> moveToData;
a645023d
A
506 for(Options::OrderedSymbolsIterator it = _options.orderedSymbolsBegin(); it != _options.orderedSymbolsEnd(); ++it) {
507 const ld::Atom* atom = this->findAtom(*it);
508 if ( atom != NULL ) {
b2fa67a8
A
509 // <rdar://problem/8612550> When order file used on data, turn ordered zero fill symbols into zero data
510 switch ( atom->section().type() ) {
511 case ld::Section::typeZeroFill:
512 case ld::Section::typeTentativeDefs:
513 if ( atom->size() <= 512 )
514 moveToData.insert(atom);
515 break;
516 default:
517 break;
518 }
519
a645023d
A
520 AtomToAtom::iterator start = _followOnStarts.find(atom);
521 if ( start != _followOnStarts.end() ) {
522 // this symbol for the order file corresponds to an atom that is in a cluster that must lay out together
523 for(const ld::Atom* nextAtom = start->second; nextAtom != NULL; nextAtom = _followOnNexts[nextAtom]) {
524 AtomToOrdinal::iterator pos = _ordinalOverrideMap.find(nextAtom);
525 if ( pos == _ordinalOverrideMap.end() ) {
526 _ordinalOverrideMap[nextAtom] = index++;
527 if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s in cluster from %s\n", index, nextAtom->name(), nextAtom->file()->path());
528 }
529 else {
530 if (_s_log ) fprintf(stderr, "could not order %s as %u because it was already laid out earlier by %s as %u\n",
531 atom->name(), index, _followOnStarts[atom]->name(), _ordinalOverrideMap[atom] );
532 }
533 }
534 }
535 else {
536 _ordinalOverrideMap[atom] = index;
537 if (_s_log ) fprintf(stderr, "override ordinal %u assigned to %s from %s\n", index, atom->name(), atom->file()->path());
538 }
539 ++matchCount;
540 }
541 else {
542 if ( _options.printOrderFileStatistics() ) {
543 if ( it->objectFileName == NULL )
544 warning("can't find match for order_file entry: %s", it->symbolName);
545 else
546 warning("can't find match for order_file entry: %s/%s", it->objectFileName, it->symbolName);
547 }
548 }
549 ++index;
550 }
551 if ( _options.printOrderFileStatistics() && (_options.orderedSymbolsCount() != matchCount) ) {
552 warning("only %u out of %lu order_file symbols were applicable", matchCount, _options.orderedSymbolsCount() );
553 }
554
b2fa67a8
A
555 // <rdar://problem/8612550> When order file used on data, turn ordered zero fill symbols into zeroed data
556 if ( ! moveToData.empty() ) {
9543cb2f
A
557 // <rdar://problem/14919139> only move zero fill symbols to __data if there is a __data section
558 ld::Internal::FinalSection* dataSect = NULL;
b2fa67a8
A
559 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
560 ld::Internal::FinalSection* sect = *sit;
9543cb2f
A
561 if ( sect->type() == ld::Section::typeUnclassified ) {
562 if ( (strcmp(sect->sectionName(), "__data") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
563 dataSect = sect;
564 }
565 }
566
567 if ( dataSect != NULL ) {
568 // add atoms to __data
569 dataSect->atoms.insert(dataSect->atoms.end(), moveToData.begin(), moveToData.end());
570 // remove atoms from original sections
571 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
572 ld::Internal::FinalSection* sect = *sit;
573 switch ( sect->type() ) {
574 case ld::Section::typeZeroFill:
575 case ld::Section::typeTentativeDefs:
576 sect->atoms.erase(std::remove_if(sect->atoms.begin(), sect->atoms.end(), InSet(moveToData)), sect->atoms.end());
577 break;
578 default:
579 break;
580 }
b2fa67a8
A
581 }
582 }
583 }
584
a645023d
A
585}
586
587void Layout::doPass()
588{
599556ff
A
589 const bool log = false;
590 if ( log ) {
591 fprintf(stderr, "Unordered atoms:\n");
592 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
593 ld::Internal::FinalSection* sect = *sit;
594 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
595 const ld::Atom* atom = *ait;
596 fprintf(stderr, "\t%p\t%s\t%s\n", atom, sect->sectionName(), atom->name());
597 }
598 }
599 }
600
a645023d
A
601 // handle .o files that cannot have their atoms rearranged
602 this->buildFollowOnTables();
603
b2fa67a8 604 // assign new ordinal value to all ordered atoms
a645023d
A
605 this->buildOrdinalOverrideMap();
606
a645023d
A
607 // sort atoms in each section
608 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
609 ld::Internal::FinalSection* sect = *sit;
599556ff
A
610 if ( sect->type() == ld::Section::typeTempAlias )
611 continue;
612 if ( log ) fprintf(stderr, "sorting section %s\n", sect->sectionName());
b2fa67a8 613 std::sort(sect->atoms.begin(), sect->atoms.end(), _comparer);
a645023d 614 }
b2fa67a8 615
599556ff
A
616 if ( log ) {
617 fprintf(stderr, "Sorted atoms:\n");
618 for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
619 ld::Internal::FinalSection* sect = *sit;
620 for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
621 const ld::Atom* atom = *ait;
622 fprintf(stderr, "\t%p\t%s\t%s\n", atom, sect->sectionName(), atom->name());
623 }
624 }
625 }
a645023d
A
626}
627
628
629void doPass(const Options& opts, ld::Internal& state)
630{
631 Layout layout(opts, state);
632 layout.doPass();
633}
634
635
636} // namespace order_file
637} // namespace passes
638} // namespace ld