Index: test/tools/llvm-objdump/call-absolute-symbol-elf.test =================================================================== --- /dev/null +++ test/tools/llvm-objdump/call-absolute-symbol-elf.test @@ -0,0 +1,5 @@ +// RUN: echo -e ".text\ncallq foo\n" | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t1.o +// RUN: ld.lld --defsym foo=0x100 %t1.o -o %t2 +// RUN: llvm-objdump --disassemble %t2 | FileCheck %s + +CHECK: 201000: e8 fb f0 df ff callq -2100997 Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -1323,6 +1323,7 @@ // Create a mapping from virtual address to symbol name. This is used to // pretty print the symbols while disassembling. std::map AllSymbols; + SectionSymbolsTy AbsoluteSymbols; for (const SymbolRef &Symbol : Obj->symbols()) { Expected AddressOrErr = Symbol.getAddress(); if (!AddressOrErr) @@ -1338,15 +1339,17 @@ Expected SectionOrErr = Symbol.getSection(); if (!SectionOrErr) report_error(Obj->getFileName(), SectionOrErr.takeError()); - section_iterator SecI = *SectionOrErr; - if (SecI == Obj->section_end()) - continue; uint8_t SymbolType = ELF::STT_NOTYPE; if (Obj->isELF()) SymbolType = getElfSymbolType(Obj, Symbol); - AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); + section_iterator SecI = *SectionOrErr; + if (SecI != Obj->section_end()) + AllSymbols[*SecI].emplace_back(Address, *Name, SymbolType); + else + AbsoluteSymbols.emplace_back(Address, *Name, SymbolType); + } if (AllSymbols.empty() && Obj->isELF()) @@ -1382,6 +1385,8 @@ if (Sec != SectionAddresses.end()) AllSymbols[Sec->second].emplace_back(VA, Name, ELF::STT_NOTYPE); + else + AbsoluteSymbols.emplace_back(VA, Name, ELF::STT_NOTYPE); } } @@ -1389,6 +1394,7 @@ // a symbol near an address. for (std::pair &SecSyms : AllSymbols) array_pod_sort(SecSyms.second.begin(), SecSyms.second.end()); + array_pod_sort(AbsoluteSymbols.begin(), AbsoluteSymbols.end()); for (const SectionRef &Section : ToolSectionFilter(*Obj)) { if (!DisassembleAll && (!Section.isText() || Section.isVirtual())) @@ -1703,29 +1709,37 @@ --SectionAddress; TargetSectionSymbols = &AllSymbols[SectionAddress->second]; } else { - TargetSectionSymbols = nullptr; + TargetSectionSymbols = &AbsoluteSymbols; } } // Find the first symbol in the section whose offset is less than - // or equal to the target. - if (TargetSectionSymbols) { - auto TargetSym = std::upper_bound( - TargetSectionSymbols->begin(), TargetSectionSymbols->end(), + // or equal to the target. If there isn't a section that contains + // the target, find the nearest preceding absolute symbol. + auto TargetSym = std::upper_bound( + TargetSectionSymbols->begin(), TargetSectionSymbols->end(), + Target, [](uint64_t LHS, + const std::tuple &RHS) { + return LHS < std::get<0>(RHS); + }); + if (TargetSym == TargetSectionSymbols->begin()) { + TargetSectionSymbols = &AbsoluteSymbols; + TargetSym = std::upper_bound( + AbsoluteSymbols.begin(), AbsoluteSymbols.end(), Target, [](uint64_t LHS, const std::tuple &RHS) { - return LHS < std::get<0>(RHS); - }); - if (TargetSym != TargetSectionSymbols->begin()) { - --TargetSym; - uint64_t TargetAddress = std::get<0>(*TargetSym); - StringRef TargetName = std::get<1>(*TargetSym); - outs() << " <" << TargetName; - uint64_t Disp = Target - TargetAddress; - if (Disp) - outs() << "+0x" << Twine::utohexstr(Disp); - outs() << '>'; - } + return LHS < std::get<0>(RHS); + }); + } + if (TargetSym != TargetSectionSymbols->begin()) { + --TargetSym; + uint64_t TargetAddress = std::get<0>(*TargetSym); + StringRef TargetName = std::get<1>(*TargetSym); + outs() << " <" << TargetName; + uint64_t Disp = Target - TargetAddress; + if (Disp) + outs() << "+0x" << Twine::utohexstr(Disp); + outs() << '>'; } } }