blob: 329a4369899aa65b74a3a9d37d5774ac15053b09 [file] [log] [blame]
//===- ResolveInfo.h ------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_LD_RESOLVEINFO_H_
#define MCLD_LD_RESOLVEINFO_H_
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/DataTypes.h>
namespace mcld {
class LDSymbol;
class LinkerConfig;
/** \class ResolveInfo
* \brief ResolveInfo records the information about how to resolve a symbol.
*
* A symbol must have some `attributes':
* - Desc - Defined, Reference, Common or Indirect
* - Binding - Global, Local, Weak
* - IsDyn - appear in dynamic objects or regular objects
* - Type - what the symbol refers to
* - Size - the size of the symbol point to
* - Value - the pointer to another LDSymbol
* In order to save the memory and speed up the performance, FragmentLinker
*uses
* a bit field to store all attributes.
*
* The maximum string length is (2^16 - 1)
*/
class ResolveInfo {
friend class FragmentLinker;
friend class IRBuilder;
public:
typedef uint64_t SizeType;
/** \enum Type
* \brief What the symbol stand for
*
* It is like ELF32_ST_TYPE
* MachO does not need this, and can not jump between Thumb and ARM code.
*/
enum Type {
NoType = 0,
Object = 1,
Function = 2,
Section = 3,
File = 4,
CommonBlock = 5,
ThreadLocal = 6,
IndirectFunc = 10,
LoProc = 13,
HiProc = 15
};
/** \enum Desc
* \brief Description of the symbols.
*
* Follow the naming in MachO. Like MachO nlist::n_desc
* In ELF, is a part of st_shndx
*/
enum Desc { Undefined = 0, Define = 1, Common = 2, Indirect = 3, NoneDesc };
enum Binding { Global = 0, Weak = 1, Local = 2, Absolute = 3, NoneBinding };
enum Visibility { Default = 0, Internal = 1, Hidden = 2, Protected = 3 };
// ----- For HashTable ----- //
typedef llvm::StringRef key_type;
public:
// ----- factory method ----- //
static ResolveInfo* Create(const key_type& pKey);
static void Destroy(ResolveInfo*& pInfo);
static ResolveInfo* Null();
// ----- modifiers ----- //
/// setRegular - set the source of the file is a regular object
void setRegular();
/// setDynamic - set the source of the file is a dynamic object
void setDynamic();
/// setSource - set the source of the file
/// @param pIsDyn is the source from a dynamic object?
void setSource(bool pIsDyn);
void setType(uint32_t pType);
void setDesc(uint32_t pDesc);
void setBinding(uint32_t pBinding);
void setOther(uint32_t pOther);
void setVisibility(Visibility pVisibility);
void setIsSymbol(bool pIsSymbol);
void setReserved(uint32_t pReserved);
void setSize(SizeType pSize) { m_Size = pSize; }
void override(const ResolveInfo& pForm);
void overrideAttributes(const ResolveInfo& pFrom);
void overrideVisibility(const ResolveInfo& pFrom);
void setSymPtr(const LDSymbol* pSymPtr) {
m_Ptr.sym_ptr = const_cast<LDSymbol*>(pSymPtr);
}
void setLink(const ResolveInfo* pTarget) {
m_Ptr.info_ptr = const_cast<ResolveInfo*>(pTarget);
m_BitField |= indirect_flag;
}
/// setInDyn - set if the symbol has been seen in the dynamic objects. Once
/// InDyn set, then it won't be set back to false
void setInDyn();
// ----- observers ----- //
bool isNull() const;
bool isSymbol() const;
bool isString() const;
bool isGlobal() const;
bool isWeak() const;
bool isLocal() const;
bool isAbsolute() const;
bool isDefine() const;
bool isUndef() const;
bool isDyn() const;
bool isCommon() const;
bool isIndirect() const;
bool isInDyn() const;
uint32_t type() const;
uint32_t desc() const;
uint32_t binding() const;
uint32_t reserved() const;
uint8_t other() const { return (uint8_t)visibility(); }
Visibility visibility() const;
LDSymbol* outSymbol() { return m_Ptr.sym_ptr; }
const LDSymbol* outSymbol() const { return m_Ptr.sym_ptr; }
ResolveInfo* link() { return m_Ptr.info_ptr; }
const ResolveInfo* link() const { return m_Ptr.info_ptr; }
SizeType size() const { return m_Size; }
const char* name() const { return m_Name; }
unsigned int nameSize() const { return (m_BitField >> NAME_LENGTH_OFFSET); }
uint32_t info() const { return (m_BitField & INFO_MASK); }
uint32_t bitfield() const { return m_BitField; }
// shouldForceLocal - check if this symbol should be forced to local
bool shouldForceLocal(const LinkerConfig& pConfig);
// ----- For HashTable ----- //
bool compare(const key_type& pKey);
private:
static const uint32_t GLOBAL_OFFSET = 0;
static const uint32_t GLOBAL_MASK = 1;
static const uint32_t DYN_OFFSET = 1;
static const uint32_t DYN_MASK = 1 << DYN_OFFSET;
static const uint32_t DESC_OFFSET = 2;
static const uint32_t DESC_MASK = 0x3 << DESC_OFFSET;
static const uint32_t LOCAL_OFFSET = 4;
static const uint32_t LOCAL_MASK = 1 << LOCAL_OFFSET;
static const uint32_t BINDING_MASK = GLOBAL_MASK | LOCAL_MASK;
static const uint32_t VISIBILITY_OFFSET = 5;
static const uint32_t VISIBILITY_MASK = 0x3 << VISIBILITY_OFFSET;
static const uint32_t TYPE_OFFSET = 7;
static const uint32_t TYPE_MASK = 0xF << TYPE_OFFSET;
static const uint32_t SYMBOL_OFFSET = 11;
static const uint32_t SYMBOL_MASK = 1 << SYMBOL_OFFSET;
static const uint32_t RESERVED_OFFSET = 12;
static const uint32_t RESERVED_MASK = 0xF << RESERVED_OFFSET;
static const uint32_t IN_DYN_OFFSET = 16;
static const uint32_t IN_DYN_MASK = 1 << IN_DYN_OFFSET;
static const uint32_t NAME_LENGTH_OFFSET = 17;
static const uint32_t INFO_MASK = 0xF;
static const uint32_t RESOLVE_MASK = 0xFFFF;
union SymOrInfo {
LDSymbol* sym_ptr;
ResolveInfo* info_ptr;
};
public:
static const uint32_t global_flag = 0 << GLOBAL_OFFSET;
static const uint32_t weak_flag = 1 << GLOBAL_OFFSET;
static const uint32_t regular_flag = 0 << DYN_OFFSET;
static const uint32_t dynamic_flag = 1 << DYN_OFFSET;
static const uint32_t undefine_flag = 0 << DESC_OFFSET;
static const uint32_t define_flag = 1 << DESC_OFFSET;
static const uint32_t common_flag = 2 << DESC_OFFSET;
static const uint32_t indirect_flag = 3 << DESC_OFFSET;
static const uint32_t local_flag = 1 << LOCAL_OFFSET;
static const uint32_t absolute_flag = BINDING_MASK;
static const uint32_t object_flag = Object << TYPE_OFFSET;
static const uint32_t function_flag = Function << TYPE_OFFSET;
static const uint32_t section_flag = Section << TYPE_OFFSET;
static const uint32_t file_flag = File << TYPE_OFFSET;
static const uint32_t string_flag = 0 << SYMBOL_OFFSET;
static const uint32_t symbol_flag = 1 << SYMBOL_OFFSET;
static const uint32_t indyn_flag = 1 << IN_DYN_OFFSET;
private:
ResolveInfo();
ResolveInfo(const ResolveInfo& pCopy);
ResolveInfo& operator=(const ResolveInfo& pCopy);
~ResolveInfo();
private:
SizeType m_Size;
SymOrInfo m_Ptr;
/** m_BitField
* 31 ... 17 16 15 12 11 10..7 6 .. 5 4 3 2
* 1 0
* |length of m_Name|InDyn|reserved|Symbol|Type |ELF
* visibility|Local|Com|Def|Dyn|Weak|
*/
uint32_t m_BitField;
char m_Name[];
};
} // namespace mcld
#endif // MCLD_LD_RESOLVEINFO_H_