From 5feb80e748924606531ba28c97fe65145c65372e Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 13 Feb 2020 17:39:29 -0800 Subject: [PATCH] [dsymutil] Fix double relocation of DW_AT_call_return_pc When the DW_AT_call_return_pc matches a relocation, the call return pc would get relocated twice, once because of the relocation in the object file and once because of dsymutil. The same problem exists for the low and high PC and the fix is the same. We remember the low, high and return pc of the original DIE and relocate that, rather than the potentially already relocated value. Reviewed offline by Fred Riss. --- llvm/include/llvm/DWARFLinker/DWARFLinker.h | 3 +++ llvm/lib/DWARFLinker/DWARFLinker.cpp | 5 +++- .../Inputs/private/tmp/call_return_pc/call | Bin 0 -> 4640 bytes .../Inputs/private/tmp/call_return_pc/call.o | Bin 0 -> 2228 bytes .../tools/dsymutil/X86/call-site-entry-reloc.test | 26 +++++++++++++++++++++ 5 files changed, 33 insertions(+), 1 deletion(-) create mode 100755 llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call create mode 100644 llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o create mode 100644 llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h index 5a8d081..31e8bcc 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -582,6 +582,9 @@ private: /// Value of AT_high_pc in the input DIE uint64_t OrigHighPc = 0; + /// Value of DW_AT_call_return_pc in the input DIE + uint64_t OrigCallReturnPc = 0; + /// Offset to apply to PC addresses inside a function. int64_t PCOffset = 0; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp index adcbebf..03919c8 100644 --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1017,7 +1017,8 @@ unsigned DWARFLinker::DIECloner::cloneAddressAttribute( } else if (AttrSpec.Attr == dwarf::DW_AT_call_return_pc) { // Relocate a return PC address within a call site entry. if (Die.getTag() == dwarf::DW_TAG_call_site) - Addr += Info.PCOffset; + Addr = (Info.OrigCallReturnPc ? Info.OrigCallReturnPc : Addr) + + Info.PCOffset; } Die.addValue(DIEAlloc, static_cast(AttrSpec.Attr), @@ -1280,6 +1281,8 @@ DIE *DWARFLinker::DIECloner::cloneDIE( // inlining function. AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), std::numeric_limits::max()); + AttrInfo.OrigCallReturnPc = + dwarf::toAddress(InputDIE.find(dwarf::DW_AT_call_return_pc), 0); } // Reset the Offset to 0 as we will be working on the local copy of diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call new file mode 100755 index 0000000000000000000000000000000000000000..d7587f944e9f761374fe3a50617306a5aa8d7b46 GIT binary patch literal 4640 zcmeHLOKTKC5U$x>O)$YtAc_(Riv)=ec0>Y+xA<60aE(h6L_FB+W0nl=i^*)<=p`Nm zk2&TKc=IRt1H9$zKS&H-^q_b!eqT?InORrx?i5sae^p)8)nCu0X79)6pF<*6T0~ON z)6jW<*OJ3Ze-ovgbyfGu zO()pVpYMaoH*XRUhj$y4^O*nQ((?Vn-KCH_@Dtw^yHw;|60 zY)o?wx(Iv*^X|CF8_Xln5|jd$)(qweX!Jb5e-eIgIp`?V?rwN?!>!o0tws%)G6`iJ z?>_FeAHAR3eS7EA_=Cxr!yB;Wp!&@0DXfCE<}!0Fbp@F9g))QtGmi(pqr!9f7W4(w zS@_(n<62P9>ehzuH1oIfsLQPc(U&kW{{n_#%$E%&Ux_3PBn%`BBn%`BBn%`BBn%`B zBnm^>s5XFpt27c&!$^8*b8{>6xn28x5#f)b^NZ&S;@gb&-@h71aV#Y^t zjYcD^D{BSKAI)bqKCX{_Y!;62zBz-#^VmT6UFCHd>EzQgpIP=@VgaN v!9NT2;_c literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/call_return_pc/call.o new file mode 100644 index 0000000000000000000000000000000000000000..df698e8a328451144fe1e97430ff79f32b157194 GIT binary patch literal 2228 zcma)7-D@0G6u*<*Nn<8%wq3z2ifpAqM6w^|gIGlqteS$t(iT#va-E%>O*ZV#E}KcZ zmdch=GzwxxeDO)}$^Ss~MFi2e{tJo^`r<#JV*LH?oV$iGr8#iUx##2l?!D)pJ9F>P zKmIwTl#@{q;4HXGQ38XC;IA3H5B(sqI_H3_4NOJ$=mcpUhr>7-C-#+Bu3q`iwxd}Y zSiHF@r6%ahs#_8=O6z9W*xS;6qcI5giGN{p{nD%B6pM35JX-cQP7qjYTfBDE>d}|R z`&1G?6aA~;&0~L)iO+0P!kC}zZ#NzoR~m1g#Rgg2p_|x8WD3vk_dB7E{BF35q%_{Q zf@e$Y$)+BJ*K6zq%t_-_Wc70bFghWg*lb9IQQryPnmF@lUbgmC+kgM-mvCFR2Dpu6g4U^imUl4}yt?3t z$#=1B$JDl8I_=0Hrt3Epyf(%f6&dj=z&S~eVT*1xcZr{x1AAKzM%cywTIfJ{JC@T(r8x_~) zZWJ@Q^WO8`OGSj=cks!{lrizRD82(5YE*a^M|O|NxmYk5c#`K-CikM}@pzwrlh-13>zRd+Vuqja-nsE5FYTsvYTI-4I-PJaZMeHp@j zj@0DGu-vQ)I)1cO+7Ac2?Os%>)yma!wKTugj@Q83dyO*M^?awZ->pzA^as72Fo??t zmX=p*)v&o-TU}`eezUsRT=K)^MZXc$s*5X&t4k}-F4vxG)oM?x!0&X*fvTuV-0fFr z=|LFp4IL;HoP0*|V;?=H{kL6E0>VEh&{+;BN``!kt7K`3C?1 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test b/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test new file mode 100644 index 0000000..46e9470 --- /dev/null +++ b/llvm/test/tools/dsymutil/X86/call-site-entry-reloc.test @@ -0,0 +1,26 @@ +Test binaries created with the following commands: + +$ cat call.c +__attribute__((noinline, noreturn)) void foo() { + asm volatile("" ::: "memory"); + __builtin_unreachable(); +} +__attribute__((noinline)) void bar() { + asm volatile("nop" :::); + foo(); +} + +int main() { bar(); } + +$ clang -g call.c -fomit-frame-pointer -c -Os -o call.o +$ clang -g call.o -o call + +The test requires the return PC to match a relocation (in this case the +DW_AT_high_pc of main). Without this change the value would get relocated +twice. + +RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/call_return_pc/call -o %t.dSYM +RUN: llvm-dwarfdump %t.dSYM | FileCheck %s -implicit-check-not=DW_AT_call_return_pc + +CHECK: DW_AT_call_return_pc (0x0000000100000f72) +CHECK: DW_AT_call_return_pc (0x0000000100000f78) -- 2.7.4