• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ELF_SECTION_REL_TABLE_HXX
18 #define ELF_SECTION_REL_TABLE_HXX
19 
20 #include "ELF.h"
21 #include "ELFHeader.h"
22 #include "ELFObject.h"
23 #include "ELFReloc.h"
24 #include "ELFTypes.h"
25 
26 #include <set>
27 
28 template <unsigned Bitwidth>
~ELFSectionRelTable()29 ELFSectionRelTable<Bitwidth>::~ELFSectionRelTable() {
30   using namespace std;
31   for (size_t i = 0; i < table.size(); ++i) {
32     delete table[i];
33   }
34 }
35 
36 template <unsigned Bitwidth>
print() const37 void ELFSectionRelTable<Bitwidth>::print() const {
38   using namespace llvm;
39 
40   out() << '\n' << fillformat('=', 79) << '\n';
41   out().changeColor(raw_ostream::WHITE, true);
42   out() << "Relocation Table" << '\n';
43   out().resetColor();
44 
45   for (size_t i = 0; i < this->size(); ++i) {
46     (*this)[i]->print();
47   }
48 
49   out() << fillformat('=', 79) << '\n';
50 }
51 
52 template <unsigned Bitwidth>
53 template <typename Archiver>
54 ELFSectionRelTable<Bitwidth> *
read(Archiver & AR,ELFSectionHeaderTy const * sh)55 ELFSectionRelTable<Bitwidth>::read(Archiver &AR,
56                                    ELFSectionHeaderTy const *sh) {
57 
58   rsl_assert(sh->getType() == SHT_REL || sh->getType() == SHT_RELA);
59 
60   std::unique_ptr<ELFSectionRelTable> rt(new ELFSectionRelTable());
61 
62   // Seek to the start of the table
63   AR.seek(sh->getOffset(), true);
64 
65   // Count the relocation entries
66   size_t size = sh->getSize() / sh->getEntrySize();
67 
68   // Read every relocation entries
69   if (sh->getType() == SHT_REL) {
70     rsl_assert(sh->getEntrySize() == TypeTraits<ELFRelocRelTy>::size);
71     for (size_t i = 0; i < size; ++i) {
72       rt->table.push_back(ELFRelocTy::readRel(AR, i));
73     }
74 
75   } else {
76     rsl_assert(sh->getEntrySize() == TypeTraits<ELFRelocRelaTy>::size);
77     for (size_t i = 0; i < size; ++i) {
78       rt->table.push_back(ELFRelocTy::readRela(AR, i));
79     }
80   }
81 
82   if (!AR) {
83     // Unable to read the table.
84     return 0;
85   }
86 
87   return rt.release();
88 }
89 
90 template <unsigned Bitwidth>
91 size_t ELFSectionRelTable<Bitwidth>::
getMaxNumStubs(ELFObjectTy const * obj) const92 getMaxNumStubs(ELFObjectTy const *obj) const {
93   switch (obj->getHeader()->getMachine()) {
94   case EM_ARM:
95     {
96       std::set<uint32_t> sym_index_set;
97 
98       for (size_t i = 0; i < size(); ++i) {
99         ELFRelocTy *rel = table[i];
100 
101         switch (rel->getType()) {
102         case R_ARM_CALL:
103         case R_ARM_THM_CALL:
104         case R_ARM_JUMP24:
105         case R_ARM_THM_JUMP24:
106           sym_index_set.insert(rel->getSymTabIndex());
107           break;
108         }
109       }
110 
111       return sym_index_set.size();
112     }
113 
114   case EM_AARCH64:
115     {
116       std::set<uint32_t> sym_index_set;
117 
118       for (size_t i = 0; i < size(); ++i) {
119         ELFRelocTy *rel = table[i];
120 
121         switch (rel->getType()) {
122         case R_AARCH64_CALL26:
123         case R_AARCH64_JUMP26:
124           sym_index_set.insert(rel->getSymTabIndex());
125           break;
126         }
127       }
128 
129       return sym_index_set.size();
130     }
131 
132   case EM_MIPS:
133     {
134       std::set<uint32_t> sym_index_set;
135 
136       for (size_t i = 0; i < size(); ++i) {
137         ELFRelocTy *rel = table[i];
138 
139         if (rel->getType() == R_MIPS_26) {
140           sym_index_set.insert(rel->getSymTabIndex());
141         }
142       }
143 
144       return sym_index_set.size();
145     }
146 
147   case EM_386:
148   case EM_X86_64:
149     return 0;
150 
151   default:
152     rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
153     return 0;
154   }
155 }
156 
157 #endif // ELF_SECTION_REL_TABLE_HXX
158