Disassembled("d", cl::desc("Alias for --disassemble"),
cl::aliasopt(Disassemble));
+cl::opt<bool>
+llvm::DisassembleAll("disassemble-all",
+ cl::desc("Display assembler mnemonics for the machine instructions"));
+static cl::alias
+DisassembleAlld("D", cl::desc("Alias for --disassemble-all"),
+ cl::aliasopt(DisassembleAll));
+
cl::opt<bool>
llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
cl::opt<bool>
llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info"));
+cl::opt<bool>
+llvm::RawClangAST("raw-clang-ast",
+ cl::desc("Dump the raw binary contents of the clang AST section"));
+
static cl::opt<bool>
MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
static cl::alias
static cl::alias
SectionHeadersShorter("h", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
+cl::list<std::string>
+llvm::Sections("j", cl::desc("Operate on the specified sections only"));
cl::list<std::string>
llvm::MAttrs("mattr",
static StringRef ToolName;
static int ReturnValue = EXIT_SUCCESS;
+namespace {
+typedef std::function<int(llvm::object::SectionRef const &)> FilterPredicate;
+
+class SectionFilterIterator {
+public:
+ SectionFilterIterator(FilterPredicate P,
+ llvm::object::section_iterator const &I,
+ llvm::object::section_iterator const &E)
+ : Predicate(P), Iterator(I), End(E) {
+ ScanPredicate();
+ }
+ llvm::object::SectionRef operator*() const { return *Iterator; }
+ SectionFilterIterator &operator++() {
+ ++Iterator;
+ ScanPredicate();
+ return *this;
+ }
+ bool operator!=(SectionFilterIterator const &Other) const {
+ return Iterator != Other.Iterator;
+ }
+
+private:
+ void ScanPredicate() {
+ while (Iterator != End && Predicate(*Iterator)) {
+ ++Iterator;
+ }
+ }
+ FilterPredicate Predicate;
+ llvm::object::section_iterator Iterator;
+ llvm::object::section_iterator End;
+};
+
+class SectionFilter {
+public:
+ SectionFilter(FilterPredicate P, llvm::object::ObjectFile const &O)
+ : Predicate(P), Object(O) {}
+ SectionFilterIterator begin() {
+ return SectionFilterIterator(Predicate, Object.section_begin(),
+ Object.section_end());
+ }
+ SectionFilterIterator end() {
+ return SectionFilterIterator(Predicate, Object.section_end(),
+ Object.section_end());
+ }
+
+private:
+ FilterPredicate Predicate;
+ llvm::object::ObjectFile const &Object;
+};
+SectionFilter ToolSectionFilter(llvm::object::ObjectFile const &O) {
+ if (Sections.empty()) {
+ return SectionFilter([](llvm::object::SectionRef const &) { return 0; }, O);
+ }
+ return SectionFilter([](llvm::object::SectionRef const &S) {
+ llvm::StringRef String;
+ std::error_code error = S.getName(String);
+ if (error) {
+ return error.value();
+ }
+ if (std::find(Sections.begin(), Sections.end(),
+ String) != Sections.end()) {
+ return 0;
+ }
+ return 1;
+ },
+ O);
+}
+}
+
bool llvm::error(std::error_code EC) {
if (!EC)
return false;
}
bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
- uint64_t a_addr = a.getOffset();
- uint64_t b_addr = b.getOffset();
- return a_addr < b_addr;
+ return a.getOffset() < b.getOffset();
}
namespace {
// If we couldn't find a symbol that this relocation refers to, try
// to find a section beginning instead.
- for (const SectionRef &Section : O->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*O)) {
std::error_code ec;
StringRef Name;
// in RelocSecs contain the relocations for section S.
std::error_code EC;
std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
section_iterator Sec2 = Section.getRelocatedSection();
if (Sec2 != Obj->section_end())
SectionRelocMap[*Sec2].push_back(Section);
}
- for (const SectionRef &Section : Obj->sections()) {
- if (!Section.isText() || Section.isVirtual())
+ // Create a mapping from virtual address to symbol name. This is used to
+ // pretty print the target of a call.
+ std::vector<std::pair<uint64_t, StringRef>> AllSymbols;
+ if (MIA) {
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ if (Symbol.getType() != SymbolRef::ST_Function)
+ continue;
+
+ ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
+ if (error(AddressOrErr.getError()))
+ break;
+ uint64_t Address = *AddressOrErr;
+
+ ErrorOr<StringRef> Name = Symbol.getName();
+ if (error(Name.getError()))
+ break;
+ if (Name->empty())
+ continue;
+ AllSymbols.push_back(std::make_pair(Address, *Name));
+ }
+
+ array_pod_sort(AllSymbols.begin(), AllSymbols.end());
+ }
+
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
+ if (!DisassembleAll && (!Section.isText() || Section.isVirtual()))
continue;
uint64_t SectionAddr = Section.getAddress();
if (error(AddressOrErr.getError()))
break;
uint64_t Address = *AddressOrErr;
- if (Address == UnknownAddress)
- continue;
Address -= SectionAddr;
if (Address >= SectSize)
continue;
SectionAddr + Index, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
+ if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) ||
+ MIA->isConditionalBranch(Inst))) {
+ uint64_t Target;
+ if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) {
+ auto TargetSym = std::upper_bound(
+ AllSymbols.begin(), AllSymbols.end(), Target,
+ [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (TargetSym != AllSymbols.begin())
+ --TargetSym;
+ else
+ TargetSym = AllSymbols.end();
+
+ if (TargetSym != AllSymbols.end()) {
+ outs() << " <" << TargetSym->second;
+ uint64_t Disp = Target - TargetSym->first;
+ if (Disp)
+ outs() << '+' << utohexstr(Disp);
+ outs() << '>';
+ }
+ }
+ }
outs() << "\n";
} else {
errs() << ToolName << ": warning: invalid instruction encoding\n";
if (!Obj->isRelocatableObject())
return;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
if (Section.relocation_begin() == Section.relocation_end())
continue;
StringRef secname;
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
unsigned i = 0;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
if (error(Section.getName(Name)))
return;
void llvm::PrintSectionContents(const ObjectFile *Obj) {
std::error_code EC;
- for (const SectionRef &Section : Obj->sections()) {
+ for (const SectionRef &Section : ToolSectionFilter(*Obj)) {
StringRef Name;
StringRef Contents;
if (error(Section.getName(Name)))
bool Common = Flags & SymbolRef::SF_Common;
bool Hidden = Flags & SymbolRef::SF_Hidden;
- if (Common)
- Address = Symbol.getCommonSize();
-
- if (Address == UnknownAddress)
- Address = 0;
char GlobLoc = ' ';
if (Type != SymbolRef::ST_Unknown)
GlobLoc = Global ? 'g' : 'l';
}
}
+/// Dump the raw contents of the __clangast section so the output can be piped
+/// into llvm-bcanalyzer.
+void llvm::printRawClangAST(const ObjectFile *Obj) {
+ if (outs().is_displayed()) {
+ errs() << "The -raw-clang-ast option will dump the raw binary contents of "
+ "the clang ast section.\n"
+ "Please redirect the output to a file or another program such as "
+ "llvm-bcanalyzer.\n";
+ return;
+ }
+
+ StringRef ClangASTSectionName("__clangast");
+ if (isa<COFFObjectFile>(Obj)) {
+ ClangASTSectionName = "clangast";
+ }
+
+ Optional<object::SectionRef> ClangASTSection;
+ for (auto Sec : ToolSectionFilter(*Obj)) {
+ StringRef Name;
+ Sec.getName(Name);
+ if (Name == ClangASTSectionName) {
+ ClangASTSection = Sec;
+ break;
+ }
+ }
+ if (!ClangASTSection)
+ return;
+
+ StringRef ClangASTContents;
+ if (error(ClangASTSection.getValue().getContents(ClangASTContents))) {
+ errs() << "Could not read the " << ClangASTSectionName << " section!\n";
+ return;
+ }
+
+ outs().write(ClangASTContents.data(), ClangASTContents.size());
+}
+
static void printFaultMaps(const ObjectFile *Obj) {
const char *FaultMapSectionName = nullptr;
Optional<object::SectionRef> FaultMapSection;
- for (auto Sec : Obj->sections()) {
+ for (auto Sec : ToolSectionFilter(*Obj)) {
StringRef Name;
Sec.getName(Name);
if (Name == FaultMapSectionName) {
}
static void DumpObject(const ObjectFile *o) {
- outs() << '\n';
- outs() << o->getFileName()
- << ":\tfile format " << o->getFileFormatName() << "\n\n";
+ // Avoid other output when using a raw option.
+ if (!RawClangAST) {
+ outs() << '\n';
+ outs() << o->getFileName()
+ << ":\tfile format " << o->getFileFormatName() << "\n\n";
+ }
if (Disassemble)
DisassembleObject(o, Relocations);
printLazyBindTable(o);
if (WeakBind)
printWeakBindTable(o);
+ if (RawClangAST)
+ printRawClangAST(o);
if (PrintFaultMaps)
printFaultMaps(o);
}
if (InputFilenames.size() == 0)
InputFilenames.push_back("a.out");
+ if (DisassembleAll)
+ Disassemble = true;
if (!Disassemble
&& !Relocations
&& !SectionHeaders
&& !Bind
&& !LazyBind
&& !WeakBind
+ && !RawClangAST
&& !(UniversalHeaders && MachOOpt)
&& !(ArchiveHeaders && MachOOpt)
&& !(IndirectSymbols && MachOOpt)