Skip to content

Commit

Permalink
[llvm-nm][MachO] Don't call getFlags on redacted symbols
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
francisvm committed Dec 5, 2020
1 parent 2dc4a14 commit 3d381a7
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 6 deletions.
Binary file not shown.
16 changes: 16 additions & 0 deletions llvm/test/tools/llvm-nm/AArch64/macho-redacted-function.test
Original file line number Diff line number Diff line change
@@ -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
14 changes: 8 additions & 6 deletions llvm/tools/llvm-nm/llvm-nm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit 3d381a7

Please sign in to comment.