static uint64_t getSymbolValue(const MCSymbolData &Data, const MCAsmLayout &Layout) { if (Data.isCommon() && Data.isExternal()) return Data.getCommonSize(); uint64_t Res; if (!Layout.getSymbolOffset(&Data, Res)) return 0; return Res; }
/// This function takes a symbol data object from the assembler /// and creates the associated COFF symbol staging object. void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler, const MCAsmLayout &Layout) { MCSymbol const &Symbol = SymbolData.getSymbol(); COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol); SymbolMap[&Symbol] = coff_symbol; if (SymbolData.getFlags() & COFF::SF_WeakExternal) { coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; if (Symbol.isVariable()) { const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); if (!SymRef) report_fatal_error("Weak externals may only alias symbols"); coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol()); } else { std::string WeakName = std::string(".weak.") + Symbol.getName().str() + ".default"; COFFSymbol *WeakDefault = createSymbol(WeakName); WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL; WeakDefault->Data.Type = 0; WeakDefault->Data.Value = 0; coff_symbol->Other = WeakDefault; } // Setup the Weak External auxiliary symbol. coff_symbol->Aux.resize(1); memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); coff_symbol->Aux[0].AuxType = ATWeakExternal; coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; coff_symbol->MCData = &SymbolData; } else { const MCSymbolData &ResSymData = Assembler.getSymbolData(Symbol.AliasedSymbol()); if (Symbol.isVariable()) { int64_t Addr; if (Symbol.getVariableValue()->EvaluateAsAbsolute(Addr, Layout)) coff_symbol->Data.Value = Addr; } else if (SymbolData.isExternal() && SymbolData.isCommon()) { coff_symbol->Data.Value = SymbolData.getCommonSize(); } coff_symbol->Data.Type = (ResSymData.getFlags() & 0x0000FFFF) >> 0; coff_symbol->Data.StorageClass = (ResSymData.getFlags() & 0x00FF0000) >> 16; // If no storage class was specified in the streamer, define it here. if (coff_symbol->Data.StorageClass == 0) { bool external = ResSymData.isExternal() || !ResSymData.Fragment; coff_symbol->Data.StorageClass = external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; } if (Symbol.isAbsolute() || Symbol.AliasedSymbol().isVariable()) coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; else if (ResSymData.Fragment) coff_symbol->Section = SectionMap[&ResSymData.Fragment->getParent()->getSection()]; coff_symbol->MCData = &ResSymData; } }