You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
7.4 KiB
275 lines
7.4 KiB
//===- ResolveInfo.cpp ----------------------------------------------------===//
|
|
//
|
|
// The MCLinker Project
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "mcld/LD/ResolveInfo.h"
|
|
|
|
#include "mcld/LinkerConfig.h"
|
|
#include "mcld/LD/LDSection.h"
|
|
#include "mcld/Support/GCFactory.h"
|
|
|
|
#include <llvm/Support/ManagedStatic.h>
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
namespace mcld {
|
|
|
|
/// g_NullResolveInfo - a pointer to Null ResolveInfo.
|
|
static ResolveInfo* g_NullResolveInfo = NULL;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ResolveInfo
|
|
//===----------------------------------------------------------------------===//
|
|
ResolveInfo::ResolveInfo() : m_Size(0), m_BitField(0) {
|
|
m_Ptr.sym_ptr = 0;
|
|
}
|
|
|
|
ResolveInfo::~ResolveInfo() {
|
|
}
|
|
|
|
void ResolveInfo::override(const ResolveInfo& pFrom) {
|
|
m_Size = pFrom.m_Size;
|
|
overrideAttributes(pFrom);
|
|
overrideVisibility(pFrom);
|
|
}
|
|
|
|
void ResolveInfo::overrideAttributes(const ResolveInfo& pFrom) {
|
|
m_BitField &= ~RESOLVE_MASK | VISIBILITY_MASK;
|
|
m_BitField |= (pFrom.m_BitField & (RESOLVE_MASK & ~VISIBILITY_MASK));
|
|
}
|
|
|
|
/// overrideVisibility - override the visibility
|
|
/// always use the most strict visibility
|
|
void ResolveInfo::overrideVisibility(const ResolveInfo& pFrom) {
|
|
// The rule for combining visibility is that we always choose the
|
|
// most constrained visibility. In order of increasing constraint,
|
|
// visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse
|
|
// of the numeric values, so the effect is that we always want the
|
|
// smallest non-zero value.
|
|
//
|
|
// enum {
|
|
// STV_DEFAULT = 0,
|
|
// STV_INTERNAL = 1,
|
|
// STV_HIDDEN = 2,
|
|
// STV_PROTECTED = 3
|
|
// };
|
|
|
|
Visibility from_vis = pFrom.visibility();
|
|
Visibility cur_vis = visibility();
|
|
if (from_vis != 0) {
|
|
if (cur_vis == 0)
|
|
setVisibility(from_vis);
|
|
else if (cur_vis > from_vis)
|
|
setVisibility(from_vis);
|
|
}
|
|
}
|
|
|
|
void ResolveInfo::setRegular() {
|
|
m_BitField &= (~dynamic_flag);
|
|
}
|
|
|
|
void ResolveInfo::setDynamic() {
|
|
m_BitField |= dynamic_flag;
|
|
}
|
|
|
|
void ResolveInfo::setSource(bool pIsDyn) {
|
|
if (pIsDyn)
|
|
m_BitField |= dynamic_flag;
|
|
else
|
|
m_BitField &= (~dynamic_flag);
|
|
}
|
|
|
|
void ResolveInfo::setInDyn() {
|
|
m_BitField |= indyn_flag;
|
|
}
|
|
|
|
void ResolveInfo::setType(uint32_t pType) {
|
|
m_BitField &= ~TYPE_MASK;
|
|
m_BitField |= ((pType << TYPE_OFFSET) & TYPE_MASK);
|
|
}
|
|
|
|
void ResolveInfo::setDesc(uint32_t pDesc) {
|
|
m_BitField &= ~DESC_MASK;
|
|
m_BitField |= ((pDesc << DESC_OFFSET) & DESC_MASK);
|
|
}
|
|
|
|
void ResolveInfo::setBinding(uint32_t pBinding) {
|
|
m_BitField &= ~BINDING_MASK;
|
|
if (pBinding == Local || pBinding == Absolute)
|
|
m_BitField |= local_flag;
|
|
if (pBinding == Weak || pBinding == Absolute)
|
|
m_BitField |= weak_flag;
|
|
}
|
|
|
|
void ResolveInfo::setReserved(uint32_t pReserved) {
|
|
m_BitField &= ~RESERVED_MASK;
|
|
m_BitField |= ((pReserved << RESERVED_OFFSET) & RESERVED_MASK);
|
|
}
|
|
|
|
void ResolveInfo::setOther(uint32_t pOther) {
|
|
setVisibility(static_cast<ResolveInfo::Visibility>(pOther & 0x3));
|
|
}
|
|
|
|
void ResolveInfo::setVisibility(ResolveInfo::Visibility pVisibility) {
|
|
m_BitField &= ~VISIBILITY_MASK;
|
|
m_BitField |= pVisibility << VISIBILITY_OFFSET;
|
|
}
|
|
|
|
void ResolveInfo::setIsSymbol(bool pIsSymbol) {
|
|
if (pIsSymbol)
|
|
m_BitField |= symbol_flag;
|
|
else
|
|
m_BitField &= ~symbol_flag;
|
|
}
|
|
|
|
bool ResolveInfo::isNull() const {
|
|
return (this == Null());
|
|
}
|
|
|
|
bool ResolveInfo::isDyn() const {
|
|
return (dynamic_flag == (m_BitField & DYN_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isUndef() const {
|
|
return (undefine_flag == (m_BitField & DESC_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isDefine() const {
|
|
return (define_flag == (m_BitField & DESC_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isCommon() const {
|
|
return (common_flag == (m_BitField & DESC_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isIndirect() const {
|
|
return (indirect_flag == (m_BitField & DESC_MASK));
|
|
}
|
|
|
|
// isGlobal - [L,W] == [0, 0]
|
|
bool ResolveInfo::isGlobal() const {
|
|
return (global_flag == (m_BitField & BINDING_MASK));
|
|
}
|
|
|
|
// isWeak - [L,W] == [0, 1]
|
|
bool ResolveInfo::isWeak() const {
|
|
return (weak_flag == (m_BitField & BINDING_MASK));
|
|
}
|
|
|
|
// isLocal - [L,W] == [1, 0]
|
|
bool ResolveInfo::isLocal() const {
|
|
return (local_flag == (m_BitField & BINDING_MASK));
|
|
}
|
|
|
|
// isAbsolute - [L,W] == [1, 1]
|
|
bool ResolveInfo::isAbsolute() const {
|
|
return (absolute_flag == (m_BitField & BINDING_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isSymbol() const {
|
|
return (symbol_flag == (m_BitField & SYMBOL_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isString() const {
|
|
return (string_flag == (m_BitField & SYMBOL_MASK));
|
|
}
|
|
|
|
bool ResolveInfo::isInDyn() const {
|
|
return (indyn_flag == (m_BitField & IN_DYN_MASK));
|
|
}
|
|
|
|
uint32_t ResolveInfo::type() const {
|
|
return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
|
|
}
|
|
|
|
uint32_t ResolveInfo::desc() const {
|
|
return (m_BitField & DESC_MASK) >> DESC_OFFSET;
|
|
}
|
|
|
|
uint32_t ResolveInfo::binding() const {
|
|
if (m_BitField & LOCAL_MASK) {
|
|
if (m_BitField & GLOBAL_MASK) {
|
|
return ResolveInfo::Absolute;
|
|
}
|
|
return ResolveInfo::Local;
|
|
}
|
|
return m_BitField & GLOBAL_MASK;
|
|
}
|
|
|
|
uint32_t ResolveInfo::reserved() const {
|
|
return (m_BitField & RESERVED_MASK) >> RESERVED_OFFSET;
|
|
}
|
|
|
|
ResolveInfo::Visibility ResolveInfo::visibility() const {
|
|
return static_cast<ResolveInfo::Visibility>((m_BitField & VISIBILITY_MASK) >>
|
|
VISIBILITY_OFFSET);
|
|
}
|
|
|
|
bool ResolveInfo::compare(const ResolveInfo::key_type& pKey) {
|
|
size_t length = nameSize();
|
|
if (length != pKey.size())
|
|
return false;
|
|
return (std::memcmp(m_Name, pKey.data(), length) == 0);
|
|
}
|
|
|
|
bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig) {
|
|
// forced local symbol matches all rules:
|
|
// 1. We are not doing incremental linking.
|
|
// 2. The symbol is with Hidden or Internal visibility.
|
|
// 3. The symbol should be global or weak. Otherwise, local symbol is local.
|
|
// 4. The symbol is defined or common
|
|
if (LinkerConfig::Object != pConfig.codeGenType() &&
|
|
(visibility() == ResolveInfo::Hidden ||
|
|
visibility() == ResolveInfo::Internal) &&
|
|
(isGlobal() || isWeak()) && (isDefine() || isCommon()))
|
|
return true;
|
|
return false;
|
|
}
|
|
//===----------------------------------------------------------------------===//
|
|
// ResolveInfo Factory Methods
|
|
//===----------------------------------------------------------------------===//
|
|
ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey) {
|
|
ResolveInfo* info =
|
|
static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + pKey.size() + 1));
|
|
if (info == NULL)
|
|
return NULL;
|
|
|
|
new (info) ResolveInfo(); // call constructor at the `result` address.
|
|
std::memcpy(info->m_Name, pKey.data(), pKey.size());
|
|
info->m_Name[pKey.size()] = '\0';
|
|
info->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
|
|
info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
|
|
return info;
|
|
}
|
|
|
|
void ResolveInfo::Destroy(ResolveInfo*& pInfo) {
|
|
if (pInfo->isNull())
|
|
return;
|
|
|
|
if (pInfo != NULL) {
|
|
pInfo->~ResolveInfo();
|
|
free(pInfo);
|
|
}
|
|
|
|
pInfo = NULL;
|
|
}
|
|
|
|
ResolveInfo* ResolveInfo::Null() {
|
|
if (g_NullResolveInfo == NULL) {
|
|
g_NullResolveInfo =
|
|
static_cast<ResolveInfo*>(malloc(sizeof(ResolveInfo) + 1));
|
|
new (g_NullResolveInfo) ResolveInfo();
|
|
g_NullResolveInfo->m_Name[0] = '\0';
|
|
g_NullResolveInfo->m_BitField = 0x0;
|
|
g_NullResolveInfo->setBinding(Local);
|
|
}
|
|
return g_NullResolveInfo;
|
|
}
|
|
|
|
} // namespace mcld
|