1 //===- SyntheticSection.h ---------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Synthetic sections represent chunks of linker-created data. If you 10 // need to create a chunk of data that to be included in some section 11 // in the result, you probably want to create that as a synthetic section. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLD_WASM_SYNTHETIC_SECTIONS_H 16 #define LLD_WASM_SYNTHETIC_SECTIONS_H 17 18 #include "OutputSections.h" 19 20 #include "llvm/ADT/SmallSet.h" 21 #include "llvm/ADT/StringMap.h" 22 #include "llvm/Object/WasmTraits.h" 23 24 #define DEBUG_TYPE "lld" 25 26 namespace lld { 27 namespace wasm { 28 29 // An init entry to be written to either the synthetic init func or the 30 // linking metadata. 31 struct WasmInitEntry { 32 const FunctionSymbol *sym; 33 uint32_t priority; 34 }; 35 36 class SyntheticSection : public OutputSection { 37 public: 38 SyntheticSection(uint32_t type, std::string name = "") 39 : OutputSection(type, name), bodyOutputStream(body) { 40 if (!name.empty()) 41 writeStr(bodyOutputStream, name, "section name"); 42 } 43 44 void writeTo(uint8_t *buf) override { 45 assert(offset); 46 log("writing " + toString(*this)); 47 memcpy(buf + offset, header.data(), header.size()); 48 memcpy(buf + offset + header.size(), body.data(), body.size()); 49 } 50 51 size_t getSize() const override { return header.size() + body.size(); } 52 53 virtual void writeBody() {} 54 55 virtual void assignIndexes() {} 56 57 void finalizeContents() override { 58 writeBody(); 59 bodyOutputStream.flush(); 60 createHeader(body.size()); 61 } 62 63 raw_ostream &getStream() { return bodyOutputStream; } 64 65 std::string body; 66 67 protected: 68 llvm::raw_string_ostream bodyOutputStream; 69 }; 70 71 // Create the custom "dylink" section containing information for the dynamic 72 // linker. 73 // See 74 // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md 75 class DylinkSection : public SyntheticSection { 76 public: 77 DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {} 78 bool isNeeded() const override { return config->isPic; } 79 void writeBody() override; 80 81 uint32_t memAlign = 0; 82 uint32_t memSize = 0; 83 }; 84 85 class TypeSection : public SyntheticSection { 86 public: 87 TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {} 88 89 bool isNeeded() const override { return types.size() > 0; }; 90 void writeBody() override; 91 uint32_t registerType(const WasmSignature &sig); 92 uint32_t lookupType(const WasmSignature &sig); 93 94 protected: 95 std::vector<const WasmSignature *> types; 96 llvm::DenseMap<WasmSignature, int32_t> typeIndices; 97 }; 98 99 class ImportSection : public SyntheticSection { 100 public: 101 ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {} 102 bool isNeeded() const override { return getNumImports() > 0; } 103 void writeBody() override; 104 void addImport(Symbol *sym); 105 void addGOTEntry(Symbol *sym); 106 void seal() { isSealed = true; } 107 uint32_t getNumImports() const; 108 uint32_t getNumImportedGlobals() const { 109 assert(isSealed); 110 return numImportedGlobals; 111 } 112 uint32_t getNumImportedFunctions() const { 113 assert(isSealed); 114 return numImportedFunctions; 115 } 116 uint32_t getNumImportedEvents() const { 117 assert(isSealed); 118 return numImportedEvents; 119 } 120 121 std::vector<const Symbol *> importedSymbols; 122 123 protected: 124 bool isSealed = false; 125 unsigned numImportedGlobals = 0; 126 unsigned numImportedFunctions = 0; 127 unsigned numImportedEvents = 0; 128 std::vector<const Symbol *> gotSymbols; 129 }; 130 131 class FunctionSection : public SyntheticSection { 132 public: 133 FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {} 134 135 bool isNeeded() const override { return inputFunctions.size() > 0; }; 136 void writeBody() override; 137 void addFunction(InputFunction *func); 138 139 std::vector<InputFunction *> inputFunctions; 140 141 protected: 142 }; 143 144 class MemorySection : public SyntheticSection { 145 public: 146 MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {} 147 148 bool isNeeded() const override { return !config->importMemory; } 149 void writeBody() override; 150 151 uint32_t numMemoryPages = 0; 152 uint32_t maxMemoryPages = 0; 153 }; 154 155 class TableSection : public SyntheticSection { 156 public: 157 TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {} 158 159 bool isNeeded() const override { 160 // Always output a table section (or table import), even if there are no 161 // indirect calls. There are two reasons for this: 162 // 1. For executables it is useful to have an empty table slot at 0 163 // which can be filled with a null function call handler. 164 // 2. If we don't do this, any program that contains a call_indirect but 165 // no address-taken function will fail at validation time since it is 166 // a validation error to include a call_indirect instruction if there 167 // is not table. 168 return !config->importTable; 169 } 170 171 void writeBody() override; 172 }; 173 174 class GlobalSection : public SyntheticSection { 175 public: 176 GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {} 177 uint32_t numGlobals() const { 178 assert(isSealed); 179 return inputGlobals.size() + dataAddressGlobals.size() + 180 staticGotSymbols.size(); 181 } 182 bool isNeeded() const override { return numGlobals() > 0; } 183 void assignIndexes() override; 184 void writeBody() override; 185 void addGlobal(InputGlobal *global); 186 void addDataAddressGlobal(DefinedData *global); 187 void addStaticGOTEntry(Symbol *sym); 188 189 std::vector<const DefinedData *> dataAddressGlobals; 190 191 protected: 192 bool isSealed = false; 193 std::vector<InputGlobal *> inputGlobals; 194 std::vector<Symbol *> staticGotSymbols; 195 }; 196 197 // The event section contains a list of declared wasm events associated with the 198 // module. Currently the only supported event kind is exceptions. A single event 199 // entry represents a single event with an event tag. All C++ exceptions are 200 // represented by a single event. An event entry in this section contains 201 // information on what kind of event it is (e.g. exception) and the type of 202 // values contained in a single event object. (In wasm, an event can contain 203 // multiple values of primitive types. But for C++ exceptions, we just throw a 204 // pointer which is an i32 value (for wasm32 architecture), so the signature of 205 // C++ exception is (i32)->(void), because all event types are assumed to have 206 // void return type to share WasmSignature with functions.) 207 class EventSection : public SyntheticSection { 208 public: 209 EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {} 210 void writeBody() override; 211 bool isNeeded() const override { return inputEvents.size() > 0; } 212 void addEvent(InputEvent *event); 213 214 std::vector<InputEvent *> inputEvents; 215 }; 216 217 class ExportSection : public SyntheticSection { 218 public: 219 ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {} 220 bool isNeeded() const override { return exports.size() > 0; } 221 void writeBody() override; 222 223 std::vector<llvm::wasm::WasmExport> exports; 224 }; 225 226 class StartSection : public SyntheticSection { 227 public: 228 StartSection(uint32_t numSegments) 229 : SyntheticSection(llvm::wasm::WASM_SEC_START), numSegments(numSegments) { 230 } 231 bool isNeeded() const override; 232 void writeBody() override; 233 234 protected: 235 uint32_t numSegments; 236 }; 237 238 class ElemSection : public SyntheticSection { 239 public: 240 ElemSection() 241 : SyntheticSection(llvm::wasm::WASM_SEC_ELEM) {} 242 bool isNeeded() const override { return indirectFunctions.size() > 0; }; 243 void writeBody() override; 244 void addEntry(FunctionSymbol *sym); 245 uint32_t numEntries() const { return indirectFunctions.size(); } 246 247 protected: 248 std::vector<const FunctionSymbol *> indirectFunctions; 249 }; 250 251 class DataCountSection : public SyntheticSection { 252 public: 253 DataCountSection(ArrayRef<OutputSegment *> segments); 254 bool isNeeded() const override; 255 void writeBody() override; 256 257 protected: 258 uint32_t numSegments; 259 }; 260 261 // Create the custom "linking" section containing linker metadata. 262 // This is only created when relocatable output is requested. 263 class LinkingSection : public SyntheticSection { 264 public: 265 LinkingSection(const std::vector<WasmInitEntry> &initFunctions, 266 const std::vector<OutputSegment *> &dataSegments) 267 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"), 268 initFunctions(initFunctions), dataSegments(dataSegments) {} 269 bool isNeeded() const override { 270 return config->relocatable || config->emitRelocs; 271 } 272 void writeBody() override; 273 void addToSymtab(Symbol *sym); 274 275 protected: 276 std::vector<const Symbol *> symtabEntries; 277 llvm::StringMap<uint32_t> sectionSymbolIndices; 278 const std::vector<WasmInitEntry> &initFunctions; 279 const std::vector<OutputSegment *> &dataSegments; 280 }; 281 282 // Create the custom "name" section containing debug symbol names. 283 class NameSection : public SyntheticSection { 284 public: 285 NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {} 286 bool isNeeded() const override { 287 return !config->stripDebug && !config->stripAll && numNames() > 0; 288 } 289 void writeBody() override; 290 unsigned numNames() const; 291 }; 292 293 class ProducersSection : public SyntheticSection { 294 public: 295 ProducersSection() 296 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {} 297 bool isNeeded() const override { 298 return !config->stripAll && fieldCount() > 0; 299 } 300 void writeBody() override; 301 void addInfo(const llvm::wasm::WasmProducerInfo &info); 302 303 protected: 304 int fieldCount() const { 305 return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty()); 306 } 307 SmallVector<std::pair<std::string, std::string>, 8> languages; 308 SmallVector<std::pair<std::string, std::string>, 8> tools; 309 SmallVector<std::pair<std::string, std::string>, 8> sDKs; 310 }; 311 312 class TargetFeaturesSection : public SyntheticSection { 313 public: 314 TargetFeaturesSection() 315 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {} 316 bool isNeeded() const override { 317 return !config->stripAll && features.size() > 0; 318 } 319 void writeBody() override; 320 321 llvm::SmallSet<std::string, 8> features; 322 }; 323 324 class RelocSection : public SyntheticSection { 325 public: 326 RelocSection(StringRef name, OutputSection *sec) 327 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, name), sec(sec) {} 328 void writeBody() override; 329 bool isNeeded() const override { return sec->getNumRelocations() > 0; }; 330 331 protected: 332 OutputSection *sec; 333 }; 334 335 // Linker generated output sections 336 struct OutStruct { 337 DylinkSection *dylinkSec; 338 TypeSection *typeSec; 339 FunctionSection *functionSec; 340 ImportSection *importSec; 341 TableSection *tableSec; 342 MemorySection *memorySec; 343 GlobalSection *globalSec; 344 EventSection *eventSec; 345 ExportSection *exportSec; 346 StartSection *startSec; 347 ElemSection *elemSec; 348 DataCountSection *dataCountSec; 349 LinkingSection *linkingSec; 350 NameSection *nameSec; 351 ProducersSection *producersSec; 352 TargetFeaturesSection *targetFeaturesSec; 353 }; 354 355 extern OutStruct out; 356 357 } // namespace wasm 358 } // namespace lld 359 360 #endif 361