Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ Changes to the LLVM tools
emitted on stdout, to account for spaces or other special characters in path.
(`#97305 <https://github.com/llvm/llvm-project/pull/97305>`_).

* `llvm-objdump` now supports using `--mcpu=help` and `--mattr=help` with the `--triple` option
without requiring an input file or the `-d` (disassemble) flag.

Changes to LLDB
---------------------------------

Expand Down
101 changes: 97 additions & 4 deletions llvm/test/tools/llvm-objdump/mattr-mcpu-help.test
Original file line number Diff line number Diff line change
@@ -1,16 +1,109 @@
# RUN: yaml2obj %s -o %t
# RUN: llvm-objdump -d %t --mattr=help 2>&1 | FileCheck %s
# RUN: llvm-objdump -d %t --mcpu=help 2>&1 | FileCheck %s
# REQUIRES: x86-registered-target

# RUN: yaml2obj --docnum=1 %s -o %t
# RUN: llvm-objdump -d %t --mattr=help 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-DISASSEMBLE
# RUN: llvm-objdump -d %t --mcpu=help 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-DISASSEMBLE

# CHECK: Available CPUs for this target:
# CHECK: Available features for this target:
## To check we still disassemble the file:
# CHECK: file format elf64-x86-64
# CHECK-DISASSEMBLE: file format elf64-x86-64

## The help message can be printed without -d.
# RUN: llvm-objdump --mattr=help %t 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DISASSEMBLE
# RUN: llvm-objdump --mcpu=help %t 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DISASSEMBLE

# CHECK-NO-DISASSEMBLE-NOT: file format elf64-x86-64

## We still handle other options.
# RUN: llvm-objdump --mattr=help --section-headers %t 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SECTION-HEADERS
# RUN: llvm-objdump --mcpu=help --section-headers %t 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SECTION-HEADERS

# CHECK-SECTION-HEADERS: Sections:
# CHECK-SECTION-HEADERS: Idx Name Size VMA Type

## We report an error when we can't infer the triple because we don't have --triple or an input object (including a.out).
# RUN: not llvm-objdump --mattr=help 2>&1 \
# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-ERROR --implicit-check-not=error: -DMSG=%errc_ENOENT
# RUN: not llvm-objdump --mcpu=help 2>&1 \
# RUN: | FileCheck %s --check-prefix=CHECK-MISSING-ERROR --implicit-check-not=error: -DMSG=%errc_ENOENT

# CHECK-MISSING-ERROR: llvm-objdump{{.*}}: error: 'a.out': triple was not specified and could not be inferred from the input file: [[MSG]]

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64

# RUN: yaml2obj --docnum=2 %s -o %t.minidump
## We report an error when the binary file isn't an object file format.
# RUN: not llvm-objdump --mattr=help %t.minidump 2>&1 \
# RUN: | FileCheck %s --check-prefix=CHECK-UNSUPPORTED-ERROR --implicit-check-not=error: -DFILE=%t.minidump
# RUN: not llvm-objdump --mcpu=help %t.minidump 2>&1 \
# RUN: | FileCheck %s --check-prefix=CHECK-UNSUPPORTED-ERROR --implicit-check-not=error: -DFILE=%t.minidump

# CHECK-UNSUPPORTED-ERROR: llvm-objdump{{.*}}: error: '[[FILE]]': target triple could not be derived from input file

--- !minidump
Streams:
- Type: SystemInfo
Processor Arch: PPC
Platform ID: Linux

# RUN: llvm-ar rc %t.a %t
# RUN: llvm-objdump --mcpu=help %t.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK
# RUN: llvm-objdump --mattr=help %t.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK

## We report an error when the triple cannot be inferred from any archive member.
# RUN: llvm-ar rc %t.empty.a
# RUN: not llvm-objdump --mcpu=help %t.empty.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-UNSUPPORTED-ERROR --implicit-check-not=error: -DFILE=%t.empty.a
# RUN: not llvm-objdump --mattr=help %t.empty.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-UNSUPPORTED-ERROR --implicit-check-not=error: -DFILE=%t.empty.a

## We are able to handle an archive with unsupported binary files. The target is
## derived from the first recognised object file.
# RUN: llvm-ar rc %t.a %t.minidump %t
# RUN: llvm-objdump --mcpu=help %t.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK
# RUN: llvm-objdump --mattr=help %t.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK

## We report an error when the archive is malformed.
# RUN: yaml2obj --docnum=3 %s -o %t.malformed.archive.a
# RUN: not llvm-objdump --mcpu=help %t.malformed.archive.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-MALFORMED-ARCHIVE-ERROR --implicit-check-not=error: -DFILE=%t.malformed.archive.a
# RUN: not llvm-objdump --mattr=help %t.malformed.archive.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-MALFORMED-ARCHIVE-ERROR --implicit-check-not=error: -DFILE=%t.malformed.archive.a

# CHECK-MALFORMED-ARCHIVE-ERROR: llvm-objdump{{.*}}: error: '[[FILE]]': truncated or malformed archive

--- !Arch
Members:
- Name: 'foo.c'
Size: '1'

## We report an error when we encounter an unexpected error while iterating files in an archive.
# RUN: yaml2obj --docnum=4 %s -o %t.invalid.error.code.archive.a
# RUN: not llvm-objdump --mcpu=help %t.invalid.error.code.archive.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-INVALID-ERROR-ARCHIVE-ERROR --implicit-check-not=error: -DFILE=%t.invalid.error.code.archive.a
# RUN: not llvm-objdump --mattr=help %t.invalid.error.code.archive.a 2>&1 \
# RUN: | FileCheck %s --check-prefixes=CHECK-INVALID-ERROR-ARCHIVE-ERROR --implicit-check-not=error: -DFILE=%t.invalid.error.code.archive.a

# CHECK-INVALID-ERROR-ARCHIVE-ERROR: llvm-objdump{{.*}}: error: [[FILE]](<file index: 1>): truncated or malformed archive (long name offset characters after the '/' are not all decimal numbers: '&a25*' for archive member header at offset 68)

--- !Arch
Members:
## We need the first member to be a valid member to trigger the right error.
- Name: 'hello.c/'
- Name: "/&a25*"
21 changes: 21 additions & 0 deletions llvm/test/tools/llvm-objdump/mattr-mcpu-triple-help.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# RUN: yaml2obj %s -o %t
# REQUIRES: x86-registered-target

## When specifying --triple, the help message should be printed for the specified target.
# RUN: llvm-objdump --mattr=help --triple=x86_64 2>&1 | FileCheck %s
# RUN: llvm-objdump --mcpu=help --triple=x86_64 2>&1 | FileCheck %s

## The help message will depend on the target specified by --triple even if the input is for a different target.
# RUN: llvm-objdump --mattr=help --triple=x86_64 %t 2>&1 | FileCheck %s
# RUN: llvm-objdump --mcpu=help --triple=x86_64 %t 2>&1 | FileCheck %s

# CHECK: Available CPUs for this target:
# CHECK: x86-64
# CHECK: Available features for this target:

--- !ELF
FileHeader:
Class: ELFCLASS32
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_MIPS
85 changes: 75 additions & 10 deletions llvm/tools/llvm-objdump/llvm-objdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3533,6 +3533,60 @@ commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
return Values;
}

static void mcpuHelp() {
Triple TheTriple;

if (!TripleName.empty()) {
TheTriple.setTriple(TripleName);
} else {
assert(!InputFilenames.empty());
Expected<OwningBinary<Binary>> OBinary = createBinary(InputFilenames[0]);
if (Error E = OBinary.takeError()) {
reportError(InputFilenames[0], "triple was not specified and could not "
"be inferred from the input file: " +
toString(std::move(E)));
}

Binary *Bin = OBinary->getBinary();
if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin)) {
TheTriple = Obj->makeTriple();
} else if (Archive *A = dyn_cast<Archive>(Bin)) {
Error Err = Error::success();
unsigned I = -1;
for (auto &C : A->children(Err)) {
++I;
Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
if (!ChildOrErr) {
if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
reportError(std::move(E), getFileNameForError(C, I),
A->getFileName());
continue;
}
if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get())) {
TheTriple = Obj->makeTriple();
break;
}
}
if (Err)
reportError(std::move(Err), A->getFileName());
}
if (TheTriple.empty())
reportError(InputFilenames[0],
"target triple could not be derived from input file");
}

std::string ErrMessage;
const Target *DummyTarget =
TargetRegistry::lookupTarget(TheTriple, ErrMessage);
if (!DummyTarget)
reportCmdLineError(ErrMessage);
// We need to access the Help() through the corresponding MCSubtargetInfo.
// To avoid a memory leak, we wrap the createMcSubtargetInfo result in a
// unique_ptr.
std::unique_ptr<MCSubtargetInfo> MSI(
DummyTarget->createMCSubtargetInfo(TheTriple, "help", ""));
}

static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
MachOOpt = true;
FullLeadingAddr = true;
Expand Down Expand Up @@ -3826,20 +3880,31 @@ int llvm_objdump_main(int argc, char **argv, const llvm::ToolContext &) {
!DisassembleSymbols.empty())
Disassemble = true;

if (!ArchiveHeaders && !Disassemble && DwarfDumpType == DIDT_Null &&
!DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&
!Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&
!DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading &&
!(MachOOpt &&
(Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||
DylibsUsed || ExportsTrie || FirstPrivateHeader ||
FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||
InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()))) {
const bool PrintCpuHelp = (MCPU == "help" || is_contained(MAttrs, "help"));

const bool ShouldDump =
ArchiveHeaders || Disassemble || DwarfDumpType != DIDT_Null ||
DynamicRelocations || FileHeaders || PrivateHeaders || RawClangAST ||
Relocations || SectionHeaders || SectionContents || SymbolTable ||
DynamicSymbolTable || UnwindInfo || FaultMapSection || Offloading ||
(MachOOpt &&
(Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||
DylibsUsed || ExportsTrie || FirstPrivateHeader ||
FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||
InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()));

if (!ShouldDump && !PrintCpuHelp) {
T->printHelp(ToolName);
return 2;
}

if (PrintCpuHelp) {
mcpuHelp();
if (!ShouldDump)
return EXIT_SUCCESS;
}

DisasmSymbolSet.insert_range(DisassembleSymbols);

llvm::for_each(InputFilenames, dumpInput);
Expand Down