1 //===-- DyldELFObject.h - Dynamically loaded ELF object ----0---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Dynamically loaded ELF object class, a subclass of ELFObjectFile. Used
11 // to represent a loadable ELF image.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
16 #define LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
18 #include "llvm/Object/ELF.h"
23 using support::endianness;
24 using namespace llvm::object;
26 template<support::endianness target_endianness, bool is64Bits>
27 class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
28 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
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;
35 typedef typename ELFObjectFile<target_endianness, is64Bits>::
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);
45 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
48 DyldELFObject(MemoryBuffer *Object, std::vector<uint8_t*> *MemoryMap,
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)));
56 static inline bool classof(
57 const ELFObjectFile<target_endianness, is64Bits> *v) {
58 return v->isDyldType();
60 static inline bool classof(const DyldELFObject *v) {
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)
70 this->isDyldELFObject = true;
71 Header = const_cast<Elf_Ehdr *>(
72 reinterpret_cast<const Elf_Ehdr *>(this->base()));
73 if (Header->e_shoff == 0)
76 // Mark the image as a dynamic shared library
77 Header->e_type = ELF::ET_DYN;
79 rebaseObject(MemoryMap);
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;
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();
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);
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);
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) {
115 if (sec->sh_flags & ELF::SHF_EXECINSTR) {
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));
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
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
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)) {
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));
151 uint8_t* SectionPtr = (uint8_t *)calloc(TotalSize, 1);
152 saveAddress(MemoryMap, SectionPtr);
154 typedef typename std::vector<std::pair<Elf_Addr *, uint64_t> >::iterator
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;
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) {
171 MemoryMap->push_back(addr);
173 errs() << "WARNING: Memory leak - cannot record memory for ELF dyld.";
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;
186 return ELFObjectFile<target_endianness, is64Bits>::getSymbolAddress(
195 //===-- DyldELFObject.h - Dynamically loaded ELF object ----0---*- C++ -*-===//
197 // The LLVM Compiler Infrastructure
199 // This file is distributed under the University of Illinois Open Source
200 // License. See LICENSE.TXT for details.
202 //===----------------------------------------------------------------------===//
204 // Dynamically loaded ELF object class, a subclass of ELFObjectFile. Used
205 // to represent a loadable ELF image.
207 //===----------------------------------------------------------------------===//
209 #ifndef LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
210 #define LLVM_RUNTIMEDYLD_DYLDELFOBJECT_H
212 #include "llvm/Object/ELF.h"
217 using support::endianness;
218 using namespace llvm::object;
220 template<support::endianness target_endianness, bool is64Bits>
221 class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
222 LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
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;
229 typedef typename ELFObjectFile<target_endianness, is64Bits>::
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);
239 virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const;
242 DyldELFObject(MemoryBuffer *Object, std::vector<uint8_t*> *MemoryMap,
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)));
250 static inline bool classof(
251 const ELFObjectFile<target_endianness, is64Bits> *v) {
252 return v->isDyldType();
254 static inline bool classof(const DyldELFObject *v) {
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)
264 this->isDyldELFObject = true;
265 Header = const_cast<Elf_Ehdr *>(
266 reinterpret_cast<const Elf_Ehdr *>(this->base()));
267 if (Header->e_shoff == 0)
270 // Mark the image as a dynamic shared library
271 Header->e_type = ELF::ET_DYN;
273 rebaseObject(MemoryMap);
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;
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();
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);
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);
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) {
309 if (sec->sh_flags & ELF::SHF_EXECINSTR) {
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));
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
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
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)) {
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));
345 uint8_t* SectionPtr = (uint8_t *)calloc(TotalSize, 1);
346 saveAddress(MemoryMap, SectionPtr);
348 typedef typename std::vector<std::pair<Elf_Addr *, uint64_t> >::iterator
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;
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) {
365 MemoryMap->push_back(addr);
367 errs() << "WARNING: Memory leak - cannot record memory for ELF dyld.";
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;
380 return ELFObjectFile<target_endianness, is64Bits>::getSymbolAddress(