Index: src/IceELFObjectWriter.h |
diff --git a/src/IceELFObjectWriter.h b/src/IceELFObjectWriter.h |
index 9f468cb05ed5efaec6defbccced13d84cd35e67e..6bc42b7d61cc5b56277069a6b784973b43258fa0 100644 |
--- a/src/IceELFObjectWriter.h |
+++ b/src/IceELFObjectWriter.h |
@@ -29,10 +29,23 @@ namespace Ice { |
// After all definitions are written out, it will finalize the bookkeeping |
// sections and write them out. Expected usage: |
// |
-// (1) writeInitialELFHeader |
-// (2) writeDataInitializer* |
-// (3) writeFunctionCode* |
-// (4) writeNonUserSections |
+// (1) writeInitialELFHeader (invoke once) |
+// (2) writeDataSection (invoke once) |
+// (3) writeFunctionCode (may invoke once per function) |
Jim Stichnoth
2015/01/28 20:35:08
Why "may"? Just based on the method signature, it
jvoung (off chromium)
2015/01/28 23:37:53
Done. Hmm yes =)
|
+// (4) writeConstantPool (may invoke once per type) |
Jim Stichnoth
2015/01/28 20:35:08
"(invoke at most once per primitive type)"
Would
jvoung (off chromium)
2015/01/28 23:37:53
Yes, or how about "must invoke once per pooled pri
Jim Stichnoth
2015/01/29 00:38:14
I agree - my main purpose of data-sections was to
|
+// (5) writeNonUserSections (invoke once) |
+// |
+// The requirement for writeDataSection to be invoked only once can |
+// be relaxed if using -fdata-sections. The requirement to invoke only once |
+// without -fdata-sections is so that variables that belong to each possible |
+// SectionType are contiguous in the file. With -fdata-sections, each global |
+// variable is in a separate section and therefore the sections will be |
+// trivially contiguous. |
+// |
+// The motivation for requiring that writeFunctionCode happen after |
+// writeDataSection: to keep the .text and .data sections contiguous in the |
+// file. Having both -fdata-sections and -ffunction-sections does allow |
+// relaxing this requirement. |
class ELFObjectWriter { |
ELFObjectWriter(const ELFObjectWriter &) = delete; |
ELFObjectWriter &operator=(const ELFObjectWriter &) = delete; |
@@ -45,26 +58,37 @@ public: |
// and data directly to the file and get the right file offsets. |
void writeInitialELFHeader(); |
+ // Copy initializer data for globals to file and note the offset and size |
+ // of each global's definition in the symbol table. |
+ // Use the given target's RelocationKind for any relocations. |
+ void writeDataSection(const VariableDeclarationList &Vars, |
+ FixupKind RelocationKind); |
+ |
// Copy data of a function's text section to file and note the offset of the |
// symbol's definition in the symbol table. |
// Copy the text fixups for use after all functions are written. |
+ // The text buffer and fixups are extracted from the Assembler object. |
void writeFunctionCode(const IceString &FuncName, bool IsInternal, |
const Assembler *Asm); |
- // Copy initializer data for a global to file and note the offset and |
- // size of the global's definition in the symbol table. |
- // TODO(jvoung): This needs to know which section. This also needs the |
- // relocations to hook them up to the symbol table references. Also |
- // TODO is handling BSS (which just needs to note the size). |
- void writeDataInitializer(const IceString &VarName, |
- const llvm::StringRef Data); |
- |
+ // Queries the GlobalContext for constant pools of the given type |
+ // and writes out read-only data sections for those constants. This also |
+ // fills the symbol table with labels for each constant pool entry. |
template <typename ConstType> void writeConstantPool(Type Ty); |
- // Do final layout and write out the rest of the object file, then |
- // patch up the initial ELF header with the final info. |
+ // Do final layout and write out the rest of the object file. |
+ // Finally, patch up the initial ELF header with the final info. |
void writeNonUserSections(); |
+ // Which type of ELF section a global variable initializer belongs to. |
+ enum SectionType { |
+ BaseSectionType = 0, |
+ ROData = BaseSectionType, |
+ Data, |
+ BSS, |
+ NumSectionTypes |
+ }; |
+ |
private: |
GlobalContext &Ctx; |
ELFStreamer &Str; |
@@ -79,8 +103,9 @@ private: |
RelSectionList RelTextSections; |
DataSectionList DataSections; |
RelSectionList RelDataSections; |
- DataSectionList RoDataSections; |
- RelSectionList RelRoDataSections; |
+ DataSectionList RODataSections; |
+ RelSectionList RelRODataSections; |
+ DataSectionList BSSSections; |
// Handles to special sections that need incremental bookkeeping. |
ELFSection *NullSection; |
@@ -93,6 +118,11 @@ private: |
Elf64_Xword ShFlags, Elf64_Xword ShAddralign, |
Elf64_Xword ShEntsize); |
+ // Create a relocation section, given the related section |
+ // (e.g., .text, .data., .rodata). |
+ ELFRelocationSection * |
+ createRelocationSection(bool IsELF64, const ELFSection *RelatedSection); |
+ |
// Align the file position before writing out a section's data, |
// and return the position of the file. |
Elf64_Off alignFileOffset(Elf64_Xword Align); |
@@ -116,6 +146,12 @@ private: |
// Link the relocation sections to the symbol table. |
void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections); |
+ // Helper function for writeDataSection. Writes a data section of type |
+ // SectionType, given the global variables Vars belonging to that SectionType. |
+ void writeDataOfType(SectionType SectionType, |
+ const VariableDeclarationList &Vars, |
+ FixupKind RelocationKind, bool IsELF64); |
+ |
// Write the final relocation sections given the final symbol table. |
// May also be able to seek around the file and resolve function calls |
// that are for functions within the same section. |