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