Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { // Relative symbols are unrepresentable in a COFF symbol table. if (isa<DefinedSynthetic>(Def)) return None; if (auto *D = dyn_cast<DefinedRegular>(Def)) { // Don't write dead symbols or symbols in codeview sections to the symbol // table. if (!D->getChunk()->isLive() || D->getChunk()->isCodeView()) return None; } if (auto *Sym = dyn_cast<DefinedImportData>(Def)) if (!Sym->File->Live) return None; if (auto *Sym = dyn_cast<DefinedImportThunk>(Def)) if (!Sym->WrappedSym->File->Live) return None; coff_symbol16 Sym; StringRef Name = Def->getName(); if (Name.size() > COFF::NameSize) { Sym.Name.Offset.Zeroes = 0; Sym.Name.Offset.Offset = addEntryToStringTable(Name); } else { memset(Sym.Name.ShortName, 0, COFF::NameSize); memcpy(Sym.Name.ShortName, Name.data(), Name.size()); } if (auto *D = dyn_cast<DefinedCOFF>(Def)) { COFFSymbolRef Ref = D->getCOFFSymbol(); Sym.Type = Ref.getType(); Sym.StorageClass = Ref.getStorageClass(); } else { Sym.Type = IMAGE_SYM_TYPE_NULL; Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL; } Sym.NumberOfAuxSymbols = 0; switch (Def->kind()) { case SymbolBody::DefinedAbsoluteKind: Sym.Value = Def->getRVA(); Sym.SectionNumber = IMAGE_SYM_ABSOLUTE; break; default: { uint64_t RVA = Def->getRVA(); OutputSection *Sec = nullptr; for (OutputSection *S : OutputSections) { if (S->getRVA() > RVA) break; Sec = S; } Sym.Value = RVA - Sec->getRVA(); Sym.SectionNumber = Sec->SectionIndex; break; } } return Sym; }
uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; if (Symb.isExternal() || Symb.isWeakExternal()) Result |= SymbolRef::SF_Global; if (Symb.isWeakExternal()) Result |= SymbolRef::SF_Weak; if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) Result |= SymbolRef::SF_Absolute; if (Symb.isFileRecord()) Result |= SymbolRef::SF_FormatSpecific; if (Symb.isSectionDefinition()) Result |= SymbolRef::SF_FormatSpecific; if (Symb.isCommon()) Result |= SymbolRef::SF_Common; if (Symb.isAnyUndefined()) Result |= SymbolRef::SF_Undefined; return Result; }
ErrorOr<section_iterator> COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) return section_end(); const coff_section *Sec = nullptr; if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) return EC; DataRefImpl Ret; Ret.p = reinterpret_cast<uintptr_t>(Sec); return section_iterator(SectionRef(Ret, this)); }
static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); // OK, this is COFF. symbol_iterator SymI(I); StringRef Name; if (error(SymI->getName(Name))) return '?'; char Ret = StringSwitch<char>(Name) .StartsWith(".debug", 'N') .StartsWith(".sxdata", 'N') .Default('?'); if (Ret != '?') return Ret; uint32_t Characteristics = 0; if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { section_iterator SecI = Obj.section_end(); if (error(SymI->getSection(SecI))) return '?'; const coff_section *Section = Obj.getCOFFSection(*SecI); Characteristics = Section->Characteristics; } switch (Symb.getSectionNumber()) { case COFF::IMAGE_SYM_DEBUG: return 'n'; default: // Check section type. if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) return 't'; else if (Characteristics & COFF::IMAGE_SCN_MEM_READ && ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. return 'r'; else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) return 'd'; else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) return 'b'; else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) return 'i'; // Check for section symbol. else if (Symb.isSectionDefinition()) return 's'; } return '?'; }
Optional<coff_symbol16> Writer::createSymbol(Defined *Def) { if (auto *D = dyn_cast<DefinedRegular>(Def)) if (!D->getChunk()->isLive()) return None; coff_symbol16 Sym; StringRef Name = Def->getName(); if (Name.size() > COFF::NameSize) { Sym.Name.Offset.Zeroes = 0; Sym.Name.Offset.Offset = addEntryToStringTable(Name); } else { memset(Sym.Name.ShortName, 0, COFF::NameSize); memcpy(Sym.Name.ShortName, Name.data(), Name.size()); } if (auto *D = dyn_cast<DefinedCOFF>(Def)) { COFFSymbolRef Ref = D->getCOFFSymbol(); Sym.Type = Ref.getType(); Sym.StorageClass = Ref.getStorageClass(); } else { Sym.Type = IMAGE_SYM_TYPE_NULL; Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL; } Sym.NumberOfAuxSymbols = 0; switch (Def->kind()) { case SymbolBody::DefinedAbsoluteKind: case SymbolBody::DefinedRelativeKind: Sym.Value = Def->getRVA(); Sym.SectionNumber = IMAGE_SYM_ABSOLUTE; break; default: { uint64_t RVA = Def->getRVA(); OutputSection *Sec = nullptr; for (OutputSection *S : OutputSections) { if (S->getRVA() > RVA) break; Sec = S; } Sym.Value = RVA - Sec->getRVA(); Sym.SectionNumber = Sec->SectionIndex; break; } } return Sym; }
ErrorOr<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { uint64_t Result = getSymbolValue(Ref); COFFSymbolRef Symb = getCOFFSymbol(Ref); int32_t SectionNumber = Symb.getSectionNumber(); if (Symb.isAnyUndefined() || Symb.isCommon() || COFF::isReservedSectionNumber(SectionNumber)) return Result; const coff_section *Section = nullptr; if (std::error_code EC = getSection(SectionNumber, Section)) return EC; Result += Section->VirtualAddress; // The section VirtualAddress does not include ImageBase, and we want to // return virtual addresses. Result += getImageBase(); return Result; }
ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { const uint8_t *Aux = nullptr; size_t SymbolSize = getSymbolTableEntrySize(); if (Symbol.getNumberOfAuxSymbols() > 0) { // AUX data comes immediately after the symbol in COFF Aux = reinterpret_cast<const uint8_t *>(Symbol.getRawPtr()) + SymbolSize; # ifndef NDEBUG // Verify that the Aux symbol points to a valid entry in the symbol table. uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); if (Offset < getPointerToSymbolTable() || Offset >= getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) report_fatal_error("Aux Symbol data was outside of symbol table."); assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && "Aux Symbol data did not point to the beginning of a symbol"); # endif } return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); }
ErrorOr<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); int32_t SectionNumber = Symb.getSectionNumber(); if (Symb.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) return SymbolRef::ST_Function; if (Symb.isAnyUndefined()) return SymbolRef::ST_Unknown; if (Symb.isCommon()) return SymbolRef::ST_Data; if (Symb.isFileRecord()) return SymbolRef::ST_File; // TODO: perhaps we need a new symbol type ST_Section. if (SectionNumber == COFF::IMAGE_SYM_DEBUG || Symb.isSectionDefinition()) return SymbolRef::ST_Debug; if (!COFF::isReservedSectionNumber(SectionNumber)) return SymbolRef::ST_Data; return SymbolRef::ST_Other; }
void ObjectFile::initializeSymbols() { uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); SymbolBodies.reserve(NumSymbols); SparseSymbolBodies.resize(NumSymbols); llvm::SmallVector<std::pair<Undefined *, uint32_t>, 8> WeakAliases; int32_t LastSectionNumber = 0; for (uint32_t I = 0; I < NumSymbols; ++I) { // Get a COFFSymbolRef object. auto SymOrErr = COFFObj->getSymbol(I); error(SymOrErr, Twine("broken object file: ") + getName()); COFFSymbolRef Sym = *SymOrErr; const void *AuxP = nullptr; if (Sym.getNumberOfAuxSymbols()) AuxP = COFFObj->getSymbol(I + 1)->getRawPtr(); bool IsFirst = (LastSectionNumber != Sym.getSectionNumber()); SymbolBody *Body = nullptr; if (Sym.isUndefined()) { Body = createUndefined(Sym); } else if (Sym.isWeakExternal()) { Body = createUndefined(Sym); uint32_t TagIndex = static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex; WeakAliases.emplace_back((Undefined *)Body, TagIndex); } else { Body = createDefined(Sym, AuxP, IsFirst); } if (Body) { SymbolBodies.push_back(Body); SparseSymbolBodies[I] = Body; } I += Sym.getNumberOfAuxSymbols(); LastSectionNumber = Sym.getSectionNumber(); } for (auto WeakAlias : WeakAliases) WeakAlias.first->WeakAlias = SparseSymbolBodies[WeakAlias.second]; }
void ObjectFile::initializeSymbols() { uint32_t NumSymbols = COFFObj->getNumberOfSymbols(); SymbolBodies.reserve(NumSymbols); SparseSymbolBodies.resize(NumSymbols); llvm::SmallVector<Undefined *, 8> WeakAliases; int32_t LastSectionNumber = 0; for (uint32_t I = 0; I < NumSymbols; ++I) { // Get a COFFSymbolRef object. auto SymOrErr = COFFObj->getSymbol(I); error(SymOrErr, Twine("broken object file: ") + getName()); COFFSymbolRef Sym = *SymOrErr; const void *AuxP = nullptr; if (Sym.getNumberOfAuxSymbols()) AuxP = COFFObj->getSymbol(I + 1)->getRawPtr(); bool IsFirst = (LastSectionNumber != Sym.getSectionNumber()); SymbolBody *Body = nullptr; if (Sym.isUndefined()) { Body = createUndefined(Sym); } else if (Sym.isWeakExternal()) { Body = createWeakExternal(Sym, AuxP); WeakAliases.push_back((Undefined *)Body); } else { Body = createDefined(Sym, AuxP, IsFirst); } if (Body) { SymbolBodies.push_back(Body); SparseSymbolBodies[I] = Body; } I += Sym.getNumberOfAuxSymbols(); LastSectionNumber = Sym.getSectionNumber(); } for (Undefined *U : WeakAliases) U->WeakAlias = SparseSymbolBodies[(uintptr_t)U->WeakAlias]; }
void COFFDumper::printSymbol(const SymbolRef &Sym) { DictScope D(W, "Symbol"); COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym); const coff_section *Section; if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) { W.startLine() << "Invalid section number: " << EC.message() << "\n"; W.flush(); return; } StringRef SymbolName; if (Obj->getSymbolName(Symbol, SymbolName)) SymbolName = ""; StringRef SectionName = ""; ErrorOr<StringRef> Res = getSectionName(Obj, Symbol.getSectionNumber(), Section); if (Res) SectionName = *Res; W.printString("Name", SymbolName); W.printNumber("Value", Symbol.getValue()); W.printNumber("Section", SectionName, Symbol.getSectionNumber()); W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType)); W.printEnum ("ComplexType", Symbol.getComplexType(), makeArrayRef(ImageSymDType)); W.printEnum ("StorageClass", Symbol.getStorageClass(), makeArrayRef(ImageSymClass)); W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols()); for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) { if (Symbol.isFunctionDefinition()) { const coff_aux_function_definition *Aux; error(getSymbolAuxData(Obj, Symbol, I, Aux)); DictScope AS(W, "AuxFunctionDef"); W.printNumber("TagIndex", Aux->TagIndex); W.printNumber("TotalSize", Aux->TotalSize); W.printHex("PointerToLineNumber", Aux->PointerToLinenumber); W.printHex("PointerToNextFunction", Aux->PointerToNextFunction); } else if (Symbol.isAnyUndefined()) { const coff_aux_weak_external *Aux; error(getSymbolAuxData(Obj, Symbol, I, Aux)); ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex); StringRef LinkedName; std::error_code EC = Linked.getError(); if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) { LinkedName = ""; error(EC); } DictScope AS(W, "AuxWeakExternal"); W.printNumber("Linked", LinkedName, Aux->TagIndex); W.printEnum ("Search", Aux->Characteristics, makeArrayRef(WeakExternalCharacteristics)); } else if (Symbol.isFileRecord()) { const char *FileName; error(getSymbolAuxData(Obj, Symbol, I, FileName)); DictScope AS(W, "AuxFileRecord"); StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() * Obj->getSymbolTableEntrySize()); W.printString("FileName", Name.rtrim(StringRef("\0", 1))); break; } else if (Symbol.isSectionDefinition()) { const coff_aux_section_definition *Aux; error(getSymbolAuxData(Obj, Symbol, I, Aux)); int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj()); DictScope AS(W, "AuxSectionDef"); W.printNumber("Length", Aux->Length); W.printNumber("RelocationCount", Aux->NumberOfRelocations); W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers); W.printHex("Checksum", Aux->CheckSum); W.printNumber("Number", AuxNumber); W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { const coff_section *Assoc; StringRef AssocName = ""; std::error_code EC = Obj->getSection(AuxNumber, Assoc); ErrorOr<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc); if (Res) AssocName = *Res; if (!EC) EC = Res.getError(); if (EC) { AssocName = ""; error(EC); } W.printNumber("AssocSection", AssocName, AuxNumber); } } else if (Symbol.isCLRToken()) { const coff_aux_clr_token *Aux; error(getSymbolAuxData(Obj, Symbol, I, Aux)); ErrorOr<COFFSymbolRef> ReferredSym = Obj->getSymbol(Aux->SymbolTableIndex); StringRef ReferredName; std::error_code EC = ReferredSym.getError(); if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) { ReferredName = ""; error(EC); } DictScope AS(W, "AuxCLRToken"); W.printNumber("AuxType", Aux->AuxType); W.printNumber("Reserved", Aux->Reserved); W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); } else { W.startLine() << "<unhandled auxiliary record>\n"; } } }
std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const { return getSymbolName(Symbol.getGeneric(), Res); }
unsigned COFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { COFFSymbolRef Symb = getCOFFSymbol(Sym.getRawDataRefImpl()); return Symb.getSectionNumber(); }
uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); return Symb.getValue(); }