diff options
Diffstat (limited to 'lld/wasm/Writer.cpp')
-rw-r--r-- | lld/wasm/Writer.cpp | 373 |
1 files changed, 208 insertions, 165 deletions
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index b176e448080..88813828dc7 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -10,6 +10,7 @@ #include "Writer.h" #include "Config.h" #include "InputChunks.h" +#include "InputGlobal.h" #include "OutputSections.h" #include "OutputSegment.h" #include "SymbolTable.h" @@ -18,6 +19,7 @@ #include "lld/Common/Memory.h" #include "lld/Common/Threads.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/BinaryFormat/Wasm.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" @@ -62,10 +64,11 @@ struct WasmSignatureDenseMapInfo { } }; -// A Wasm export to be written into the export section. -struct WasmExportEntry { +// An init entry to be written to either the synthetic init func or the +// linking metadata. +struct WasmInitEntry { const Symbol *Sym; - StringRef FieldName; // may not match the Symbol name + uint32_t Priority; }; // The writer writes a SymbolTable result to a file. @@ -78,11 +81,13 @@ private: uint32_t lookupType(const WasmSignature &Sig); uint32_t registerType(const WasmSignature &Sig); + void createCtorFunction(); void calculateInitFunctions(); void assignIndexes(); void calculateImports(); void calculateExports(); + void assignSymtab(); void calculateTypes(); void createOutputSegments(); void layoutMemory(); @@ -118,13 +123,16 @@ private: std::vector<const WasmSignature *> Types; DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices; - std::vector<const FunctionSymbol *> ImportedFunctions; - std::vector<const DataSymbol *> ImportedGlobals; - std::vector<WasmExportEntry> ExportedSymbols; - std::vector<const DefinedData *> DefinedDataSymbols; + std::vector<const Symbol *> ImportedSymbols; + unsigned NumImportedFunctions = 0; + unsigned NumImportedGlobals = 0; + std::vector<Symbol *> ExportedSymbols; + std::vector<const DefinedData *> DefinedFakeGlobals; + std::vector<InputGlobal *> InputGlobals; std::vector<InputFunction *> InputFunctions; std::vector<const FunctionSymbol *> IndirectFunctions; - std::vector<WasmInitFunc> InitFunctions; + std::vector<const Symbol *> SymtabEntries; + std::vector<WasmInitEntry> InitFunctions; // Elements that are used to construct the final output std::string Header; @@ -150,7 +158,7 @@ static void debugPrint(const char *fmt, ...) { } void Writer::createImportSection() { - uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size(); + uint32_t NumImports = ImportedSymbols.size(); if (Config->ImportMemory) ++NumImports; @@ -162,15 +170,6 @@ void Writer::createImportSection() { writeUleb128(OS, NumImports, "import count"); - for (const FunctionSymbol *Sym : ImportedFunctions) { - WasmImport Import; - Import.Module = "env"; - Import.Field = Sym->getName(); - Import.Kind = WASM_EXTERNAL_FUNCTION; - Import.SigIndex = lookupType(*Sym->getFunctionType()); - writeImport(OS, Import); - } - if (Config->ImportMemory) { WasmImport Import; Import.Module = "env"; @@ -181,13 +180,18 @@ void Writer::createImportSection() { writeImport(OS, Import); } - for (const Symbol *Sym : ImportedGlobals) { + for (const Symbol *Sym : ImportedSymbols) { WasmImport Import; Import.Module = "env"; Import.Field = Sym->getName(); - Import.Kind = WASM_EXTERNAL_GLOBAL; - Import.Global.Mutable = false; - Import.Global.Type = WASM_TYPE_I32; + if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) { + Import.Kind = WASM_EXTERNAL_FUNCTION; + Import.SigIndex = lookupType(*FunctionSym->getFunctionType()); + } else { + auto *GlobalSym = cast<GlobalSymbol>(Sym); + Import.Kind = WASM_EXTERNAL_GLOBAL; + Import.Global = *GlobalSym->getGlobalType(); + } writeImport(OS, Import); } } @@ -225,17 +229,19 @@ void Writer::createMemorySection() { } void Writer::createGlobalSection() { - if (DefinedDataSymbols.empty()) + unsigned NumGlobals = InputGlobals.size() + DefinedFakeGlobals.size(); + if (NumGlobals == 0) return; SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); raw_ostream &OS = Section->getStream(); - writeUleb128(OS, DefinedDataSymbols.size(), "global count"); - for (const DefinedData *Sym : DefinedDataSymbols) { + writeUleb128(OS, NumGlobals, "global count"); + for (const InputGlobal *G : InputGlobals) + writeGlobal(OS, G->Global); + for (const DefinedData *Sym : DefinedFakeGlobals) { WasmGlobal Global; - Global.Type.Type = WASM_TYPE_I32; - Global.Type.Mutable = Sym == WasmSym::StackPointer; + Global.Type = {WASM_TYPE_I32, false}; Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); writeGlobal(OS, Global); @@ -283,15 +289,23 @@ void Writer::createExportSection() { writeExport(OS, MemoryExport); } - for (const WasmExportEntry &E : ExportedSymbols) { - DEBUG(dbgs() << "Export: " << E.Sym->getName() << "\n"); + unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size(); + for (const Symbol *Sym : ExportedSymbols) { + DEBUG(dbgs() << "Export: " << Sym->getName() << "\n"); WasmExport Export; - Export.Name = E.FieldName; - Export.Index = E.Sym->getOutputIndex(); - if (isa<FunctionSymbol>(E.Sym)) + Export.Name = Sym->getName(); + if (isa<FunctionSymbol>(Sym)) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_FUNCTION; - else + } else if (isa<GlobalSymbol>(Sym)) { + Export.Index = Sym->getOutputIndex(); Export.Kind = WASM_EXTERNAL_GLOBAL; + } else if (isa<DataSymbol>(Sym)) { + Export.Index = FakeGlobalIndex++; + Export.Kind = WASM_EXTERNAL_GLOBAL; + } else { + llvm_unreachable("unexpected symbol type"); + } writeExport(OS, Export); } } @@ -383,28 +397,39 @@ void Writer::createLinkingSection() { if (!Config->Relocatable) return; - std::vector<std::pair<StringRef, uint32_t>> SymbolInfo; - auto addSymInfo = [&](const Symbol *Sym, StringRef ExternalName) { - uint32_t Flags = - (Sym->isLocal() ? WASM_SYMBOL_BINDING_LOCAL : - Sym->isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0) | - (Sym->isHidden() ? WASM_SYMBOL_VISIBILITY_HIDDEN : 0); - if (Flags) - SymbolInfo.emplace_back(ExternalName, Flags); - }; - // (Imports can't have internal linkage, their names don't need to be budged.) - for (const Symbol *Sym : ImportedFunctions) - addSymInfo(Sym, Sym->getName()); - for (const Symbol *Sym : ImportedGlobals) - addSymInfo(Sym, Sym->getName()); - for (const WasmExportEntry &E : ExportedSymbols) - addSymInfo(E.Sym, E.FieldName); - if (!SymbolInfo.empty()) { - SubSection SubSection(WASM_SYMBOL_INFO); - writeUleb128(SubSection.getStream(), SymbolInfo.size(), "num sym info"); - for (auto Pair: SymbolInfo) { - writeStr(SubSection.getStream(), Pair.first, "sym name"); - writeUleb128(SubSection.getStream(), Pair.second, "sym flags"); + if (!SymtabEntries.empty()) { + SubSection SubSection(WASM_SYMBOL_TABLE); + writeUleb128(SubSection.getStream(), SymtabEntries.size(), "num symbols"); + for (const Symbol *Sym : SymtabEntries) { + assert(Sym->isDefined() || Sym->isUndefined()); + WasmSymbolType Kind = Sym->getWasmType(); + uint32_t Flags = Sym->isLocal() ? WASM_SYMBOL_BINDING_LOCAL : 0; + if (Sym->isWeak()) + Flags |= WASM_SYMBOL_BINDING_WEAK; + if (Sym->isHidden()) + Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; + if (Sym->isUndefined()) + Flags |= WASM_SYMBOL_UNDEFINED; + writeUleb128(SubSection.getStream(), Kind, "sym kind"); + writeUleb128(SubSection.getStream(), Flags, "sym flags"); + switch (Kind) { + case llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION: + case llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL: + writeUleb128(SubSection.getStream(), Sym->getOutputIndex(), "index"); + if (Sym->isDefined()) + writeStr(SubSection.getStream(), Sym->getName(), "sym name"); + break; + case llvm::wasm::WASM_SYMBOL_TYPE_DATA: + writeStr(SubSection.getStream(), Sym->getName(), "sym name"); + if (auto *DataSym = dyn_cast<DefinedData>(Sym)) { + writeUleb128(SubSection.getStream(), DataSym->getOutputSegmentIndex(), + "index"); + writeUleb128(SubSection.getStream(), + DataSym->getOutputSegmentOffset(), "data offset"); + writeUleb128(SubSection.getStream(), DataSym->getSize(), "data size"); + } + break; + } } SubSection.finalizeContents(); SubSection.writeToStream(OS); @@ -426,9 +451,10 @@ void Writer::createLinkingSection() { SubSection SubSection(WASM_INIT_FUNCS); writeUleb128(SubSection.getStream(), InitFunctions.size(), "num init functions"); - for (const WasmInitFunc &F : InitFunctions) { + for (const WasmInitEntry &F : InitFunctions) { writeUleb128(SubSection.getStream(), F.Priority, "priority"); - writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index"); + writeUleb128(SubSection.getStream(), F.Sym->getOutputSymbolIndex(), + "function index"); } SubSection.finalizeContents(); SubSection.writeToStream(OS); @@ -475,7 +501,7 @@ void Writer::createLinkingSection() { // Create the custom "name" section containing debug symbol names. void Writer::createNameSection() { - unsigned NumNames = ImportedFunctions.size(); + unsigned NumNames = NumImportedFunctions; for (const InputFunction *F : InputFunctions) if (!F->getName().empty()) ++NumNames; @@ -489,10 +515,12 @@ void Writer::createNameSection() { raw_ostream &OS = FunctionSubsection.getStream(); writeUleb128(OS, NumNames, "name count"); - // Names must appear in function index order. As it happens ImportedFunctions - // and InputFunctions are numbers in order with imported functions coming + // Names must appear in function index order. As it happens ImportedSymbols + // and InputFunctions are numbered in order with imported functions coming // first. - for (const Symbol *S : ImportedFunctions) { + for (const Symbol *S : ImportedSymbols) { + if (!isa<FunctionSymbol>(S)) + continue; writeUleb128(OS, S->getOutputIndex(), "import index"); writeStr(OS, S->getName(), "symbol name"); } @@ -562,8 +590,9 @@ void Writer::layoutMemory() { debugPrint("mem: stack size = %d\n", Config->ZStackSize); debugPrint("mem: stack base = %d\n", MemoryPtr); MemoryPtr += Config->ZStackSize; - WasmSym::StackPointer->setVirtualAddress(MemoryPtr); + WasmSym::StackPointer->Global->Global.InitExpr.Value.Int32 = MemoryPtr; debugPrint("mem: stack top = %d\n", MemoryPtr); + // Set `__heap_base` to directly follow the end of the stack. We don't // allocate any heap memory up front, but instead really on the malloc/brk // implementation growing the memory at runtime. @@ -614,69 +643,85 @@ void Writer::createSections() { void Writer::calculateImports() { for (Symbol *Sym : Symtab->getSymbols()) { - if (!Sym->isUndefined() || (Sym->isWeak() && !Config->Relocatable)) + if (!Sym->isUndefined()) + continue; + if (isa<DataSymbol>(Sym)) + continue; + if (Sym->isWeak() && !Config->Relocatable) continue; - if (auto *F = dyn_cast<FunctionSymbol>(Sym)) { - F->setOutputIndex(ImportedFunctions.size()); - ImportedFunctions.push_back(F); - } else if (auto *G = dyn_cast<DataSymbol>(Sym)) { - G->setOutputIndex(ImportedGlobals.size()); - ImportedGlobals.push_back(G); - } + DEBUG(dbgs() << "import: " << Sym->getName() << "\n"); + Sym->setOutputIndex(ImportedSymbols.size()); + ImportedSymbols.emplace_back(Sym); + if (isa<FunctionSymbol>(Sym)) + ++NumImportedFunctions; + else + ++NumImportedGlobals; } } void Writer::calculateExports() { - bool ExportHidden = Config->Relocatable; - StringSet<> UsedNames; - - auto BudgeLocalName = [&](const Symbol *Sym) { - StringRef SymName = Sym->getName(); - // We can't budge non-local names. - if (!Sym->isLocal()) - return SymName; - // We must budge local names that have a collision with a symbol that we - // haven't yet processed. - if (!Symtab->find(SymName) && UsedNames.insert(SymName).second) - return SymName; - for (unsigned I = 1; ; ++I) { - std::string NameBuf = (SymName + "." + Twine(I)).str(); - if (!UsedNames.count(NameBuf)) { - StringRef Name = Saver.save(NameBuf); - UsedNames.insert(Name); // Insert must use safe StringRef from save() - return Name; - } + if (Config->Relocatable) + return; + + auto ExportSym = [&](Symbol *Sym) { + if (!Sym->isDefined()) + return; + if (Sym->isHidden() || Sym->isLocal()) + return; + if (!Sym->isLive()) + return; + + DEBUG(dbgs() << "exporting sym: " << Sym->getName() << "\n"); + + if (auto *D = dyn_cast<DefinedData>(Sym)) { + // TODO Remove this check here; for non-relocatable output we actually + // used only to create fake-global exports for the synthetic symbols. Fix + // this in a future commit + if (Sym != WasmSym::DataEnd && Sym != WasmSym::HeapBase) + return; + DefinedFakeGlobals.emplace_back(D); } + ExportedSymbols.emplace_back(Sym); }; - if (WasmSym::CallCtors && (!WasmSym::CallCtors->isHidden() || ExportHidden)) - ExportedSymbols.emplace_back( - WasmExportEntry{WasmSym::CallCtors, WasmSym::CallCtors->getName()}); + // TODO The two loops below should be replaced with this single loop, with + // ExportSym inlined: + // for (Symbol *Sym : Symtab->getSymbols()) + // ExportSym(Sym); + // Making that change would reorder the output though, so it should be done as + // a separate commit. + + for (ObjFile *File : Symtab->ObjectFiles) + for (Symbol *Sym : File->getSymbols()) + if (File == Sym->getFile()) + ExportSym(Sym); + for (Symbol *Sym : Symtab->getSymbols()) + if (Sym->getFile() == nullptr) + ExportSym(Sym); +} + +void Writer::assignSymtab() { + if (!Config->Relocatable) + return; + + unsigned SymbolIndex = SymtabEntries.size(); for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Symtab entries: " << File->getName() << "\n"); for (Symbol *Sym : File->getSymbols()) { - if (!Sym->isDefined() || File != Sym->getFile()) - continue; - if (!isa<FunctionSymbol>(Sym)) - continue; - if (!Sym->getChunk()->Live) + if (Sym->getFile() != File) continue; - - if ((Sym->isHidden() || Sym->isLocal()) && !ExportHidden) - continue; - ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)}); + if (!Sym->isLive()) + return; + Sym->setOutputSymbolIndex(SymbolIndex++); + SymtabEntries.emplace_back(Sym); } } - for (const Symbol *Sym : DefinedDataSymbols) { - // Can't export the SP right now because its mutable, and mutuable globals - // are yet supported in the official binary format. - // TODO(sbc): Remove this if/when the "mutable global" proposal is accepted. - if (Sym == WasmSym::StackPointer) - continue; - ExportedSymbols.emplace_back(WasmExportEntry{Sym, BudgeLocalName(Sym)}); - } + // For the moment, relocatable output doesn't contain any synthetic functions, + // so no need to look through the Symtab for symbols not referenced by + // Symtab->ObjectFiles. } uint32_t Writer::lookupType(const WasmSignature &Sig) { @@ -710,45 +755,16 @@ void Writer::calculateTypes() { File->TypeMap[I] = registerType(Types[I]); } - for (const FunctionSymbol *Sym : ImportedFunctions) - registerType(*Sym->getFunctionType()); + for (const Symbol *Sym : ImportedSymbols) + if (auto *F = dyn_cast<FunctionSymbol>(Sym)) + registerType(*F->getFunctionType()); for (const InputFunction *F : InputFunctions) registerType(F->Signature); } void Writer::assignIndexes() { - uint32_t GlobalIndex = ImportedGlobals.size() + DefinedDataSymbols.size(); - uint32_t FunctionIndex = ImportedFunctions.size() + InputFunctions.size(); - - auto AddDefinedData = [&](DefinedData *Sym) { - if (Sym) { - DefinedDataSymbols.emplace_back(Sym); - Sym->setOutputIndex(GlobalIndex++); - } - }; - AddDefinedData(WasmSym::StackPointer); - AddDefinedData(WasmSym::HeapBase); - AddDefinedData(WasmSym::DataEnd); - - if (Config->Relocatable) - DefinedDataSymbols.reserve(Symtab->getSymbols().size()); - - uint32_t TableIndex = kInitialTableOffset; - - if (Config->Relocatable) { - for (ObjFile *File : Symtab->ObjectFiles) { - DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); - for (Symbol *Sym : File->getSymbols()) { - // Create wasm globals for data symbols defined in this file - if (File != Sym->getFile()) - continue; - if (auto *G = dyn_cast<DefinedData>(Sym)) - AddDefinedData(G); - } - } - } - + uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size(); for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); for (InputFunction *Func : File->Functions) { @@ -759,12 +775,13 @@ void Writer::assignIndexes() { } } + uint32_t TableIndex = kInitialTableOffset; auto HandleRelocs = [&](InputChunk *Chunk) { if (!Chunk->Live) return; ObjFile *File = Chunk->File; ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); - for (const WasmRelocation& Reloc : Chunk->getRelocations()) { + for (const WasmRelocation &Reloc : Chunk->getRelocations()) { if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32 || Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB) { FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); @@ -773,20 +790,45 @@ void Writer::assignIndexes() { Sym->setTableIndex(TableIndex++); IndirectFunctions.emplace_back(Sym); } else if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) { + // Mark target type as live File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); File->TypeIsUsed[Reloc.Index] = true; + } else if (Reloc.Type == R_WEBASSEMBLY_GLOBAL_INDEX_LEB) { + // Mark target global as live + GlobalSymbol *Sym = File->getGlobalSymbol(Reloc.Index); + if (auto *G = dyn_cast<DefinedGlobal>(Sym)) { + DEBUG(dbgs() << "marking global live: " << Sym->getName() << "\n"); + G->Global->Live = true; + } } } }; for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); - - for (InputChunk* Chunk : File->Functions) + for (InputChunk *Chunk : File->Functions) HandleRelocs(Chunk); - for (InputChunk* Chunk : File->Segments) + for (InputChunk *Chunk : File->Segments) HandleRelocs(Chunk); } + + uint32_t GlobalIndex = NumImportedGlobals + InputGlobals.size(); + auto AddDefinedGlobal = [&](InputGlobal *Global) { + if (Global->Live) { + DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n"); + Global->setOutputIndex(GlobalIndex++); + InputGlobals.push_back(Global); + } + }; + + if (WasmSym::StackPointer) + AddDefinedGlobal(WasmSym::StackPointer->Global); + + for (ObjFile *File : Symtab->ObjectFiles) { + DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); + for (InputGlobal *Global : File->Globals) + AddDefinedGlobal(Global); + } } static StringRef getOutputDataSegmentName(StringRef Name) { @@ -814,7 +856,7 @@ void Writer::createOutputSegments() { OutputSegment *&S = SegmentMap[Name]; if (S == nullptr) { DEBUG(dbgs() << "new segment: " << Name << "\n"); - S = make<OutputSegment>(Name); + S = make<OutputSegment>(Name, Segments.size()); Segments.push_back(S); } S->addInputSegment(Segment); @@ -829,18 +871,18 @@ static const int OPCODE_END = 0xb; // Create synthetic "__wasm_call_ctors" function based on ctor functions // in input object. void Writer::createCtorFunction() { - uint32_t FunctionIndex = ImportedFunctions.size() + InputFunctions.size(); + uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size(); WasmSym::CallCtors->setOutputIndex(FunctionIndex); // First write the body bytes to a string. std::string FunctionBody; - static WasmSignature Signature = {{}, WASM_TYPE_NORESULT}; + const WasmSignature *Signature = WasmSym::CallCtors->getFunctionType(); { raw_string_ostream OS(FunctionBody); writeUleb128(OS, 0, "num locals"); - for (const WasmInitFunc &F : InitFunctions) { + for (const WasmInitEntry &F : InitFunctions) { writeU8(OS, OPCODE_CALL, "CALL"); - writeUleb128(OS, F.FunctionIndex, "function index"); + writeUleb128(OS, F.Sym->getOutputIndex(), "function index"); } writeU8(OS, OPCODE_END, "END"); } @@ -853,9 +895,11 @@ void Writer::createCtorFunction() { ArrayRef<uint8_t> BodyArray( reinterpret_cast<const uint8_t *>(CtorFunctionBody.data()), CtorFunctionBody.size()); - SyntheticFunction *F = make<SyntheticFunction>(Signature, BodyArray, + SyntheticFunction *F = make<SyntheticFunction>(*Signature, BodyArray, WasmSym::CallCtors->getName()); F->setOutputIndex(FunctionIndex); + F->Live = true; + WasmSym::CallCtors->Function = F; InputFunctions.emplace_back(F); } @@ -867,13 +911,13 @@ void Writer::calculateInitFunctions() { const WasmLinkingData &L = File->getWasmObj()->linkingData(); InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size()); for (const WasmInitFunc &F : L.InitFunctions) - InitFunctions.emplace_back(WasmInitFunc{ - F.Priority, File->relocateFunctionIndex(F.FunctionIndex)}); + InitFunctions.emplace_back( + WasmInitEntry{File->getFunctionSymbol(F.Symbol), F.Priority}); } // Sort in order of priority (lowest first) so that they are called // in the correct order. std::stable_sort(InitFunctions.begin(), InitFunctions.end(), - [](const WasmInitFunc &L, const WasmInitFunc &R) { + [](const WasmInitEntry &L, const WasmInitEntry &R) { return L.Priority < R.Priority; }); } @@ -883,29 +927,28 @@ void Writer::run() { calculateImports(); log("-- assignIndexes"); assignIndexes(); - log("-- calculateExports"); - calculateExports(); log("-- calculateInitFunctions"); calculateInitFunctions(); if (!Config->Relocatable) createCtorFunction(); log("-- calculateTypes"); calculateTypes(); + log("-- layoutMemory"); + layoutMemory(); + log("-- calculateExports"); + calculateExports(); + log("-- assignSymtab"); + assignSymtab(); if (errorHandler().Verbose) { log("Defined Functions: " + Twine(InputFunctions.size())); - log("Defined Data Syms: " + Twine(DefinedDataSymbols.size())); - log("Function Imports : " + Twine(ImportedFunctions.size())); - log("Global Imports : " + Twine(ImportedGlobals.size())); - log("Total Imports : " + - Twine(ImportedFunctions.size() + ImportedGlobals.size())); + log("Defined Globals : " + Twine(InputGlobals.size())); + log("Function Imports : " + Twine(NumImportedFunctions)); + log("Global Imports : " + Twine(NumImportedGlobals)); for (ObjFile *File : Symtab->ObjectFiles) File->dumpInfo(); } - log("-- layoutMemory"); - layoutMemory(); - createHeader(); log("-- createSections"); createSections(); |