LLVM  4.0.0
WasmObjectFile.cpp
Go to the documentation of this file.
1 //===- WasmObjectFile.cpp - Wasm object file implementation -----*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Object/Wasm.h"
11 #include "llvm/Support/Endian.h"
12 #include "llvm/Support/LEB128.h"
13 
14 namespace llvm {
15 namespace object {
16 
17 Expected<std::unique_ptr<WasmObjectFile>>
19  Error Err = Error::success();
20  auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
21  if (Err)
22  return std::move(Err);
23 
24  return std::move(ObjectFile);
25 }
26 
27 namespace {
28 
29 uint32_t readUint32(const uint8_t *&Ptr) {
30  uint32_t Result = support::endian::read32le(Ptr);
31  Ptr += sizeof(Result);
32  return Result;
33 }
34 
35 uint64_t readULEB128(const uint8_t *&Ptr) {
36  unsigned Count;
37  uint64_t Result = decodeULEB128(Ptr, &Count);
38  Ptr += Count;
39  return Result;
40 }
41 
42 StringRef readString(const uint8_t *&Ptr) {
43  uint32_t StringLen = readULEB128(Ptr);
44  StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen);
45  Ptr += StringLen;
46  return Return;
47 }
48 
49 Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,
50  const uint8_t *Start) {
51  // TODO(sbc): Avoid reading past EOF in the case of malformed files.
52  Section.Offset = Ptr - Start;
53  Section.Type = readULEB128(Ptr);
54  uint32_t Size = readULEB128(Ptr);
55  if (Size == 0)
56  return make_error<StringError>("Zero length section",
58  Section.Content = ArrayRef<uint8_t>(Ptr, Size);
59  Ptr += Size;
60  return Error::success();
61 }
62 }
63 
65  : ObjectFile(Binary::ID_Wasm, Buffer) {
66  ErrorAsOutParameter ErrAsOutParam(&Err);
67  Header.Magic = getData().substr(0, 4);
68  if (Header.Magic != StringRef("\0asm", 4)) {
69  Err = make_error<StringError>("Bad magic number",
71  return;
72  }
73  const uint8_t *Ptr = getPtr(4);
74  Header.Version = readUint32(Ptr);
75  if (Header.Version != wasm::WasmVersion) {
76  Err = make_error<StringError>("Bad version number",
78  return;
79  }
80 
81  const uint8_t *Eof = getPtr(getData().size());
83  while (Ptr < Eof) {
84  if ((Err = readSection(Sec, Ptr, getPtr(0))))
85  return;
86  if (Sec.Type == wasm::WASM_SEC_USER) {
87  if ((Err = parseUserSection(Sec, Sec.Content.data(), Sec.Content.size())))
88  return;
89  }
90  Sections.push_back(Sec);
91  }
92 }
93 
94 Error WasmObjectFile::parseUserSection(wasm::WasmSection &Sec,
95  const uint8_t *Ptr, size_t Length) {
96  Sec.Name = readString(Ptr);
97  return Error::success();
98 }
99 
100 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
101  return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
102 }
103 
105  return Header;
106 }
107 
109  llvm_unreachable("not yet implemented");
110 }
111 
113  DataRefImpl Symb) const {
114  llvm_unreachable("not yet implemented");
116 }
117 
119  llvm_unreachable("not yet implemented");
120  return 0;
121 }
122 
124  return BasicSymbolRef(DataRefImpl(), this);
125 }
126 
128  return BasicSymbolRef(DataRefImpl(), this);
129 }
130 
132  llvm_unreachable("not yet implemented");
134 }
135 
137  llvm_unreachable("not yet implemented");
139 }
140 
142  llvm_unreachable("not yet implemented");
143  return 0;
144 }
145 
147  llvm_unreachable("not yet implemented");
148  return 0;
149 }
150 
152  llvm_unreachable("not yet implemented");
153  return 0;
154 }
155 
158  llvm_unreachable("not yet implemented");
160 }
161 
164  llvm_unreachable("not yet implemented");
166 }
167 
168 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
169 
171  StringRef &Res) const {
172  const wasm::WasmSection &S = Sections[Sec.d.a];
173 #define ECase(X) \
174  case wasm::WASM_SEC_##X: \
175  Res = #X; \
176  break
177  switch (S.Type) {
178  ECase(TYPE);
179  ECase(IMPORT);
180  ECase(FUNCTION);
181  ECase(TABLE);
182  ECase(MEMORY);
183  ECase(GLOBAL);
184  ECase(EXPORT);
185  ECase(START);
186  ECase(ELEM);
187  ECase(CODE);
188  ECase(DATA);
189  case wasm::WASM_SEC_USER:
190  Res = S.Name;
191  break;
192  default:
194  }
195 #undef ECase
196  return std::error_code();
197 }
198 
199 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
200 
202  const wasm::WasmSection &S = Sections[Sec.d.a];
203  return S.Content.size();
204 }
205 
207  StringRef &Res) const {
208  const wasm::WasmSection &S = Sections[Sec.d.a];
209  // This will never fail since wasm sections can never be empty (user-sections
210  // must have a name and non-user sections each have a defined structure).
211  Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
212  S.Content.size());
213  return std::error_code();
214 }
215 
217  return 1;
218 }
219 
221  return false;
222 }
223 
225  const wasm::WasmSection &S = Sections[Sec.d.a];
226  return S.Type == wasm::WASM_SEC_CODE;
227 }
228 
230  const wasm::WasmSection &S = Sections[Sec.d.a];
231  return S.Type == wasm::WASM_SEC_DATA;
232 }
233 
234 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
235 
236 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
237 
238 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
239 
241  llvm_unreachable("not yet implemented");
242  RelocationRef Rel;
243  return relocation_iterator(Rel);
244 }
245 
247  llvm_unreachable("not yet implemented");
248  RelocationRef Rel;
249  return relocation_iterator(Rel);
250 }
251 
253  llvm_unreachable("not yet implemented");
254  SectionRef Ref;
255  return section_iterator(Ref);
256 }
257 
259  llvm_unreachable("not yet implemented");
260 }
261 
263  llvm_unreachable("not yet implemented");
264  return 0;
265 }
266 
268  llvm_unreachable("not yet implemented");
269  SymbolRef Ref;
270  return symbol_iterator(Ref);
271 }
272 
274  llvm_unreachable("not yet implemented");
275  return 0;
276 }
277 
279  DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
280  llvm_unreachable("not yet implemented");
281 }
282 
284  DataRefImpl Ref;
285  Ref.d.a = 0;
286  return section_iterator(SectionRef(Ref, this));
287 }
288 
290  DataRefImpl Ref;
291  Ref.d.a = Sections.size();
292  return section_iterator(SectionRef(Ref, this));
293 }
294 
295 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
296 
298 
299 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
300 
302  return SubtargetFeatures();
303 }
304 
305 bool WasmObjectFile::isRelocatableObject() const { return false; }
306 
307 const wasm::WasmSection *
309  return &Sections[Section.getRawDataRefImpl().d.a];
310 }
311 
312 } // end namespace object
313 } // end namespace llvm
uint64_t getRelocationType(DataRefImpl Rel) const override
ArrayRef< uint8_t > Content
Definition: Support/Wasm.h:37
std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override
unsigned getArch() const override
friend class SectionRef
Definition: ObjectFile.h:211
section_iterator section_end() const override
uint64_t getSectionAddress(DataRefImpl Sec) const override
This class is the base class for all object file types.
Definition: ObjectFile.h:178
bool isSectionCompressed(DataRefImpl Sec) const override
struct llvm::object::DataRefImpl::@119 d
DataRefImpl getRawDataRefImpl() const
Definition: ObjectFile.h:428
void moveSymbolNext(DataRefImpl &Symb) const override
std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
bool isSectionVirtual(DataRefImpl Sec) const override
uint8_t getBytesInAddress() const override
The number of bytes used to represent an address in this object file format.
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:41
StringRef getData() const
Definition: Binary.cpp:33
static Expected< std::unique_ptr< WasmObjectFile > > createWasmObjectFile(MemoryBufferRef Object)
Tagged union holding either a T or a Error.
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
StringRef getFileFormatName() const override
const uint32_t WasmVersion
Definition: Support/Wasm.h:26
bool isSectionText(DataRefImpl Sec) const override
basic_symbol_iterator symbol_begin() const override
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override
Expected< uint64_t > getSymbolAddress(DataRefImpl Symb) const override
void moveRelocationNext(DataRefImpl &Rel) const override
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:141
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr)
Utility function to decode a ULEB128 value.
Definition: LEB128.h:80
uint64_t getSectionAlignment(DataRefImpl Sec) const override
content_iterator< SectionRef > section_iterator
Definition: ObjectFile.h:36
WasmObjectFile(MemoryBufferRef Object, Error &Err)
uint32_t getSymbolAlignment(DataRefImpl Symb) const override
void moveSectionNext(DataRefImpl &Sec) const override
Expected< SymbolRef::Type > getSymbolType(DataRefImpl Symb) const override
Expected< section_iterator > getSymbolSection(DataRefImpl Symb) const override
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
const wasm::WasmSection * getWasmSection(const SectionRef &Section) const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:587
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override
uint32_t Offset
SubtargetFeatures getFeatures() const override
Expected< StringRef > getSymbolName(DataRefImpl Symb) const override
uint64_t getSectionSize(DataRefImpl Sec) const override
content_iterator< RelocationRef > relocation_iterator
Definition: ObjectFile.h:66
basic_symbol_iterator symbol_end() const override
const wasm::WasmObjectHeader & getHeader() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
section_iterator section_begin() const override
static ErrorSuccess success()
Create a success value.
std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override
SubtargetFeatures - Manages the enabling and disabling of subtarget specific features.
Helper for Errors used as out-parameters.
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: ObjectFile.h:116
bool isSectionData(DataRefImpl Sec) const override
section_iterator getRelocatedSection(DataRefImpl Sec) const override
void getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl< char > &Result) const override
uint32_t read32le(const void *P)
Definition: Endian.h:318
This is a value type class that represents a single symbol in the list of symbols in the object file...
Definition: SymbolicFile.h:86
bool isRelocatableObject() const override
True if this is a relocatable object (.o/.obj).
bool isSectionBitcode(DataRefImpl Sec) const override
uint32_t getSymbolFlags(DataRefImpl Symb) const override
Lightweight error class with error context and mandatory checking.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:125
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
int * Ptr
const T * data() const
Definition: ArrayRef.h:138
#define ECase(X)
bool isSectionBSS(DataRefImpl Sec) const override
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:70
uint64_t getRelocationOffset(DataRefImpl Rel) const override