|
@@ -250,20 +250,52 @@ std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref,
|
|
|
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.
|
|
|
+
|
|
|
+ // Let's attempt to get the size of the symbol by looking at the address of
|
|
|
+ // the symbol after the symbol in question.
|
|
|
+ uint64_t SymbAddr;
|
|
|
+ if (std::error_code EC = getSymbolAddress(Ref, SymbAddr))
|
|
|
+ return EC;
|
|
|
int32_t SectionNumber = Symb.getSectionNumber();
|
|
|
- if (!COFF::isReservedSectionNumber(SectionNumber)) {
|
|
|
+ if (COFF::isReservedSectionNumber(SectionNumber)) {
|
|
|
+ // Absolute and debug symbols aren't sorted in any interesting way.
|
|
|
+ Result = 0;
|
|
|
+ return object_error::success;
|
|
|
+ }
|
|
|
+ const section_iterator SecEnd = section_end();
|
|
|
+ uint64_t AfterAddr = UnknownAddressOrSize;
|
|
|
+ for (const symbol_iterator &SymbI : symbols()) {
|
|
|
+ section_iterator SecI = SecEnd;
|
|
|
+ if (std::error_code EC = SymbI->getSection(SecI))
|
|
|
+ return EC;
|
|
|
+ // Check the symbol's section, skip it if it's in the wrong section.
|
|
|
+ // First, make sure it is in any section.
|
|
|
+ if (SecI == SecEnd)
|
|
|
+ continue;
|
|
|
+ // Second, make sure it is in the same section as the symbol in question.
|
|
|
+ if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref))
|
|
|
+ continue;
|
|
|
+ uint64_t Addr;
|
|
|
+ if (std::error_code EC = SymbI->getAddress(Addr))
|
|
|
+ return EC;
|
|
|
+ // We want to compare our symbol in question with the closest possible
|
|
|
+ // symbol that comes after.
|
|
|
+ if (AfterAddr > Addr && Addr > SymbAddr)
|
|
|
+ AfterAddr = Addr;
|
|
|
+ }
|
|
|
+ if (AfterAddr == UnknownAddressOrSize) {
|
|
|
+ // No symbol comes after this one, assume that everything after our symbol
|
|
|
+ // is part of it.
|
|
|
const coff_section *Section = nullptr;
|
|
|
if (std::error_code EC = getSection(SectionNumber, Section))
|
|
|
return EC;
|
|
|
-
|
|
|
Result = Section->SizeOfRawData - Symb.getValue();
|
|
|
- return object_error::success;
|
|
|
+ } else {
|
|
|
+ // Take the difference between our symbol and the symbol that comes after
|
|
|
+ // our symbol.
|
|
|
+ Result = AfterAddr - SymbAddr;
|
|
|
}
|
|
|
|
|
|
- Result = 0;
|
|
|
return object_error::success;
|
|
|
}
|
|
|
|