//===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ELFObjectFile class.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include <limits>
#include <utility>
using namespace llvm;
using namespace object;
// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
namespace {
template<support::endianness target_endianness>
struct ELFDataTypeTypedefHelperCommon {
typedef support::detail::packed_endian_specific_integral
<uint16_t, target_endianness, support::aligned> Elf_Half;
typedef support::detail::packed_endian_specific_integral
<uint32_t, target_endianness, support::aligned> Elf_Word;
typedef support::detail::packed_endian_specific_integral
<int32_t, target_endianness, support::aligned> Elf_Sword;
typedef support::detail::packed_endian_specific_integral
<uint64_t, target_endianness, support::aligned> Elf_Xword;
typedef support::detail::packed_endian_specific_integral
<int64_t, target_endianness, support::aligned> Elf_Sxword;
};
}
namespace {
template<support::endianness target_endianness, bool is64Bits>
struct ELFDataTypeTypedefHelper;
/// ELF 32bit types.
template<support::endianness target_endianness>
struct ELFDataTypeTypedefHelper<target_endianness, false>
: ELFDataTypeTypedefHelperCommon<target_endianness> {
typedef support::detail::packed_endian_specific_integral
<uint32_t, target_endianness, support::aligned> Elf_Addr;
typedef support::detail::packed_endian_specific_integral
<uint32_t, target_endianness, support::aligned> Elf_Off;
};
/// ELF 64bit types.
template<support::endianness target_endianness>
struct ELFDataTypeTypedefHelper<target_endianness, true>
: ELFDataTypeTypedefHelperCommon<target_endianness>{
typedef support::detail::packed_endian_specific_integral
<uint64_t, target_endianness, support::aligned> Elf_Addr;
typedef support::detail::packed_endian_specific_integral
<uint64_t, target_endianness, support::aligned> Elf_Off;
};
}
// I really don't like doing this, but the alternative is copypasta.
#define LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits) \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Addr Elf_Addr; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Off Elf_Off; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Half Elf_Half; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Word Elf_Word; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sword Elf_Sword; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Xword Elf_Xword; \
typedef typename \
ELFDataTypeTypedefHelper<target_endianness, is64Bits>::Elf_Sxword Elf_Sxword;
// Section header.
namespace {
template<support::endianness target_endianness, bool is64Bits>
struct Elf_Shdr_Base;
template<support::endianness target_endianness>
struct Elf_Shdr_Base<target_endianness, false> {
LLVM_ELF_IMPORT_TYPES(target_endianness, false)
Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*)
Elf_Word sh_flags; // Section flags (SHF_*)
Elf_Addr sh_addr; // Address where section is to be loaded
Elf_Off sh_offset; // File offset of section data, in bytes
Elf_Word sh_size; // Size of section, in bytes
Elf_Word sh_link; // Section type-specific header table index link
Elf_Word sh_info; // Section type-specific extra information
Elf_Word sh_addralign;// Section address alignment
Elf_Word sh_entsize; // Size of records contained within the section
};
template<support::endianness target_endianness>
struct Elf_Shdr_Base<target_endianness, true> {
LLVM_ELF_IMPORT_TYPES(target_endianness, true)
Elf_Word sh_name; // Section name (index into string table)
Elf_Word sh_type; // Section type (SHT_*)
Elf_Xword sh_flags; // Section flags (SHF_*)
Elf_Addr sh_addr; // Address where section is to be loaded
Elf_Off sh_offset; // File offset of section data, in bytes
Elf_Xword sh_size; // Size of section, in bytes
Elf_Word sh_link; // Section type-specific header table index link
Elf_Word sh_info; // Section type-specific extra information
Elf_Xword sh_addralign;// Section address alignment