Skip to content

Commit 2fe9643

Browse files
authored
[DirectX] Add ObjectFile boilerplate for objdump (#151434)
This change adds boilerplate code to implement the object::ObjectFile interface for the DXContainer object file and an empty implementation of the objdump Dumper object. Adding an ObjectFile implementation for DXContainer is a bit odd because the DXContainer format doesn't have a symbol table, so there isn't a reasonable implementation for the SymbolicFile interfaces. That said, it does have sections, and it will be useful for objdump to be able to inspect some of the structured data stored in some of the special named sections. At this point in the implementation it can't do much other than dump the part names, offsets, and sizes. Dumping detailed structured section contents to be extended in subsequent PRs. Fixes #151433
1 parent 2cf276d commit 2fe9643

File tree

14 files changed

+373
-2
lines changed

14 files changed

+373
-2
lines changed

llvm/include/llvm-c/Object.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ typedef enum {
5555
LLVMBinaryTypeMachO64B, /**< MachO 64-bit, big endian. */
5656
LLVMBinaryTypeWasm, /**< Web Assembly. */
5757
LLVMBinaryTypeOffload, /**< Offloading fatbinary. */
58+
LLVMBinaryTypeDXcontainer, /**< DirectX Binary Container. */
5859

5960
} LLVMBinaryType;
6061

llvm/include/llvm/Object/Binary.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class LLVM_ABI Binary {
7272

7373
ID_GOFF,
7474
ID_Wasm,
75+
ID_DXContainer,
7576

7677
ID_EndObjects
7778
};
@@ -161,6 +162,8 @@ class LLVM_ABI Binary {
161162

162163
bool isWinRes() const { return TypeID == ID_WinRes; }
163164

165+
bool isDXContainer() const { return TypeID == ID_DXContainer; }
166+
164167
Triple::ObjectFormatType getTripleObjectFormat() const {
165168
if (isCOFF())
166169
return Triple::COFF;

llvm/include/llvm/Object/DXContainer.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ADT/Twine.h"
2121
#include "llvm/BinaryFormat/DXContainer.h"
2222
#include "llvm/Object/Error.h"
23+
#include "llvm/Object/ObjectFile.h"
2324
#include "llvm/Support/Compiler.h"
2425
#include "llvm/Support/Endian.h"
2526
#include "llvm/Support/Error.h"
@@ -499,6 +500,7 @@ class DXContainer {
499500
} IteratorState;
500501

501502
friend class DXContainer;
503+
friend class DXContainerObjectFile;
502504

503505
PartIterator(const DXContainer &C,
504506
SmallVectorImpl<uint32_t>::const_iterator It)
@@ -584,6 +586,79 @@ class DXContainer {
584586
}
585587
};
586588

589+
class DXContainerObjectFile : public ObjectFile {
590+
private:
591+
friend class ObjectFile;
592+
DXContainer Container;
593+
594+
using PartData = DXContainer::PartIterator::PartData;
595+
llvm::SmallVector<PartData> Parts;
596+
using PartIterator = llvm::SmallVector<PartData>::iterator;
597+
598+
DXContainerObjectFile(DXContainer C)
599+
: ObjectFile(ID_DXContainer, MemoryBufferRef(C.getData(), "")),
600+
Container(C) {
601+
for (auto &P : C)
602+
Parts.push_back(P);
603+
}
604+
605+
public:
606+
static bool classof(const Binary *v) { return v->isDXContainer(); }
607+
608+
Expected<StringRef> getSymbolName(DataRefImpl) const override;
609+
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
610+
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
611+
uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
612+
613+
Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
614+
Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
615+
void moveSectionNext(DataRefImpl &Sec) const override;
616+
Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
617+
uint64_t getSectionAddress(DataRefImpl Sec) const override;
618+
uint64_t getSectionIndex(DataRefImpl Sec) const override;
619+
uint64_t getSectionSize(DataRefImpl Sec) const override;
620+
Expected<ArrayRef<uint8_t>>
621+
getSectionContents(DataRefImpl Sec) const override;
622+
623+
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
624+
bool isSectionCompressed(DataRefImpl Sec) const override;
625+
bool isSectionText(DataRefImpl Sec) const override;
626+
bool isSectionData(DataRefImpl Sec) const override;
627+
bool isSectionBSS(DataRefImpl Sec) const override;
628+
bool isSectionVirtual(DataRefImpl Sec) const override;
629+
630+
relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
631+
relocation_iterator section_rel_end(DataRefImpl Sec) const override;
632+
633+
void moveRelocationNext(DataRefImpl &Rel) const override;
634+
uint64_t getRelocationOffset(DataRefImpl Rel) const override;
635+
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
636+
uint64_t getRelocationType(DataRefImpl Rel) const override;
637+
void getRelocationTypeName(DataRefImpl Rel,
638+
SmallVectorImpl<char> &Result) const override;
639+
640+
section_iterator section_begin() const override;
641+
section_iterator section_end() const override;
642+
643+
uint8_t getBytesInAddress() const override;
644+
StringRef getFileFormatName() const override;
645+
Triple::ArchType getArch() const override;
646+
Expected<SubtargetFeatures> getFeatures() const override;
647+
648+
void moveSymbolNext(DataRefImpl &Symb) const override {}
649+
Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override;
650+
Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
651+
basic_symbol_iterator symbol_begin() const override {
652+
return basic_symbol_iterator(SymbolRef());
653+
}
654+
basic_symbol_iterator symbol_end() const override {
655+
return basic_symbol_iterator(SymbolRef());
656+
}
657+
bool is64Bit() const override { return false; }
658+
659+
bool isRelocatableObject() const override { return false; }
660+
};
661+
587662
} // namespace object
588663
} // namespace llvm
589664

llvm/include/llvm/Object/ObjectFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class SectionRef;
4444
class SymbolRef;
4545
class symbol_iterator;
4646
class WasmObjectFile;
47+
class DXContainerObjectFile;
4748

4849
using section_iterator = content_iterator<SectionRef>;
4950

@@ -401,6 +402,9 @@ class LLVM_ABI ObjectFile : public SymbolicFile {
401402

402403
static Expected<std::unique_ptr<WasmObjectFile>>
403404
createWasmObjectFile(MemoryBufferRef Object);
405+
406+
static Expected<std::unique_ptr<DXContainerObjectFile>>
407+
createDXContainerObjectFile(MemoryBufferRef Object);
404408
};
405409

406410
/// A filtered iterator for SectionRefs that skips sections based on some given

llvm/lib/Object/Binary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
7575
case file_magic::xcoff_object_32:
7676
case file_magic::xcoff_object_64:
7777
case file_magic::wasm_object:
78+
case file_magic::dxcontainer_object:
7879
return ObjectFile::createSymbolicFile(Buffer, Type, Context, InitContent);
7980
case file_magic::macho_universal_binary:
8081
return MachOUniversalBinary::create(Buffer);
@@ -87,7 +88,6 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
8788
case file_magic::clang_ast:
8889
case file_magic::cuda_fatbinary:
8990
case file_magic::coff_cl_gl_object:
90-
case file_magic::dxcontainer_object:
9191
case file_magic::offload_bundle:
9292
case file_magic::offload_bundle_compressed:
9393
case file_magic::spirv_object:

llvm/lib/Object/DXContainer.cpp

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvm/Object/Error.h"
1212
#include "llvm/Support/Endian.h"
1313
#include "llvm/Support/FormatVariadic.h"
14+
#include "llvm/TargetParser/SubtargetFeature.h"
1415

1516
using namespace llvm;
1617
using namespace llvm::object;
@@ -515,3 +516,183 @@ uint8_t DirectX::PSVRuntimeInfo::getSigPatchOrPrimCount() const {
515516
return P->SigPatchOrPrimElements;
516517
return 0;
517518
}
519+
520+
class DXNotSupportedError : public ErrorInfo<DXNotSupportedError> {
521+
public:
522+
static char ID;
523+
524+
DXNotSupportedError(StringRef S) : FeatureString(S) {}
525+
526+
void log(raw_ostream &OS) const override {
527+
OS << "DXContainer does not support " << FeatureString;
528+
}
529+
530+
std::error_code convertToErrorCode() const override {
531+
return inconvertibleErrorCode();
532+
}
533+
534+
private:
535+
StringRef FeatureString;
536+
};
537+
538+
char DXNotSupportedError::ID = 0;
539+
540+
Expected<section_iterator>
541+
DXContainerObjectFile::getSymbolSection(DataRefImpl Symb) const {
542+
return make_error<DXNotSupportedError>("Symbol sections");
543+
}
544+
545+
Expected<StringRef> DXContainerObjectFile::getSymbolName(DataRefImpl) const {
546+
return make_error<DXNotSupportedError>("Symbol names");
547+
}
548+
549+
Expected<uint64_t>
550+
DXContainerObjectFile::getSymbolAddress(DataRefImpl Symb) const {
551+
return make_error<DXNotSupportedError>("Symbol addresses");
552+
}
553+
554+
uint64_t DXContainerObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
555+
llvm_unreachable("DXContainer does not support symbols");
556+
}
557+
uint64_t
558+
DXContainerObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
559+
llvm_unreachable("DXContainer does not support symbols");
560+
}
561+
562+
Expected<SymbolRef::Type>
563+
DXContainerObjectFile::getSymbolType(DataRefImpl Symb) const {
564+
return make_error<DXNotSupportedError>("Symbol types");
565+
}
566+
567+
void DXContainerObjectFile::moveSectionNext(DataRefImpl &Sec) const {
568+
PartIterator It = reinterpret_cast<PartIterator>(Sec.p);
569+
if (It == Parts.end())
570+
return;
571+
572+
++It;
573+
Sec.p = reinterpret_cast<uintptr_t>(It);
574+
}
575+
576+
Expected<StringRef>
577+
DXContainerObjectFile::getSectionName(DataRefImpl Sec) const {
578+
PartIterator It = reinterpret_cast<PartIterator>(Sec.p);
579+
return StringRef(It->Part.getName());
580+
}
581+
582+
uint64_t DXContainerObjectFile::getSectionAddress(DataRefImpl Sec) const {
583+
PartIterator It = reinterpret_cast<PartIterator>(Sec.p);
584+
return It->Offset;
585+
}
586+
587+
uint64_t DXContainerObjectFile::getSectionIndex(DataRefImpl Sec) const {
588+
return (Sec.p - reinterpret_cast<uintptr_t>(Parts.begin())) /
589+
sizeof(PartIterator);
590+
}
591+
592+
uint64_t DXContainerObjectFile::getSectionSize(DataRefImpl Sec) const {
593+
PartIterator It = reinterpret_cast<PartIterator>(Sec.p);
594+
return It->Data.size();
595+
}
596+
Expected<ArrayRef<uint8_t>>
597+
DXContainerObjectFile::getSectionContents(DataRefImpl Sec) const {
598+
PartIterator It = reinterpret_cast<PartIterator>(Sec.p);
599+
return ArrayRef<uint8_t>(It->Data.bytes_begin(), It->Data.size());
600+
}
601+
602+
uint64_t DXContainerObjectFile::getSectionAlignment(DataRefImpl Sec) const {
603+
return 1;
604+
}
605+
606+
bool DXContainerObjectFile::isSectionCompressed(DataRefImpl Sec) const {
607+
return false;
608+
}
609+
610+
bool DXContainerObjectFile::isSectionText(DataRefImpl Sec) const {
611+
return false;
612+
}
613+
614+
bool DXContainerObjectFile::isSectionData(DataRefImpl Sec) const {
615+
return false;
616+
}
617+
618+
bool DXContainerObjectFile::isSectionBSS(DataRefImpl Sec) const {
619+
return false;
620+
}
621+
622+
bool DXContainerObjectFile::isSectionVirtual(DataRefImpl Sec) const {
623+
return false;
624+
}
625+
626+
relocation_iterator
627+
DXContainerObjectFile::section_rel_begin(DataRefImpl Sec) const {
628+
return relocation_iterator(RelocationRef());
629+
}
630+
631+
relocation_iterator
632+
DXContainerObjectFile::section_rel_end(DataRefImpl Sec) const {
633+
return relocation_iterator(RelocationRef());
634+
}
635+
636+
void DXContainerObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
637+
llvm_unreachable("DXContainer does not support relocations");
638+
}
639+
640+
uint64_t DXContainerObjectFile::getRelocationOffset(DataRefImpl Rel) const {
641+
llvm_unreachable("DXContainer does not support relocations");
642+
}
643+
644+
symbol_iterator
645+
DXContainerObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
646+
return symbol_iterator(SymbolRef());
647+
}
648+
649+
uint64_t DXContainerObjectFile::getRelocationType(DataRefImpl Rel) const {
650+
llvm_unreachable("DXContainer does not support relocations");
651+
}
652+
653+
void DXContainerObjectFile::getRelocationTypeName(
654+
DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
655+
llvm_unreachable("DXContainer does not support relocations");
656+
}
657+
658+
section_iterator DXContainerObjectFile::section_begin() const {
659+
DataRefImpl Sec;
660+
Sec.p = reinterpret_cast<uintptr_t>(Parts.begin());
661+
return section_iterator(SectionRef(Sec, this));
662+
}
663+
section_iterator DXContainerObjectFile::section_end() const {
664+
DataRefImpl Sec;
665+
Sec.p = reinterpret_cast<uintptr_t>(Parts.end());
666+
return section_iterator(SectionRef(Sec, this));
667+
}
668+
669+
uint8_t DXContainerObjectFile::getBytesInAddress() const { return 4; }
670+
671+
StringRef DXContainerObjectFile::getFileFormatName() const {
672+
return "DirectX Container";
673+
}
674+
675+
Triple::ArchType DXContainerObjectFile::getArch() const { return Triple::dxil; }
676+
677+
Expected<SubtargetFeatures> DXContainerObjectFile::getFeatures() const {
678+
return SubtargetFeatures();
679+
}
680+
681+
Error DXContainerObjectFile::printSymbolName(raw_ostream &OS,
682+
DataRefImpl Symb) const {
683+
return make_error<DXNotSupportedError>("Symbol names");
684+
}
685+
686+
Expected<uint32_t>
687+
DXContainerObjectFile::getSymbolFlags(DataRefImpl Symb) const {
688+
return make_error<DXNotSupportedError>("Symbol flags");
689+
}
690+
691+
Expected<std::unique_ptr<DXContainerObjectFile>>
692+
ObjectFile::createDXContainerObjectFile(MemoryBufferRef Object) {
693+
auto ExC = DXContainer::create(Object);
694+
if (!ExC)
695+
return ExC.takeError();
696+
std::unique_ptr<DXContainerObjectFile> Obj(new DXContainerObjectFile(*ExC));
697+
return std::move(Obj);
698+
}

llvm/lib/Object/Object.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) {
124124
return LLVMBinaryTypeOffload;
125125
case ID_Wasm:
126126
return LLVMBinaryTypeWasm;
127+
case ID_DXContainer:
128+
return LLVMBinaryTypeDXcontainer;
127129
case ID_StartObjects:
128130
case ID_EndObjects:
129131
llvm_unreachable("Marker types are not valid binary kinds!");

llvm/lib/Object/ObjectFile.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/BinaryFormat/Magic.h"
1616
#include "llvm/Object/Binary.h"
1717
#include "llvm/Object/COFF.h"
18+
#include "llvm/Object/DXContainer.h"
1819
#include "llvm/Object/Error.h"
1920
#include "llvm/Object/MachO.h"
2021
#include "llvm/Object/Wasm.h"
@@ -165,7 +166,6 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
165166
case file_magic::goff_object:
166167
case file_magic::cuda_fatbinary:
167168
case file_magic::offload_binary:
168-
case file_magic::dxcontainer_object:
169169
case file_magic::offload_bundle:
170170
case file_magic::offload_bundle_compressed:
171171
case file_magic::spirv_object:
@@ -201,6 +201,8 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
201201
return createXCOFFObjectFile(Object, Binary::ID_XCOFF64);
202202
case file_magic::wasm_object:
203203
return createWasmObjectFile(Object);
204+
case file_magic::dxcontainer_object:
205+
return createDXContainerObjectFile(Object);
204206
}
205207
llvm_unreachable("Unexpected Object File Type");
206208
}

llvm/lib/Object/SymbolicFile.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type,
6868
case file_magic::xcoff_object_32:
6969
case file_magic::xcoff_object_64:
7070
case file_magic::wasm_object:
71+
case file_magic::dxcontainer_object:
7172
return ObjectFile::createObjectFile(Object, Type, InitContent);
7273
case file_magic::coff_import_library:
7374
return std::unique_ptr<SymbolicFile>(new COFFImportFile(Object));
@@ -123,6 +124,7 @@ bool SymbolicFile::isSymbolicFile(file_magic Type, const LLVMContext *Context) {
123124
case file_magic::elf_relocatable:
124125
case file_magic::macho_object:
125126
case file_magic::coff_object:
127+
case file_magic::dxcontainer_object:
126128
return true;
127129
default:
128130
return false;

0 commit comments

Comments
 (0)