Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1435)

Side by Side Diff: src/IceELFSection.h

Issue 678533005: Subzero: Add basic ELFObjectWriter (text section, symtab, strtab, headers) (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: minor cleanup Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceELFObjectWriter.cpp ('k') | src/IceELFSection.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/src/IceELFSection.h - Model of ELF sections ------*- C++ -*-===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Representation of ELF sections.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef SUBZERO_SRC_ICEELFSECTION_H
15 #define SUBZERO_SRC_ICEELFSECTION_H
16
17 #include "IceDefs.h"
18 #include "IceELFStreamer.h"
19
20 using namespace llvm::ELF;
21
22 namespace Ice {
23
24 class ELFStreamer;
25 class ELFStringTableSection;
26
27 // Base representation of an ELF section.
28 class ELFSection {
29 ELFSection(const ELFSection &) = delete;
30 ELFSection &operator=(const ELFSection &) = delete;
31
32 public:
33 // Sentinel value for a section number/index for before the final
34 // section index is actually known. The dummy NULL section will be assigned
35 // number 0, and it is referenced by the dummy 0-th symbol in the symbol
36 // table, so use max() instead of 0.
37 enum { NoSectionNumber = std::numeric_limits<SizeT>::max() };
38
39 // Constructs an ELF section, filling in fields that will be known
40 // once the *type* of section is decided. Other fields may be updated
41 // incrementally or only after the program is completely defined.
42 ELFSection(const IceString &Name, Elf64_Word ShType, Elf64_Xword ShFlags,
43 Elf64_Xword ShAddralign, Elf64_Xword ShEntsize)
44 : Name(Name), Header(), Number(NoSectionNumber) {
45 Header.sh_type = ShType;
46 Header.sh_flags = ShFlags;
47 Header.sh_addralign = ShAddralign;
48 Header.sh_entsize = ShEntsize;
49 }
50
51 // Set the section number/index after it is finally known.
52 void setNumber(SizeT N) {
53 // Should only set the number once: from NoSectionNumber -> N.
54 assert(Number == NoSectionNumber);
55 Number = N;
56 }
57 SizeT getNumber() const {
58 assert(Number != NoSectionNumber);
59 return Number;
60 }
61
62 void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; }
63 SizeT getCurrentSize() const { return Header.sh_size; }
64
65 void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; }
66
67 IceString getName() const { return Name; }
68
69 void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; }
70
71 void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; }
72
73 void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; }
74
75 Elf64_Xword getSectionAlign() const { return Header.sh_addralign; }
76
77 // Write the section header out with the given streamer.
78 template <bool IsELF64> void writeHeader(ELFStreamer &Str);
79
80 protected:
81 ~ELFSection() {}
82
83 // Name of the section in convenient string form (instead of a index
84 // into the Section Header String Table, which is not known till later).
85 IceString Name;
86
87 // The fields of the header. May only be partially initialized, but should
88 // be fully initialized before writing.
89 Elf64_Shdr Header;
90
91 // The number of the section after laying out sections.
92 SizeT Number;
93 };
94
95 // Models text/code sections. Code is written out incrementally and the
96 // size of the section is then updated incrementally.
97 class ELFTextSection : public ELFSection {
98 ELFTextSection(const ELFTextSection &) = delete;
99 ELFTextSection &operator=(const ELFTextSection &) = delete;
100
101 public:
102 using ELFSection::ELFSection;
103
104 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
105 };
106
107 // Models data/rodata sections. Data is written out incrementally and the
108 // size of the section is then updated incrementally.
109 // Some rodata sections may have fixed entsize and duplicates may be mergeable.
110 class ELFDataSection : public ELFSection {
111 ELFDataSection(const ELFDataSection &) = delete;
112 ELFDataSection &operator=(const ELFDataSection &) = delete;
113
114 public:
115 using ELFSection::ELFSection;
116
117 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
118 };
119
120 // Model of ELF symbol table entries. Besides keeping track of the fields
121 // required for an elf symbol table entry it also tracks the number that
122 // represents the symbol's final index in the symbol table.
123 struct ELFSym {
124 Elf64_Sym Sym;
125 SizeT Number;
126
127 // Sentinel value for symbols that haven't been assigned a number yet.
128 // The dummy 0-th symbol will be assigned number 0, so don't use that.
129 enum { UnknownNumber = std::numeric_limits<SizeT>::max() };
130
131 void setNumber(SizeT N) {
132 assert(Number == UnknownNumber);
133 Number = N;
134 }
135
136 SizeT getNumber() const {
137 assert(Number != UnknownNumber);
138 return Number;
139 }
140 };
141
142 // Models a symbol table. Symbols may be added up until updateIndices is
143 // called. At that point the indices of each symbol will be finalized.
144 class ELFSymbolTableSection : public ELFSection {
145 public:
146 using ELFSection::ELFSection;
147
148 // Create initial entry for a symbol when it is defined.
149 // Each entry should only be defined once.
150 // We might want to allow Name to be a dummy name initially, then
151 // get updated to the real thing, since Data initializers are read
152 // before the bitcode's symbol table is read.
153 void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding,
154 ELFSection *Section, RelocOffsetT Offset, SizeT Size);
155
156 // Note that a symbol table entry needs to be created for the given
157 // symbol because it is undefined.
158 void noteUndefinedSym(const IceString &Name, ELFSection *NullSection);
159
160 size_t getSectionDataSize() const {
161 return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize;
162 }
163
164 size_t getNumLocals() const { return LocalSymbols.size(); }
165
166 void updateIndices(const ELFStringTableSection *StrTab);
167
168 void writeData(ELFStreamer &Str, bool IsELF64);
169
170 private:
171 // Map from symbol name + section to its symbol information.
172 typedef std::pair<IceString, ELFSection *> SymtabKey;
173 typedef std::map<SymtabKey, ELFSym> SymMap;
174
175 template <bool IsELF64>
176 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map);
177
178 // Keep Local and Global symbols separate, since the sh_info needs to
179 // know the index of the last LOCAL.
180 SymMap LocalSymbols;
181 SymMap GlobalSymbols;
182 };
183
184 // Base model of a relocation section.
185 class ELFRelocationSectionBase : public ELFSection {
186 ELFRelocationSectionBase(const ELFRelocationSectionBase &) = delete;
187 ELFRelocationSectionBase &
188 operator=(const ELFRelocationSectionBase &) = delete;
189
190 public:
191 ELFRelocationSectionBase(const IceString &Name, Elf64_Word ShType,
192 Elf64_Xword ShFlags, Elf64_Xword ShAddralign,
193 Elf64_Xword ShEntsize, ELFSection *RelatedSection)
194 : ELFSection(Name, ShType, ShFlags, ShAddralign, ShEntsize),
195 RelatedSection(RelatedSection) {}
196
197 ELFSection *getRelatedSection() const { return RelatedSection; }
198
199 private:
200 ELFSection *RelatedSection;
201 };
202
203 // ELFRelocationSection which depends on the actual relocation type.
204 // Specializations are needed depending on the ELFCLASS and whether
205 // or not addends are explicit or implicitly embedded in the related
206 // section (ELFCLASS64 pack their r_info field differently from ELFCLASS32).
207 template <typename RelType>
208 class ELFRelocationSection : ELFRelocationSectionBase {
209 ELFRelocationSection(const ELFRelocationSectionBase &) = delete;
210 ELFRelocationSection &operator=(const ELFRelocationSectionBase &) = delete;
211
212 public:
213 using ELFRelocationSectionBase::ELFRelocationSectionBase;
214
215 void addRelocations() {
216 // TODO: fill me in
217 }
218
219 private:
220 typedef std::pair<RelType, ELFSym *> ELFRelSym;
221 typedef std::vector<ELFRelSym> RelocationList;
222 RelocationList Relocations;
223 };
224
225 // Models a string table. The user will build the string table by
226 // adding strings incrementally. At some point, all strings should be
227 // known and doLayout() should be called. After that, no other
228 // strings may be added. However, the final offsets of the strings
229 // can be discovered and used to fill out section headers and symbol
230 // table entries.
231 class ELFStringTableSection : public ELFSection {
232 ELFStringTableSection(const ELFStringTableSection &) = delete;
233 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete;
234
235 public:
236 using ELFSection::ELFSection;
237
238 // Add a string to the table, in preparation for final layout.
239 void add(const IceString &Str);
240
241 // Finalizes the layout of the string table and fills in the section Data.
242 void doLayout();
243
244 // The first byte of the string table should be \0, so it is an
245 // invalid index. Indices start out as unknown until layout is complete.
246 enum { UnknownIndex = 0 };
247
248 // Grabs the final index of a string after layout. Returns UnknownIndex
249 // if the string's index is not found.
250 size_t getIndex(const IceString &Str) const;
251
252 llvm::StringRef getSectionData() const {
253 assert(isLaidOut());
254 return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()),
255 StringData.size());
256 }
257
258 size_t getSectionDataSize() const { return getSectionData().size(); }
259
260 private:
261 bool isLaidOut() const { return !StringData.empty(); }
262
263 // Strings can share a string table entry if they share the same
264 // suffix. E.g., "pop" and "lollipop" can both use the characters
265 // in "lollipop", but "pops" cannot, and "unpop" cannot either.
266 // Though, "pop", "lollipop", and "unpop" share "pop" as the suffix,
267 // "pop" can only share the characters with one of them.
268 struct SuffixComparator {
269 bool operator()(const IceString &StrA, const IceString &StrB) const;
270 };
271
272 typedef std::map<IceString, size_t, SuffixComparator> StringToIndexType;
273
274 // Track strings to their index. Index will be UnknownIndex if not
275 // yet laid out.
276 StringToIndexType StringToIndexMap;
277
278 typedef std::vector<uint8_t> RawDataType;
279 RawDataType StringData;
280 };
281
282 template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) {
283 Str.writeELFWord<IsELF64>(Header.sh_name);
284 Str.writeELFWord<IsELF64>(Header.sh_type);
285 Str.writeELFXword<IsELF64>(Header.sh_flags);
286 Str.writeAddrOrOffset<IsELF64>(Header.sh_addr);
287 Str.writeAddrOrOffset<IsELF64>(Header.sh_offset);
288 Str.writeELFXword<IsELF64>(Header.sh_size);
289 Str.writeELFWord<IsELF64>(Header.sh_link);
290 Str.writeELFWord<IsELF64>(Header.sh_info);
291 Str.writeELFXword<IsELF64>(Header.sh_addralign);
292 Str.writeELFXword<IsELF64>(Header.sh_entsize);
293 }
294
295 template <bool IsELF64>
296 void ELFSymbolTableSection::writeSymbolMap(ELFStreamer &Str,
297 const SymMap &Map) {
298 // The order of the fields is different, so branch on IsELF64.
299 if (IsELF64) {
300 for (auto &KeyValue : Map) {
301 const Elf64_Sym &SymInfo = KeyValue.second.Sym;
302 Str.writeELFWord<IsELF64>(SymInfo.st_name);
303 Str.write8(SymInfo.st_info);
304 Str.write8(SymInfo.st_other);
305 Str.writeLE16(SymInfo.st_shndx);
306 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
307 Str.writeELFXword<IsELF64>(SymInfo.st_size);
308 }
309 } else {
310 for (auto &KeyValue : Map) {
311 const Elf64_Sym &SymInfo = KeyValue.second.Sym;
312 Str.writeELFWord<IsELF64>(SymInfo.st_name);
313 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
314 Str.writeELFWord<IsELF64>(SymInfo.st_size);
315 Str.write8(SymInfo.st_info);
316 Str.write8(SymInfo.st_other);
317 Str.writeLE16(SymInfo.st_shndx);
318 }
319 }
320 }
321
322 } // end of namespace Ice
323
324 #endif // SUBZERO_SRC_ICEELFSECTION_H
OLDNEW
« no previous file with comments | « src/IceELFObjectWriter.cpp ('k') | src/IceELFSection.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698