Chromium Code Reviews| 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. |