Revert a series of commits to MCJIT to get the build working in CMake
[oota-llvm.git] / lib / ExecutionEngine / RuntimeDyld / DyldELFObject.h
1 //===-- DyldELFObject.h - Dynamically loaded ELF object  ----0---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Dynamically loaded ELF object class, a subclass of ELFObjectFile. Used
11 // to represent a loadable ELF image.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
16 #define LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
17
18 #include "llvm/Object/ELF.h"
19
20
21 namespace llvm {
22
23 using support::endianness;
24 using namespace llvm::object;
25
26 template<support::endianness target_endianness, bool is64Bits>
27 class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
28   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
29
30   typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
31   typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
32   typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
33   typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
34
35   typedef typename ELFObjectFile<target_endianness, is64Bits>::
36     Elf_Ehdr Elf_Ehdr;
37   Elf_Ehdr *Header;
38
39   // Update section headers according to the current location in memory
40   virtual void rebaseObject(std::vector<uint8_t*> *MemoryMap);
41   // Record memory addresses for cleanup
42   virtual void saveAddress(std::vector<uint8_t*> *MemoryMap, uint8_t *addr);
43
44 protected:
45   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
46
47 public:
48   DyldELFObject(MemoryBuffer *Object, std::vector<uint8_t*> *MemoryMap,
49                 error_code &ec);
50
51   // Methods for type inquiry through isa, cast, and dyn_cast
52   static inline bool classof(const Binary *v) {
53     return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
54             && classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v)));
55   }
56   static inline bool classof(
57       const ELFObjectFile<target_endianness, is64Bits> *v) {
58     return v->isDyldType();
59   }
60   static inline bool classof(const DyldELFObject *v) {
61     return true;
62   }
63 };
64
65 template<support::endianness target_endianness, bool is64Bits>
66 DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object,
67       std::vector<uint8_t*> *MemoryMap, error_code &ec)
68   : ELFObjectFile<target_endianness, is64Bits>(Object, ec)
69   , Header(0) {
70   this->isDyldELFObject = true;
71   Header = const_cast<Elf_Ehdr *>(
72       reinterpret_cast<const Elf_Ehdr *>(this->base()));
73   if (Header->e_shoff == 0)
74     return;
75
76   // Mark the image as a dynamic shared library
77   Header->e_type = ELF::ET_DYN;
78
79   rebaseObject(MemoryMap);
80 }
81
82 // Walk through the ELF headers, updating virtual addresses to reflect where
83 // the object is currently loaded in memory
84 template<support::endianness target_endianness, bool is64Bits>
85 void DyldELFObject<target_endianness, is64Bits>::rebaseObject(
86     std::vector<uint8_t*> *MemoryMap) {
87   typedef typename ELFDataTypeTypedefHelper<
88           target_endianness, is64Bits>::value_type addr_type;
89
90   uint8_t *base_p = const_cast<uint8_t *>(this->base());
91   Elf_Shdr *sectionTable =
92       reinterpret_cast<Elf_Shdr *>(base_p + Header->e_shoff);
93   uint64_t numSections = this->getNumSections();
94
95   // Allocate memory space for NOBITS sections (such as .bss), which only exist
96   // in memory, but don't occupy space in the object file.
97   // Update the address in the section headers to reflect this allocation.
98   for (uint64_t index = 0; index < numSections; index++) {
99     Elf_Shdr *sec = reinterpret_cast<Elf_Shdr *>(
100         reinterpret_cast<char *>(sectionTable) + index * Header->e_shentsize);
101
102     // Only update sections that are meant to be present in program memory
103     if (sec->sh_flags & ELF::SHF_ALLOC) {
104       uint8_t *addr = base_p + sec->sh_offset;
105       if (sec->sh_type == ELF::SHT_NOBITS) {
106         addr = static_cast<uint8_t *>(calloc(sec->sh_size, 1));
107         saveAddress(MemoryMap, addr);
108       }
109       else {
110         // FIXME: Currently memory with RWX permissions is allocated. In the
111         // future, make sure that permissions are as necessary
112         if (sec->sh_flags & ELF::SHF_WRITE) {
113             // see FIXME above
114         }
115         if (sec->sh_flags & ELF::SHF_EXECINSTR) {
116             // see FIXME above
117         }
118       }
119       assert(sizeof(addr_type) == sizeof(intptr_t) &&
120              "Cross-architecture ELF dy-load is not supported!");
121       sec->sh_addr = static_cast<addr_type>(intptr_t(addr));
122     }
123   }
124
125   // Now allocate actual space for COMMON symbols, which also don't occupy
126   // space in the object file.
127   // We want to allocate space for all COMMON symbols at once, so the flow is:
128   // 1. Go over all symbols, find those that are in COMMON. For each such
129   //    symbol, record its size and the value field in its symbol header in a
130   //    special vector.
131   // 2. Allocate memory for all COMMON symbols in one fell swoop.
132   // 3. Using the recorded information from (1), update the address fields in
133   //    the symbol headers of the COMMON symbols to reflect their allocated
134   //    address.
135   uint64_t TotalSize = 0;
136   std::vector<std::pair<Elf_Addr *, uint64_t> > SymbAddrInfo;
137   error_code ec = object_error::success;
138   for (symbol_iterator si = this->begin_symbols(),
139        se = this->end_symbols(); si != se; si.increment(ec)) {
140     uint64_t Size = 0;
141     ec = si->getSize(Size);
142     Elf_Sym* symb = const_cast<Elf_Sym*>(
143         this->getSymbol(si->getRawDataRefImpl()));
144     if (ec == object_error::success &&
145         this->getSymbolTableIndex(symb) == ELF::SHN_COMMON && Size > 0) {
146       SymbAddrInfo.push_back(std::make_pair(&(symb->st_value), Size));
147       TotalSize += Size;
148     }
149   }
150
151   uint8_t* SectionPtr = (uint8_t *)calloc(TotalSize, 1);
152   saveAddress(MemoryMap, SectionPtr);
153
154   typedef typename std::vector<std::pair<Elf_Addr *, uint64_t> >::iterator
155       AddrInfoIterator;
156   AddrInfoIterator EndIter = SymbAddrInfo.end();
157   for (AddrInfoIterator AddrIter = SymbAddrInfo.begin();
158        AddrIter != EndIter; ++AddrIter) {
159     assert(sizeof(addr_type) == sizeof(intptr_t) &&
160            "Cross-architecture ELF dy-load is not supported!");
161     *(AddrIter->first) = static_cast<addr_type>(intptr_t(SectionPtr));
162     SectionPtr += AddrIter->second;
163   }
164 }
165
166 // Record memory addresses for callers
167 template<support::endianness target_endianness, bool is64Bits>
168 void DyldELFObject<target_endianness, is64Bits>::saveAddress(
169     std::vector<uint8_t*> *MemoryMap, uint8_t* addr) {
170   if (MemoryMap)
171     MemoryMap->push_back(addr);
172   else
173     errs() << "WARNING: Memory leak - cannot record memory for ELF dyld.";
174 }
175
176 template<support::endianness target_endianness, bool is64Bits>
177 error_code DyldELFObject<target_endianness, is64Bits>::getSymbolAddress(
178     DataRefImpl Symb, uint64_t &Result) const {
179   this->validateSymbol(Symb);
180   const Elf_Sym *symb = this->getSymbol(Symb);
181   if (this->getSymbolTableIndex(symb) == ELF::SHN_COMMON) {
182     Result = symb->st_value;
183     return object_error::success;
184   }
185   else {
186     return ELFObjectFile<target_endianness, is64Bits>::getSymbolAddress(
187         Symb, Result);
188   }
189 }
190
191 }
192
193 #endif
194
195 //===-- DyldELFObject.h - Dynamically loaded ELF object  ----0---*- C++ -*-===//
196 //
197 //                     The LLVM Compiler Infrastructure
198 //
199 // This file is distributed under the University of Illinois Open Source
200 // License. See LICENSE.TXT for details.
201 //
202 //===----------------------------------------------------------------------===//
203 //
204 // Dynamically loaded ELF object class, a subclass of ELFObjectFile. Used
205 // to represent a loadable ELF image.
206 //
207 //===----------------------------------------------------------------------===//
208
209 #ifndef LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
210 #define LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
211
212 #include "llvm/Object/ELF.h"
213
214
215 namespace llvm {
216
217 using support::endianness;
218 using namespace llvm::object;
219
220 template<support::endianness target_endianness, bool is64Bits>
221 class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
222   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
223
224   typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
225   typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
226   typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
227   typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
228
229   typedef typename ELFObjectFile<target_endianness, is64Bits>::
230     Elf_Ehdr Elf_Ehdr;
231   Elf_Ehdr *Header;
232
233   // Update section headers according to the current location in memory
234   virtual void rebaseObject(std::vector<uint8_t*> *MemoryMap);
235   // Record memory addresses for cleanup
236   virtual void saveAddress(std::vector<uint8_t*> *MemoryMap, uint8_t *addr);
237
238 protected:
239   virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
240
241 public:
242   DyldELFObject(MemoryBuffer *Object, std::vector<uint8_t*> *MemoryMap,
243                 error_code &ec);
244
245   // Methods for type inquiry through isa, cast, and dyn_cast
246   static inline bool classof(const Binary *v) {
247     return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
248             && classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v)));
249   }
250   static inline bool classof(
251       const ELFObjectFile<target_endianness, is64Bits> *v) {
252     return v->isDyldType();
253   }
254   static inline bool classof(const DyldELFObject *v) {
255     return true;
256   }
257 };
258
259 template<support::endianness target_endianness, bool is64Bits>
260 DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object,
261       std::vector<uint8_t*> *MemoryMap, error_code &ec)
262   : ELFObjectFile<target_endianness, is64Bits>(Object, ec)
263   , Header(0) {
264   this->isDyldELFObject = true;
265   Header = const_cast<Elf_Ehdr *>(
266       reinterpret_cast<const Elf_Ehdr *>(this->base()));
267   if (Header->e_shoff == 0)
268     return;
269
270   // Mark the image as a dynamic shared library
271   Header->e_type = ELF::ET_DYN;
272
273   rebaseObject(MemoryMap);
274 }
275
276 // Walk through the ELF headers, updating virtual addresses to reflect where
277 // the object is currently loaded in memory
278 template<support::endianness target_endianness, bool is64Bits>
279 void DyldELFObject<target_endianness, is64Bits>::rebaseObject(
280     std::vector<uint8_t*> *MemoryMap) {
281   typedef typename ELFDataTypeTypedefHelper<
282           target_endianness, is64Bits>::value_type addr_type;
283
284   uint8_t *base_p = const_cast<uint8_t *>(this->base());
285   Elf_Shdr *sectionTable =
286       reinterpret_cast<Elf_Shdr *>(base_p + Header->e_shoff);
287   uint64_t numSections = this->getNumSections();
288
289   // Allocate memory space for NOBITS sections (such as .bss), which only exist
290   // in memory, but don't occupy space in the object file.
291   // Update the address in the section headers to reflect this allocation.
292   for (uint64_t index = 0; index < numSections; index++) {
293     Elf_Shdr *sec = reinterpret_cast<Elf_Shdr *>(
294         reinterpret_cast<char *>(sectionTable) + index * Header->e_shentsize);
295
296     // Only update sections that are meant to be present in program memory
297     if (sec->sh_flags & ELF::SHF_ALLOC) {
298       uint8_t *addr = base_p + sec->sh_offset;
299       if (sec->sh_type == ELF::SHT_NOBITS) {
300         addr = static_cast<uint8_t *>(calloc(sec->sh_size, 1));
301         saveAddress(MemoryMap, addr);
302       }
303       else {
304         // FIXME: Currently memory with RWX permissions is allocated. In the
305         // future, make sure that permissions are as necessary
306         if (sec->sh_flags & ELF::SHF_WRITE) {
307             // see FIXME above
308         }
309         if (sec->sh_flags & ELF::SHF_EXECINSTR) {
310             // see FIXME above
311         }
312       }
313       assert(sizeof(addr_type) == sizeof(intptr_t) &&
314              "Cross-architecture ELF dy-load is not supported!");
315       sec->sh_addr = static_cast<addr_type>(intptr_t(addr));
316     }
317   }
318
319   // Now allocate actual space for COMMON symbols, which also don't occupy
320   // space in the object file.
321   // We want to allocate space for all COMMON symbols at once, so the flow is:
322   // 1. Go over all symbols, find those that are in COMMON. For each such
323   //    symbol, record its size and the value field in its symbol header in a
324   //    special vector.
325   // 2. Allocate memory for all COMMON symbols in one fell swoop.
326   // 3. Using the recorded information from (1), update the address fields in
327   //    the symbol headers of the COMMON symbols to reflect their allocated
328   //    address.
329   uint64_t TotalSize = 0;
330   std::vector<std::pair<Elf_Addr *, uint64_t> > SymbAddrInfo;
331   error_code ec = object_error::success;
332   for (symbol_iterator si = this->begin_symbols(),
333        se = this->end_symbols(); si != se; si.increment(ec)) {
334     uint64_t Size = 0;
335     ec = si->getSize(Size);
336     Elf_Sym* symb = const_cast<Elf_Sym*>(
337         this->getSymbol(si->getRawDataRefImpl()));
338     if (ec == object_error::success &&
339         this->getSymbolTableIndex(symb) == ELF::SHN_COMMON && Size > 0) {
340       SymbAddrInfo.push_back(std::make_pair(&(symb->st_value), Size));
341       TotalSize += Size;
342     }
343   }
344
345   uint8_t* SectionPtr = (uint8_t *)calloc(TotalSize, 1);
346   saveAddress(MemoryMap, SectionPtr);
347
348   typedef typename std::vector<std::pair<Elf_Addr *, uint64_t> >::iterator
349       AddrInfoIterator;
350   AddrInfoIterator EndIter = SymbAddrInfo.end();
351   for (AddrInfoIterator AddrIter = SymbAddrInfo.begin();
352        AddrIter != EndIter; ++AddrIter) {
353     assert(sizeof(addr_type) == sizeof(intptr_t) &&
354            "Cross-architecture ELF dy-load is not supported!");
355     *(AddrIter->first) = static_cast<addr_type>(intptr_t(SectionPtr));
356     SectionPtr += AddrIter->second;
357   }
358 }
359
360 // Record memory addresses for callers
361 template<support::endianness target_endianness, bool is64Bits>
362 void DyldELFObject<target_endianness, is64Bits>::saveAddress(
363     std::vector<uint8_t*> *MemoryMap, uint8_t* addr) {
364   if (MemoryMap)
365     MemoryMap->push_back(addr);
366   else
367     errs() << "WARNING: Memory leak - cannot record memory for ELF dyld.";
368 }
369
370 template<support::endianness target_endianness, bool is64Bits>
371 error_code DyldELFObject<target_endianness, is64Bits>::getSymbolAddress(
372     DataRefImpl Symb, uint64_t &Result) const {
373   this->validateSymbol(Symb);
374   const Elf_Sym *symb = this->getSymbol(Symb);
375   if (this->getSymbolTableIndex(symb) == ELF::SHN_COMMON) {
376     Result = symb->st_value;
377     return object_error::success;
378   }
379   else {
380     return ELFObjectFile<target_endianness, is64Bits>::getSymbolAddress(
381         Symb, Result);
382   }
383 }
384
385 }
386
387 #endif
388