diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-10-31 05:07:00 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-10-31 05:07:00 +0000 |
commit | c7d7c6fb3a63538fb88cb2c529b691ba8ab7e44e (patch) | |
tree | 391556c9e217843c0b8fe886e34fae50fe3c48b2 /llvm/lib | |
parent | e5204efeaf1761005a08084b1d68019d8bbf8b66 (diff) | |
download | bcm5719-llvm-c7d7c6fb3a63538fb88cb2c529b691ba8ab7e44e.tar.gz bcm5719-llvm-c7d7c6fb3a63538fb88cb2c529b691ba8ab7e44e.zip |
Object, COFF: Cleanup symbol type code, improve binutils compatibility
Do a better job classifying symbols. This increases the consistency
between the COFF handling code and the ELF side of things.
llvm-svn: 220952
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Object/COFFObjectFile.cpp | 119 |
1 files changed, 75 insertions, 44 deletions
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 3beab00ed7d..a8ae5f15c41 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -147,39 +147,54 @@ std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, uint64_t &Result) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) - return EC; - if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) + if (Symb.isAnyUndefined()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + if (Symb.isCommon()) { Result = UnknownAddressOrSize; - else if (Section) + return object_error::success; + } + int32_t SectionNumber = Symb.getSectionNumber(); + if (!COFF::isReservedSectionNumber(SectionNumber)) { + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; + Result = Section->VirtualAddress + Symb.getValue(); - else - Result = Symb.getValue(); + return object_error::success; + } + + Result = Symb.getValue(); return object_error::success; } std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, SymbolRef::Type &Result) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); + int32_t SectionNumber = Symb.getSectionNumber(); Result = SymbolRef::ST_Other; - if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && - Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { + if (Symb.isAnyUndefined()) { Result = SymbolRef::ST_Unknown; } else if (Symb.isFunctionDefinition()) { Result = SymbolRef::ST_Function; - } else { - uint32_t Characteristics = 0; - if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) - return EC; - Characteristics = Section->Characteristics; - } - if (Characteristics & COFF::IMAGE_SCN_MEM_READ && - ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. + } else if (Symb.isCommon()) { + Result = SymbolRef::ST_Data; + } else if (Symb.isFileRecord()) { + Result = SymbolRef::ST_File; + } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { + Result = SymbolRef::ST_Debug; + } else if (!COFF::isReservedSectionNumber(SectionNumber)) { + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; + uint32_t Characteristics = Section->Characteristics; + if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) + Result = SymbolRef::ST_Function; + else if (Characteristics & (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) Result = SymbolRef::ST_Data; } return object_error::success; @@ -189,50 +204,66 @@ uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; - // TODO: Correctly set SF_FormatSpecific, SF_Common - - if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { - if (Symb.getValue() == 0) - Result |= SymbolRef::SF_Undefined; - else - Result |= SymbolRef::SF_Common; - } - - - // TODO: This are certainly too restrictive. - if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL) + if (Symb.isExternal() || Symb.isWeakExternal()) Result |= SymbolRef::SF_Global; - if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + 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; } std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, uint64_t &Result) const { + COFFSymbolRef Symb = getCOFFSymbol(Ref); + + if (Symb.isAnyUndefined()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + if (Symb.isCommon()) { + Result = Symb.getValue(); + return object_error::success; + } + if (Symb.isFunctionDefinition()) { + ArrayRef<uint8_t> AuxData = getSymbolAuxData(Symb); + if (!AuxData.empty()) { + const auto *CAFD = + reinterpret_cast<const coff_aux_function_definition *>( + AuxData.data()); + Result = CAFD->TotalSize; + return object_error::success; + } + } // FIXME: Return the correct size. This requires looking at all the symbols // in the same section as this symbol, and looking for either the next // symbol, or the end of the section. - COFFSymbolRef Symb = getCOFFSymbol(Ref); - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb.getSectionNumber(), Section)) - return EC; + int32_t SectionNumber = Symb.getSectionNumber(); + if (!COFF::isReservedSectionNumber(SectionNumber)) { + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; - if (Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) { - if (Symb.getValue() == 0) - Result = UnknownAddressOrSize; - else - Result = Symb.getValue(); - } else if (Section) { Result = Section->SizeOfRawData - Symb.getValue(); - } else { - Result = 0; + return object_error::success; } + Result = 0; return object_error::success; } |