LLVM API Documentation
00001 //===-- llvm/MC/MCMachObjectWriter.h - Mach Object Writer -------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #ifndef LLVM_MC_MCMACHOBJECTWRITER_H 00011 #define LLVM_MC_MCMACHOBJECTWRITER_H 00012 00013 #include "llvm/ADT/DenseMap.h" 00014 #include "llvm/ADT/OwningPtr.h" 00015 #include "llvm/ADT/SmallString.h" 00016 #include "llvm/MC/MCExpr.h" 00017 #include "llvm/MC/MCObjectWriter.h" 00018 #include "llvm/Object/MachOFormat.h" 00019 #include "llvm/Support/DataTypes.h" 00020 #include <vector> 00021 00022 namespace llvm { 00023 00024 class MCSectionData; 00025 class MachObjectWriter; 00026 00027 class MCMachObjectTargetWriter { 00028 const unsigned Is64Bit : 1; 00029 const uint32_t CPUType; 00030 const uint32_t CPUSubtype; 00031 // FIXME: Remove this, we should just always use it once we no longer care 00032 // about Darwin 'as' compatibility. 00033 const unsigned UseAggressiveSymbolFolding : 1; 00034 unsigned LocalDifference_RIT; 00035 00036 protected: 00037 MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_, 00038 uint32_t CPUSubtype_, 00039 bool UseAggressiveSymbolFolding_ = false); 00040 00041 void setLocalDifferenceRelocationType(unsigned Type) { 00042 LocalDifference_RIT = Type; 00043 } 00044 00045 public: 00046 virtual ~MCMachObjectTargetWriter(); 00047 00048 /// @name Lifetime Management 00049 /// @{ 00050 00051 virtual void reset() {}; 00052 00053 /// @} 00054 00055 /// @name Accessors 00056 /// @{ 00057 00058 bool is64Bit() const { return Is64Bit; } 00059 bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; } 00060 uint32_t getCPUType() const { return CPUType; } 00061 uint32_t getCPUSubtype() const { return CPUSubtype; } 00062 unsigned getLocalDifferenceRelocationType() const { 00063 return LocalDifference_RIT; 00064 } 00065 00066 /// @} 00067 00068 /// @name API 00069 /// @{ 00070 00071 virtual void RecordRelocation(MachObjectWriter *Writer, 00072 const MCAssembler &Asm, 00073 const MCAsmLayout &Layout, 00074 const MCFragment *Fragment, 00075 const MCFixup &Fixup, 00076 MCValue Target, 00077 uint64_t &FixedValue) = 0; 00078 00079 /// @} 00080 }; 00081 00082 class MachObjectWriter : public MCObjectWriter { 00083 /// MachSymbolData - Helper struct for containing some precomputed information 00084 /// on symbols. 00085 struct MachSymbolData { 00086 MCSymbolData *SymbolData; 00087 uint64_t StringIndex; 00088 uint8_t SectionIndex; 00089 00090 // Support lexicographic sorting. 00091 bool operator<(const MachSymbolData &RHS) const; 00092 }; 00093 00094 /// The target specific Mach-O writer instance. 00095 llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter; 00096 00097 /// @name Relocation Data 00098 /// @{ 00099 00100 llvm::DenseMap<const MCSectionData*, 00101 std::vector<object::macho::RelocationEntry> > Relocations; 00102 llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase; 00103 00104 /// @} 00105 /// @name Symbol Table Data 00106 /// @{ 00107 00108 SmallString<256> StringTable; 00109 std::vector<MachSymbolData> LocalSymbolData; 00110 std::vector<MachSymbolData> ExternalSymbolData; 00111 std::vector<MachSymbolData> UndefinedSymbolData; 00112 00113 /// @} 00114 00115 public: 00116 MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, 00117 bool _IsLittleEndian) 00118 : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) { 00119 } 00120 00121 /// @name Lifetime management Methods 00122 /// @{ 00123 00124 virtual void reset(); 00125 00126 /// @} 00127 00128 /// @name Utility Methods 00129 /// @{ 00130 00131 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); 00132 00133 SectionAddrMap SectionAddress; 00134 00135 SectionAddrMap &getSectionAddressMap() { return SectionAddress; } 00136 00137 uint64_t getSectionAddress(const MCSectionData* SD) const { 00138 return SectionAddress.lookup(SD); 00139 } 00140 uint64_t getSymbolAddress(const MCSymbolData* SD, 00141 const MCAsmLayout &Layout) const; 00142 00143 uint64_t getFragmentAddress(const MCFragment *Fragment, 00144 const MCAsmLayout &Layout) const; 00145 00146 uint64_t getPaddingSize(const MCSectionData *SD, 00147 const MCAsmLayout &Layout) const; 00148 00149 bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); 00150 00151 /// @} 00152 00153 /// @name Target Writer Proxy Accessors 00154 /// @{ 00155 00156 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } 00157 bool isARM() const { 00158 uint32_t CPUType = TargetObjectWriter->getCPUType() & 00159 ~object::mach::CTFM_ArchMask; 00160 return CPUType == object::mach::CTM_ARM; 00161 } 00162 00163 /// @} 00164 00165 void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize, 00166 bool SubsectionsViaSymbols); 00167 00168 /// WriteSegmentLoadCommand - Write a segment load command. 00169 /// 00170 /// \param NumSections The number of sections in this segment. 00171 /// \param SectionDataSize The total size of the sections. 00172 void WriteSegmentLoadCommand(unsigned NumSections, 00173 uint64_t VMSize, 00174 uint64_t SectionDataStartOffset, 00175 uint64_t SectionDataSize); 00176 00177 void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout, 00178 const MCSectionData &SD, uint64_t FileOffset, 00179 uint64_t RelocationsStart, unsigned NumRelocations); 00180 00181 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols, 00182 uint32_t StringTableOffset, 00183 uint32_t StringTableSize); 00184 00185 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol, 00186 uint32_t NumLocalSymbols, 00187 uint32_t FirstExternalSymbol, 00188 uint32_t NumExternalSymbols, 00189 uint32_t FirstUndefinedSymbol, 00190 uint32_t NumUndefinedSymbols, 00191 uint32_t IndirectSymbolOffset, 00192 uint32_t NumIndirectSymbols); 00193 00194 void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout); 00195 00196 void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset, 00197 uint32_t DataSize); 00198 00199 void WriteLinkerOptionsLoadCommand(const std::vector<std::string> &Options); 00200 00201 // FIXME: We really need to improve the relocation validation. Basically, we 00202 // want to implement a separate computation which evaluates the relocation 00203 // entry as the linker would, and verifies that the resultant fixup value is 00204 // exactly what the encoder wanted. This will catch several classes of 00205 // problems: 00206 // 00207 // - Relocation entry bugs, the two algorithms are unlikely to have the same 00208 // exact bug. 00209 // 00210 // - Relaxation issues, where we forget to relax something. 00211 // 00212 // - Input errors, where something cannot be correctly encoded. 'as' allows 00213 // these through in many cases. 00214 00215 void addRelocation(const MCSectionData *SD, 00216 object::macho::RelocationEntry &MRE) { 00217 Relocations[SD].push_back(MRE); 00218 } 00219 00220 void RecordScatteredRelocation(const MCAssembler &Asm, 00221 const MCAsmLayout &Layout, 00222 const MCFragment *Fragment, 00223 const MCFixup &Fixup, MCValue Target, 00224 unsigned Log2Size, 00225 uint64_t &FixedValue); 00226 00227 void RecordTLVPRelocation(const MCAssembler &Asm, 00228 const MCAsmLayout &Layout, 00229 const MCFragment *Fragment, 00230 const MCFixup &Fixup, MCValue Target, 00231 uint64_t &FixedValue); 00232 00233 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, 00234 const MCFragment *Fragment, const MCFixup &Fixup, 00235 MCValue Target, uint64_t &FixedValue); 00236 00237 void BindIndirectSymbols(MCAssembler &Asm); 00238 00239 /// ComputeSymbolTable - Compute the symbol table data 00240 /// 00241 /// \param StringTable [out] - The string table data. 00242 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, 00243 std::vector<MachSymbolData> &LocalSymbolData, 00244 std::vector<MachSymbolData> &ExternalSymbolData, 00245 std::vector<MachSymbolData> &UndefinedSymbolData); 00246 00247 void computeSectionAddresses(const MCAssembler &Asm, 00248 const MCAsmLayout &Layout); 00249 00250 void markAbsoluteVariableSymbols(MCAssembler &Asm, 00251 const MCAsmLayout &Layout); 00252 void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); 00253 00254 virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 00255 const MCSymbolData &DataA, 00256 const MCFragment &FB, 00257 bool InSet, 00258 bool IsPCRel) const; 00259 00260 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); 00261 }; 00262 00263 00264 /// \brief Construct a new Mach-O writer instance. 00265 /// 00266 /// This routine takes ownership of the target writer subclass. 00267 /// 00268 /// \param MOTW - The target specific Mach-O writer subclass. 00269 /// \param OS - The stream to write to. 00270 /// \returns The constructed object writer. 00271 MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, 00272 raw_ostream &OS, bool IsLittleEndian); 00273 00274 } // End llvm namespace 00275 00276 #endif