mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220952 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
534d9042b1
commit
a2715904e5
@ -301,9 +301,26 @@ public:
|
|||||||
|
|
||||||
uint8_t getComplexType() const { return (getType() & 0xF0) >> 4; }
|
uint8_t getComplexType() const { return (getType() & 0xF0) >> 4; }
|
||||||
|
|
||||||
|
bool isExternal() const {
|
||||||
|
return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isCommon() const {
|
||||||
|
return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
|
||||||
|
getValue() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isUndefined() const {
|
||||||
|
return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED &&
|
||||||
|
getValue() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isWeakExternal() const {
|
||||||
|
return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
bool isFunctionDefinition() const {
|
bool isFunctionDefinition() const {
|
||||||
return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
|
return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
|
||||||
getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
|
|
||||||
getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
|
getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
|
||||||
!COFF::isReservedSectionNumber(getSectionNumber());
|
!COFF::isReservedSectionNumber(getSectionNumber());
|
||||||
}
|
}
|
||||||
@ -312,10 +329,8 @@ public:
|
|||||||
return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
|
return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWeakExternal() const {
|
bool isAnyUndefined() const {
|
||||||
return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
|
return isUndefined() || isWeakExternal();
|
||||||
(getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
|
|
||||||
getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && getValue() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileRecord() const {
|
bool isFileRecord() const {
|
||||||
@ -329,6 +344,8 @@ public:
|
|||||||
getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
|
getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
|
||||||
getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
|
getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE;
|
||||||
bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
|
bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC;
|
||||||
|
if (!getNumberOfAuxSymbols())
|
||||||
|
return false;
|
||||||
return isAppdomainGlobal || isOrdinarySection;
|
return isAppdomainGlobal || isOrdinarySection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,39 +147,54 @@ std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref,
|
|||||||
std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref,
|
std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref,
|
||||||
uint64_t &Result) const {
|
uint64_t &Result) const {
|
||||||
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
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;
|
Result = UnknownAddressOrSize;
|
||||||
else if (Section)
|
return object_error::success;
|
||||||
|
}
|
||||||
|
if (Symb.isCommon()) {
|
||||||
|
Result = UnknownAddressOrSize;
|
||||||
|
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();
|
Result = Section->VirtualAddress + Symb.getValue();
|
||||||
else
|
return object_error::success;
|
||||||
Result = Symb.getValue();
|
}
|
||||||
|
|
||||||
|
Result = Symb.getValue();
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref,
|
std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref,
|
||||||
SymbolRef::Type &Result) const {
|
SymbolRef::Type &Result) const {
|
||||||
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
||||||
|
int32_t SectionNumber = Symb.getSectionNumber();
|
||||||
Result = SymbolRef::ST_Other;
|
Result = SymbolRef::ST_Other;
|
||||||
|
|
||||||
if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
|
if (Symb.isAnyUndefined()) {
|
||||||
Symb.getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED) {
|
|
||||||
Result = SymbolRef::ST_Unknown;
|
Result = SymbolRef::ST_Unknown;
|
||||||
} else if (Symb.isFunctionDefinition()) {
|
} else if (Symb.isFunctionDefinition()) {
|
||||||
Result = SymbolRef::ST_Function;
|
Result = SymbolRef::ST_Function;
|
||||||
} else {
|
} else if (Symb.isCommon()) {
|
||||||
uint32_t Characteristics = 0;
|
Result = SymbolRef::ST_Data;
|
||||||
if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
|
} else if (Symb.isFileRecord()) {
|
||||||
const coff_section *Section = nullptr;
|
Result = SymbolRef::ST_File;
|
||||||
if (std::error_code EC = getSection(Symb.getSectionNumber(), Section))
|
} else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) {
|
||||||
return EC;
|
Result = SymbolRef::ST_Debug;
|
||||||
Characteristics = Section->Characteristics;
|
} else if (!COFF::isReservedSectionNumber(SectionNumber)) {
|
||||||
}
|
const coff_section *Section = nullptr;
|
||||||
if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
|
if (std::error_code EC = getSection(SectionNumber, Section))
|
||||||
~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
|
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;
|
Result = SymbolRef::ST_Data;
|
||||||
}
|
}
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
@ -189,50 +204,66 @@ uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
|
|||||||
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
||||||
uint32_t Result = SymbolRef::SF_None;
|
uint32_t Result = SymbolRef::SF_None;
|
||||||
|
|
||||||
// TODO: Correctly set SF_FormatSpecific, SF_Common
|
if (Symb.isExternal() || Symb.isWeakExternal())
|
||||||
|
|
||||||
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)
|
|
||||||
Result |= SymbolRef::SF_Global;
|
Result |= SymbolRef::SF_Global;
|
||||||
|
|
||||||
if (Symb.getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)
|
if (Symb.isWeakExternal())
|
||||||
Result |= SymbolRef::SF_Weak;
|
Result |= SymbolRef::SF_Weak;
|
||||||
|
|
||||||
if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
|
if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE)
|
||||||
Result |= SymbolRef::SF_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;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref,
|
std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref,
|
||||||
uint64_t &Result) const {
|
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
|
// 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
|
// in the same section as this symbol, and looking for either the next
|
||||||
// symbol, or the end of the section.
|
// symbol, or the end of the section.
|
||||||
COFFSymbolRef Symb = getCOFFSymbol(Ref);
|
int32_t SectionNumber = Symb.getSectionNumber();
|
||||||
const coff_section *Section = nullptr;
|
if (!COFF::isReservedSectionNumber(SectionNumber)) {
|
||||||
if (std::error_code EC = getSection(Symb.getSectionNumber(), Section))
|
const coff_section *Section = nullptr;
|
||||||
return EC;
|
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();
|
Result = Section->SizeOfRawData - Symb.getValue();
|
||||||
} else {
|
return object_error::success;
|
||||||
Result = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result = 0;
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
# than 15 characters, thus, unlike coff_archive.lib, it has no string
|
# than 15 characters, thus, unlike coff_archive.lib, it has no string
|
||||||
# table as the third member.
|
# table as the third member.
|
||||||
#
|
#
|
||||||
RUN: llvm-nm --numeric-sort -M %p/Inputs/coff_archive_short.lib | FileCheck -check-prefix=CHECKIDX %s
|
RUN: llvm-nm -a --numeric-sort -M %p/Inputs/coff_archive_short.lib | FileCheck -check-prefix=CHECKIDX %s
|
||||||
|
|
||||||
CHECKIDX: Archive map
|
CHECKIDX: Archive map
|
||||||
CHECKIDX: _shortfn1 in short1.obj
|
CHECKIDX: _shortfn1 in short1.obj
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Check if the index is appearing properly in the output file
|
# Check if the index is appearing properly in the output file
|
||||||
#
|
#
|
||||||
RUN: llvm-nm --numeric-sort -M %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s
|
RUN: llvm-nm -a --numeric-sort -M %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s
|
||||||
|
|
||||||
CHECKIDX: Archive map
|
CHECKIDX: Archive map
|
||||||
CHECKIDX: ??0invalid_argument@std@@QAE@PBD@Z in Debug\mymath.obj
|
CHECKIDX: ??0invalid_argument@std@@QAE@PBD@Z in Debug\mymath.obj
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
RUN: llvm-nm %p/Inputs/archive-test.a-coff-i386 \
|
RUN: llvm-nm -a %p/Inputs/archive-test.a-coff-i386 \
|
||||||
RUN: | FileCheck %s -check-prefix COFF
|
RUN: | FileCheck %s -check-prefix COFF
|
||||||
|
|
||||||
COFF: trivial-object-test.coff-i386:
|
COFF: trivial-object-test.coff-i386:
|
||||||
@ -9,7 +9,7 @@ COFF-NEXT: U _SomeOtherFunction
|
|||||||
COFF-NEXT: 00000000 T _main
|
COFF-NEXT: 00000000 T _main
|
||||||
COFF-NEXT: U _puts
|
COFF-NEXT: U _puts
|
||||||
|
|
||||||
RUN: llvm-nm -o %p/Inputs/archive-test.a-coff-i386 \
|
RUN: llvm-nm -a -o %p/Inputs/archive-test.a-coff-i386 \
|
||||||
RUN: | FileCheck %s -check-prefix COFF-o
|
RUN: | FileCheck %s -check-prefix COFF-o
|
||||||
|
|
||||||
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d .data
|
COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d .data
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm - \
|
RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm -a - \
|
||||||
RUN: | FileCheck %s -check-prefix COFF
|
RUN: | FileCheck %s -check-prefix COFF
|
||||||
RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm - \
|
RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm -a - \
|
||||||
RUN: | FileCheck %s -check-prefix COFF
|
RUN: | FileCheck %s -check-prefix COFF
|
||||||
RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \
|
RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \
|
||||||
RUN: | FileCheck %s -check-prefix ELF
|
RUN: | FileCheck %s -check-prefix ELF
|
||||||
@ -36,7 +36,7 @@ RUN: llvm-nm -p -a %p/Inputs/macho-hello-g.macho-x86_64 \
|
|||||||
RUN: | FileCheck %s -check-prefix macho-pa
|
RUN: | FileCheck %s -check-prefix macho-pa
|
||||||
RUN: llvm-nm -u %p/Inputs/macho-hello-g.macho-x86_64 \
|
RUN: llvm-nm -u %p/Inputs/macho-hello-g.macho-x86_64 \
|
||||||
RUN: | FileCheck %s -check-prefix macho-u
|
RUN: | FileCheck %s -check-prefix macho-u
|
||||||
RUN: llvm-nm -S %p/Inputs/common.coff-i386 \
|
RUN: llvm-nm -S -a %p/Inputs/common.coff-i386 \
|
||||||
RUN: | FileCheck %s -check-prefix COFF-COMMON
|
RUN: | FileCheck %s -check-prefix COFF-COMMON
|
||||||
RUN: llvm-nm %p/Inputs/relocatable-with-section-address.elf-x86-64 \
|
RUN: llvm-nm %p/Inputs/relocatable-with-section-address.elf-x86-64 \
|
||||||
RUN: | FileCheck %s -check-prefix ELF-SEC-ADDR64
|
RUN: | FileCheck %s -check-prefix ELF-SEC-ADDR64
|
||||||
|
@ -721,18 +721,14 @@ static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
|
|||||||
// Check section type.
|
// Check section type.
|
||||||
if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
|
if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
|
||||||
return 't';
|
return 't';
|
||||||
else if (Characteristics & COFF::IMAGE_SCN_MEM_READ &&
|
if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
|
||||||
~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only.
|
return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
|
||||||
return 'r';
|
if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
|
||||||
else if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
|
|
||||||
return 'd';
|
|
||||||
else if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
|
|
||||||
return 'b';
|
return 'b';
|
||||||
else if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
|
if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
|
||||||
return 'i';
|
return 'i';
|
||||||
|
|
||||||
// Check for section symbol.
|
// Check for section symbol.
|
||||||
else if (Symb.isSectionDefinition())
|
if (Symb.isSectionDefinition())
|
||||||
return 's';
|
return 's';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +857,7 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) {
|
|||||||
W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
|
W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
|
||||||
W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
|
W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
|
||||||
|
|
||||||
} else if (Symbol.isWeakExternal()) {
|
} else if (Symbol.isAnyUndefined()) {
|
||||||
const coff_aux_weak_external *Aux;
|
const coff_aux_weak_external *Aux;
|
||||||
if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
|
if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
|
||||||
break;
|
break;
|
||||||
|
@ -161,7 +161,7 @@ void COFFDumper::dumpSymbols(unsigned NumSymbols) {
|
|||||||
reinterpret_cast<const object::coff_aux_bf_and_ef_symbol *>(
|
reinterpret_cast<const object::coff_aux_bf_and_ef_symbol *>(
|
||||||
AuxData.data());
|
AuxData.data());
|
||||||
dumpbfAndEfLineInfo(&Sym, ObjBES);
|
dumpbfAndEfLineInfo(&Sym, ObjBES);
|
||||||
} else if (Symbol.isWeakExternal()) {
|
} else if (Symbol.isAnyUndefined()) {
|
||||||
// This symbol represents a weak external definition.
|
// This symbol represents a weak external definition.
|
||||||
assert(Symbol.getNumberOfAuxSymbols() == 1 &&
|
assert(Symbol.getNumberOfAuxSymbols() == 1 &&
|
||||||
"Expected a single aux symbol to describe this weak symbol!");
|
"Expected a single aux symbol to describe this weak symbol!");
|
||||||
|
Loading…
Reference in New Issue
Block a user