llvm.org GIT mirror llvm / 1e975c1
[WebAssembly] Add support for weak symbols in the binary format This also introduces the updated format for the "linking" section which can represent extra symbol information. See: https://github.com/WebAssembly/tool-conventions/pull/10 Differential Revision: https://reviews.llvm.org/D34019 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305769 91177308-0d34-0410-b5e6-96231b3b80d8 Sam Clegg 2 years ago
13 changed file(s) with 508 addition(s) and 107 deletion(s). Raw diff Collapse all Expand all
175175 // Linking metadata kinds.
176176 enum : unsigned {
177177 WASM_STACK_POINTER = 0x1,
178 WASM_SYMBOL_INFO = 0x2,
179 };
180
181 enum : unsigned {
182 WASM_SYMBOL_FLAG_WEAK = 0x1,
178183 };
179184
180185 #define WASM_RELOC(name, value) name = value,
1616 class MCSymbolWasm : public MCSymbol {
1717 private:
1818 bool IsFunction = false;
19 bool IsWeak = false;
1920 std::string ModuleName;
2021 SmallVector Returns;
2122 SmallVector Params;
3839 bool isFunction() const { return IsFunction; }
3940 void setIsFunction(bool isFunc) { IsFunction = isFunc; }
4041
42 bool isWeak() const { return IsWeak; }
43 void setWeak(bool isWeak) { IsWeak = isWeak; }
44
4145 const StringRef getModuleName() const { return ModuleName; }
4246
4347 const SmallVector &getReturns() const { return Returns; }
1818
1919 #include "llvm/ADT/ArrayRef.h"
2020 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/StringMap.h"
2122 #include "llvm/BinaryFormat/Wasm.h"
2223 #include "llvm/Object/Binary.h"
2324 #include "llvm/Object/ObjectFile.h"
4748 StringRef Name;
4849 SymbolType Type;
4950 uint32_t Section;
51 uint32_t Flags = 0;
52
53 // Index into the imports, exports or functions array of the object depending
54 // on the type
5055 uint32_t ElementIndex;
56
57 bool isWeak() const {
58 return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
59 }
60
61 void print(raw_ostream &Out) const {
62 Out << "Name=" << Name << ", Type=" << static_cast(Type)
63 << ", Flags=" << Flags;
64 }
65
66 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
67 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
68 #endif
5169 };
5270
5371 class WasmSection {
6280 };
6381
6482 class WasmObjectFile : public ObjectFile {
83
6584 public:
6685 WasmObjectFile(MemoryBufferRef Object, Error &Err);
6786
175194
176195 // Custom section types
177196 Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
197 Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
178198 Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
179199 const uint8_t *End);
180200
189209 std::vector Exports;
190210 std::vector ElemSegments;
191211 std::vector DataSegments;
212 std::vector Functions;
192213 std::vector Symbols;
193 std::vector Functions;
194214 ArrayRef CodeSection;
195215 uint32_t StartFunction = -1;
216
217 StringMap SymbolMap;
196218 };
197219
198220 } // end namespace object
221
222 inline raw_ostream &operator<<(raw_ostream &OS,
223 const object::WasmSymbol &Sym) {
224 Sym.print(OS);
225 return OS;
226 }
227
199228 } // end namespace llvm
200229
201230 #endif // LLVM_OBJECT_WASM_H
111111 ValueType ReturnType;
112112 };
113113
114 struct SymbolInfo {
115 StringRef Name;
116 uint32_t Flags;
117 };
118
114119 struct Section {
115 Section(SectionType SecType) : Type(SecType) {}
120 explicit Section(SectionType SecType) : Type(SecType) {}
116121 virtual ~Section();
117122
118123 SectionType Type;
120125 };
121126
122127 struct CustomSection : Section {
123 CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
128 explicit CustomSection(StringRef Name)
129 : Section(wasm::WASM_SEC_CUSTOM), Name(Name) {}
124130 static bool classof(const Section *S) {
125131 return S->Type == wasm::WASM_SEC_CUSTOM;
126132 }
127133
128134 StringRef Name;
129135 yaml::BinaryRef Payload;
130
131 // The follow is used by the "name" custom section.
132 // TODO(sbc): Add support for more then just functions names. The wasm
133 // name section can support multiple sub-sections.
136 };
137
138 struct NameSection : CustomSection {
139 NameSection() : CustomSection("name") {}
140 static bool classof(const Section *S) {
141 auto C = dyn_cast(S);
142 return C && C->Name == "name";
143 }
144
134145 std::vector FunctionNames;
146 };
147
148 struct LinkingSection : CustomSection {
149 LinkingSection() : CustomSection("linking") {}
150 static bool classof(const Section *S) {
151 auto C = dyn_cast(S);
152 return C && C->Name == "linking";
153 }
154
155 std::vector SymbolInfos;
135156 };
136157
137158 struct TypeSection : Section {
255276 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
256277 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
257278 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
279 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
258280 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
259281
260282 namespace llvm {
328350 static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
329351 };
330352
353 template <> struct MappingTraits {
354 static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
355 };
356
331357 template <> struct ScalarEnumerationTraits {
332358 static void enumeration(IO &IO, WasmYAML::ValueType &Type);
333359 };
9797 case MCSA_WeakDefAutoPrivate:
9898 case MCSA_Invalid:
9999 case MCSA_IndirectSymbol:
100 case MCSA_Hidden:
100101 return false;
102
103 case MCSA_Weak:
104 case MCSA_WeakReference:
105 Symbol->setWeak(true);
106 Symbol->setExternal(true);
107 break;
108
101109 case MCSA_Global:
102110 Symbol->setExternal(true);
103111 break;
112
104113 case MCSA_ELF_TypeFunction:
105114 Symbol->setIsFunction(true);
106115 break;
116
107117 case MCSA_ELF_TypeObject:
108118 Symbol->setIsFunction(false);
109119 break;
120
110121 default:
111122 // unrecognized directive
123 llvm_unreachable("unexpected MCSymbolAttr");
112124 return false;
113125 }
114126
155155 Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
156156 << ", Type=" << Type << ", FixupSection=" << FixupSection;
157157 }
158 void dump() const { print(errs()); }
158
159 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
160 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
161 #endif
159162 };
163
164 inline raw_ostream &operator<<(raw_ostream &OS,
165 const WasmRelocationEntry &Rel) {
166 Rel.print(OS);
167 return OS;
168 }
160169
161170 class WasmObjectWriter : public MCObjectWriter {
162171 /// Helper struct for containing some precomputed information on symbols.
227236 const MCAsmLayout &Layout) override;
228237
229238 void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
239
240 void writeString(const StringRef Str) {
241 encodeULEB128(Str.size(), getStream());
242 writeBytes(Str);
243 }
230244
231245 void writeValueType(wasm::ValType Ty) {
232246 encodeSLEB128(int32_t(Ty), getStream());
249263 uint32_t NumFuncImports);
250264 void writeCodeRelocSection();
251265 void writeDataRelocSection(uint64_t DataSectionHeaderSize);
252 void writeLinkingMetaDataSection(bool HasStackPointer,
266 void writeLinkingMetaDataSection(ArrayRef WeakSymbols,
267 bool HasStackPointer,
253268 uint32_t StackPointerGlobal);
254269
255270 void applyRelocations(ArrayRef Relocations,
281296 assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
282297 "Only custom sections can have names");
283298
299 DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
284300 encodeULEB128(SectionId, getStream());
285301
286302 Section.SizeOffset = getStream().tell();
294310
295311 // Custom sections in wasm also have a string identifier.
296312 if (SectionId == wasm::WASM_SEC_CUSTOM) {
297 encodeULEB128(strlen(Name), getStream());
298 writeBytes(Name);
313 assert(Name);
314 writeString(StringRef(Name));
299315 }
300316 }
301317
306322 if (uint32_t(Size) != Size)
307323 report_fatal_error("section size does not fit in a uint32_t");
308324
325 DEBUG(dbgs() << "endSection size=" << Size << "\n");
309326 unsigned Padding = PaddingFor5ByteULEB128(Size);
310327
311328 // Write the final section size to the payload_len field, which follows
410427 unsigned Type = getRelocType(Target, Fixup);
411428
412429 WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
430 DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
413431
414432 if (FixupSection.hasInstructions())
415433 CodeRelocations.push_back(Rec);
454472 const MCSymbolWasm *Sym = RelEntry.Symbol;
455473
456474 // For undefined symbols, use a hopefully invalid value.
457 if (!Sym->isDefined(false))
475 if (!Sym->isDefined(/*SetUsed=*/false))
458476 return UINT32_MAX;
459477
460478 MCSectionWasm &Section =
472490 switch (RelEntry.Type) {
473491 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
474492 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
475 assert(IndirectSymbolIndices.count(RelEntry.Symbol));
493 if (!IndirectSymbolIndices.count(RelEntry.Symbol))
494 report_fatal_error("symbol not found table index space:" +
495 RelEntry.Symbol->getName());
476496 return IndirectSymbolIndices[RelEntry.Symbol];
477497 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
478498 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
479499 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
480500 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
481501 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
482 assert(SymbolIndices.count(RelEntry.Symbol));
502 if (!SymbolIndices.count(RelEntry.Symbol))
503 report_fatal_error("symbol not found function/global index space:" +
504 RelEntry.Symbol->getName());
483505 return SymbolIndices[RelEntry.Symbol];
484506 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
485 assert(TypeIndices.count(RelEntry.Symbol));
507 if (!TypeIndices.count(RelEntry.Symbol))
508 report_fatal_error("symbol not found in type index space:" +
509 RelEntry.Symbol->getName());
486510 return TypeIndices[RelEntry.Symbol];
487511 default:
488512 llvm_unreachable("invalid relocation type");
499523 RelEntry.FixupSection->getSectionOffset() +
500524 RelEntry.Offset;
501525
526 DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
502527 switch (RelEntry.Type) {
503528 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
504529 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
576601 endSection(Section);
577602 }
578603
604
579605 void WasmObjectWriter::writeImportSection(
580606 const SmallVector &Imports) {
581607 if (Imports.empty())
586612
587613 encodeULEB128(Imports.size(), getStream());
588614 for (const WasmImport &Import : Imports) {
589 StringRef ModuleName = Import.ModuleName;
590 encodeULEB128(ModuleName.size(), getStream());
591 writeBytes(ModuleName);
592
593 StringRef FieldName = Import.FieldName;
594 encodeULEB128(FieldName.size(), getStream());
595 writeBytes(FieldName);
615 writeString(Import.ModuleName);
616 writeString(Import.FieldName);
596617
597618 encodeULEB128(Import.Kind, getStream());
598619
700721
701722 encodeULEB128(Exports.size(), getStream());
702723 for (const WasmExport &Export : Exports) {
703 encodeULEB128(Export.FieldName.size(), getStream());
704 writeBytes(Export.FieldName);
705
724 writeString(Export.FieldName);
706725 encodeSLEB128(Export.Kind, getStream());
707
708726 encodeULEB128(Export.Index, getStream());
709727 }
710728
748766 for (const WasmFunction &Func : Functions) {
749767 MCSectionWasm &FuncSection =
750768 static_cast(Func.Sym->getSection());
751
752 if (Func.Sym->isVariable())
753 report_fatal_error("weak symbols not supported yet");
754
755 if (Func.Sym->getOffset() != 0)
756 report_fatal_error("function sections must contain one function each");
757
758 if (!Func.Sym->getSize())
759 report_fatal_error("function symbols must have a size set with .size");
760769
761770 int64_t Size = 0;
762771 if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
818827 for (const WasmImport &Import : Imports) {
819828 if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
820829 encodeULEB128(Index, getStream());
821 encodeULEB128(Import.FieldName.size(), getStream());
822 writeBytes(Import.FieldName);
830 writeString(Import.FieldName);
823831 ++Index;
824832 }
825833 }
826834 for (const WasmFunction &Func : Functions) {
827835 encodeULEB128(Index, getStream());
828 encodeULEB128(Func.Sym->getName().size(), getStream());
829 writeBytes(Func.Sym->getName());
836 writeString(Func.Sym->getName());
830837 ++Index;
831838 }
832839
871878 }
872879
873880 void WasmObjectWriter::writeLinkingMetaDataSection(
874 bool HasStackPointer, uint32_t StackPointerGlobal) {
875 if (!HasStackPointer)
881 ArrayRef WeakSymbols, bool HasStackPointer,
882 uint32_t StackPointerGlobal) {
883 if (!HasStackPointer && WeakSymbols.empty())
876884 return;
885
877886 SectionBookkeeping Section;
878887 startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
879
880 encodeULEB128(1, getStream()); // count
881
882 encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
883 encodeULEB128(StackPointerGlobal, getStream()); // id
888 SectionBookkeeping SubSection;
889
890 if (HasStackPointer) {
891 startSection(SubSection, wasm::WASM_STACK_POINTER);
892 encodeULEB128(StackPointerGlobal, getStream()); // id
893 endSection(SubSection);
894 }
895
896 if (WeakSymbols.size() != 0) {
897 startSection(SubSection, wasm::WASM_SYMBOL_INFO);
898 encodeULEB128(WeakSymbols.size(), getStream());
899 for (const StringRef Export: WeakSymbols) {
900 writeString(Export);
901 encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
902 }
903 endSection(SubSection);
904 }
884905
885906 endSection(Section);
886907 }
887908
888909 void WasmObjectWriter::writeObject(MCAssembler &Asm,
889910 const MCAsmLayout &Layout) {
911 DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
890912 MCContext &Ctx = Asm.getContext();
891913 wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
892914
897919 SmallVector Globals;
898920 SmallVector Imports;
899921 SmallVector Exports;
922 SmallVector WeakSymbols;
900923 SmallPtrSet IsAddressTaken;
901924 unsigned NumFuncImports = 0;
902925 unsigned NumGlobalImports = 0;
905928 bool HasStackPointer = false;
906929
907930 // Populate the IsAddressTaken set.
908 for (WasmRelocationEntry RelEntry : CodeRelocations) {
931 for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
909932 switch (RelEntry.Type) {
910933 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
911934 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
915938 break;
916939 }
917940 }
918 for (WasmRelocationEntry RelEntry : DataRelocations) {
941 for (const WasmRelocationEntry &RelEntry : DataRelocations) {
919942 switch (RelEntry.Type) {
920943 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
921944 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
10441067 StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
10451068 }
10461069
1047 // Handle defined symbols.
1070 // Handle regular defined and undefined symbols.
10481071 for (const MCSymbol &S : Asm.symbols()) {
10491072 // Ignore unnamed temporary symbols, which aren't ever exported, imported,
10501073 // or used in relocations.
10511074 if (S.isTemporary() && S.getName().empty())
10521075 continue;
1076
1077 // Variable references (weak references) are handled in a second pass
1078 if (S.isVariable())
1079 continue;
1080
10531081 const auto &WS = static_cast(S);
1082 DEBUG(dbgs() << "MCSymbol: '" << S << "'"
1083 << " isDefined=" << S.isDefined() << " isExternal="
1084 << S.isExternal() << " isTemporary=" << S.isTemporary()
1085 << " isFunction=" << WS.isFunction()
1086 << " isWeak=" << WS.isWeak()
1087 << " isVariable=" << WS.isVariable() << "\n");
1088
1089 if (WS.isWeak())
1090 WeakSymbols.push_back(WS.getName());
1091
10541092 unsigned Index;
1093
1094 //<< " function=" << S.isFunction()
1095
10551096 if (WS.isFunction()) {
10561097 // Prepare the function's type, if we haven't seen it yet.
10571098 WasmFunctionType F;
10651106 int32_t Type = Pair.first->second;
10661107
10671108 if (WS.isDefined(/*SetUsed=*/false)) {
1109 if (WS.getOffset() != 0)
1110 report_fatal_error(
1111 "function sections must contain one function each");
1112
1113 if (WS.getSize() == 0)
1114 report_fatal_error(
1115 "function symbols must have a size set with .size");
1116
10681117 // A definition. Take the next available index.
10691118 Index = NumFuncImports + Functions.size();
10701119
10751124 SymbolIndices[&WS] = Index;
10761125 Functions.push_back(Func);
10771126 } else {
1127 // Should be no such thing as weak undefined symbol
1128 assert(!WS.isVariable());
1129
10781130 // An import; the index was assigned above.
10791131 Index = SymbolIndices.find(&WS)->second;
10801132 }
10881140 if (WS.isTemporary() && !WS.getSize())
10891141 continue;
10901142
1091 if (WS.isDefined(false)) {
1143 if (WS.isDefined(/*SetUsed=*/false)) {
10921144 if (WS.getOffset() != 0)
10931145 report_fatal_error("data sections must contain one variable each: " +
10941146 WS.getName());
11531205 }
11541206
11551207 // If the symbol is visible outside this translation unit, export it.
1156 if (WS.isExternal()) {
1157 assert(WS.isDefined(false));
1208 if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
11581209 WasmExport Export;
11591210 Export.FieldName = WS.getName();
11601211 Export.Index = Index;
1161
11621212 if (WS.isFunction())
11631213 Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
11641214 else
11651215 Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1166
11671216 Exports.push_back(Export);
11681217 }
1218 }
1219
1220 // Handle weak aliases
1221 for (const MCSymbol &S : Asm.symbols()) {
1222 if (!S.isVariable())
1223 continue;
1224 assert(S.isExternal());
1225 assert(S.isDefined(/*SetUsed=*/false));
1226
1227 const auto &WS = static_cast(S);
1228
1229 // Find the target symbol of this weak alias
1230 const MCExpr *Expr = WS.getVariableValue();
1231 auto *Inner = dyn_cast(Expr);
1232 const MCSymbolWasm *ResolvedSym = cast(&Inner->getSymbol());
1233 uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
1234 DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
1235 SymbolIndices[&WS] = Index;
1236
1237 WasmExport Export;
1238 Export.FieldName = WS.getName();
1239 Export.Index = Index;
1240 if (WS.isFunction())
1241 Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1242 else
1243 Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1244 WeakSymbols.push_back(Export.FieldName);
1245 Exports.push_back(Export);
11691246 }
11701247
11711248 // Add types for indirect function calls.
12011278 writeNameSection(Functions, Imports, NumFuncImports);
12021279 writeCodeRelocSection();
12031280 writeDataRelocSection(DataSectionHeaderSize);
1204 writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal);
1281 writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
12051282
12061283 // TODO: Translate the .comment section to the output.
12071284 // TODO: Translate debug sections to the output.
2626 #include
2727 #include
2828 #include
29
30 #define DEBUG_TYPE "wasm-object"
2931
3032 using namespace llvm;
3133 using namespace object;
255257 while (Ptr < End) {
256258 uint8_t Type = readVarint7(Ptr);
257259 uint32_t Size = readVaruint32(Ptr);
260 const uint8_t *SubSectionEnd = Ptr + Size;
258261 switch (Type) {
259262 case wasm::WASM_NAMES_FUNCTION: {
260263 uint32_t Count = readVaruint32(Ptr);
274277 Ptr += Size;
275278 break;
276279 }
280 if (Ptr != SubSectionEnd)
281 return make_error("Name sub-section ended prematurely",
282 object_error::parse_failed);
277283 }
278284
279285 if (Ptr != End)
280286 return make_error("Name section ended prematurely",
287 object_error::parse_failed);
288 return Error::success();
289 }
290
291 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
292 const uint8_t *End) {
293 while (Ptr < End) {
294 uint8_t Type = readVarint7(Ptr);
295 uint32_t Size = readVaruint32(Ptr);
296 const uint8_t *SubSectionEnd = Ptr + Size;
297 switch (Type) {
298 case wasm::WASM_SYMBOL_INFO: {
299 uint32_t Count = readVaruint32(Ptr);
300 while (Count--) {
301 StringRef Symbol = readString(Ptr);
302 DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n");
303 uint32_t Flags = readVaruint32(Ptr);
304 auto iter = SymbolMap.find(Symbol);
305 if (iter == SymbolMap.end()) {
306 return make_error(
307 "Invalid symbol name in linking section",
308 object_error::parse_failed);
309 }
310 uint32_t SymIndex = iter->second;
311 assert(SymIndex < Symbols.size());
312 Symbols[SymIndex].Flags = Flags;
313 DEBUG(dbgs() << "Set symbol flags index:"
314 << SymIndex << " name:"
315 << Symbols[SymIndex].Name << " exptected:"
316 << Symbol << " flags: " << Flags << "\n");
317 }
318 break;
319 }
320 case wasm::WASM_STACK_POINTER:
321 default:
322 Ptr += Size;
323 break;
324 }
325 if (Ptr != SubSectionEnd)
326 return make_error(
327 "Linking sub-section ended prematurely", object_error::parse_failed);
328 }
329 if (Ptr != End)
330 return make_error("Linking section ended prematurely",
281331 object_error::parse_failed);
282332 return Error::success();
283333 }
350400 if (Sec.Name == "name") {
351401 if (Error Err = parseNameSection(Ptr, End))
352402 return Err;
403 } else if (Sec.Name == "linking") {
404 if (Error Err = parseLinkingSection(Ptr, End))
405 return Err;
353406 } else if (Sec.Name.startswith("reloc.")) {
354407 if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
355408 return Err;
401454 switch (Im.Kind) {
402455 case wasm::WASM_EXTERNAL_FUNCTION:
403456 Im.SigIndex = readVaruint32(Ptr);
457 SymbolMap.try_emplace(Im.Field, Symbols.size());
404458 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
405459 Sections.size(), i);
460 DEBUG(dbgs() << "Adding import: " << Symbols.back()
461 << " sym index:" << Symbols.size() << "\n");
406462 break;
407463 case wasm::WASM_EXTERNAL_GLOBAL:
408464 Im.Global.Type = readVarint7(Ptr);
409465 Im.Global.Mutable = readVaruint1(Ptr);
466 SymbolMap.try_emplace(Im.Field, Symbols.size());
410467 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
411468 Sections.size(), i);
469 DEBUG(dbgs() << "Adding import: " << Symbols.back()
470 << " sym index:" << Symbols.size() << "\n");
412471 break;
413472 case wasm::WASM_EXTERNAL_MEMORY:
414473 Im.Memory = readLimits(Ptr);
497556 Ex.Name = readString(Ptr);
498557 Ex.Kind = readUint8(Ptr);
499558 Ex.Index = readVaruint32(Ptr);
500 Exports.push_back(Ex);
501559 switch (Ex.Kind) {
502560 case wasm::WASM_EXTERNAL_FUNCTION:
561 SymbolMap.try_emplace(Ex.Name, Symbols.size());
503562 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
504563 Sections.size(), i);
564 DEBUG(dbgs() << "Adding export: " << Symbols.back()
565 << " sym index:" << Symbols.size() << "\n");
505566 break;
506567 case wasm::WASM_EXTERNAL_GLOBAL:
568 SymbolMap.try_emplace(Ex.Name, Symbols.size());
507569 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
508570 Sections.size(), i);
571 DEBUG(dbgs() << "Adding export: " << Symbols.back()
572 << " sym index:" << Symbols.size() << "\n");
509573 break;
510574 case wasm::WASM_EXTERNAL_MEMORY:
511575 case wasm::WASM_EXTERNAL_TABLE:
514578 return make_error(
515579 "Unexpected export kind", object_error::parse_failed);
516580 }
581 Exports.push_back(Ex);
517582 }
518583 if (Ptr != End)
519584 return make_error("Export section ended prematurely",
621686 uint32_t Result = SymbolRef::SF_None;
622687 const WasmSymbol &Sym = getWasmSymbol(Symb);
623688
689 DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
690 if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
691 Result |= SymbolRef::SF_Weak;
692
624693 switch (Sym.Type) {
625694 case WasmSymbol::SymbolType::FUNCTION_IMPORT:
626695 Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
630699 break;
631700 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
632701 Result |= SymbolRef::SF_Executable;
702 Result |= SymbolRef::SF_FormatSpecific;
633703 break;
634704 case WasmSymbol::SymbolType::GLOBAL_IMPORT:
635705 Result |= SymbolRef::SF_Undefined;
663733 }
664734
665735 Expected WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
666 const WasmSymbol &Sym = getWasmSymbol(Symb);
667 return Sym.Name;
736 return getWasmSymbol(Symb).Name;
668737 }
669738
670739 Expected WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
672741 }
673742
674743 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
675 const WasmSymbol &Sym = getWasmSymbol(Symb);
676 return Sym.ElementIndex;
744 const WasmSymbol& Sym = getWasmSymbol(Symb);
745 switch (Sym.Type) {
746 case WasmSymbol::SymbolType::FUNCTION_IMPORT:
747 case WasmSymbol::SymbolType::GLOBAL_IMPORT:
748 return 0;
749 case WasmSymbol::SymbolType::FUNCTION_EXPORT:
750 case WasmSymbol::SymbolType::GLOBAL_EXPORT:
751 return Exports[Sym.ElementIndex].Index;
752 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
753 return Sym.ElementIndex;
754 }
677755 }
678756
679757 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
4646 IO.mapOptional("Relocations", Section.Relocations);
4747 }
4848
49 static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
50 commonSectionMapping(IO, Section);
51 IO.mapRequired("Name", Section.Name);
52 IO.mapOptional("FunctionNames", Section.FunctionNames);
53 }
54
55 static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
56 commonSectionMapping(IO, Section);
57 IO.mapRequired("Name", Section.Name);
58 IO.mapRequired("SymbolInfo", Section.SymbolInfos);
59 }
60
4961 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
5062 commonSectionMapping(IO, Section);
5163 IO.mapRequired("Name", Section.Name);
52 if (Section.Name == "name") {
53 IO.mapOptional("FunctionNames", Section.FunctionNames);
54 } else {
55 IO.mapRequired("Payload", Section.Payload);
56 }
64 IO.mapRequired("Payload", Section.Payload);
5765 }
5866
5967 static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
120128 IO.mapRequired("Type", SectionType);
121129
122130 switch (SectionType) {
123 case wasm::WASM_SEC_CUSTOM:
124 if (!IO.outputting())
125 Section.reset(new WasmYAML::CustomSection());
126 sectionMapping(IO, *cast(Section.get()));
127 break;
131 case wasm::WASM_SEC_CUSTOM: {
132 StringRef SectionName;
133 if (IO.outputting()) {
134 auto CustomSection = cast(Section.get());
135 SectionName = CustomSection->Name;
136 } else {
137 IO.mapRequired("Name", SectionName);
138 }
139 if (SectionName == "linking") {
140 if (!IO.outputting())
141 Section.reset(new WasmYAML::LinkingSection());
142 sectionMapping(IO, *cast(Section.get()));
143 } else if (SectionName == "name") {
144 if (!IO.outputting())
145 Section.reset(new WasmYAML::NameSection());
146 sectionMapping(IO, *cast(Section.get()));
147 } else {
148 if (!IO.outputting())
149 Section.reset(new WasmYAML::CustomSection(SectionName));
150 sectionMapping(IO, *cast(Section.get()));
151 }
152 break;
153 }
128154 case wasm::WASM_SEC_TYPE:
129155 if (!IO.outputting())
130156 Section.reset(new WasmYAML::TypeSection());
320346 IO.mapRequired("Content", Segment.Content);
321347 }
322348
349 void MappingTraits::mapping(IO &IO,
350 WasmYAML::SymbolInfo &Info) {
351 IO.mapRequired("Name", Info.Name);
352 IO.mapRequired("Flags", Info.Flags);
353 }
354
323355 void ScalarEnumerationTraits::enumeration(
324356 IO &IO, WasmYAML::ValueType &Type) {
325357 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: EXPORT
6 Exports:
7 - Name: function_export
8 Kind: FUNCTION
9 Index: 1
10 - Name: global_export
11 Kind: GLOBAL
12 Index: 2
13 - Type: CUSTOM
14 Name: linking
15 SymbolInfo:
16 - Name: function_export
17 Flags: 1
18 - Name: global_export
19 Flags: 1
20 ...
21 # CHECK: --- !WASM
22 # CHECK: FileHeader:
23 # CHECK: Version: 0x00000001
24 # CHECK: Sections:
25 # CHECK: - Type: EXPORT
26 # CHECK: Exports:
27 # CHECK: - Name: function_export
28 # CHECK: Kind: FUNCTION
29 # CHECK: Index: 1
30 # CHECK: - Name: global_export
31 # CHECK: Kind: GLOBAL
32 # CHECK: Index: 2
33 # CHECK: - Type: CUSTOM
34 # CHECK: Name: linking
35 # CHECK: SymbolInfo:
36 # CHECK: - Name: function_export
37 # CHECK: Flags: 1
38 # CHECK: - Name: global_export
39 # CHECK: Flags: 1
0 # RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
1
2 # That wasm exports of functions and globals are displayed as global data and
3 # code symbols.
14
25 --- !WASM
36 FileHeader:
1215 Exports:
1316 - Name: foo
1417 Kind: FUNCTION
15 Index: 0x00000000
18 Index: 0x00000004
1619 - Name: bar
1720 Kind: GLOBAL
18 Index: 0x00000000
21 Index: 0x00000002
1922
20 # CHECK: 00000001 D bar
21 # CHECK: 00000000 T foo
23 # CHECK: 00000002 D bar
24 # CHECK: 00000004 T foo
0 # RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
1
2 # That wasm exports of functions and globals are displayed as global data and
3 # code symbols.
4
5 --- !WASM
6 FileHeader:
7 Version: 0x00000001
8 Sections:
9 - Type: TYPE
10 Signatures:
11 - ReturnType: I32
12 ParamTypes:
13 - I32
14 - Type: IMPORT
15 Imports:
16 - Module: env
17 Field: weak_import_func
18 Kind: FUNCTION
19 SigIndex: 0
20 - Module: env
21 Field: weak_import_data
22 Kind: GLOBAL
23 GlobalType: I32
24 GlobalMutable: false
25 - Type: EXPORT
26 Exports:
27 - Name: weak_global_func
28 Kind: FUNCTION
29 Index: 0x00000004
30 - Name: weak_global_data
31 Kind: GLOBAL
32 Index: 0x00000002
33 - Type: CUSTOM
34 Name: linking
35 SymbolInfo:
36 - Name: weak_global_func
37 Flags: 1
38 - Name: weak_global_data
39 Flags: 1
40 - Name: weak_import_func
41 Flags: 1
42 - Name: weak_import_data
43 Flags: 1
44
45 # CHECK: 00000002 W weak_global_data
46 # CHECK: 00000004 W weak_global_func
47 # CHECK: w weak_import_data
48 # CHECK: w weak_import_func
1313 #include "llvm/Support/YAMLTraits.h"
1414
1515 using namespace llvm;
16 using object::WasmSection;
1617
1718 namespace {
1819
2122
2223 public:
2324 WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
25
2426 ErrorOr dump();
27
28 std::unique_ptr
29 dumpCustomSection(const WasmSection &WasmSec);
2530 };
2631
27 WasmYAML::Table make_table(const wasm::WasmTable &Table) {
32 } // namespace
33
34 static WasmYAML::Table make_table(const wasm::WasmTable &Table) {
2835 WasmYAML::Table T;
2936 T.ElemType = Table.ElemType;
3037 T.TableLimits.Flags = Table.Limits.Flags;
3340 return T;
3441 }
3542
36 WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
43 static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
3744 WasmYAML::Limits L;
3845 L.Flags = Limits.Flags;
3946 L.Initial = Limits.Initial;
4148 return L;
4249 }
4350
51 std::unique_ptr WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
52 std::unique_ptr CustomSec;
53 if (WasmSec.Name == "name") {
54 std::unique_ptr NameSec = make_unique();
55 for (const object::SymbolRef& Sym: Obj.symbols()) {
56 uint32_t Flags = Sym.getFlags();
57 // Skip over symbols that come from imports or exports
58 if (Flags &
59 (object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
60 continue;
61 Expected NameOrError = Sym.getName();
62 if (!NameOrError)
63 continue;
64 WasmYAML::NameEntry NameEntry;
65 NameEntry.Name = *NameOrError;
66 NameEntry.Index = Sym.getValue();
67 NameSec->FunctionNames.push_back(NameEntry);
68 }
69 CustomSec = std::move(NameSec);
70 } else if (WasmSec.Name == "linking") {
71 std::unique_ptr LinkingSec = make_unique();
72 for (const object::SymbolRef& Sym: Obj.symbols()) {
73 const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
74 if (Symbol.Flags != 0) {
75 WasmYAML::SymbolInfo Info = { Symbol.Name, Symbol.Flags };
76 LinkingSec->SymbolInfos.push_back(Info);
77 }
78 }
79 CustomSec = std::move(LinkingSec);
80 } else {
81 CustomSec = make_unique(WasmSec.Name);
82 }
83 CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
84 return CustomSec;
85 }
86
4487 ErrorOr WasmDumper::dump() {
4588 auto Y = make_unique();
4689
4992
5093 // Dump sections
5194 for (const auto &Sec : Obj.sections()) {
52 const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
95 const WasmSection &WasmSec = Obj.getWasmSection(Sec);
5396 std::unique_ptr S;
5497 switch (WasmSec.Type) {
5598 case wasm::WASM_SEC_CUSTOM: {
58101 // being represented as a custom section in the YAML output.
59102 continue;
60103 }
61 auto CustomSec = make_unique();
62 CustomSec->Name = WasmSec.Name;
63 if (CustomSec->Name == "name") {
64 for (const object::SymbolRef& Sym: Obj.symbols()) {
65 uint32_t Flags = Sym.getFlags();
66 // Skip over symbols that come from imports or exports
67 if (Flags &
68 (object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
69 continue;
70 Expected NameOrError = Sym.getName();
71 if (!NameOrError)
72 continue;
73 WasmYAML::NameEntry NameEntry;
74 NameEntry.Name = *NameOrError;
75 NameEntry.Index = Sym.getValue();
76 CustomSec->FunctionNames.push_back(NameEntry);
77 }
78 } else {
79 CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
80 }
81 S = std::move(CustomSec);
104 S = dumpCustomSection(WasmSec);
82105 break;
83106 }
84107 case wasm::WASM_SEC_TYPE: {
236259 return Y.release();
237260 }
238261
239 } // namespace
240
241262 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
242263 WasmDumper Dumper(Obj);
243264 ErrorOr YAMLOrErr = Dumper.dump();
2525 public:
2626 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
2727 int writeWasm(raw_ostream &OS);
28
29 private:
2830 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
29 int writeNameSection(raw_ostream &OS, WasmYAML::CustomSection &Section);
3031
3132 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
3233 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
4142 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
4243 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
4344
44 private:
45 // Custom section types
46 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
47 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
4548 WasmYAML::Object &Obj;
4649 };
4750
106109 return 0;
107110 }
108111
109 int WasmWriter::writeNameSection(raw_ostream &OS,
110 WasmYAML::CustomSection &Section) {
112 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
113 writeStringRef(Section.Name, OS);
114 if (Section.SymbolInfos.size()) {
115 encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
116 std::string OutString;
117 raw_string_ostream StringStream(OutString);
118
119 encodeULEB128(Section.SymbolInfos.size(), StringStream);
120 for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
121 writeStringRef(Info.Name, StringStream);
122 encodeULEB128(Info.Flags, StringStream);
123 }
124
125 StringStream.flush();
126 encodeULEB128(OutString.size(), OS);
127 OS << OutString;
128 }
129 return 0;
130 }
131
132 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
111133 writeStringRef(Section.Name, OS);
112134 if (Section.FunctionNames.size()) {
113135 encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
114
115136 std::string OutString;
116137 raw_string_ostream StringStream(OutString);
117138
130151
131152 int WasmWriter::writeSectionContent(raw_ostream &OS,
132153 WasmYAML::CustomSection &Section) {
133 if (Section.Name == "name") {
134 writeNameSection(OS, Section);
154 if (auto S = dyn_cast(&Section)) {
155 if (auto Err = writeSectionContent(OS, *S))
156 return Err;
157 } else if (auto S = dyn_cast(&Section)) {
158 if (auto Err = writeSectionContent(OS, *S))
159 return Err;
135160 } else {
136161 Section.Payload.writeAsBinary(OS);
137162 }