General clean up of Mach-O error handling in llvm-objdump.

To get a good error message for all files that could contain Mach-O
files the code in llvm-objdump needs to use the archive member name
and name of the architecture of a slice of a universal file in those cases
where the error come from a Mach-O file in an archive or a universal file.

Most of this is fixed by moving the call to checkSymbolTable() into
ProcessMachO() and calling it when the operation needs the symbol
table.  And then calling the form of report_error() that has the
ArchiveName and ArchitectureName arguments.  One other place
needed to call this form of report_error() also with these arguments.

Also changed the code in MachODump.cpp to not use report_fatal_error()
and use report_error() instead to make the code smaller and cleaner.  All
cases of this are for errors with the symbol table which should now never
be tripped since checkSymbolTable() should be called first to get a good
error message in these cases.

llvm-svn: 287050
This commit is contained in:
Kevin Enderby 2016-11-15 23:07:41 +00:00
parent 07529a313a
commit 844c4ac55a
5 changed files with 81 additions and 173 deletions

View File

@ -43,11 +43,20 @@
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-nsect 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-NSECT %s
INVALID-SYMBOL-NSECT: macho-invalid-symbol-nsect': truncated or malformed object (bad section index: 97 for symbol at index 1)
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-nsect-archive 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-NSECT-ARCHIVE %s
INVALID-SYMBOL-NSECT-ARCHIVE: macho-invalid-symbol-nsect-archive(macho-invalid-symbol-nsect): truncated or malformed object (bad section index: 97 for symbol at index 1)
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-indr 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-INDR %s
INVALID-SYMBOL-INDR: macho-invalid-symbol-indr': truncated or malformed object (bad n_value: 22 past the end of string table, for N_INDR symbol at index 1)
RUN: not llvm-objdump -macho -disassemble -arch all %p/Inputs/macho-invalid-symbol-indr-archive-universal 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-INDR-ARCHIVE-UNIVERSAL %s
INVALID-SYMBOL-INDR-ARCHIVE-UNIVERSAL: macho-invalid-symbol-indr-archive-universal(macho-invalid-symbol-indr) (for architecture i386): truncated or malformed object (bad n_value: 22 past the end of string table, for N_INDR symbol at index 1)
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-strx 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-STRX %s
INVALID-SYMBOL-STRX: macho-invalid-symbol-strx': truncated or malformed object (bad string table index: 22 past the end of string table, for symbol at index 1)
RUN: not llvm-objdump -macho -disassemble -arch all %p/Inputs/macho-invalid-symbol-strx-universal 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-STRX-UNIVERSAL %s
INVALID-SYMBOL-STRX-UNIVERSAL: macho-invalid-symbol-strx-universal' (for architecture i386): truncated or malformed object (bad string table index: 22 past the end of string table, for symbol at index 1)
RUN: not llvm-objdump -macho -disassemble %p/Inputs/macho-invalid-symbol-lib_ordinal 2>&1 | FileCheck -check-prefix INVALID-SYMBOL-LIB_ORDINAL %s
INVALID-SYMBOL-LIB_ORDINAL: macho-invalid-symbol-lib_ordinal': truncated or malformed object (bad library ordinal: 7 for symbol at index 2)

View File

@ -183,22 +183,12 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj,
struct SymbolSorter {
bool operator()(const SymbolRef &A, const SymbolRef &B) {
Expected<SymbolRef::Type> ATypeOrErr = A.getType();
if (!ATypeOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(ATypeOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!ATypeOrErr)
report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
SymbolRef::Type AType = *ATypeOrErr;
Expected<SymbolRef::Type> BTypeOrErr = B.getType();
if (!BTypeOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(BTypeOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!BTypeOrErr)
report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
SymbolRef::Type BType = *BTypeOrErr;
uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
@ -295,13 +285,8 @@ static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
uint64_t &BaseSegmentAddress) {
for (const SymbolRef &Symbol : MachOObj->symbols()) {
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(MachOObj->getFileName(), SymName.takeError());
if (!SymName->startswith("ltmp"))
Symbols.push_back(Symbol);
}
@ -380,13 +365,8 @@ static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(O->getFileName(), SymName.takeError());
outs() << *SymName;
} else {
outs() << "?";
@ -612,25 +592,15 @@ static void CreateSymbolAddressMap(MachOObjectFile *O,
// Create a map of symbol addresses to symbol names.
for (const SymbolRef &Symbol : O->symbols()) {
Expected<SymbolRef::Type> STOrErr = Symbol.getType();
if (!STOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(STOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!STOrErr)
report_error(O->getFileName(), STOrErr.takeError());
SymbolRef::Type ST = *STOrErr;
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
uint64_t Address = Symbol.getValue();
Expected<StringRef> SymNameOrErr = Symbol.getName();
if (!SymNameOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymNameOrErr)
report_error(O->getFileName(), SymNameOrErr.takeError());
StringRef SymName = *SymNameOrErr;
if (!SymName.startswith(".objc"))
(*AddrMap)[Address] = SymName;
@ -865,13 +835,8 @@ static void DumpLiteralPointerSection(MachOObjectFile *O,
if (Reloc != Relocs.end()) {
symbol_iterator RelocSym = Reloc->second;
Expected<StringRef> SymName = RelocSym->getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(O->getFileName(), SymName.takeError());
outs() << "external relocation entry for symbol:" << *SymName << "\n";
continue;
}
@ -1216,7 +1181,7 @@ static void printObjcMetaData(MachOObjectFile *O, bool verbose);
// archive member and or in a slice of a universal file. It prints the
// the file name and header info and then processes it according to the
// command line options.
static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
StringRef ArchiveMemberName = StringRef(),
StringRef ArchitectureName = StringRef()) {
// If we are doing some processing here on the Mach-O file print the header
@ -1225,16 +1190,35 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
outs() << Filename;
outs() << Name;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << ":\n";
}
// To use the report_error() form with an ArchiveName and FileName set
// these up based on what is passed for Name and ArchiveMemberName.
StringRef ArchiveName;
StringRef FileName;
if (!ArchiveMemberName.empty()) {
ArchiveName = Name;
FileName = ArchiveMemberName;
} else {
ArchiveName = StringRef();
FileName = Name;
}
// If we need the symbol table to do the operation then check it here to
// produce a good error message as to where the Mach-O file comes from in
// the error message.
if (Disassemble || IndirectSymbols || FilterSections.size() != 0 ||
UnwindInfo)
if (Error Err = MachOOF->checkSymbolTable())
report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
if (Disassemble)
DisassembleMachO(Filename, MachOOF, "__TEXT", "__text");
DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
if (IndirectSymbols)
PrintIndirectSymbols(MachOOF, !NonVerbose);
if (DataInCode)
@ -1248,17 +1232,15 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
if (SectionContents)
PrintSectionContents(MachOOF);
if (FilterSections.size() != 0)
DumpSectionContents(Filename, MachOOF, !NonVerbose);
DumpSectionContents(FileName, MachOOF, !NonVerbose);
if (InfoPlist)
DumpInfoPlistSectionContents(Filename, MachOOF);
DumpInfoPlistSectionContents(FileName, MachOOF);
if (DylibsUsed)
PrintDylibs(MachOOF, false);
if (DylibId)
PrintDylibs(MachOOF, true);
if (SymbolTable) {
StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename;
if (SymbolTable)
PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
}
if (UnwindInfo)
printMachOUnwindInfo(MachOOF);
if (PrivateHeaders) {
@ -1552,7 +1534,7 @@ static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
if (Err)
report_error(Filename, std::move(Err));
report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
}
// ParseInputMachO() parses the named Mach-O file in Filename and handles the
@ -1896,13 +1878,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
}
if (reloc_found && isExtern) {
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@ -1971,13 +1948,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (info->O->getAnyRelocationPCRel(RE))
op_info->Value -= Pc + Offset + Size;
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
unsigned Type = info->O->getAnyRelocationType(RE);
if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
@ -1993,13 +1965,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
Symbol = *RelocSymNext;
Expected<StringRef> SymNameNext = Symbol.getName();
if (!SymNameNext) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymNameNext.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymNameNext)
report_error(info->O->getFileName(), SymNameNext.takeError());
name = SymNameNext->data();
}
}
@ -2070,13 +2037,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (isExtern) {
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@ -2194,13 +2156,8 @@ static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
if (!info->O->getPlainRelocationExternal(RE))
return 0;
Expected<StringRef> SymName = Reloc->getSymbol()->getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
@ -2329,13 +2286,8 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
return name;
}
@ -2369,13 +2321,8 @@ static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
SymbolRef Symbol = *Sym;
Expected<StringRef> SymName = Symbol.getName();
if (!SymName) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymName.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymName)
report_error(info->O->getFileName(), SymName.takeError());
const char *name = SymName->data();
return name;
}
@ -2603,13 +2550,8 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
if (reloc_found && isExtern) {
n_value = Symbol.getValue();
Expected<StringRef> NameOrError = Symbol.getName();
if (!NameOrError) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(NameOrError.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!NameOrError)
report_error(info->O->getFileName(), NameOrError.takeError());
StringRef Name = *NameOrError;
if (!Name.empty()) {
SymbolName = Name.data();
@ -6523,9 +6465,6 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SmallVector<uint64_t, 8> FoundFns;
uint64_t BaseSegmentAddress;
if (Error Err = MachOOF->checkSymbolTable())
report_error(Filename, std::move(Err));
getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
BaseSegmentAddress);
@ -6604,25 +6543,15 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
bool DisSymNameFound = false;
for (const SymbolRef &Symbol : MachOOF->symbols()) {
Expected<SymbolRef::Type> STOrErr = Symbol.getType();
if (!STOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(STOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!STOrErr)
report_error(MachOOF->getFileName(), STOrErr.takeError());
SymbolRef::Type ST = *STOrErr;
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
uint64_t Address = Symbol.getValue();
Expected<StringRef> SymNameOrErr = Symbol.getName();
if (!SymNameOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymNameOrErr)
report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
StringRef SymName = *SymNameOrErr;
AddrMap[Address] = SymName;
if (!DisSymName.empty() && DisSymName == SymName)
@ -6669,23 +6598,13 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
// Disassemble symbol by symbol.
for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
if (!SymNameOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SymNameOrErr)
report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
StringRef SymName = *SymNameOrErr;
Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
if (!STOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(STOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!STOrErr)
report_error(MachOOF->getFileName(), STOrErr.takeError());
SymbolRef::Type ST = *STOrErr;
if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
continue;
@ -6740,13 +6659,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
uint64_t NextSymIdx = SymIdx + 1;
while (Symbols.size() > NextSymIdx) {
Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
if (!STOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(STOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!STOrErr)
report_error(MachOOF->getFileName(), STOrErr.takeError());
SymbolRef::Type NextSymType = *STOrErr;
if (NextSymType == SymbolRef::ST_Function) {
containsNextSym =
@ -6992,13 +6906,8 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
StringRef &Name, uint64_t &Addend) {
if (Reloc.getSymbol() != Obj->symbol_end()) {
Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
if (!NameOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!NameOrErr)
report_error(Obj->getFileName(), NameOrErr.takeError());
Name = *NameOrErr;
Addend = Addr;
return;
@ -7022,24 +6931,14 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
--Sym;
auto SectOrErr = Sym->second.getSection();
if (!SectOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!SectOrErr)
report_error(Obj->getFileName(), SectOrErr.takeError());
section_iterator SymSection = *SectOrErr;
if (RelocSection == *SymSection) {
// There's a valid symbol in the same section before this reference.
Expected<StringRef> NameOrErr = Sym->second.getName();
if (!NameOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
OS.flush();
report_fatal_error(Buf);
}
if (!NameOrErr)
report_error(Obj->getFileName(), NameOrErr.takeError());
Name = *NameOrErr;
Addend = Addr - Sym->first;
return;