Skip to content

Commit

Permalink
[llvm-objdump][MachO] Add support for dumping function starts
Browse files Browse the repository at this point in the history
Add support for dumping function starts for Mach-O binaries.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D97027
  • Loading branch information
Alexander Shaposhnikov committed Mar 9, 2021
1 parent 3d61836 commit 5f2f84a
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 5 deletions.
4 changes: 4 additions & 0 deletions llvm/docs/CommandGuide/llvm-objdump.rst
Expand Up @@ -304,6 +304,10 @@ MACH-O ONLY OPTIONS AND COMMANDS

Display exported symbols.

.. option:: --function-starts

Print the function starts table for Mach-O objects.

.. option:: -g

Print line information from debug info if available.
Expand Down
7 changes: 7 additions & 0 deletions llvm/test/tools/llvm-objdump/MachO/function-starts.test
@@ -0,0 +1,7 @@
## This test verifies that llvm-objdump correctly prints function starts data.

RUN: llvm-objdump --macho --function-starts %p/Inputs/hello.exe.macho-i386 | FileCheck %s --check-prefix=32-BIT
32-BIT: 00001f40

RUN: llvm-objdump --macho --function-starts %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=64-BIT
64-BIT: 0000000100000f30
49 changes: 47 additions & 2 deletions llvm/tools/llvm-objdump/MachODump.cpp
Expand Up @@ -128,6 +128,12 @@ cl::opt<bool> objdump::DataInCode(
"Print the data in code table for Mach-O objects (requires --macho)"),
cl::cat(MachOCat));

cl::opt<bool>
objdump::FunctionStarts("function-starts",
cl::desc("Print the function starts table for "
"Mach-O objects (requires --macho)"),
cl::cat(MachOCat));

cl::opt<bool>
objdump::LinkOptHints("link-opt-hints",
cl::desc("Print the linker optimization hints for "
Expand Down Expand Up @@ -1103,6 +1109,43 @@ static void PrintRelocations(const MachOObjectFile *O, const bool verbose) {
}
}

static void PrintFunctionStarts(MachOObjectFile *O) {
uint64_t BaseSegmentAddress = 0;
for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
if (Command.C.cmd == MachO::LC_SEGMENT) {
MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
if (StringRef(SLC.segname) == "__TEXT") {
BaseSegmentAddress = SLC.vmaddr;
break;
}
} else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
if (StringRef(SLC.segname) == "__TEXT") {
BaseSegmentAddress = SLC.vmaddr;
break;
}
}
}

SmallVector<uint64_t, 8> FunctionStarts;
for (const MachOObjectFile::LoadCommandInfo &LC : O->load_commands()) {
if (LC.C.cmd == MachO::LC_FUNCTION_STARTS) {
MachO::linkedit_data_command FunctionStartsLC =
O->getLinkeditDataLoadCommand(LC);
O->ReadULEB128s(FunctionStartsLC.dataoff, FunctionStarts);
break;
}
}

for (uint64_t S : FunctionStarts) {
uint64_t Addr = BaseSegmentAddress + S;
if (O->is64Bit())
outs() << format("%016" PRIx64, Addr) << "\n";
else
outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n";
}
}

static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
Expand Down Expand Up @@ -1910,8 +1953,8 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
// UniversalHeaders or ArchiveHeaders.
if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
DataInCode || LinkOptHints || DylibsUsed || DylibId || ObjcMetaData ||
(!FilterSections.empty())) {
DataInCode || FunctionStarts || LinkOptHints || DylibsUsed || DylibId ||
ObjcMetaData || (!FilterSections.empty())) {
if (!NoLeadingHeaders) {
outs() << Name;
if (!ArchiveMemberName.empty())
Expand Down Expand Up @@ -1966,6 +2009,8 @@ static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
PrintIndirectSymbols(MachOOF, !NonVerbose);
if (DataInCode)
PrintDataInCodeTable(MachOOF, !NonVerbose);
if (FunctionStarts)
PrintFunctionStarts(MachOOF);
if (LinkOptHints)
PrintLinkOptHints(MachOOF);
if (Relocations)
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-objdump/MachODump.h
Expand Up @@ -34,6 +34,7 @@ extern cl::opt<bool> DylibsUsed;
extern cl::opt<bool> DylibId;
extern cl::opt<bool> ExportsTrie;
extern cl::opt<bool> FirstPrivateHeader;
extern cl::opt<bool> FunctionStarts;
extern cl::opt<bool> IndirectSymbols;
extern cl::opt<bool> InfoPlist;
extern cl::opt<bool> LazyBind;
Expand Down
6 changes: 3 additions & 3 deletions llvm/tools/llvm-objdump/llvm-objdump.cpp
Expand Up @@ -2994,9 +2994,9 @@ int main(int argc, char **argv) {
!DynamicSymbolTable && !UnwindInfo && !FaultMapSection &&
!(MachOOpt &&
(Bind || DataInCode || DylibId || DylibsUsed || ExportsTrie ||
FirstPrivateHeader || IndirectSymbols || InfoPlist || LazyBind ||
LinkOptHints || ObjcMetaData || Rebase || UniversalHeaders ||
WeakBind || !FilterSections.empty()))) {
FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist ||
LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
UniversalHeaders || WeakBind || !FilterSections.empty()))) {
cl::PrintHelpMessage();
return 2;
}
Expand Down

0 comments on commit 5f2f84a

Please sign in to comment.