15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFReader.h --------------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#ifndef MCLD_LD_ELFREADER_H_ 1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#define MCLD_LD_ELFREADER_H_ 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFReaderIf.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h" 165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/StringRef.h> 185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h> 195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/Host.h> 20cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaonamespace mcld { 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 23d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liaoclass IRBuilder; 2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoclass LDSection; 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass SectionData; 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/** \class ELFReader 286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines * \brief ELFReader is a template scaffolding for partial specification. 296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines */ 3037b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <size_t BIT, bool LITTLEENDIAN> 3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass ELFReader {}; 326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/** \class ELFReader<32, true> 346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines * \brief ELFReader<32, true> is a 32-bit, little endian ELFReader. 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 3637b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <> 3737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass ELFReader<32, true> : public ELFReaderIF { 3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf32_Ehdr ELFHeader; 406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf32_Shdr SectionHeader; 4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines typedef llvm::ELF::Elf32_Sym Symbol; 4237b74a387bb3993387029859c2d9d051c41c724eStephen Hines typedef llvm::ELF::Elf32_Rel Rel; 436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf32_Rela Rela; 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines explicit ELFReader(GNULDBackend& pBackend); 476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ~ELFReader(); 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// ELFHeaderSize - return the size of the ELFHeader 5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines size_t getELFHeaderSize() const { return sizeof(ELFHeader); } 525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isELF - is this a ELF file 5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isELF(const void* pELFHeader) const; 555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isMyEndian - is this ELF file in the same endian to me? 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isMyEndian(const void* pELFHeader) const; 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isMyMachine - is this ELF file generated for the same machine. 6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isMyMachine(const void* pELFHeader) const; 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// fileType - the file type of this file 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Input::Type fileType(const void* pELFHeader) const; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readSectionHeaders - read ELF section header table and create LDSections 6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool readSectionHeaders(Input& pInput, const void* pELFHeader) const; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRegularSection - read a regular section and create fragments. 696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool readRegularSection(Input& pInput, SectionData& pSD) const; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readSymbols - read ELF symbols and create LDSymbol 726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool readSymbols(Input& pInput, 736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion, 756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const char* StrTab) const; 765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao /// readSignature - read a symbol from the given Input and index in symtab 7867e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao /// This is used to get the signature of a group section. 796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* readSignature(Input& pInput, 8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& pSymTab, 8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t pSymIdx) const; 825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRela - read ELF rela and create Relocation 846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool readRela(Input& pInput, 856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection, 8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion) const; 875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRel - read ELF rel and create Relocation 896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool readRel(Input& pInput, 906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection, 9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion) const; 92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /// readDynamic - read ELF .dynamic in input dynobj 946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines bool readDynamic(Input& pInput) const; 95f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines private: 97f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines struct AliasInfo { 9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol* pt_alias; /// potential alias 99f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t ld_value; 100f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Binding ld_binding; 101f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines }; 102f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 103f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines /// comparison function to sort symbols for analyzing weak alias. 104f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines /// sort symbols by symbol value and then weak before strong. 105f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines static bool less(AliasInfo p1, AliasInfo p2) { 106f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (p1.ld_value != p2.ld_value) 107f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return (p1.ld_value < p2.ld_value); 108f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (p1.ld_binding != p2.ld_binding) { 10937b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (ResolveInfo::Weak == p1.ld_binding) 110f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 11137b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (ResolveInfo::Weak == p2.ld_binding) 112f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return false; 113f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 114f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return p1.pt_alias->str() < p2.pt_alias->str(); 115f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/** \class ELFReader<64, true> 1196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines * \brief ELFReader<64, true> is a 64-bit, little endian ELFReader. 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao */ 12137b74a387bb3993387029859c2d9d051c41c724eStephen Hinestemplate <> 12237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesclass ELFReader<64, true> : public ELFReaderIF { 12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 1246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf64_Ehdr ELFHeader; 1256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf64_Shdr SectionHeader; 12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines typedef llvm::ELF::Elf64_Sym Symbol; 12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines typedef llvm::ELF::Elf64_Rel Rel; 1286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines typedef llvm::ELF::Elf64_Rela Rela; 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines public: 13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines explicit ELFReader(GNULDBackend& pBackend); 1325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ~ELFReader(); 1345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// ELFHeaderSize - return the size of the ELFHeader 13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines size_t getELFHeaderSize() const { return sizeof(ELFHeader); } 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isELF - is this a ELF file 13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isELF(const void* pELFHeader) const; 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isMyEndian - is this ELF file in the same endian to me? 14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isMyEndian(const void* pELFHeader) const; 1435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// isMyMachine - is this ELF file generated for the same machine. 14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool isMyMachine(const void* pELFHeader) const; 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// fileType - the file type of this file 14887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines Input::Type fileType(const void* pELFHeader) const; 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readSectionHeaders - read ELF section header table and create LDSections 15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines bool readSectionHeaders(Input& pInput, const void* pELFHeader) const; 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRegularSection - read a regular section and create fragments. 15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool readRegularSection(Input& pInput, SectionData& pSD) const; 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readSymbols - read ELF symbols and create LDSymbol 15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool readSymbols(Input& pInput, 158d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao IRBuilder& pBuilder, 15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion, 160d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao const char* StrTab) const; 1615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao /// readSignature - read a symbol from the given Input and index in symtab 16367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao /// This is used to get the signature of a group section. 16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ResolveInfo* readSignature(Input& pInput, 16587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines LDSection& pSymTab, 16687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines uint32_t pSymIdx) const; 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRela - read ELF rela and create Relocation 16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool readRela(Input& pInput, 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& pSection, 17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion) const; 1725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /// readRel - read ELF rel and create Relocation 17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool readRel(Input& pInput, 17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& pSection, 17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef pRegion) const; 177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 178affc150dc44fab1911775a49636d0ce85333b634Zonr Chang /// readDynamic - read ELF .dynamic in input dynobj 17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool readDynamic(Input& pInput) const; 180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 18137b74a387bb3993387029859c2d9d051c41c724eStephen Hines private: 182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines struct AliasInfo { 18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines LDSymbol* pt_alias; /// potential alias 184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines uint64_t ld_value; 185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines ResolveInfo::Binding ld_binding; 186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines }; 187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines 188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines /// comparison function to sort symbols for analyzing weak alias. 189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines /// sort symbols by symbol value and then weak before strong. 190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines static bool less(AliasInfo p1, AliasInfo p2) { 191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (p1.ld_value != p2.ld_value) 192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return (p1.ld_value < p2.ld_value); 193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines if (p1.ld_binding != p2.ld_binding) { 19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (ResolveInfo::Weak == p1.ld_binding) 195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return true; 19637b74a387bb3993387029859c2d9d051c41c724eStephen Hines else if (ResolveInfo::Weak == p2.ld_binding) 197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return false; 198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines return p1.pt_alias->str() < p2.pt_alias->str(); 200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines } 2015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}; 2025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 204affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#endif // MCLD_LD_ELFREADER_H_ 206