From 320181576e3fba72792d8db130e771a2c31939e3 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 27 Jun 2005 06:28:45 +0000 Subject: [PATCH] iniital checkin of ELFWriter header. For now, the elf writer is only capable of emitting an empty elf file, with a section table and a section table string table. This will be enhanced in the future :) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22290 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/ELFWriter.h | 174 +++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 include/llvm/CodeGen/ELFWriter.h diff --git a/include/llvm/CodeGen/ELFWriter.h b/include/llvm/CodeGen/ELFWriter.h new file mode 100644 index 00000000000..3f53702aaaa --- /dev/null +++ b/include/llvm/CodeGen/ELFWriter.h @@ -0,0 +1,174 @@ +//===-- ELFWriter.h - Target-independent ELF writer support -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ELFWriter class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ELFWRITER_H +#define LLVM_CODEGEN_ELFWRITER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + class GlobalVariable; + + /// ELFWriter - This class implements the common target-independent code for + /// writing ELF files. Targets should derive a class from this to + /// parameterize the output format. + /// + class ELFWriter : public MachineFunctionPass { + protected: + ELFWriter(std::ostream &O, TargetMachine &TM); + + /// Output stream to send the resultant object file to. + /// + std::ostream &O; + + /// Target machine description. + /// + TargetMachine &TM; + + //===------------------------------------------------------------------===// + // Properties to be set by the derived class ctor, used to configure the + // ELFWriter. + + // e_machine - This field is the target specific value to emit as the + // e_machine member of the ELF header. + unsigned short e_machine; + + // e_flags - The machine flags for the target. This defaults to zero. + unsigned e_flags; + + //===------------------------------------------------------------------===// + // Properties inferred automatically from the target machine. + // + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating whether to emit a 32- or 64-bit ELF file. + bool is64Bit, isLittleEndian; + + /// doInitialization - Emit the file header and all of the global variables + /// for the module to the ELF file. + bool doInitialization(Module &M); + + bool runOnMachineFunction(MachineFunction &MF); + + + /// doFinalization - Now that the module has been completely processed, emit + /// the ELF file to 'O'. + bool doFinalization(Module &M); + + private: + // The buffer we are accumulating the file into. Note that this should be + // changed into something much more efficient later (and the bytecode writer + // as well!). + std::vector OutputBuffer; + + /// ELFSection - This struct contains information about each section that is + /// emitted to the OutputBuffer. This is eventually turned into the section + /// header table at the end of the file. + struct ELFSection { + std::string Name; // Name of the section. + unsigned NameIdx; // Index in .shstrtab of name, once emitted. + unsigned Type; + unsigned Flags; + uint64_t Addr; + unsigned Offset; + unsigned Size; + unsigned Link; + unsigned Info; + unsigned Align; + unsigned EntSize; + ELFSection() : Type(0), Flags(0), Addr(0), Offset(0), Size(0), Link(0), + Info(0), Align(0), EntSize(0) { + } + ELFSection(const char *name, unsigned offset) + : Name(name), Type(0), Flags(0), Addr(0), Offset(offset), Size(0), + Link(0), Info(0), Align(0), EntSize(0) { + } + }; + + /// SectionList - This is the list of sections that we have emitted to the + /// file. Once the file has been completely built, the section header table + /// is constructed from this info. + std::vector SectionList; + + // As we accumulate the ELF file into OutputBuffer, we occasionally need to + // keep track of locations to update later (e.g. the location of the section + // table in the ELF header. These members keep track of the offset in + // OffsetBuffer of these various pieces to update and other locations in the + // file. + unsigned ELFHeader_e_shoff_Offset; // e_shoff in ELF header. + unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header. + unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header. + + void outbyte(unsigned char X) { OutputBuffer.push_back(X); } + void outhalf(unsigned short X) { + if (isLittleEndian) { + OutputBuffer.push_back(X&255); + OutputBuffer.push_back(X >> 8); + } else { + OutputBuffer.push_back(X >> 8); + OutputBuffer.push_back(X&255); + } + } + void outword(unsigned X) { + if (isLittleEndian) { + OutputBuffer.push_back((X >> 0) & 255); + OutputBuffer.push_back((X >> 8) & 255); + OutputBuffer.push_back((X >> 16) & 255); + OutputBuffer.push_back((X >> 24) & 255); + } else { + OutputBuffer.push_back((X >> 24) & 255); + OutputBuffer.push_back((X >> 16) & 255); + OutputBuffer.push_back((X >> 8) & 255); + OutputBuffer.push_back((X >> 0) & 255); + } + } + void outaddr(uint64_t X) { + if (!is64Bit) + outword((unsigned)X); + else + assert(0 && "Emission of 64-bit data not implemented yet!"); + } + + // fix functions - Replace an existing entry at an offset. + void fixhalf(unsigned short X, unsigned Offset) { + unsigned char *P = &OutputBuffer[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; + } + + void fixword(unsigned X, unsigned Offset) { + unsigned char *P = &OutputBuffer[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; + } + + void fixaddr(uint64_t X, unsigned Offset) { + if (!is64Bit) + fixword((unsigned)X, Offset); + else + assert(0 && "Emission of 64-bit data not implemented yet!"); + } + + private: + void EmitDATASectionGlobal(GlobalVariable *GV); + void EmitBSSSectionGlobal(GlobalVariable *GV); + void EmitGlobal(GlobalVariable *GV); + + void EmitSectionTableStringTable(); + void EmitSectionTable(); + }; +} + +#endif