1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-*
3 * Copyright (c) 2009-2010 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
27 #include <sys/types.h>
30 #include <sys/sysctl.h>
42 #include <ext/hash_map>
43 #include <ext/hash_set>
48 #include "InputFiles.h"
49 #include "SymbolTable.h"
57 // HACK, I can't find a way to pass values in the compare classes (e.g. ContentFuncs)
58 // so use global variable to pass info.
59 static ld::IndirectBindingTable
* _s_indirectBindingTable
= NULL
;
60 bool SymbolTable::_s_doDemangle
= false;
63 SymbolTable::SymbolTable(const Options
& opts
, std::vector
<const ld::Atom
*>& ibt
)
64 : _options(opts
), _cstringTable(6151), _indirectBindingTable(ibt
), _hasExternalTentativeDefinitions(false)
66 _s_indirectBindingTable
= this;
67 _s_doDemangle
= _options
.demangleSymbols();
71 size_t SymbolTable::ContentFuncs::operator()(const ld::Atom
* atom
) const
73 return atom
->contentHash(*_s_indirectBindingTable
);
76 bool SymbolTable::ContentFuncs::operator()(const ld::Atom
* left
, const ld::Atom
* right
) const
78 return (memcmp(left
->rawContentPointer(), right
->rawContentPointer(), left
->size()) == 0);
83 size_t SymbolTable::CStringHashFuncs::operator()(const ld::Atom
* atom
) const
85 return atom
->contentHash(*_s_indirectBindingTable
);
88 bool SymbolTable::CStringHashFuncs::operator()(const ld::Atom
* left
, const ld::Atom
* right
) const
90 return (strcmp((char*)left
->rawContentPointer(), (char*)right
->rawContentPointer()) == 0);
94 size_t SymbolTable::UTF16StringHashFuncs::operator()(const ld::Atom
* atom
) const
96 return atom
->contentHash(*_s_indirectBindingTable
);
99 bool SymbolTable::UTF16StringHashFuncs::operator()(const ld::Atom
* left
, const ld::Atom
* right
) const
103 const void* leftContent
= left
->rawContentPointer();
104 const void* rightContent
= right
->rawContentPointer();
105 unsigned int amount
= left
->size()-2;
106 bool result
= (memcmp(leftContent
, rightContent
, amount
) == 0);
111 size_t SymbolTable::ReferencesHashFuncs::operator()(const ld::Atom
* atom
) const
113 return atom
->contentHash(*_s_indirectBindingTable
);
116 bool SymbolTable::ReferencesHashFuncs::operator()(const ld::Atom
* left
, const ld::Atom
* right
) const
118 return left
->canCoalesceWith(*right
, *_s_indirectBindingTable
);
123 bool SymbolTable::addByName(const ld::Atom
& newAtom
, bool ignoreDuplicates
)
126 bool checkVisibilityMismatch
= false;
127 assert(newAtom
.name() != NULL
);
128 const char* name
= newAtom
.name();
129 IndirectBindingSlot slot
= this->findSlotForName(name
);
130 const ld::Atom
* existingAtom
= _indirectBindingTable
[slot
];
131 //fprintf(stderr, "addByName(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
132 if ( existingAtom
!= NULL
) {
133 assert(&newAtom
!= existingAtom
);
134 switch ( existingAtom
->definition() ) {
135 case ld::Atom::definitionRegular
:
136 switch ( newAtom
.definition() ) {
137 case ld::Atom::definitionRegular
:
138 if ( existingAtom
->combine() == ld::Atom::combineByName
) {
139 if ( newAtom
.combine() == ld::Atom::combineByName
) {
140 // <rdar://problem/9183821> always choose mach-o over llvm bit code, otherwise LTO may eliminate the llvm atom
141 const bool existingIsLTO
= (existingAtom
->contentType() == ld::Atom::typeLTOtemporary
);
142 const bool newIsLTO
= (newAtom
.contentType() == ld::Atom::typeLTOtemporary
);
143 if ( existingIsLTO
!= newIsLTO
) {
144 useNew
= existingIsLTO
;
147 // both weak, prefer non-auto-hide one
148 if ( newAtom
.autoHide() != existingAtom
->autoHide() ) {
149 // <rdar://problem/6783167> support auto hidden weak symbols: .weak_def_can_be_hidden
150 useNew
= existingAtom
->autoHide();
151 // don't check for visibility mismatch
153 else if ( newAtom
.autoHide() && existingAtom
->autoHide() ) {
154 // both have auto-hide, so use one with greater alignment
155 useNew
= ( newAtom
.alignment().trailingZeros() > existingAtom
->alignment().trailingZeros() );
158 // neither auto-hide, check visibility
159 if ( newAtom
.scope() != existingAtom
->scope() ) {
160 // <rdar://problem/8304984> use more visible weak def symbol
161 useNew
= (newAtom
.scope() == ld::Atom::scopeGlobal
);
164 // both have same visibility, use one with greater alignment
165 useNew
= ( newAtom
.alignment().trailingZeros() > existingAtom
->alignment().trailingZeros() );
171 // existing weak, new is not-weak
176 if ( newAtom
.combine() == ld::Atom::combineByName
) {
177 // existing not-weak, new is weak
181 // existing not-weak, new is not-weak
182 if ( newAtom
.section().type() == ld::Section::typeMachHeader
) {
183 warning("ignoring override of built-in symbol %s from %s", newAtom
.name(), existingAtom
->file()->path());
186 else if ( existingAtom
->section().type() == ld::Section::typeMachHeader
) {
187 warning("ignoring override of built-in symbol %s from %s", newAtom
.name(), newAtom
.file()->path());
191 if ( ignoreDuplicates
) {
193 static bool fullWarning
= false;
194 if ( ! fullWarning
) {
195 warning("-dead_strip with lazy loaded static (library) archives "
196 "has resulted in a duplicate symbol. You can change your "
197 "source code to rename symbols to avoid the collision. "
198 "This will be an error in a future linker.");
201 warning("duplicate symbol %s originally in %s now lazily loaded from %s",
202 SymbolTable::demangle(name
), existingAtom
->file()->path(), newAtom
.file()->path());
205 throwf("duplicate symbol %s in %s and %s",
206 SymbolTable::demangle(name
), newAtom
.file()->path(), existingAtom
->file()->path());
212 case ld::Atom::definitionTentative
:
213 // ignore new tentative atom, because we already have a regular one
215 checkVisibilityMismatch
= true;
216 if ( newAtom
.size() > existingAtom
->size() ) {
217 warning("for symbol %s tentative definition of size %llu from %s is "
218 "is smaller than the real definition of size %llu from %s",
219 newAtom
.name(), newAtom
.size(), newAtom
.file()->path(),
220 existingAtom
->size(), existingAtom
->file()->path());
223 case ld::Atom::definitionAbsolute
:
224 throwf("duplicate symbol %s in %s and %s", name
, newAtom
.file()->path(), existingAtom
->file()->path());
225 case ld::Atom::definitionProxy
:
226 // ignore external atom, because we already have a one
231 case ld::Atom::definitionTentative
:
232 switch ( newAtom
.definition() ) {
233 case ld::Atom::definitionRegular
:
234 // replace existing tentative atom with regular one
235 if ( newAtom
.section().type() == ld::Section::typeMachHeader
) {
236 // silently replace tentative __dso_handle with real linker created symbol
239 else if ( existingAtom
->section().type() == ld::Section::typeMachHeader
) {
240 // silently replace tentative __dso_handle with real linker created symbol
244 checkVisibilityMismatch
= true;
245 if ( newAtom
.size() < existingAtom
->size() ) {
246 warning("for symbol %s tentative definition of size %llu from %s is "
247 "being replaced by a real definition of size %llu from %s",
248 newAtom
.name(), existingAtom
->size(), existingAtom
->file()->path(),
249 newAtom
.size(), newAtom
.file()->path());
251 if ( newAtom
.section().type() == ld::Section::typeCode
) {
252 warning("for symbol %s tentative (data) defintion from %s is "
253 "being replaced by code from %s", newAtom
.name(), existingAtom
->file()->path(),
254 newAtom
.file()->path());
258 case ld::Atom::definitionTentative
:
259 // new and existing are both tentative definitions, use largest
260 checkVisibilityMismatch
= true;
261 if ( newAtom
.size() < existingAtom
->size() ) {
265 if ( newAtom
.alignment().trailingZeros() < existingAtom
->alignment().trailingZeros() )
266 warning("alignment lost in merging tentative definition %s", newAtom
.name());
269 case ld::Atom::definitionAbsolute
:
270 // replace tentative with absolute
273 case ld::Atom::definitionProxy
:
274 // a tentative definition and a dylib definition, so commons-mode decides how to handle
275 switch ( _options
.commonsMode() ) {
276 case Options::kCommonsIgnoreDylibs
:
277 if ( _options
.warnCommons() )
278 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
279 existingAtom
->name(), existingAtom
->file()->path(), newAtom
.file()->path());
282 case Options::kCommonsOverriddenByDylibs
:
283 if ( _options
.warnCommons() )
284 warning("replacing common symbol %s from %s with true definition from dylib %s",
285 existingAtom
->name(), existingAtom
->file()->path(), newAtom
.file()->path());
287 case Options::kCommonsConflictsDylibsError
:
288 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
289 existingAtom
->name(), existingAtom
->file()->path(), newAtom
.file()->path());
294 case ld::Atom::definitionAbsolute
:
295 switch ( newAtom
.definition() ) {
296 case ld::Atom::definitionRegular
:
297 throwf("duplicate symbol %s in %s and %s", name
, newAtom
.file()->path(), existingAtom
->file()->path());
298 case ld::Atom::definitionTentative
:
299 // ignore new tentative atom, because we already have a regular one
302 case ld::Atom::definitionAbsolute
:
303 throwf("duplicate symbol %s in %s and %s", name
, newAtom
.file()->path(), existingAtom
->file()->path());
304 case ld::Atom::definitionProxy
:
305 // ignore external atom, because we already have a one
310 case ld::Atom::definitionProxy
:
311 switch ( newAtom
.definition() ) {
312 case ld::Atom::definitionRegular
:
313 // replace external atom with regular one
316 case ld::Atom::definitionTentative
:
317 // a tentative definition and a dylib definition, so commons-mode decides how to handle
318 switch ( _options
.commonsMode() ) {
319 case Options::kCommonsIgnoreDylibs
:
320 if ( _options
.warnCommons() )
321 warning("using common symbol %s from %s and ignoring defintion from dylib %s",
322 newAtom
.name(), newAtom
.file()->path(), existingAtom
->file()->path());
324 case Options::kCommonsOverriddenByDylibs
:
325 if ( _options
.warnCommons() )
326 warning("replacing defintion of %s from dylib %s with common symbol from %s",
327 newAtom
.name(), existingAtom
->file()->path(), newAtom
.file()->path());
330 case Options::kCommonsConflictsDylibsError
:
331 throwf("common symbol %s from %s conflicts with defintion from dylib %s",
332 newAtom
.name(), newAtom
.file()->path(), existingAtom
->file()->path());
335 case ld::Atom::definitionAbsolute
:
336 // replace external atom with absolute one
339 case ld::Atom::definitionProxy
:
340 // <rdar://problem/5137732> ld should keep looking when it finds a weak definition in a dylib
341 if ( newAtom
.combine() == ld::Atom::combineByName
) {
345 if ( existingAtom
->combine() == ld::Atom::combineByName
)
348 throwf("symbol %s exported from both %s and %s\n", name
, newAtom
.file()->path(), existingAtom
->file()->path());
355 if ( (existingAtom
!= NULL
) && checkVisibilityMismatch
&& (newAtom
.scope() != existingAtom
->scope()) ) {
356 warning("%s has different visibility (%s) in %s and (%s) in %s",
357 SymbolTable::demangle(newAtom
.name()), (newAtom
.scope() == 1 ? "hidden" : "default"), newAtom
.file()->path(), (existingAtom
->scope() == 1 ? "hidden" : "default"), existingAtom
->file()->path());
360 _indirectBindingTable
[slot
] = &newAtom
;
361 if ( existingAtom
!= NULL
) {
362 markCoalescedAway(existingAtom
);
363 // if ( fOwner.fInitialLoadsDone ) {
364 // //fprintf(stderr, "existing %p %s overridden by %p\n", existingAtom, existingAtom->name(), &newAtom);
365 // fOwner.fAtomsOverriddenByLateLoads.insert(existingAtom);
368 if ( newAtom
.scope() == ld::Atom::scopeGlobal
) {
369 if ( newAtom
.definition() == ld::Atom::definitionTentative
) {
370 _hasExternalTentativeDefinitions
= true;
375 markCoalescedAway(&newAtom
);
377 // return if existing atom in symbol table was replaced
378 return useNew
&& (existingAtom
!= NULL
);
382 bool SymbolTable::addByContent(const ld::Atom
& newAtom
)
385 const ld::Atom
* existingAtom
;
386 IndirectBindingSlot slot
= this->findSlotForContent(&newAtom
, &existingAtom
);
387 //fprintf(stderr, "addByContent(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
388 if ( existingAtom
!= NULL
) {
389 // use existing unless new one has greater alignment requirements
390 useNew
= ( newAtom
.alignment().trailingZeros() > existingAtom
->alignment().trailingZeros() );
393 _indirectBindingTable
[slot
] = &newAtom
;
394 if ( existingAtom
!= NULL
)
395 markCoalescedAway(existingAtom
);
398 _indirectBindingTable
[slot
] = existingAtom
;
399 if ( existingAtom
!= &newAtom
)
400 markCoalescedAway(&newAtom
);
402 // return if existing atom in symbol table was replaced
403 return useNew
&& (existingAtom
!= NULL
);
406 bool SymbolTable::addByReferences(const ld::Atom
& newAtom
)
409 const ld::Atom
* existingAtom
;
410 IndirectBindingSlot slot
= this->findSlotForReferences(&newAtom
, &existingAtom
);
411 //fprintf(stderr, "addByReferences(%p) name=%s, slot=%u, existing=%p\n", &newAtom, newAtom.name(), slot, existingAtom);
412 if ( existingAtom
!= NULL
) {
413 // use existing unless new one has greater alignment requirements
414 useNew
= ( newAtom
.alignment().trailingZeros() > existingAtom
->alignment().trailingZeros() );
417 _indirectBindingTable
[slot
] = &newAtom
;
418 if ( existingAtom
!= NULL
)
419 markCoalescedAway(existingAtom
);
422 if ( existingAtom
!= &newAtom
)
423 markCoalescedAway(&newAtom
);
425 // return if existing atom in symbol table was replaced
426 return useNew
&& (existingAtom
!= NULL
);
430 bool SymbolTable::add(const ld::Atom
& atom
, bool ignoreDuplicates
)
432 //fprintf(stderr, "SymbolTable::add(%p), name=%s\n", &atom, atom.name());
433 assert(atom
.scope() != ld::Atom::scopeTranslationUnit
);
434 switch ( atom
.combine() ) {
435 case ld::Atom::combineNever
:
436 case ld::Atom::combineByName
:
437 return this->addByName(atom
, ignoreDuplicates
);
439 case ld::Atom::combineByNameAndContent
:
440 return this->addByContent(atom
);
442 case ld::Atom::combineByNameAndReferences
:
443 return this->addByReferences(atom
);
450 void SymbolTable::markCoalescedAway(const ld::Atom
* atom
)
452 // remove this from list of all atoms used
453 //fprintf(stderr, "markCoalescedAway(%p) from %s\n", atom, atom->file()->path());
454 (const_cast<ld::Atom
*>(atom
))->setCoalescedAway();
457 // The fixupNoneGroupSubordinate* fixup kind is used to model group comdat.
458 // The "signature" atom in the group has a fixupNoneGroupSubordinate* fixup to
459 // all other members of the group. So, if the signature atom is
460 // coalesced away, all other atoms in the group should also be removed.
462 for (ld::Fixup::iterator fit
=atom
->fixupsBegin(), fend
=atom
->fixupsEnd(); fit
!= fend
; ++fit
) {
463 switch ( fit
->kind
) {
464 case ld::Fixup::kindNoneGroupSubordinate
:
465 case ld::Fixup::kindNoneGroupSubordinateFDE
:
466 case ld::Fixup::kindNoneGroupSubordinateLSDA
:
467 assert(fit
->binding
== ld::Fixup::bindingDirectlyBound
);
468 this->markCoalescedAway(fit
->u
.target
);
477 void SymbolTable::undefines(std::vector
<const char*>& undefs
)
479 // return all names in _byNameTable that have no associated atom
480 for (NameToSlot::iterator it
=_byNameTable
.begin(); it
!= _byNameTable
.end(); ++it
) {
481 //fprintf(stderr, " _byNameTable[%s] = slot %d which has atom %p\n", it->first, it->second, _indirectBindingTable[it->second]);
482 if ( _indirectBindingTable
[it
->second
] == NULL
)
483 undefs
.push_back(it
->first
);
485 // sort so that undefines are in a stable order (not dependent on hashing functions)
486 std::sort(undefs
.begin(), undefs
.end());
490 void SymbolTable::tentativeDefs(std::vector
<const char*>& tents
)
492 // return all names in _byNameTable that have no associated atom
493 for (NameToSlot::iterator it
=_byNameTable
.begin(); it
!= _byNameTable
.end(); ++it
) {
494 const char* name
= it
->first
;
495 const ld::Atom
* atom
= _indirectBindingTable
[it
->second
];
496 if ( (atom
!= NULL
) && (atom
->definition() == ld::Atom::definitionTentative
) )
497 tents
.push_back(name
);
499 std::sort(tents
.begin(), tents
.end());
503 bool SymbolTable::hasName(const char* name
)
505 NameToSlot::iterator pos
= _byNameTable
.find(name
);
506 if ( pos
== _byNameTable
.end() )
508 return (_indirectBindingTable
[pos
->second
] != NULL
);
511 // find existing or create new slot
512 SymbolTable::IndirectBindingSlot
SymbolTable::findSlotForName(const char* name
)
514 NameToSlot::iterator pos
= _byNameTable
.find(name
);
515 if ( pos
!= _byNameTable
.end() )
517 // create new slot for this name
518 SymbolTable::IndirectBindingSlot slot
= _indirectBindingTable
.size();
519 _indirectBindingTable
.push_back(NULL
);
520 _byNameTable
[name
] = slot
;
521 _byNameReverseTable
[slot
] = name
;
526 // find existing or create new slot
527 SymbolTable::IndirectBindingSlot
SymbolTable::findSlotForContent(const ld::Atom
* atom
, const ld::Atom
** existingAtom
)
529 //fprintf(stderr, "findSlotForContent(%p)\n", atom);
530 SymbolTable::IndirectBindingSlot slot
= 0;
531 UTF16StringToSlot::iterator upos
;
532 CStringToSlot::iterator cspos
;
533 ContentToSlot::iterator pos
;
534 switch ( atom
->section().type() ) {
535 case ld::Section::typeCString
:
536 cspos
= _cstringTable
.find(atom
);
537 if ( cspos
!= _cstringTable
.end() ) {
538 *existingAtom
= _indirectBindingTable
[cspos
->second
];
539 return cspos
->second
;
541 slot
= _indirectBindingTable
.size();
542 _cstringTable
[atom
] = slot
;
544 case ld::Section::typeNonStdCString
:
546 // use seg/sect name is key to map to avoid coalescing across segments and sections
548 sprintf(segsect
, "%s/%s", atom
->section().segmentName(), atom
->section().sectionName());
549 NameToMap::iterator mpos
= _nonStdCStringSectionToMap
.find(segsect
);
550 CStringToSlot
* map
= NULL
;
551 if ( mpos
== _nonStdCStringSectionToMap
.end() ) {
552 map
= new CStringToSlot();
553 _nonStdCStringSectionToMap
[strdup(segsect
)] = map
;
558 cspos
= map
->find(atom
);
559 if ( cspos
!= map
->end() ) {
560 *existingAtom
= _indirectBindingTable
[cspos
->second
];
561 return cspos
->second
;
563 slot
= _indirectBindingTable
.size();
564 map
->operator[](atom
) = slot
;
567 case ld::Section::typeUTF16Strings
:
568 upos
= _utf16Table
.find(atom
);
569 if ( upos
!= _utf16Table
.end() ) {
570 *existingAtom
= _indirectBindingTable
[upos
->second
];
573 slot
= _indirectBindingTable
.size();
574 _utf16Table
[atom
] = slot
;
576 case ld::Section::typeLiteral4
:
577 pos
= _literal4Table
.find(atom
);
578 if ( pos
!= _literal4Table
.end() ) {
579 *existingAtom
= _indirectBindingTable
[pos
->second
];
582 slot
= _indirectBindingTable
.size();
583 _literal4Table
[atom
] = slot
;
585 case ld::Section::typeLiteral8
:
586 pos
= _literal8Table
.find(atom
);
587 if ( pos
!= _literal8Table
.end() ) {
588 *existingAtom
= _indirectBindingTable
[pos
->second
];
591 slot
= _indirectBindingTable
.size();
592 _literal8Table
[atom
] = slot
;
594 case ld::Section::typeLiteral16
:
595 pos
= _literal16Table
.find(atom
);
596 if ( pos
!= _literal16Table
.end() ) {
597 *existingAtom
= _indirectBindingTable
[pos
->second
];
600 slot
= _indirectBindingTable
.size();
601 _literal16Table
[atom
] = slot
;
604 assert(0 && "section type does not support coalescing by content");
606 _indirectBindingTable
.push_back(atom
);
607 *existingAtom
= NULL
;
613 // find existing or create new slot
614 SymbolTable::IndirectBindingSlot
SymbolTable::findSlotForReferences(const ld::Atom
* atom
, const ld::Atom
** existingAtom
)
616 //fprintf(stderr, "findSlotForReferences(%p)\n", atom);
618 SymbolTable::IndirectBindingSlot slot
= 0;
619 ReferencesToSlot::iterator pos
;
620 switch ( atom
->section().type() ) {
621 case ld::Section::typeNonLazyPointer
:
622 pos
= _nonLazyPointerTable
.find(atom
);
623 if ( pos
!= _nonLazyPointerTable
.end() ) {
624 *existingAtom
= _indirectBindingTable
[pos
->second
];
627 slot
= _indirectBindingTable
.size();
628 _nonLazyPointerTable
[atom
] = slot
;
630 case ld::Section::typeCFString
:
631 pos
= _cfStringTable
.find(atom
);
632 if ( pos
!= _cfStringTable
.end() ) {
633 *existingAtom
= _indirectBindingTable
[pos
->second
];
636 slot
= _indirectBindingTable
.size();
637 _cfStringTable
[atom
] = slot
;
639 case ld::Section::typeObjCClassRefs
:
640 pos
= _objc2ClassRefTable
.find(atom
);
641 if ( pos
!= _objc2ClassRefTable
.end() ) {
642 *existingAtom
= _indirectBindingTable
[pos
->second
];
645 slot
= _indirectBindingTable
.size();
646 _objc2ClassRefTable
[atom
] = slot
;
648 case ld::Section::typeCStringPointer
:
649 pos
= _pointerToCStringTable
.find(atom
);
650 if ( pos
!= _pointerToCStringTable
.end() ) {
651 *existingAtom
= _indirectBindingTable
[pos
->second
];
654 slot
= _indirectBindingTable
.size();
655 _pointerToCStringTable
[atom
] = slot
;
658 assert(0 && "section type does not support coalescing by references");
660 _indirectBindingTable
.push_back(atom
);
661 *existingAtom
= NULL
;
666 const char* SymbolTable::indirectName(IndirectBindingSlot slot
) const
668 assert(slot
< _indirectBindingTable
.size());
669 const ld::Atom
* target
= _indirectBindingTable
[slot
];
670 if ( target
!= NULL
) {
671 return target
->name();
673 // handle case when by-name reference is indirected and no atom yet in _byNameTable
674 SlotToName::const_iterator pos
= _byNameReverseTable
.find(slot
);
675 if ( pos
!= _byNameReverseTable
.end() )
681 const ld::Atom
* SymbolTable::indirectAtom(IndirectBindingSlot slot
) const
683 assert(slot
< _indirectBindingTable
.size());
684 return _indirectBindingTable
[slot
];
687 extern "C" char* __cxa_demangle (const char* mangled_name
,
692 const char* SymbolTable::demangle(const char* sym
)
694 // only try to demangle symbols if -demangle on command line
695 if ( !_s_doDemangle
)
698 // only try to demangle symbols that look like C++ symbols
699 if ( strncmp(sym
, "__Z", 3) != 0 )
702 static size_t size
= 1024;
703 static char* buff
= (char*)malloc(size
);
706 char* result
= __cxa_demangle(&sym
[1], buff
, &size
, &status
);
707 if ( result
!= NULL
) {
708 // if demangling succesful, keep buffer for next demangle
716 void SymbolTable::printStatistics()
718 // fprintf(stderr, "cstring table size: %lu, bucket count: %lu, hash func called %u times\n",
719 // _cstringTable.size(), _cstringTable.bucket_count(), cstringHashCount);
721 for(unsigned int b
=0; b
< 11; ++b
) {
724 for(unsigned int i
=0; i
< _cstringTable
.bucket_count(); ++i
) {
725 unsigned int n
= _cstringTable
.elems_in_bucket(i
);
731 fprintf(stderr
, "cstring table distribution\n");
732 for(unsigned int b
=0; b
< 11; ++b
) {
733 fprintf(stderr
, "%u buckets have %u elements\n", count
[b
], b
);
735 fprintf(stderr
, "indirect table size: %lu\n", _indirectBindingTable
.size());
736 fprintf(stderr
, "by-name table size: %lu\n", _byNameTable
.size());
737 // fprintf(stderr, "by-content table size: %lu, hash count: %u, equals count: %u, lookup count: %u\n",
738 // _byContentTable.size(), contentHashCount, contentEqualCount, contentLookupCount);
739 // fprintf(stderr, "by-ref table size: %lu, hashed count: %u, equals count: %u, lookup count: %u, insert count: %u\n",
740 // _byReferencesTable.size(), refHashCount, refEqualsCount, refLookupCount, refInsertCount);
742 //ReferencesHash obj;
743 //for(ReferencesHashToSlot::iterator it=_byReferencesTable.begin(); it != _byReferencesTable.end(); ++it) {
744 // if ( obj.operator()(it->first) == 0x2F3AC0EAC744EA70 ) {
745 // fprintf(stderr, "hash=0x2F3AC0EAC744EA70 for %p %s from %s\n", it->first, it->first->name(), it->first->file()->path());