Index: test/tools/llvm-objdump/Inputs/simple-executable-x86_64.yaml =================================================================== --- /dev/null +++ test/tools/llvm-objdump/Inputs/simple-executable-x86_64.yaml @@ -0,0 +1,73 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000010 + Content: 554889E58B0425A80000005DC30F1F00 + - Name: .anothertext + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x0000000000000010 + AddressAlign: 0x0000000000000010 + Content: 554889E54883EC20488D0425A8000000C745FC00000000488945F0488B45F08B08894DECE8C7FFFFFF8B4DEC01C189C84883C4205D746573742073747200C3 + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x0000000000000050 + AddressAlign: 0x0000000000000008 + Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C00000090FFFFFF0D00000000410E108602430D06000000000000001C0000003C00000080FFFFFF3F00000000410E108602430D0600000000000000 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x00000000000000A8 + AddressAlign: 0x0000000000000004 + Content: '01000000' + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x0000000000000001 + Content: 5562756E747520636C616E672076657273696F6E20332E352D317562756E74753120287472756E6B2920286261736564206F6E204C4C564D20332E352900 +Symbols: + Local: + - Type: STT_SECTION + Section: .text + - Type: STT_SECTION + Section: .anothertext + Value: 0x0000000000000010 + - Type: STT_SECTION + Section: .eh_frame + Value: 0x0000000000000050 + - Type: STT_SECTION + Section: .data + Value: 0x00000000000000A8 + - Type: STT_SECTION + Section: .comment + - Name: /tmp/a.c + Type: STT_FILE + - Type: STT_FILE + Global: + - Name: somedata + Type: STT_OBJECT + Section: .anothertext + Value: 0x0000000000000045 + - Name: main + Type: STT_FUNC + Section: .anothertext + Value: 0x0000000000000010 + Size: 0x000000000000003F + - Name: foo + Type: STT_FUNC + Section: .text + Size: 0x000000000000000D + - Name: a + Type: STT_OBJECT + Section: .data + Value: 0x00000000000000A8 + Size: 0x0000000000000004 +... Index: test/tools/llvm-objdump/start-stop-address.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/start-stop-address.test @@ -0,0 +1,29 @@ +// RUN: yaml2obj -o %t.out %p/Inputs/simple-executable-x86_64.yaml +// RUN: llvm-objdump -d %t.out --start-address=0x18 --stop-address=0x2f | FileCheck %s +// RUN: llvm-objdump -d %t.out --start-address=0xc --stop-address=0x11 | FileCheck %s --check-prefix "CROSSSECTION" +// RUN: llvm-objdump -d %t.out --start-address=0x40 --stop-address=0x47 | FileCheck %s --check-prefix "CROSSDATA" + +// CHECK: Disassembly of section .anothertext: +// CHECK-NEXT: main: +// CHECK-NEXT: 18: 48 8d 04 25 a8 00 00 00 leaq 168, %rax +// CHECK-NEXT: 20: c7 45 fc 00 00 00 00 movl $0, -4(%rbp) +// CHECK-NEXT: 27: 48 89 45 f0 movq %rax, -16(%rbp) +// CHECK-NEXT: 2b: 48 8b 45 f0 movq -16(%rbp), %rax +// CHECK-NOT: 2f: + +// CROSSSECTION: Disassembly of section .text: +// CROSSSECTION-NEXT: foo: +// CROSSSECTION-NEXT: c: c3 retq +// CROSSSECTION-NEXT: d: 0f 1f 00 nopl (%rax) +// CROSSSECTION-NEXT: Disassembly of section .anothertext: +// CROSSSECTION-NEXT: main: +// CROSSSECTION-NEXT: 10: 55 pushq %rbp +// CROSSSECTION-NOT: 11: + +// CROSSDATA: Disassembly of section .anothertext: +// CROSSDATA: main: +// CROSSDATA: 40: 48 83 c4 20 addq $32, %rsp +// CROSSDATA: 44: 5d popq %rbp +// CROSSDATA-DAG: somedata: +// CROSSDATA-NEXT: 45: 74 65 te + Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -205,6 +205,13 @@ cl::alias PrintLinesShort("l", cl::desc("Alias for -line-numbers"), cl::aliasopt(PrintLines)); + +cl::opt + StartAddress("start-address", cl::desc("Disassemble beginning at address"), + cl::value_desc("address"), cl::init(0)); +cl::opt + StopAddress("stop-address", cl::desc("Stop disassembly at address"), + cl::value_desc("address"), cl::init(UINT64_MAX)); static StringRef ToolName; namespace { @@ -1060,6 +1067,9 @@ } static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { + if (StartAddress > StopAddress) + error("Start address should be less than stop address"); + const Target *TheTarget = getTarget(Obj); // Package up features to be passed to target/subtarget @@ -1238,10 +1248,14 @@ } StringRef name; error(Section.getName(name)); + + if ((SectionAddr <= StopAddress) && + (SectionAddr + SectSize) >= StartAddress) { outs() << "Disassembly of section "; if (!SegmentName.empty()) outs() << SegmentName << ","; outs() << name << ':'; + } // If the section has no symbol at the start, just insert a dummy one. if (Symbols.empty() || std::get<0>(Symbols[0]) != 0) { @@ -1278,6 +1292,17 @@ if (Start >= End) continue; + // Check if we need to skip symbol + // Skip if the symbol's data is not between StartAddress and StopAddress + if (End + SectionAddr < StartAddress || + Start + SectionAddr > StopAddress) { + continue; + } + + // Stop disassembly at the stop address specified + if (End + SectionAddr > StopAddress) + End = StopAddress - SectionAddr; + if (Obj->isELF() && Obj->getArch() == Triple::amdgcn) { // make size 4 bytes folded End = Start + ((End - Start) & ~0x3ull); @@ -1308,6 +1333,12 @@ for (Index = Start; Index < End; Index += Size) { MCInst Inst; + if (Index + SectionAddr < StartAddress || + Index + SectionAddr > StopAddress) { + // skip byte by byte till StartAddress is reached + Size = 1; + continue; + } // AArch64 ELF binaries can interleave data and text in the // same section. We rely on the markers introduced to // understand what we need to dump. If the data marker is within a @@ -1384,6 +1415,9 @@ int NumBytes = 0; for (Index = Start; Index < End; Index += 1) { + if (((SectionAddr + Index) < StartAddress) || + ((SectionAddr + Index) > StopAddress)) + continue; if (NumBytes == 0) { outs() << format("%8" PRIx64 ":", SectionAddr + Index); outs() << "\t"; @@ -1489,7 +1523,10 @@ SmallString<32> val; // If this relocation is hidden, skip it. - if (hidden) goto skip_print_rel; + if (hidden || ((SectionAddr + addr) < StartAddress)) { + ++rel_cur; + continue; + } // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; @@ -1497,8 +1534,6 @@ error(getRelocationValueString(*rel_cur, val)); outs() << format(Fmt.data(), SectionAddr + addr) << name << "\t" << val << "\n"; - - skip_print_rel: ++rel_cur; } } @@ -1525,7 +1560,7 @@ uint64_t address = Reloc.getOffset(); SmallString<32> relocname; SmallString<32> valuestr; - if (hidden) + if (address < StartAddress || address > StopAddress || hidden) continue; Reloc.getTypeName(relocname); error(getRelocationValueString(Reloc, valuestr)); @@ -1616,6 +1651,8 @@ if (!AddressOrError) report_error(ArchiveName, o->getFileName(), AddressOrError.takeError()); uint64_t Address = *AddressOrError; + if ((Address < StartAddress) || (Address > StopAddress)) + continue; Expected TypeOrError = Symbol.getType(); if (!TypeOrError) report_error(ArchiveName, o->getFileName(), TypeOrError.takeError());