llvm-objdump should ignore Mach-O stab symbols for disassembly.

Summary:
llvm-objdump will commonly error out when disassembling a Mach-O binary with
stab symbols, or when printing a Mach-O symbol table that includesstab symbols.
That is because the Mach-O N_OSO symbol has been modified to include the
bottom 8-bit value of the Mach-O's cpusubtype value in the section field. In
general, one cannot blindly assume a stab symbol's section field is valid
unless one has actually consulted the specification for the specific stab.

Since objdump mostly just walks the symbol table to get mnemonics for code
disassembly it's best for objdump to just ignore stab symbols. llvm-nm will
do a more complete and correct job of displaying Mach-O symbol table contents.

Reviewers: pete, lhames, ab, thegameg, jhenderson, MaskRay

Reviewed By: thegameg, MaskRay

Subscribers: MaskRay, rupprecht, seiya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D71394
This commit is contained in:
Michael Trent 2019-12-11 22:43:46 -08:00
parent adf7a0a558
commit f72d001e09
3 changed files with 33 additions and 2 deletions

Binary file not shown.

View File

@ -0,0 +1,2 @@
# RUN: llvm-objdump --syms %p/Inputs/macho-stabs-x86_64
# RUN: llvm-objdump -D %p/Inputs/macho-stabs-x86_64

View File

@ -1134,6 +1134,7 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
std::map<SectionRef, SectionSymbolsTy> AllSymbols;
SectionSymbolsTy AbsoluteSymbols;
const StringRef FileName = Obj->getFileName();
const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj);
for (const SymbolRef &Symbol : Obj->symbols()) {
uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName);
@ -1148,6 +1149,18 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
continue;
}
// Don't ask a Mach-O STAB symbol for its section unless you know that
// STAB symbol's section field refers to a valid section index. Otherwise
// the symbol may error trying to load a section that does not exist.
if (MachO) {
DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
uint8_t NType = (MachO->is64Bit() ?
MachO->getSymbol64TableEntry(SymDRI).n_type:
MachO->getSymbolTableEntry(SymDRI).n_type);
if (NType & MachO::N_STAB)
continue;
}
section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
if (SecI != Obj->section_end())
AllSymbols[*SecI].emplace_back(Address, Name, SymbolType);
@ -1244,7 +1257,7 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj,
}
StringRef SegmentName = "";
if (const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(Obj)) {
if (MachO) {
DataRefImpl DR = Section.getRawDataRefImpl();
SegmentName = MachO->getSectionFinalSegmentName(DR);
}
@ -1804,6 +1817,7 @@ void printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
}
const StringRef FileName = O->getFileName();
const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(O);
for (auto I = O->symbol_begin(), E = O->symbol_end(); I != E; ++I) {
const SymbolRef &Symbol = *I;
uint64_t Address = unwrapOrError(Symbol.getAddress(), FileName, ArchiveName,
@ -1813,8 +1827,23 @@ void printSymbolTable(const ObjectFile *O, StringRef ArchiveName,
SymbolRef::Type Type = unwrapOrError(Symbol.getType(), FileName,
ArchiveName, ArchitectureName);
uint32_t Flags = Symbol.getFlags();
section_iterator Section = unwrapOrError(Symbol.getSection(), FileName,
// Don't ask a Mach-O STAB symbol for its section unless you know that
// STAB symbol's section field refers to a valid section index. Otherwise
// the symbol may error trying to load a section that does not exist.
bool isSTAB = false;
if (MachO) {
DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
uint8_t NType = (MachO->is64Bit() ?
MachO->getSymbol64TableEntry(SymDRI).n_type:
MachO->getSymbolTableEntry(SymDRI).n_type);
if (NType & MachO::N_STAB)
isSTAB = true;
}
section_iterator Section = isSTAB ? O->section_end() :
unwrapOrError(Symbol.getSection(), FileName,
ArchiveName, ArchitectureName);
StringRef Name;
if (Type == SymbolRef::ST_Debug && Section != O->section_end()) {
if (Expected<StringRef> NameOrErr = Section->getName())