/*
* Copyright 2011, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ELF_OBJECT_H
#define ELF_OBJECT_H
#include "ELFTypes.h"
#include "MemChunk.h"
#include "utils/rsl_assert.h"
#include <memory>
#include <string>
#include <vector>
template <unsigned Bitwidth>
class ELFObject {
public:
ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
private:
std::unique_ptr<ELFHeaderTy> header;
std::unique_ptr<ELFSectionHeaderTableTy> shtab;
std::vector<ELFSectionTy *> stab;
MemChunk SHNCommonData;
unsigned char *SHNCommonDataPtr;
size_t SHNCommonDataFreeSize;
bool missingSymbols;
// TODO: Need refactor!
bool initSHNCommonDataSize(size_t SHNCommonDataSize) {
rsl_assert(!SHNCommonDataPtr && "Can't init twice.");
if (!SHNCommonData.allocate(SHNCommonDataSize)) {
return false;
}
SHNCommonDataPtr = SHNCommonData.getBuffer();
SHNCommonDataFreeSize = SHNCommonDataSize;
return true;
}
private:
ELFObject() : SHNCommonDataPtr(NULL), missingSymbols(false) { }
public:
template <typename Archiver>
static ELFObject *read(Archiver &AR);
ELFHeaderTy const *getHeader() const {
return header.get();
}
ELFSectionHeaderTableTy const *getSectionHeaderTable() const {
return shtab.get();
}
char const *getSectionName(size_t i) const;
ELFSectionTy const *getSectionByIndex(size_t i) const;
ELFSectionTy *getSectionByIndex(size_t i);
ELFSectionTy const *getSectionByName(std::string const &str) const;
ELFSectionTy *getSectionByName(std::string const &str);
inline bool getMissingSymbols() const {
return missingSymbols;
}
void *allocateSHNCommonData(size_t size, size_t align = 1) {
rsl_assert(size > 0 && align != 0);
rsl_assert(SHNCommonDataPtr && "Must init common data size before use!");
// Ensure alignment
size_t rem = ((uintptr_t)SHNCommonDataPtr) % align;
if (rem != 0) {
SHNCommonDataPtr += align - rem;
SHNCommonDataFreeSize -= align - rem;
}
// Ensure the free size is sufficient
if (SHNCommonDataFreeSize < size) {
return NULL;
}
// Allcoate
void *result = SHNCommonDataPtr;
SHNCommonDataPtr += size;
SHNCommonDataFreeSize -= size;
return result;
}
void relocate(void *(*find_sym)(void *context, char const *name),
void *context);
void print() const;
~ELFObject() {
for (size_t i = 0; i < stab.size(); ++i) {
// Delete will check the pointer is nullptr or not by himself.
delete stab[i];
}
}
private:
void relocateARM(void *(*find_sym)(void *context, char const *name),
void *context,
ELFSectionRelTableTy *reltab,
ELFSectionProgBitsTy *text);
void relocateAARCH64(void *(*find_sym)(void *context, char const *name),
void *context,
ELFSectionRelTableTy *reltab,
ELFSectionProgBitsTy *text);
void relocateX86_32(void *(*find_sym)(void *context, char const *name),
void *context,
ELFSectionRelTableTy *reltab,
ELFSectionProgBitsTy *text);
void relocateX86_64(void *(*find_sym)(void *context, char const *name),
void *context,
ELFSectionRelTableTy *reltab,
ELFSectionProgBitsTy *text);
void relocateMIPS(void *(*find_sym)(void *context, char const *name),
void *context,
ELFSectionRelTableTy *reltab,
ELFSectionProgBitsTy *text);
};
#include "impl/ELFObject.hxx"
#endif // ELF_OBJECT_H