[llvm-nm][MachO] Don't call getFlags on redacted symbols

Avoid calling getFlags on a non-existent symbol.

The way this is triggered is by calling strip -N on a binary, which sets
the MH_NLIST_OUTOFSYNC_WITH_DYLDINFO header flag. Then, in the
LC_FUNCTION_STARTS command, nm is trying to print the stripped symbols
and needs the proper checks.
This commit is contained in:
Francis Visoiu Mistrih 2020-12-04 20:10:06 -08:00
parent 2dc4a14e4d
commit 3d381a7102
3 changed files with 24 additions and 6 deletions

View File

@ -0,0 +1,16 @@
RUN: llvm-nm %p/Inputs/redacted-function.macho-aarch64 | FileCheck %s
CHECK: <redacted function 1>
# Generated with:
# $ cat /tmp/a.c
# static int i(void) {
# return 0;
# }
#
# int main(void) {
# return i();
# }
#
# $ xcrun -sdk watchos clang -arch arm64_32 /tmp/a.c -o /tmp/redacted-function.macho-aarch64
# $ xcrun -sdk watchos strip -N /tmp/redacted-function.macho-aarch64

View File

@ -316,18 +316,20 @@ struct NMSymbol {
static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
bool ADefined;
// Symbol flags have been checked in the caller.
uint32_t AFlags = cantFail(A.Sym.getFlags());
if (A.Sym.getRawDataRefImpl().p)
if (A.Sym.getRawDataRefImpl().p) {
uint32_t AFlags = cantFail(A.Sym.getFlags());
ADefined = !(AFlags & SymbolRef::SF_Undefined);
else
} else {
ADefined = A.TypeChar != 'U';
}
bool BDefined;
// Symbol flags have been checked in the caller.
uint32_t BFlags = cantFail(B.Sym.getFlags());
if (B.Sym.getRawDataRefImpl().p)
if (B.Sym.getRawDataRefImpl().p) {
uint32_t BFlags = cantFail(B.Sym.getFlags());
BDefined = !(BFlags & SymbolRef::SF_Undefined);
else
} else {
BDefined = B.TypeChar != 'U';
}
return std::make_tuple(ADefined, A.Address, A.Name, A.Size) <
std::make_tuple(BDefined, B.Address, B.Name, B.Size);
}