From a8631b87aef95da6cd44dd94508c4f37c26b4867 Mon Sep 17 00:00:00 2001 From: Jake Ehrlich <jakehehrlich@google.com> Date: Fri, 3 Nov 2017 18:58:41 +0000 Subject: [PATCH] [llvm-objcopy] Add support for dwarf fission This change adds support for dwarf fission. Differential Revision: https://reviews.llvm.org/D39207 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317350 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/llvm-objcopy/Inputs/dwarf.dwo | Bin 0 -> 3568 bytes test/tools/llvm-objcopy/drawf-fission.test | 43 +++++++++++ tools/llvm-objcopy/Object.h | 1 + tools/llvm-objcopy/llvm-objcopy.cpp | 81 +++++++++++++++++---- 4 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 test/tools/llvm-objcopy/Inputs/dwarf.dwo create mode 100644 test/tools/llvm-objcopy/drawf-fission.test diff --git a/test/tools/llvm-objcopy/Inputs/dwarf.dwo b/test/tools/llvm-objcopy/Inputs/dwarf.dwo new file mode 100644 index 0000000000000000000000000000000000000000..4b6fd5055061e0b2c85d03a5af0a8d85d7b0006c GIT binary patch literal 3568 zcmbVOO>7%g5T5ngZ5pR(ehMiqKbA<Pv})E4DhMcbQ=?ESMTi!m(hFg2uYbsTH`-k{ z=?RgFBO(_NC(a;&DB=JTmr6)nxN$;4aIR1f<%mF(nYVB3=gIm2Bkh}+Z)V=idvD&e z-&tFKDQ8*0WI+{%8lwPP2Zr*h5?A4I^nCT@_s^4hmxh%)*T3(0z8{_`ZHJNHgv5&z zr@0+MxgSSmKWw;uxgCaW-z#^*o>zX`-Sj$MC-S?EPPysT`|V{40c#d!7H-$3PfUMR zJNR{NVb+?X{AcjXQzDocsqwRGADn(K`S}NB(!(tALH>sC2JO-fFN(WiP&(^WoJwga zaochE>e~9+#n;w0&Q>brRyT0{Q}9BZG`m3+dTuv>Zjh)M58?O>epUQl#P1Y-gIcU9 z$Z-)lpw!ki+p?EXu=9mHuE)Av+pV75t<D$h-6}2$Am_mByVbb^tH%&|zId*9dH%v9 z=)VZ4SBu3W1|P;R2j~oz_1Cnq<^^TI0V?=mSXwLr59603L7AuoUIP55T~JfNQDhI0 z@-P9`&dk)oi9J=uqp5i?s_jPY;`EHd&f%DY$8e;|596qs3}dbIR2s?+4yC1{a<pJi z-YQuATn?R6W5!rRQy%_!AWfSHSo%Q7Mmxu3>-}JzxeWytN4Twad<0U8jeC$qwmR|s z7F!)m7JgzMIEm|;GwS61d=fp=9UToxTQ5Cn+QPr-kdUZNiO5bJ#5iByNyN-mPoYjk zILDICISJ=ngi}8dG0rh1g{C<5E7PJD=tOM>4K8uBPL|1?Wy;Gk;oOIWo2OGEBa)o| zbPDgo!BNl8hFh;k-VJaf&v%`~+eyG_guR}JufSG6iM1j1-Rjqqn_J#KFmQVWrcMz) zJVPx`B5>9n#Z(HNwb?}6tU$e*8bR-ku+@saBo?r#c7s-E>V7xyM)a^@sy(+s5hDvy zfO_?uAWS^x(krho$BEn69Py%wM}Ss@3+7u*YfIcZIPuM%;!)Ui6PMr>XGQP+|7Vx+ zK(qR2LN|4X4%{H2s{SR+>>+Yrr2&cWU8)W50qaLlFz*B7-|C|1IVPf)kM1S+<S_z~ zu48h_|CG{(!xb%>?-oH^Kl8UV#(Btx=*^VDvzjyGIOe~gfo1j~{*kE|vh*cgV&u;8 z^uuJ5^!*2o5+naFbdX$^^!*e4viAS3-v2#45A8qgz1;t+h{-uA<X0LpNc#ScJ`$ra zj+Zv6f3D-@I)9@{kS?WcFmgQe57EN%zzKzu8sztxZPNF<G4ao7$7K%GT*luT6W`K~ z<NA-M{c%kECpuo<Kbe1fO#GMHk<Xj+$@mBjS^cx4LB6NdKU53P$9N4fIVVE!jRxf} zyYxMezFGPAGV;%(ugp*9Bj-d2e$wD^QVf#5OK8i=|7k}4htOB%r}=44*}wO6A_r|I zaen4UP+-~gJ5G;f21(zi$HbR(yzD=&pQo;1eAfE!Xpq-M=TCpDIiAmdaZLU<bp8vR jNOM{L6Jzq<&)9$JC7J&U#%FES#~Li@gv8AML|p&B-Blwt literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objcopy/drawf-fission.test b/test/tools/llvm-objcopy/drawf-fission.test new file mode 100644 index 00000000000..112bffbc891 --- /dev/null +++ b/test/tools/llvm-objcopy/drawf-fission.test @@ -0,0 +1,43 @@ +# RUN: llvm-objcopy -extract-dwo %p/Inputs/dwarf.dwo %t +# RUN: llvm-objcopy -strip-dwo %p/Inputs/dwarf.dwo %t2 +# RUN: llvm-objcopy -split-dwo=%t3 %p/Inputs/dwarf.dwo %t4 +# RUN: llvm-readobj -file-headers -sections %t | FileCheck %s -check-prefix=DWARF +# RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s -check-prefix=STRIP +# RUN: diff %t %t3 +# RUN: diff %t2 %t4 + +#DWARF: SectionHeaderCount: 8 + +#DWARF: Name: .debug_loc.dwo +#DWARF: Name: .debug_str.dwo +#DWARF: Name: .debug_str_offsets.dwo +#DWARF: Name: .debug_info.dwo +#DWARF: Name: .debug_abbrev.dwo +#DWARF: Name: .debug_line.dwo +#DWARF: Name: .strtab + +#STRIP: SectionHeaderCount: 24 + +#STRIP: Name: .text +#STRIP: Name: .rodata.str1.1 +#STRIP: Name: .debug_str +#STRIP: Name: .debug_abbrev +#STRIP: Name: .debug_info +#STRIP: Name: .debug_ranges +#STRIP: Name: .debug_macinfo +#STRIP: Name: .debug_addr +#STRIP: Name: .debug_pubnames +#STRIP: Name: .debug_pubtypes +#STRIP: Name: .comment +#STRIP: Name: .note.GNU-stack +#STRIP: Name: .debug_frame +#STRIP: Name: .debug_line +#STRIP: Name: .symtab +#STRIP: Name: .rela.text +#STRIP: Name: .rela.debug_info +#STRIP: Name: .rela.debug_addr +#STRIP: Name: .rela.debug_pubnames +#STRIP: Name: .rela.debug_pubtypes +#STRIP: Name: .rela.debug_frame +#STRIP: Name: .rela.debug_line +#STRIP: Name: .strtab diff --git a/tools/llvm-objcopy/Object.h b/tools/llvm-objcopy/Object.h index 9c77f5900ce..f12e6da7d21 100644 --- a/tools/llvm-objcopy/Object.h +++ b/tools/llvm-objcopy/Object.h @@ -368,6 +368,7 @@ public: Object(const object::ELFObjectFile<ELFT> &Obj); virtual ~Object() = default; + const SectionBase *getSectionHeaderStrTab() const { return SectionNames; } void removeSections(std::function<bool(const SectionBase &)> ToRemove); virtual size_t totalSize() const = 0; virtual void finalize() = 0; diff --git a/tools/llvm-objcopy/llvm-objcopy.cpp b/tools/llvm-objcopy/llvm-objcopy.cpp index f3e9c7750a6..52091d3e183 100644 --- a/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/tools/llvm-objcopy/llvm-objcopy.cpp @@ -83,12 +83,63 @@ static cl::alias ToRemoveA("R", cl::desc("Alias for remove-section"), cl::aliasopt(ToRemove)); static cl::opt<bool> StripSections("strip-sections", cl::desc("Remove all section headers")); +static cl::opt<bool> + StripDWO("strip-dwo", cl::desc("remove all DWARF .dwo sections from file")); +static cl::opt<bool> ExtractDWO( + "extract-dwo", + cl::desc("remove all sections that are not DWARF .dwo sections from file")); +static cl::opt<std::string> + SplitDWO("split-dwo", + cl::desc("equivalent to extract-dwo on the input file to " + "<dwo-file>, then strip-dwo on the input file"), + cl::value_desc("dwo-file")); using SectionPred = std::function<bool(const SectionBase &Sec)>; -void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { +bool IsDWOSection(const SectionBase &Sec) { + return Sec.Name.endswith(".dwo"); +} + +template <class ELFT> +bool OnlyKeepDWOPred(const Object<ELFT> &Obj, const SectionBase &Sec) { + // We can't remove the section header string table. + if (&Sec == Obj.getSectionHeaderStrTab()) + return false; + // Short of keeping the string table we want to keep everything that is a DWO + // section and remove everything else. + return !IsDWOSection(Sec); +} + +template <class ELFT> +void WriteObjectFile(const Object<ELFT> &Obj, StringRef File) { std::unique_ptr<FileOutputBuffer> Buffer; + ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = + FileOutputBuffer::create(File, Obj.totalSize(), + FileOutputBuffer::F_executable); + if (BufferOrErr.getError()) + error("failed to open " + OutputFilename); + else + Buffer = std::move(*BufferOrErr); + Obj.write(*Buffer); + if (auto EC = Buffer->commit()) + reportError(File, EC); +} + +template <class ELFT> +void SplitDWOToFile(const ELFObjectFile<ELFT> &ObjFile, StringRef File) { + // Construct a second output file for the DWO sections. + ELFObject<ELFT> DWOFile(ObjFile); + + DWOFile.removeSections([&](const SectionBase &Sec) { + return OnlyKeepDWOPred<ELFT>(DWOFile, Sec); + }); + DWOFile.finalize(); + WriteObjectFile(DWOFile, File); +} + +void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { std::unique_ptr<Object<ELF64LE>> Obj; + if (!OutputFormat.empty() && OutputFormat != "binary") error("invalid output format '" + OutputFormat + "'"); if (!OutputFormat.empty() && OutputFormat == "binary") @@ -96,6 +147,9 @@ void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { else Obj = llvm::make_unique<ELFObject<ELF64LE>>(ObjFile); + if (!SplitDWO.empty()) + SplitDWOToFile<ELF64LE>(ObjFile, SplitDWO.getValue()); + SectionPred RemovePred = [](const SectionBase &) { return false; }; if (!ToRemove.empty()) { @@ -105,6 +159,16 @@ void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { }; } + if (StripDWO || !SplitDWO.empty()) + RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { + return IsDWOSection(Sec) || RemovePred(Sec); + }; + + if (ExtractDWO) + RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { + return OnlyKeepDWOPred(*Obj, Sec) || RemovePred(Sec); + }; + if (StripSections) { RemovePred = [RemovePred](const SectionBase &Sec) { return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0; @@ -113,21 +177,8 @@ void CopyBinary(const ELFObjectFile<ELF64LE> &ObjFile) { } Obj->removeSections(RemovePred); - Obj->finalize(); - ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = - FileOutputBuffer::create(OutputFilename, Obj->totalSize(), - FileOutputBuffer::F_executable); - if (BufferOrErr.getError()) - error("failed to open " + OutputFilename); - else - Buffer = std::move(*BufferOrErr); - std::error_code EC; - if (EC) - report_fatal_error(EC.message()); - Obj->write(*Buffer); - if (auto EC = Buffer->commit()) - reportError(OutputFilename, EC); + WriteObjectFile(*Obj, OutputFilename.getValue()); } int main(int argc, char **argv) { -- 2.40.0