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

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: stuff Created 6 years, 1 month 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
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 // Constructs an ELF section, filling in fields that will be known
34 // once the *type* of section is decided. Other fields may be updated
35 // incrementally or only after the program is completely defined.
36 ELFSection(const IceString &Name, Elf64_Word sh_type, Elf64_Xword sh_flags,
37 Elf64_Xword sh_addralign, Elf64_Xword sh_entsize)
38 : Name(Name), Header(), Number(NoSectionNumber) {
39 Header.sh_type = sh_type;
40 Header.sh_flags = sh_flags;
41 Header.sh_addralign = sh_addralign;
42 Header.sh_entsize = sh_entsize;
43 }
44
45 // Sentinel value for a section number/index for before the final
46 // section index is actually known.
47 static const SizeT NoSectionNumber;
Jim Stichnoth 2014/11/21 21:32:22 I think you could do this instead, for slightly be
jvoung (off chromium) 2014/11/24 21:35:46 Done.
48
49 // Set the section number/index after it is finally known.
50 void setNumber(SizeT N) {
51 // Should only set the number once: from NoSectionNumber -> N.
52 assert(Number == NoSectionNumber);
53 Number = N;
54 }
55 SizeT getNumber() const {
56 assert(Number != NoSectionNumber);
57 return Number;
58 }
59
60 void setSize(Elf64_Xword sh_size) { Header.sh_size = sh_size; }
61 SizeT getCurrentSize() const { return Header.sh_size; }
62
63 void setNameStrIndex(Elf64_Word sh_name) { Header.sh_name = sh_name; }
64
65 IceString getName() const { return Name; }
66
67 void setLinkNum(Elf64_Word sh_link) { Header.sh_link = sh_link; }
68
69 void setInfoNum(Elf64_Word sh_info) { Header.sh_info = sh_info; }
70
71 void setFileOffset(Elf64_Off sh_offset) { Header.sh_offset = sh_offset; }
72
73 Elf64_Xword getSectionAlign() const { return Header.sh_addralign; }
74
75 // Write the section header out with the given streamer.
76 template <bool IsELF64> void writeHeader(ELFStreamer &Str);
77
78 protected:
79 ~ELFSection() {}
80
81 // Name of the section in convenient string form (instead of a index
82 // into the Section Header String Table, which is not known till later).
83 IceString Name;
84
85 // The fields of the header. May only be partially initialized, but should
86 // be fully initialized before writing.
87 Elf64_Shdr Header;
88
89 // The number of the section after laying out sections.
90 SizeT Number;
91 };
92
93 // Models text/code sections. Code is written out incrementally and the
94 // size of the section is then updated incrementally.
95 class ELFTextSection : public ELFSection {
96 ELFTextSection(const ELFTextSection &) = delete;
97 ELFTextSection &operator=(const ELFTextSection &) = delete;
98
99 public:
100 using ELFSection::ELFSection;
101
102 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
103 };
104
105 // Models data/rodata sections. Data is written out incrementally and the
106 // size of the section is then updated incrementally.
107 // Some rodata sections may have fixed entsize and duplicates may be mergeable.
108 class ELFDataSection : public ELFSection {
109 ELFDataSection(const ELFDataSection &) = delete;
110 ELFDataSection &operator=(const ELFDataSection &) = delete;
111
112 public:
113 using ELFSection::ELFSection;
114
115 void appendData(ELFStreamer &Str, const llvm::StringRef MoreData);
116 };
117
118 // Model of ELF symbol table entries. Besides keeping track of the fields
119 // required for an elf symbol table entry it also tracks the number that
120 // represents the symbol's final index in the symbol table.
121 struct ELFSym {
122 Elf64_Sym Sym;
123 SizeT Number;
124
125 static const SizeT UnknownNumber;
126
127 void setNumber(SizeT N) {
128 assert(Number == UnknownNumber);
129 Number = N;
130 }
131
132 SizeT getNumber() const {
133 assert(Number != UnknownNumber);
134 return Number;
135 }
136 };
137
138 // Models a symbol table. Symbols may be added up until updateIndices is
139 // called. At that point the indices of each symbol will be finalized.
140 class ELFSymbolTableSection : public ELFSection {
141 public:
142 using ELFSection::ELFSection;
143
144 // Create initial entry for a symbol when it is defined.
145 // Each entry should only be defined once.
146 // We might want to allow Name to be a dummy name initially, then
147 // get updated to the real thing, since Data initializers are read
148 // before the bitcode's symbol table is read.
149 void createDefinedSym(const IceString &Name, uint8_t Type, uint8_t Binding,
150 ELFSection *Section, RelocOffsetT Offset, SizeT Size);
151
152 // Note that a symbol table entry needs to be created for the given
153 // symbol because it is undefined.
154 void noteUndefinedSym(const IceString &Name, ELFSection *NullSection);
155
156 size_t getSectionDataSize() const {
157 return (LocalSymbols.size() + GlobalSymbols.size()) * Header.sh_entsize;
158 }
159
160 size_t getNumLocals() const { return LocalSymbols.size(); }
161
162 void updateIndices(const ELFStringTableSection *StrTab);
163
164 void writeData(ELFStreamer &Str, bool IsELF64);
165
166 private:
167 // Map from symbol name + section to its symbol information.
168 typedef std::pair<IceString, ELFSection *> SymtabKey;
169 typedef std::map<SymtabKey, ELFSym> SymMap;
170
171 template <bool IsELF64>
172 void writeSymbolMap(ELFStreamer &Str, const SymMap &Map);
173
174 // Keep Local and Global symbols separate, since the sh_info needs to
175 // know the index of the last LOCAL.
176 SymMap LocalSymbols;
177 SymMap GlobalSymbols;
178 };
179
180 // Base model of a relocation section.
181 class ELFRelocationSectionBase : public ELFSection {
182 ELFRelocationSectionBase(const ELFRelocationSectionBase &) = delete;
183 ELFRelocationSectionBase &
184 operator=(const ELFRelocationSectionBase &) = delete;
185
186 public:
187 ELFRelocationSectionBase(const IceString &Name, Elf64_Word sh_type,
188 Elf64_Xword sh_flags, Elf64_Xword sh_addralign,
189 Elf64_Xword sh_entsize, ELFSection *RelatedSection)
190 : ELFSection(Name, sh_type, sh_flags, sh_addralign, sh_entsize),
191 RelatedSection(RelatedSection) {}
192
193 ELFSection *getRelatedSection() const { return RelatedSection; }
194
195 private:
196 ELFSection *RelatedSection;
197 };
198
199 // ELFRelocationSection which depends on the actual relocation type.
200 // Specializations are needed depending on the ELFCLASS and whether
201 // or not addends are explicit or implicitly embedded in the related
202 // section (ELFCLASS64 pack their r_info field differently from ELFCLASS32).
203 template <typename RelType>
204 class ELFRelocationSection : ELFRelocationSectionBase {
205 ELFRelocationSection(const ELFRelocationSectionBase &) = delete;
206 ELFRelocationSection &operator=(const ELFRelocationSectionBase &) = delete;
207
208 public:
209 using ELFRelocationSectionBase::ELFRelocationSectionBase;
210
211 void addRelocations() {
212 // TODO: fill me in
213 }
214
215 private:
216 typedef std::pair<RelType, ELFSym *> ELFRelSym;
217 typedef std::vector<ELFRelSym> RelocationList;
218 RelocationList Relocations;
219 };
220
221 // Models a string table. The user will build the string table by
222 // adding strings incrementally. At some point, all strings should be
223 // known and layOutStrings() should be called. After that, no other
224 // strings may be added. However, the final offsets of the strings
225 // can be discovered and used to fill out section headers and symbol
226 // table entries.
227 class ELFStringTableSection : public ELFSection {
228 ELFStringTableSection(const ELFStringTableSection &) = delete;
229 ELFStringTableSection &operator=(const ELFStringTableSection &) = delete;
230
231 public:
232 using ELFSection::ELFSection;
233
234 // Add a string to the table, in preparation for final layout.
235 void add(const IceString &Str);
236
237 // Finalizes the layout of the string table and fills in the section Data.
238 void doLayout();
239
240 // Grabs the final index of a string after layout.
241 size_t getIndex(const IceString &Str) const;
242
243 llvm::StringRef getSectionData() const {
244 assert(isLaidOut());
245 return llvm::StringRef(reinterpret_cast<const char *>(StringData.data()),
246 StringData.size());
247 }
248
249 size_t getSectionDataSize() const { return getSectionData().size(); }
250
251 private:
252 bool isLaidOut() const { return !StringData.empty(); }
253
254 // Strings can share a string table entry if they share the same suffix.
255 // E.g., "pop\\0" and "lollipop\0" can both use the characters in
Jim Stichnoth 2014/11/21 21:32:22 Did you mean for the backslashes to be doubled? (
jvoung (off chromium) 2014/11/24 21:35:46 Hmm, I guess \0 should be fine -- making consisten
256 // "lolipop\\0", but "pops\\0" cannot, and "unpop\\0" cannot either.
257 // Though, "pop\\0", "lollipop\\0", and "unpop\\0" share "pop\\0" as
258 // the suffix, "pop\\0" can only share the characters with one of them.
259 struct SuffixComparator {
260 bool operator()(const IceString &StrA, const IceString &StrB) const;
261 };
262
263 typedef std::map<IceString, size_t, SuffixComparator> StringToIndexType;
264
265 static const size_t UnknownIndex;
266
267 // Track strings to their index. Index will be UnknownIndex if not
268 // yet laid out.
269 StringToIndexType StringToIndexMap;
270
271 typedef std::vector<uint8_t> RawDataType;
272 RawDataType StringData;
273 };
274
275 template <bool IsELF64> void ELFSection::writeHeader(ELFStreamer &Str) {
276 Str.writeELFWord<IsELF64>(Header.sh_name);
277 Str.writeELFWord<IsELF64>(Header.sh_type);
278 Str.writeELFXword<IsELF64>(Header.sh_flags);
279 Str.writeAddrOrOffset<IsELF64>(Header.sh_addr);
280 Str.writeAddrOrOffset<IsELF64>(Header.sh_offset);
281 Str.writeELFXword<IsELF64>(Header.sh_size);
282 Str.writeELFWord<IsELF64>(Header.sh_link);
283 Str.writeELFWord<IsELF64>(Header.sh_info);
284 Str.writeELFXword<IsELF64>(Header.sh_addralign);
285 Str.writeELFXword<IsELF64>(Header.sh_entsize);
286 }
287
288 template <bool IsELF64>
289 void ELFSymbolTableSection::writeSymbolMap(ELFStreamer &Str,
290 const SymMap &Map) {
291 // The order of the fields is different, so branch on IsELF64.
292 if (IsELF64) {
293 for (auto &KeyValue : Map) {
294 const Elf64_Sym &SymInfo = KeyValue.second.Sym;
295 Str.writeELFWord<IsELF64>(SymInfo.st_name);
296 Str.write8(SymInfo.st_info);
297 Str.write8(SymInfo.st_other);
298 Str.writeLE16(SymInfo.st_shndx);
299 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
300 Str.writeELFXword<IsELF64>(SymInfo.st_size);
301 }
302 } else {
303 for (auto &KeyValue : Map) {
304 const Elf64_Sym &SymInfo = KeyValue.second.Sym;
305 Str.writeELFWord<IsELF64>(SymInfo.st_name);
306 Str.writeAddrOrOffset<IsELF64>(SymInfo.st_value);
307 Str.writeELFWord<IsELF64>(SymInfo.st_size);
308 Str.write8(SymInfo.st_info);
309 Str.write8(SymInfo.st_other);
310 Str.writeLE16(SymInfo.st_shndx);
311 }
312 }
313 }
314
315 } // end of namespace Ice
316
317 #endif // SUBZERO_SRC_ICEELFSECTION_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698