forked from OSchip/llvm-project
[llvm-objcopy] Add support for dwarf fission
This change adds support for dwarf fission. Differential Revision: https://reviews.llvm.org/D39207 llvm-svn: 317350
This commit is contained in:
parent
9dcf099944
commit
5de70d996c
Binary file not shown.
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue