//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements ELF object file writer information.
//
//===----------------------------------------------------------------------===//
#include "llvm/MC/ELFObjectWriter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCELFSymbolFlags.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ELF.h"
#include "llvm/Target/TargetAsmBackend.h"
#include "../Target/X86/X86FixupKinds.h"
#include <vector>
using namespace llvm;
namespace {
class ELFObjectWriterImpl {
static bool isFixupKindX86PCRel(unsigned Kind) {
switch (Kind) {
default:
return false;
case X86::reloc_pcrel_1byte:
case X86::reloc_pcrel_4byte:
case X86::reloc_riprel_4byte:
case X86::reloc_riprel_4byte_movq_load:
return true;
}
}
/*static bool isFixupKindX86RIPRel(unsigned Kind) {
return Kind == X86::reloc_riprel_4byte ||
Kind == X86::reloc_riprel_4byte_movq_load;
}*/
/// ELFSymbolData - Helper struct for containing some precomputed information
/// on symbols.
struct ELFSymbolData {
MCSymbolData *SymbolData;
uint64_t StringIndex;
uint32_t SectionIndex;
// Support lexicographic sorting.
bool operator<(const ELFSymbolData &RHS) const {
return SymbolData->getSymbol().getName() <
RHS.SymbolData->getSymbol().getName();
}
};
/// @name Relocation Data
/// @{
struct ELFRelocationEntry {
// Make these big enough for both 32-bit and 64-bit
uint64_t r_offset;
uint64_t r_info;
uint64_t r_addend;
// Support lexicographic sorting.
bool operator<(const ELFRelocationEntry &RE) const {
return RE.r_offset < r_offset;
}
};
llvm::DenseMap<const MCSectionData*,
std::vector<ELFRelocationEntry> > Relocations;
DenseMap<const MCSection*, uint64_t> SectionStringTableIndex;
/// @}
/// @name Symbol Table Data
/// @{
SmallString<256> StringTable;
std::vector<ELFSymbolData> LocalSymbolData;
std::vector<ELFSymbolData> ExternalSymbolData;
std::vector<ELFSymbolData> UndefinedSymbolData;
/// @}
ELFObjectWriter *Writer;
raw_ostream &OS;
// This holds the current offset into the object file.
size_t FileOff;
unsigned Is64Bit : 1;
bool HasRelocationAddend;
// This holds the symbol table index of the last local symbol.
unsigned LastLocalSymbolIndex;
// This holds the .strtab section index.
unsigned StringTableIndex;
unsigned ShstrtabIndex;
public:
ELFObjectWriterImpl(ELFObjectWriter *_Writer, bool _Is64Bit,
bool _HasRelAddend)
: Writer(_Writer), OS(Writer->getStream()), FileOff(0),
Is64Bit(_Is64Bit), HasRelocationAddend(_HasRelAddend) {
}
void Write8(uint8_t Value) { Writer->Write8(Value); }
void Write16(uint16_t Value) { Writer->Write16(Value); }
void Write32(uint32_t Value) { Writer->Write32(Value); }
//void Write64(uint64_t Value) { Writer->Write64(Value); }
void WriteZeros(unsigned N) { Writer->WriteZeros(N); }
//void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
// Writer->WriteBytes(Str, ZeroFillSize);
//}
void WriteWord(uint64_t W) {
if (Is64Bit)
Writer->Write64(W);
else
Writer->Write32(W);
}
void String8(char *buf, uint8_t Value) {
buf[0] = Value;
}
void StringLE16(char *buf, uint16_t Value) {
buf[0] = char(Value >> 0);
buf[1] = char(Value >> 8);
}
void StringLE32(char *buf, uint32_t Value) {
StringLE16(buf, uint16_t(Value >> 0));
StringLE16(buf + 2, uint16_t(Value >> 16));
}
void StringLE64(char *buf, uint64_t Value) {
StringLE32(buf, uint32_t(Value >> 0));
StringLE32(buf