275 lines
7.2 KiB
C++
275 lines
7.2 KiB
C++
//===- 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_
|