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>> 18 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 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", 57 object_error::parse_failed); 58 Section.Content = ArrayRef<uint8_t>(Ptr, Size); 59 Ptr += Size; 60 return Error::success(); 61 } 62 } 63 64 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 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", 70 object_error::parse_failed); 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", 77 object_error::parse_failed); 78 return; 79 } 80 81 const uint8_t *Eof = getPtr(getData().size()); 82 wasm::WasmSection Sec; 83 while (Ptr < Eof) { 84 if ((Err = readSection(Sec, Ptr, getPtr(0)))) 85 return; 86 if (Sec.Type == wasm::WASM_SEC_CUSTOM) { 87 if ((Err = 88 parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size()))) 89 return; 90 } 91 Sections.push_back(Sec); 92 } 93 } 94 95 Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec, 96 const uint8_t *Ptr, size_t Length) { 97 Sec.Name = readString(Ptr); 98 return Error::success(); 99 } 100 101 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 102 return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 103 } 104 105 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 106 return Header; 107 } 108 109 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 110 llvm_unreachable("not yet implemented"); 111 } 112 113 std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS, 114 DataRefImpl Symb) const { 115 llvm_unreachable("not yet implemented"); 116 return object_error::invalid_symbol_index; 117 } 118 119 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 120 llvm_unreachable("not yet implemented"); 121 return 0; 122 } 123 124 basic_symbol_iterator WasmObjectFile::symbol_begin() const { 125 return BasicSymbolRef(DataRefImpl(), this); 126 } 127 128 basic_symbol_iterator WasmObjectFile::symbol_end() const { 129 return BasicSymbolRef(DataRefImpl(), this); 130 } 131 132 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 133 llvm_unreachable("not yet implemented"); 134 return errorCodeToError(object_error::invalid_symbol_index); 135 } 136 137 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 138 llvm_unreachable("not yet implemented"); 139 return errorCodeToError(object_error::invalid_symbol_index); 140 } 141 142 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 143 llvm_unreachable("not yet implemented"); 144 return 0; 145 } 146 147 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 148 llvm_unreachable("not yet implemented"); 149 return 0; 150 } 151 152 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 153 llvm_unreachable("not yet implemented"); 154 return 0; 155 } 156 157 Expected<SymbolRef::Type> 158 WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 159 llvm_unreachable("not yet implemented"); 160 return errorCodeToError(object_error::invalid_symbol_index); 161 } 162 163 Expected<section_iterator> 164 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 165 llvm_unreachable("not yet implemented"); 166 return errorCodeToError(object_error::invalid_symbol_index); 167 } 168 169 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 170 171 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 172 StringRef &Res) const { 173 const wasm::WasmSection &S = Sections[Sec.d.a]; 174 #define ECase(X) \ 175 case wasm::WASM_SEC_##X: \ 176 Res = #X; \ 177 break 178 switch (S.Type) { 179 ECase(TYPE); 180 ECase(IMPORT); 181 ECase(FUNCTION); 182 ECase(TABLE); 183 ECase(MEMORY); 184 ECase(GLOBAL); 185 ECase(EXPORT); 186 ECase(START); 187 ECase(ELEM); 188 ECase(CODE); 189 ECase(DATA); 190 case wasm::WASM_SEC_CUSTOM: 191 Res = S.Name; 192 break; 193 default: 194 return object_error::invalid_section_index; 195 } 196 #undef ECase 197 return std::error_code(); 198 } 199 200 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 201 202 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 203 const wasm::WasmSection &S = Sections[Sec.d.a]; 204 return S.Content.size(); 205 } 206 207 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 208 StringRef &Res) const { 209 const wasm::WasmSection &S = Sections[Sec.d.a]; 210 // This will never fail since wasm sections can never be empty (user-sections 211 // must have a name and non-user sections each have a defined structure). 212 Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 213 S.Content.size()); 214 return std::error_code(); 215 } 216 217 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 218 return 1; 219 } 220 221 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 222 return false; 223 } 224 225 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 226 const wasm::WasmSection &S = Sections[Sec.d.a]; 227 return S.Type == wasm::WASM_SEC_CODE; 228 } 229 230 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 231 const wasm::WasmSection &S = Sections[Sec.d.a]; 232 return S.Type == wasm::WASM_SEC_DATA; 233 } 234 235 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 236 237 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 238 239 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 240 241 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const { 242 llvm_unreachable("not yet implemented"); 243 RelocationRef Rel; 244 return relocation_iterator(Rel); 245 } 246 247 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const { 248 llvm_unreachable("not yet implemented"); 249 RelocationRef Rel; 250 return relocation_iterator(Rel); 251 } 252 253 section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const { 254 llvm_unreachable("not yet implemented"); 255 SectionRef Ref; 256 return section_iterator(Ref); 257 } 258 259 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 260 llvm_unreachable("not yet implemented"); 261 } 262 263 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const { 264 llvm_unreachable("not yet implemented"); 265 return 0; 266 } 267 268 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 269 llvm_unreachable("not yet implemented"); 270 SymbolRef Ref; 271 return symbol_iterator(Ref); 272 } 273 274 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const { 275 llvm_unreachable("not yet implemented"); 276 return 0; 277 } 278 279 void WasmObjectFile::getRelocationTypeName( 280 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 281 llvm_unreachable("not yet implemented"); 282 } 283 284 section_iterator WasmObjectFile::section_begin() const { 285 DataRefImpl Ref; 286 Ref.d.a = 0; 287 return section_iterator(SectionRef(Ref, this)); 288 } 289 290 section_iterator WasmObjectFile::section_end() const { 291 DataRefImpl Ref; 292 Ref.d.a = Sections.size(); 293 return section_iterator(SectionRef(Ref, this)); 294 } 295 296 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 297 298 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 299 300 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 301 302 SubtargetFeatures WasmObjectFile::getFeatures() const { 303 return SubtargetFeatures(); 304 } 305 306 bool WasmObjectFile::isRelocatableObject() const { return false; } 307 308 const wasm::WasmSection * 309 WasmObjectFile::getWasmSection(const SectionRef &Section) const { 310 return &Sections[Section.getRawDataRefImpl().d.a]; 311 } 312 313 } // end namespace object 314 } // end namespace llvm 315