Skip to content

Commit 28fcafb

Browse files
author
Jim Grosbach
committed
Refactor MachO relocation generaration into the Target directories.
Move the target-specific RecordRelocation logic out of the generic MC MachObjectWriter and into the target-specific object writers. This allows nuking quite a bit of target knowledge from the supposedly target-independent bits in lib/MC. llvm-svn: 133844
1 parent a81d2af commit 28fcafb

File tree

5 files changed

+1096
-985
lines changed

5 files changed

+1096
-985
lines changed

llvm/include/llvm/MC/MCMachObjectWriter.h

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@
1010
#ifndef LLVM_MC_MCMACHOBJECTWRITER_H
1111
#define LLVM_MC_MCMACHOBJECTWRITER_H
1212

13+
#include "llvm/ADT/DenseMap.h"
14+
#include "llvm/ADT/OwningPtr.h"
15+
#include "llvm/ADT/SmallString.h"
16+
#include "llvm/MC/MCExpr.h"
1317
#include "llvm/MC/MCObjectWriter.h"
18+
#include "llvm/Object/MachOFormat.h"
1419
#include "llvm/Support/DataTypes.h"
20+
#include <vector>
1521

1622
namespace llvm {
1723

24+
class MCSectionData;
25+
class MachObjectWriter;
26+
1827
class MCMachObjectTargetWriter {
1928
const unsigned Is64Bit : 1;
2029
const uint32_t CPUType;
@@ -48,8 +57,191 @@ class MCMachObjectTargetWriter {
4857
}
4958

5059
/// @}
60+
61+
/// @name API
62+
/// @{
63+
64+
virtual void RecordRelocation(MachObjectWriter *Writer,
65+
const MCAssembler &Asm,
66+
const MCAsmLayout &Layout,
67+
const MCFragment *Fragment,
68+
const MCFixup &Fixup,
69+
MCValue Target,
70+
uint64_t &FixedValue) = 0;
71+
72+
/// @}
5173
};
5274

75+
class MachObjectWriter : public MCObjectWriter {
76+
/// MachSymbolData - Helper struct for containing some precomputed information
77+
/// on symbols.
78+
struct MachSymbolData {
79+
MCSymbolData *SymbolData;
80+
uint64_t StringIndex;
81+
uint8_t SectionIndex;
82+
83+
// Support lexicographic sorting.
84+
bool operator<(const MachSymbolData &RHS) const;
85+
};
86+
87+
/// The target specific Mach-O writer instance.
88+
llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter;
89+
90+
/// @name Relocation Data
91+
/// @{
92+
93+
llvm::DenseMap<const MCSectionData*,
94+
std::vector<object::macho::RelocationEntry> > Relocations;
95+
llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
96+
97+
/// @}
98+
/// @name Symbol Table Data
99+
/// @{
100+
101+
SmallString<256> StringTable;
102+
std::vector<MachSymbolData> LocalSymbolData;
103+
std::vector<MachSymbolData> ExternalSymbolData;
104+
std::vector<MachSymbolData> UndefinedSymbolData;
105+
106+
/// @}
107+
108+
public:
109+
MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
110+
bool _IsLittleEndian)
111+
: MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
112+
}
113+
114+
/// @name Utility Methods
115+
/// @{
116+
117+
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
118+
119+
SectionAddrMap SectionAddress;
120+
121+
SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
122+
123+
uint64_t getSectionAddress(const MCSectionData* SD) const {
124+
return SectionAddress.lookup(SD);
125+
}
126+
uint64_t getSymbolAddress(const MCSymbolData* SD,
127+
const MCAsmLayout &Layout) const;
128+
129+
uint64_t getFragmentAddress(const MCFragment *Fragment,
130+
const MCAsmLayout &Layout) const;
131+
132+
uint64_t getPaddingSize(const MCSectionData *SD,
133+
const MCAsmLayout &Layout) const;
134+
135+
bool doesSymbolRequireExternRelocation(const MCSymbolData *SD);
136+
137+
/// @}
138+
139+
/// @name Target Writer Proxy Accessors
140+
/// @{
141+
142+
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
143+
bool isARM() const {
144+
uint32_t CPUType = TargetObjectWriter->getCPUType() &
145+
~object::mach::CTFM_ArchMask;
146+
return CPUType == object::mach::CTM_ARM;
147+
}
148+
149+
/// @}
150+
151+
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
152+
bool SubsectionsViaSymbols);
153+
154+
/// WriteSegmentLoadCommand - Write a segment load command.
155+
///
156+
/// \arg NumSections - The number of sections in this segment.
157+
/// \arg SectionDataSize - The total size of the sections.
158+
void WriteSegmentLoadCommand(unsigned NumSections,
159+
uint64_t VMSize,
160+
uint64_t SectionDataStartOffset,
161+
uint64_t SectionDataSize);
162+
163+
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
164+
const MCSectionData &SD, uint64_t FileOffset,
165+
uint64_t RelocationsStart, unsigned NumRelocations);
166+
167+
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
168+
uint32_t StringTableOffset,
169+
uint32_t StringTableSize);
170+
171+
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
172+
uint32_t NumLocalSymbols,
173+
uint32_t FirstExternalSymbol,
174+
uint32_t NumExternalSymbols,
175+
uint32_t FirstUndefinedSymbol,
176+
uint32_t NumUndefinedSymbols,
177+
uint32_t IndirectSymbolOffset,
178+
uint32_t NumIndirectSymbols);
179+
180+
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
181+
182+
// FIXME: We really need to improve the relocation validation. Basically, we
183+
// want to implement a separate computation which evaluates the relocation
184+
// entry as the linker would, and verifies that the resultant fixup value is
185+
// exactly what the encoder wanted. This will catch several classes of
186+
// problems:
187+
//
188+
// - Relocation entry bugs, the two algorithms are unlikely to have the same
189+
// exact bug.
190+
//
191+
// - Relaxation issues, where we forget to relax something.
192+
//
193+
// - Input errors, where something cannot be correctly encoded. 'as' allows
194+
// these through in many cases.
195+
196+
void addRelocation(const MCSectionData *SD,
197+
object::macho::RelocationEntry &MRE) {
198+
Relocations[SD].push_back(MRE);
199+
}
200+
201+
void RecordScatteredRelocation(const MCAssembler &Asm,
202+
const MCAsmLayout &Layout,
203+
const MCFragment *Fragment,
204+
const MCFixup &Fixup, MCValue Target,
205+
unsigned Log2Size,
206+
uint64_t &FixedValue);
207+
208+
void RecordTLVPRelocation(const MCAssembler &Asm,
209+
const MCAsmLayout &Layout,
210+
const MCFragment *Fragment,
211+
const MCFixup &Fixup, MCValue Target,
212+
uint64_t &FixedValue);
213+
214+
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
215+
const MCFragment *Fragment, const MCFixup &Fixup,
216+
MCValue Target, uint64_t &FixedValue);
217+
218+
void BindIndirectSymbols(MCAssembler &Asm);
219+
220+
/// ComputeSymbolTable - Compute the symbol table data
221+
///
222+
/// \param StringTable [out] - The string table data.
223+
/// \param StringIndexMap [out] - Map from symbol names to offsets in the
224+
/// string table.
225+
void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
226+
std::vector<MachSymbolData> &LocalSymbolData,
227+
std::vector<MachSymbolData> &ExternalSymbolData,
228+
std::vector<MachSymbolData> &UndefinedSymbolData);
229+
230+
void computeSectionAddresses(const MCAssembler &Asm,
231+
const MCAsmLayout &Layout);
232+
233+
void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout);
234+
235+
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
236+
const MCSymbolData &DataA,
237+
const MCFragment &FB,
238+
bool InSet,
239+
bool IsPCRel) const;
240+
241+
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout);
242+
};
243+
244+
53245
/// \brief Construct a new Mach-O writer instance.
54246
///
55247
/// This routine takes ownership of the target writer subclass.

0 commit comments

Comments
 (0)