Skip to content

Commit 2f5835f

Browse files
committed
[ObjCopy][DX] Support for -dump-section flag
This adds support for the -dump-section=<section>=<file> flag for the DXContainer file format. This flag dumps the contents of a named section to the specified file. This flag is particularly handy for ripping DXIL bitcode out of the object files so that we can use LLVM tools to inspect and operate on the bitcode. To facilitate that workflow this flag also strips the program headers from parts containing DXIL so that the resulting file is a valid bitcode file. ../llvm/lib/ObjCopy/DXContainer/DXContainerObjcopy.cpp ../llvm/test/tools/llvm-objcopy/DXContainer/dump-section.yaml
1 parent e764e19 commit 2f5835f

File tree

3 files changed

+326
-8
lines changed

3 files changed

+326
-8
lines changed

llvm/lib/ObjCopy/ConfigManager.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,14 @@ ConfigManager::getDXContainerConfig() const {
122122
if (!Common.AddGnuDebugLink.empty() || !Common.SplitDWO.empty() ||
123123
!Common.AllocSectionsPrefix.empty() ||
124124
Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
125-
!Common.DumpSection.empty() || !Common.KeepSection.empty() ||
126-
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
127-
!Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
128-
Common.ExtractDWO || Common.OnlyKeepDebug || Common.StripAllGNU ||
129-
Common.StripDWO || Common.StripDebug || Common.StripNonAlloc ||
130-
Common.StripSections || Common.StripUnneeded ||
131-
Common.DecompressDebugSections || Common.GapFill != 0 ||
132-
Common.PadTo != 0 || Common.ChangeSectionLMAValAll != 0 ||
125+
!Common.KeepSection.empty() || !Common.SectionsToRename.empty() ||
126+
!Common.SetSectionAlignment.empty() || !Common.SetSectionFlags.empty() ||
127+
!Common.SetSectionType.empty() || Common.ExtractDWO ||
128+
Common.OnlyKeepDebug || Common.StripAllGNU || Common.StripDWO ||
129+
Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
130+
Common.StripUnneeded || Common.DecompressDebugSections ||
131+
Common.GapFill != 0 || Common.PadTo != 0 ||
132+
Common.ChangeSectionLMAValAll != 0 ||
133133
!Common.ChangeSectionAddress.empty()) {
134134
return createStringError(llvm::errc::invalid_argument,
135135
"option is not supported for DXContainer");

llvm/lib/ObjCopy/DXContainer/DXContainerObjcopy.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
#include "llvm/ObjCopy/DXContainer/DXContainerObjcopy.h"
1010
#include "DXContainerReader.h"
1111
#include "DXContainerWriter.h"
12+
#include "llvm/BinaryFormat/DXContainer.h"
1213
#include "llvm/ObjCopy/CommonConfig.h"
1314
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
15+
#include "llvm/Support/FileOutputBuffer.h"
1416
#include "llvm/Support/raw_ostream.h"
1517

1618
namespace llvm {
@@ -42,7 +44,40 @@ static Error extractPartAsObject(StringRef PartName, StringRef OutFilename,
4244
"part '%s' not found", PartName.str().c_str());
4345
}
4446

47+
static Error dumpPartToFile(StringRef PartName, StringRef Filename,
48+
StringRef InputFilename, Object &Obj) {
49+
for (const Part &P : Obj.Parts) {
50+
if (P.Name == PartName) {
51+
ArrayRef<uint8_t> Contents = P.Data;
52+
// For parts containing llvm bitcode, don't dump the program headers so
53+
// that we get a valid .bc file.
54+
if (PartName == "DXIL" || PartName == "STAT")
55+
Contents = Contents.drop_front(sizeof(llvm::dxbc::ProgramHeader));
56+
Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
57+
FileOutputBuffer::create(Filename, Contents.size());
58+
if (!BufferOrErr)
59+
return createFileError(Filename, BufferOrErr.takeError());
60+
std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
61+
llvm::copy(Contents, Buf->getBufferStart());
62+
if (Error E = Buf->commit())
63+
return createFileError(Filename, std::move(E));
64+
return Error::success();
65+
}
66+
}
67+
return createFileError(Filename,
68+
std::make_error_code(std::errc::invalid_argument),
69+
"part '%s' not found", PartName.str().c_str());
70+
}
71+
4572
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
73+
for (StringRef Flag : Config.DumpSection) {
74+
StringRef SecName;
75+
StringRef FileName;
76+
std::tie(SecName, FileName) = Flag.split("=");
77+
if (Error E = dumpPartToFile(SecName, FileName, Config.InputFilename, Obj))
78+
return E;
79+
}
80+
4681
// Extract all sections before any modifications.
4782
for (StringRef Flag : Config.ExtractSection) {
4883
StringRef SectionName;

0 commit comments

Comments
 (0)