xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceELFObjectWriter.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceELFObjectWriter.h - ELF object writer -----*- C++ -*-===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Abstraction for a writer that is responsible for writing an ELF file.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICEELFOBJECTWRITER_H
16*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICEELFOBJECTWRITER_H
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceELFSection.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceELFStreamer.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h"
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker using namespace llvm::ELF;
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
26*03ce13f7SAndroid Build Coastguard Worker 
27*03ce13f7SAndroid Build Coastguard Worker using VariableDeclarationPartition = std::vector<VariableDeclaration *>;
28*03ce13f7SAndroid Build Coastguard Worker 
29*03ce13f7SAndroid Build Coastguard Worker /// Higher level ELF object writer. Manages section information and writes the
30*03ce13f7SAndroid Build Coastguard Worker /// final ELF object. The object writer will write to file the code and data as
31*03ce13f7SAndroid Build Coastguard Worker /// it is being defined (rather than keep a copy). After all definitions are
32*03ce13f7SAndroid Build Coastguard Worker /// written out, it will finalize the bookkeeping sections and write them out.
33*03ce13f7SAndroid Build Coastguard Worker /// Expected usage:
34*03ce13f7SAndroid Build Coastguard Worker ///
35*03ce13f7SAndroid Build Coastguard Worker /// (1) writeInitialELFHeader (invoke once)
36*03ce13f7SAndroid Build Coastguard Worker /// (2) writeDataSection      (may be invoked multiple times, as long as
37*03ce13f7SAndroid Build Coastguard Worker ///                            SectionSuffix is unique)
38*03ce13f7SAndroid Build Coastguard Worker /// (3) writeFunctionCode     (must invoke once per function)
39*03ce13f7SAndroid Build Coastguard Worker /// (4) writeConstantPool     (must invoke once per pooled primitive type)
40*03ce13f7SAndroid Build Coastguard Worker /// (5) setUndefinedSyms      (invoke once)
41*03ce13f7SAndroid Build Coastguard Worker /// (6) writeNonUserSections  (invoke once)
42*03ce13f7SAndroid Build Coastguard Worker ///
43*03ce13f7SAndroid Build Coastguard Worker /// The requirement for writeDataSection to be invoked only once can be relaxed
44*03ce13f7SAndroid Build Coastguard Worker /// if using -fdata-sections. The requirement to invoke only once without
45*03ce13f7SAndroid Build Coastguard Worker /// -fdata-sections is so that variables that belong to each possible
46*03ce13f7SAndroid Build Coastguard Worker /// SectionType are contiguous in the file. With -fdata-sections, each global
47*03ce13f7SAndroid Build Coastguard Worker /// variable is in a separate section and therefore the sections will be
48*03ce13f7SAndroid Build Coastguard Worker /// trivially contiguous.
49*03ce13f7SAndroid Build Coastguard Worker class ELFObjectWriter {
50*03ce13f7SAndroid Build Coastguard Worker   ELFObjectWriter() = delete;
51*03ce13f7SAndroid Build Coastguard Worker   ELFObjectWriter(const ELFObjectWriter &) = delete;
52*03ce13f7SAndroid Build Coastguard Worker   ELFObjectWriter &operator=(const ELFObjectWriter &) = delete;
53*03ce13f7SAndroid Build Coastguard Worker 
54*03ce13f7SAndroid Build Coastguard Worker public:
55*03ce13f7SAndroid Build Coastguard Worker   ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out);
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker   /// Write the initial ELF header. This is just to reserve space in the ELF
58*03ce13f7SAndroid Build Coastguard Worker   /// file. Reserving space allows the other functions to write text and data
59*03ce13f7SAndroid Build Coastguard Worker   /// directly to the file and get the right file offsets.
60*03ce13f7SAndroid Build Coastguard Worker   void writeInitialELFHeader();
61*03ce13f7SAndroid Build Coastguard Worker 
62*03ce13f7SAndroid Build Coastguard Worker   /// Copy initializer data for globals to file and note the offset and size of
63*03ce13f7SAndroid Build Coastguard Worker   /// each global's definition in the symbol table. Use the given target's
64*03ce13f7SAndroid Build Coastguard Worker   /// RelocationKind for any relocations.
65*03ce13f7SAndroid Build Coastguard Worker   void writeDataSection(const VariableDeclarationList &Vars,
66*03ce13f7SAndroid Build Coastguard Worker                         FixupKind RelocationKind,
67*03ce13f7SAndroid Build Coastguard Worker                         const std::string &SectionSuffix, bool IsPIC);
68*03ce13f7SAndroid Build Coastguard Worker 
69*03ce13f7SAndroid Build Coastguard Worker   /// Copy data of a function's text section to file and note the offset of the
70*03ce13f7SAndroid Build Coastguard Worker   /// symbol's definition in the symbol table. Copy the text fixups for use
71*03ce13f7SAndroid Build Coastguard Worker   /// after all functions are written. The text buffer and fixups are extracted
72*03ce13f7SAndroid Build Coastguard Worker   /// from the Assembler object.
73*03ce13f7SAndroid Build Coastguard Worker   void writeFunctionCode(GlobalString FuncName, bool IsInternal,
74*03ce13f7SAndroid Build Coastguard Worker                          Assembler *Asm);
75*03ce13f7SAndroid Build Coastguard Worker 
76*03ce13f7SAndroid Build Coastguard Worker   /// Queries the GlobalContext for constant pools of the given type and writes
77*03ce13f7SAndroid Build Coastguard Worker   /// out read-only data sections for those constants. This also fills the
78*03ce13f7SAndroid Build Coastguard Worker   /// symbol table with labels for each constant pool entry.
79*03ce13f7SAndroid Build Coastguard Worker   template <typename ConstType> void writeConstantPool(Type Ty);
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker   /// Write a jump table and register fixups for the target addresses.
82*03ce13f7SAndroid Build Coastguard Worker   void writeJumpTable(const JumpTableData &JT, FixupKind RelocationKind,
83*03ce13f7SAndroid Build Coastguard Worker                       bool IsPIC);
84*03ce13f7SAndroid Build Coastguard Worker 
85*03ce13f7SAndroid Build Coastguard Worker   /// Populate the symbol table with a list of external/undefined symbols.
86*03ce13f7SAndroid Build Coastguard Worker   void setUndefinedSyms(const ConstantList &UndefSyms);
87*03ce13f7SAndroid Build Coastguard Worker 
88*03ce13f7SAndroid Build Coastguard Worker   /// Do final layout and write out the rest of the object file. Finally, patch
89*03ce13f7SAndroid Build Coastguard Worker   /// up the initial ELF header with the final info.
90*03ce13f7SAndroid Build Coastguard Worker   void writeNonUserSections();
91*03ce13f7SAndroid Build Coastguard Worker 
92*03ce13f7SAndroid Build Coastguard Worker   /// Which type of ELF section a global variable initializer belongs to. This
93*03ce13f7SAndroid Build Coastguard Worker   /// is used as an array index so should start at 0 and be contiguous.
94*03ce13f7SAndroid Build Coastguard Worker   enum SectionType { ROData = 0, Data, BSS, NumSectionTypes };
95*03ce13f7SAndroid Build Coastguard Worker 
96*03ce13f7SAndroid Build Coastguard Worker   /// Create target specific section with the given information about section.
97*03ce13f7SAndroid Build Coastguard Worker   void writeTargetRODataSection(const std::string &Name, Elf64_Word ShType,
98*03ce13f7SAndroid Build Coastguard Worker                                 Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
99*03ce13f7SAndroid Build Coastguard Worker                                 Elf64_Xword ShEntsize,
100*03ce13f7SAndroid Build Coastguard Worker                                 const llvm::StringRef &SecData);
101*03ce13f7SAndroid Build Coastguard Worker 
102*03ce13f7SAndroid Build Coastguard Worker private:
103*03ce13f7SAndroid Build Coastguard Worker   GlobalContext &Ctx;
104*03ce13f7SAndroid Build Coastguard Worker   ELFStreamer &Str;
105*03ce13f7SAndroid Build Coastguard Worker   bool SectionNumbersAssigned = false;
106*03ce13f7SAndroid Build Coastguard Worker   bool ELF64;
107*03ce13f7SAndroid Build Coastguard Worker 
108*03ce13f7SAndroid Build Coastguard Worker   // All created sections, separated into different pools.
109*03ce13f7SAndroid Build Coastguard Worker   using SectionList = std::vector<ELFSection *>;
110*03ce13f7SAndroid Build Coastguard Worker   using TextSectionList = std::vector<ELFTextSection *>;
111*03ce13f7SAndroid Build Coastguard Worker   using DataSectionList = std::vector<ELFDataSection *>;
112*03ce13f7SAndroid Build Coastguard Worker   using RelSectionList = std::vector<ELFRelocationSection *>;
113*03ce13f7SAndroid Build Coastguard Worker   TextSectionList TextSections;
114*03ce13f7SAndroid Build Coastguard Worker   RelSectionList RelTextSections;
115*03ce13f7SAndroid Build Coastguard Worker   DataSectionList DataSections;
116*03ce13f7SAndroid Build Coastguard Worker   RelSectionList RelDataSections;
117*03ce13f7SAndroid Build Coastguard Worker   DataSectionList RODataSections;
118*03ce13f7SAndroid Build Coastguard Worker   RelSectionList RelRODataSections;
119*03ce13f7SAndroid Build Coastguard Worker   DataSectionList BSSSections;
120*03ce13f7SAndroid Build Coastguard Worker 
121*03ce13f7SAndroid Build Coastguard Worker   // Handles to special sections that need incremental bookkeeping.
122*03ce13f7SAndroid Build Coastguard Worker   ELFSection *NullSection;
123*03ce13f7SAndroid Build Coastguard Worker   ELFStringTableSection *ShStrTab;
124*03ce13f7SAndroid Build Coastguard Worker   ELFSymbolTableSection *SymTab;
125*03ce13f7SAndroid Build Coastguard Worker   ELFStringTableSection *StrTab;
126*03ce13f7SAndroid Build Coastguard Worker 
127*03ce13f7SAndroid Build Coastguard Worker   template <typename T>
128*03ce13f7SAndroid Build Coastguard Worker   T *createSection(const std::string &Name, Elf64_Word ShType,
129*03ce13f7SAndroid Build Coastguard Worker                    Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
130*03ce13f7SAndroid Build Coastguard Worker                    Elf64_Xword ShEntsize);
131*03ce13f7SAndroid Build Coastguard Worker 
132*03ce13f7SAndroid Build Coastguard Worker   /// Create a relocation section, given the related section (e.g., .text,
133*03ce13f7SAndroid Build Coastguard Worker   /// .data., .rodata).
134*03ce13f7SAndroid Build Coastguard Worker   ELFRelocationSection *
135*03ce13f7SAndroid Build Coastguard Worker   createRelocationSection(const ELFSection *RelatedSection);
136*03ce13f7SAndroid Build Coastguard Worker 
137*03ce13f7SAndroid Build Coastguard Worker   /// Align the file position before writing out a section's data, and return
138*03ce13f7SAndroid Build Coastguard Worker   /// the position of the file.
139*03ce13f7SAndroid Build Coastguard Worker   Elf64_Off alignFileOffset(Elf64_Xword Align);
140*03ce13f7SAndroid Build Coastguard Worker 
141*03ce13f7SAndroid Build Coastguard Worker   /// Assign an ordering / section numbers to each section. Fill in other
142*03ce13f7SAndroid Build Coastguard Worker   /// information that is only known near the end (such as the size, if it
143*03ce13f7SAndroid Build Coastguard Worker   /// wasn't already incrementally updated). This then collects all sections in
144*03ce13f7SAndroid Build Coastguard Worker   /// the decided order, into one vector, for conveniently writing out all of
145*03ce13f7SAndroid Build Coastguard Worker   /// the section headers.
146*03ce13f7SAndroid Build Coastguard Worker   void assignSectionNumbersInfo(SectionList &AllSections);
147*03ce13f7SAndroid Build Coastguard Worker 
148*03ce13f7SAndroid Build Coastguard Worker   /// This function assigns .foo and .rel.foo consecutive section numbers. It
149*03ce13f7SAndroid Build Coastguard Worker   /// also sets the relocation section's sh_info field to the related section's
150*03ce13f7SAndroid Build Coastguard Worker   /// number.
151*03ce13f7SAndroid Build Coastguard Worker   template <typename UserSectionList>
152*03ce13f7SAndroid Build Coastguard Worker   void assignRelSectionNumInPairs(SizeT &CurSectionNumber,
153*03ce13f7SAndroid Build Coastguard Worker                                   UserSectionList &UserSections,
154*03ce13f7SAndroid Build Coastguard Worker                                   RelSectionList &RelSections,
155*03ce13f7SAndroid Build Coastguard Worker                                   SectionList &AllSections);
156*03ce13f7SAndroid Build Coastguard Worker 
157*03ce13f7SAndroid Build Coastguard Worker   /// Link the relocation sections to the symbol table.
158*03ce13f7SAndroid Build Coastguard Worker   void assignRelLinkNum(SizeT SymTabNumber, RelSectionList &RelSections);
159*03ce13f7SAndroid Build Coastguard Worker 
160*03ce13f7SAndroid Build Coastguard Worker   /// Helper function for writeDataSection. Writes a data section of type
161*03ce13f7SAndroid Build Coastguard Worker   /// SectionType, given the global variables Vars belonging to that
162*03ce13f7SAndroid Build Coastguard Worker   /// SectionType.
163*03ce13f7SAndroid Build Coastguard Worker   void writeDataOfType(SectionType SectionType,
164*03ce13f7SAndroid Build Coastguard Worker                        const VariableDeclarationPartition &Vars,
165*03ce13f7SAndroid Build Coastguard Worker                        FixupKind RelocationKind,
166*03ce13f7SAndroid Build Coastguard Worker                        const std::string &SectionSuffix, bool IsPIC);
167*03ce13f7SAndroid Build Coastguard Worker 
168*03ce13f7SAndroid Build Coastguard Worker   /// Write the final relocation sections given the final symbol table. May also
169*03ce13f7SAndroid Build Coastguard Worker   /// be able to seek around the file and resolve function calls that are for
170*03ce13f7SAndroid Build Coastguard Worker   /// functions within the same section.
171*03ce13f7SAndroid Build Coastguard Worker   void writeAllRelocationSections();
172*03ce13f7SAndroid Build Coastguard Worker   void writeRelocationSections(RelSectionList &RelSections);
173*03ce13f7SAndroid Build Coastguard Worker 
174*03ce13f7SAndroid Build Coastguard Worker   /// Write the ELF file header with the given information about sections.
175*03ce13f7SAndroid Build Coastguard Worker   template <bool IsELF64>
176*03ce13f7SAndroid Build Coastguard Worker   void writeELFHeaderInternal(Elf64_Off SectionHeaderOffset,
177*03ce13f7SAndroid Build Coastguard Worker                               SizeT SectHeaderStrIndex, SizeT NumSections);
178*03ce13f7SAndroid Build Coastguard Worker };
179*03ce13f7SAndroid Build Coastguard Worker 
180*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
181*03ce13f7SAndroid Build Coastguard Worker 
182*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICEELFOBJECTWRITER_H
183