llvm.org GIT mirror llvm / a8631b8
[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 Jake Ehrlich 1 year, 11 months ago
4 changed file(s) with 110 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
0 # RUN: llvm-objcopy -extract-dwo %p/Inputs/dwarf.dwo %t
1 # RUN: llvm-objcopy -strip-dwo %p/Inputs/dwarf.dwo %t2
2 # RUN: llvm-objcopy -split-dwo=%t3 %p/Inputs/dwarf.dwo %t4
3 # RUN: llvm-readobj -file-headers -sections %t | FileCheck %s -check-prefix=DWARF
4 # RUN: llvm-readobj -file-headers -sections %t2 | FileCheck %s -check-prefix=STRIP
5 # RUN: diff %t %t3
6 # RUN: diff %t2 %t4
7
8 #DWARF: SectionHeaderCount: 8
9
10 #DWARF: Name: .debug_loc.dwo
11 #DWARF: Name: .debug_str.dwo
12 #DWARF: Name: .debug_str_offsets.dwo
13 #DWARF: Name: .debug_info.dwo
14 #DWARF: Name: .debug_abbrev.dwo
15 #DWARF: Name: .debug_line.dwo
16 #DWARF: Name: .strtab
17
18 #STRIP: SectionHeaderCount: 24
19
20 #STRIP: Name: .text
21 #STRIP: Name: .rodata.str1.1
22 #STRIP: Name: .debug_str
23 #STRIP: Name: .debug_abbrev
24 #STRIP: Name: .debug_info
25 #STRIP: Name: .debug_ranges
26 #STRIP: Name: .debug_macinfo
27 #STRIP: Name: .debug_addr
28 #STRIP: Name: .debug_pubnames
29 #STRIP: Name: .debug_pubtypes
30 #STRIP: Name: .comment
31 #STRIP: Name: .note.GNU-stack
32 #STRIP: Name: .debug_frame
33 #STRIP: Name: .debug_line
34 #STRIP: Name: .symtab
35 #STRIP: Name: .rela.text
36 #STRIP: Name: .rela.debug_info
37 #STRIP: Name: .rela.debug_addr
38 #STRIP: Name: .rela.debug_pubnames
39 #STRIP: Name: .rela.debug_pubtypes
40 #STRIP: Name: .rela.debug_frame
41 #STRIP: Name: .rela.debug_line
42 #STRIP: Name: .strtab
367367 Object(const object::ELFObjectFile &Obj);
368368 virtual ~Object() = default;
369369
370 const SectionBase *getSectionHeaderStrTab() const { return SectionNames; }
370371 void removeSections(std::function ToRemove);
371372 virtual size_t totalSize() const = 0;
372373 virtual void finalize() = 0;
8282 cl::aliasopt(ToRemove));
8383 static cl::opt StripSections("strip-sections",
8484 cl::desc("Remove all section headers"));
85 static cl::opt
86 StripDWO("strip-dwo", cl::desc("remove all DWARF .dwo sections from file"));
87 static cl::opt ExtractDWO(
88 "extract-dwo",
89 cl::desc("remove all sections that are not DWARF .dwo sections from file"));
90 static cl::opt
91 SplitDWO("split-dwo",
92 cl::desc("equivalent to extract-dwo on the input file to "
93 ", then strip-dwo on the input file"),
94 cl::value_desc("dwo-file"));
8595
8696 using SectionPred = std::function;
8797
98 bool IsDWOSection(const SectionBase &Sec) {
99 return Sec.Name.endswith(".dwo");
100 }
101
102 template
103 bool OnlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
104 // We can't remove the section header string table.
105 if (&Sec == Obj.getSectionHeaderStrTab())
106 return false;
107 // Short of keeping the string table we want to keep everything that is a DWO
108 // section and remove everything else.
109 return !IsDWOSection(Sec);
110 }
111
112 template
113 void WriteObjectFile(const Object &Obj, StringRef File) {
114 std::unique_ptr Buffer;
115 ErrorOr> BufferOrErr =
116 FileOutputBuffer::create(File, Obj.totalSize(),
117 FileOutputBuffer::F_executable);
118 if (BufferOrErr.getError())
119 error("failed to open " + OutputFilename);
120 else
121 Buffer = std::move(*BufferOrErr);
122 Obj.write(*Buffer);
123 if (auto EC = Buffer->commit())
124 reportError(File, EC);
125 }
126
127 template
128 void SplitDWOToFile(const ELFObjectFile &ObjFile, StringRef File) {
129 // Construct a second output file for the DWO sections.
130 ELFObject DWOFile(ObjFile);
131
132 DWOFile.removeSections([&](const SectionBase &Sec) {
133 return OnlyKeepDWOPred(DWOFile, Sec);
134 });
135 DWOFile.finalize();
136 WriteObjectFile(DWOFile, File);
137 }
138
88139 void CopyBinary(const ELFObjectFile &ObjFile) {
89 std::unique_ptr Buffer;
90140 std::unique_ptr> Obj;
141
91142 if (!OutputFormat.empty() && OutputFormat != "binary")
92143 error("invalid output format '" + OutputFormat + "'");
93144 if (!OutputFormat.empty() && OutputFormat == "binary")
95146 else
96147 Obj = llvm::make_unique>(ObjFile);
97148
149 if (!SplitDWO.empty())
150 SplitDWOToFile(ObjFile, SplitDWO.getValue());
151
98152 SectionPred RemovePred = [](const SectionBase &) { return false; };
99153
100154 if (!ToRemove.empty()) {
104158 };
105159 }
106160
161 if (StripDWO || !SplitDWO.empty())
162 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
163 return IsDWOSection(Sec) || RemovePred(Sec);
164 };
165
166 if (ExtractDWO)
167 RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
168 return OnlyKeepDWOPred(*Obj, Sec) || RemovePred(Sec);
169 };
170
107171 if (StripSections) {
108172 RemovePred = [RemovePred](const SectionBase &Sec) {
109173 return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0;
112176 }
113177
114178 Obj->removeSections(RemovePred);
115
116179 Obj->finalize();
117 ErrorOr> BufferOrErr =
118 FileOutputBuffer::create(OutputFilename, Obj->totalSize(),
119 FileOutputBuffer::F_executable);
120 if (BufferOrErr.getError())
121 error("failed to open " + OutputFilename);
122 else
123 Buffer = std::move(*BufferOrErr);
124 std::error_code EC;
125 if (EC)
126 report_fatal_error(EC.message());
127 Obj->write(*Buffer);
128 if (auto EC = Buffer->commit())
129 reportError(OutputFilename, EC);
180 WriteObjectFile(*Obj, OutputFilename.getValue());
130181 }
131182
132183 int main(int argc, char **argv) {