boiler plate to add dxcontainer to objcopy

This commit is contained in:
Finn Plummer 2025-08-07 18:42:27 +00:00
parent dbaa82b384
commit 44f66db8dc
14 changed files with 366 additions and 0 deletions

View File

@ -11,6 +11,7 @@
#include "llvm/ObjCopy/COFF/COFFConfig.h"
#include "llvm/ObjCopy/CommonConfig.h"
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
#include "llvm/ObjCopy/ELF/ELFConfig.h"
#include "llvm/ObjCopy/MachO/MachOConfig.h"
#include "llvm/ObjCopy/MultiFormatConfig.h"
@ -36,6 +37,8 @@ struct LLVM_ABI ConfigManager : public MultiFormatConfig {
Expected<const XCOFFConfig &> getXCOFFConfig() const override;
Expected<const DXContainerConfig &> getDXContainerConfig() const override;
// All configs.
CommonConfig Common;
ELFConfig ELF;
@ -43,6 +46,7 @@ struct LLVM_ABI ConfigManager : public MultiFormatConfig {
MachOConfig MachO;
WasmConfig Wasm;
XCOFFConfig XCOFF;
DXContainerConfig DXContainer;
};
} // namespace objcopy

View File

@ -0,0 +1,21 @@
//===- DXContainerConfig.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H
#define LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H
namespace llvm {
namespace objcopy {
// DXContainer specific configuration for copying/stripping a single file.
struct DXContainerConfig {};
} // namespace objcopy
} // namespace llvm
#endif // LLVM_OBJCOPY_DXCONTAINER_DXCONTAINERCONFIG_H

View File

@ -0,0 +1,36 @@
//===- DXContainerObjcopy.h -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H
#define LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H
namespace llvm {
class Error;
class raw_ostream;
namespace object {
class DXContainerObjectFile;
} // end namespace object
namespace objcopy {
struct CommonConfig;
struct DXContainerConfig;
namespace dxc {
/// Apply the transformations described by \p Config and \p DXContainerConfig
/// to \p In and writes the result into \p Out.
/// \returns any Error encountered whilst performing the operation.
Error executeObjcopyOnBinary(const CommonConfig &Config,
const DXContainerConfig &,
object::DXContainerObjectFile &In,
raw_ostream &Out);
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_OBJCOPY_DXCONTAINER_DXCONTAINEROBJCOPY_H

View File

@ -20,6 +20,7 @@ struct COFFConfig;
struct MachOConfig;
struct WasmConfig;
struct XCOFFConfig;
struct DXContainerConfig;
class MultiFormatConfig {
public:
@ -31,6 +32,7 @@ public:
virtual Expected<const MachOConfig &> getMachOConfig() const = 0;
virtual Expected<const WasmConfig &> getWasmConfig() const = 0;
virtual Expected<const XCOFFConfig &> getXCOFFConfig() const = 0;
virtual Expected<const DXContainerConfig &> getDXContainerConfig() const = 0;
};
} // namespace objcopy

View File

@ -605,6 +605,8 @@ private:
public:
static bool classof(const Binary *v) { return v->isDXContainer(); }
const dxbc::Header &getHeader() const { return Container.getHeader(); }
Expected<StringRef> getSymbolName(DataRefImpl) const override;
Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;

View File

@ -16,6 +16,9 @@ source_group("Header Files\\wasm" REGULAR_EXPRESSION
source_group("Header Files\\XCOFF" REGULAR_EXPRESSION
XCOFF/.*[.]h
)
source_group("Header Files\\DXContainer" REGULAR_EXPRESSION
DXContainer/.*[.]h
)
source_group("Source Files" REGULAR_EXPRESSION
.*[.]cpp
)
@ -34,9 +37,15 @@ source_group("Source Files\\wasm" REGULAR_EXPRESSION
source_group("Source Files\\XCOFF" REGULAR_EXPRESSION
XCOFF/.*[.]cpp
)
source_group("Source Files\\DXContainer" REGULAR_EXPRESSION
DXContainer/.*[.]cpp
)
add_llvm_component_library(LLVMObjCopy
Archive.cpp
DXContainer/DXContainerObjcopy.cpp
DXContainer/DXContainerReader.cpp
DXContainer/DXContainerWriter.cpp
CommonConfig.cpp
ObjCopy.cpp
ConfigManager.cpp
@ -62,11 +71,13 @@ add_llvm_component_library(LLVMObjCopy
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/COFF
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/DXContainer
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/ELF
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/MachO
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/wasm
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjCopy/XCOFF
COFF
DXContainer
ELF
MachO
wasm

View File

@ -107,3 +107,35 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
return XCOFF;
}
Expected<const DXContainerConfig &>
ConfigManager::getDXContainerConfig() const {
if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition ||
!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() ||
!Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() ||
!Common.AllocSectionsPrefix.empty() ||
Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() ||
!Common.DumpSection.empty() || !Common.SymbolsToAdd.empty() ||
!Common.KeepSection.empty() || !Common.OnlySection.empty() ||
!Common.ToRemove.empty() || !Common.SymbolsToGlobalize.empty() ||
!Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() ||
!Common.SymbolsToRemove.empty() ||
!Common.UnneededSymbolsToRemove.empty() ||
!Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
!Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
!Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
!Common.SymbolsToRename.empty() || Common.ExtractDWO ||
Common.ExtractMainPartition || Common.OnlyKeepDebug ||
Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
Common.Weaken || Common.StripUnneeded || Common.DecompressDebugSections ||
Common.GapFill != 0 || Common.PadTo != 0 ||
Common.ChangeSectionLMAValAll != 0 ||
!Common.ChangeSectionAddress.empty()) {
return createStringError(
llvm::errc::invalid_argument,
"no flags are supported yet, only basic copying is allowed");
}
return DXContainer;
}

View File

@ -0,0 +1,47 @@
//===- DXContainerObjcopy.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ObjCopy/DXContainer/DXContainerObjcopy.h"
#include "llvm/ObjCopy/CommonConfig.h"
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
#include "DXContainerReader.h"
#include "DXContainerWriter.h"
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
static Error handleArgs(const CommonConfig &Config, Object &Obj) {
return Error::success();
}
Error executeObjcopyOnBinary(const CommonConfig &Config,
const DXContainerConfig &,
DXContainerObjectFile &In, raw_ostream &Out) {
DXContainerReader Reader(In);
Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create();
if (!ObjOrErr)
return createFileError(Config.InputFilename, ObjOrErr.takeError());
Object *Obj = ObjOrErr->get();
assert(Obj && "Unable to deserialize DXContainer object");
if (Error E = handleArgs(Config, *Obj))
return E;
DXContainerWriter Writer(*Obj, Out);
if (Error E = Writer.write())
return createFileError(Config.OutputFilename, std::move(E));
return Error::success();
}
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm

View File

@ -0,0 +1,38 @@
//===- DXContainerObject.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_OBJCOPY_DXContainer_DXContainerOBJECT_H
#define LLVM_LIB_OBJCOPY_DXContainer_DXContainerOBJECT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/DXContainer.h"
#include <vector>
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
struct Part {
StringRef Name;
uint32_t Offset;
ArrayRef<uint8_t> Data;
};
struct Object {
dxbc::Header Header;
SmallVector<Part> Parts;
};
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_LIB_OBJCOPY_DXContainer_DXContainerOBJECT_H

View File

@ -0,0 +1,38 @@
//===- DXContainerReader.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DXContainerReader.h"
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
Expected<std::unique_ptr<Object>> DXContainerReader::create() const {
auto Obj = std::make_unique<Object>();
Obj->Header = DXContainerObj.getHeader();
for (const SectionRef &Part : DXContainerObj.sections()) {
DataRefImpl PartDRI = Part.getRawDataRefImpl();
Expected<StringRef> Name = DXContainerObj.getSectionName(PartDRI);
if (auto E = Name.takeError())
return createStringError(inconvertibleErrorCode(), "Missing Part Name");
uint32_t Offset = DXContainerObj.getSectionAddress(PartDRI);
Expected<ArrayRef<uint8_t>> Data =
DXContainerObj.getSectionContents(PartDRI);
if (auto E = Data.takeError())
return createStringError(inconvertibleErrorCode(),
"Missing Part Contents");
Obj->Parts.push_back({*Name, Offset, *Data});
}
return std::move(Obj);
}
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm

View File

@ -0,0 +1,34 @@
//===- DXContainerReader.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERREADER_H
#define LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERREADER_H
#include "DXContainerObject.h"
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
class DXContainerReader {
public:
explicit DXContainerReader(const DXContainerObjectFile &Obj)
: DXContainerObj(Obj) {}
Expected<std::unique_ptr<Object>> create() const;
private:
const DXContainerObjectFile &DXContainerObj;
};
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERREADER_H

View File

@ -0,0 +1,50 @@
//===- DXContainerWriter.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DXContainerWriter.h"
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
size_t DXContainerWriter::finalize() {
size_t ObjectSize = sizeof(dxbc::Header);
ObjectSize += Obj.Parts.size() * sizeof(uint32_t);
Offsets.reserve(Obj.Parts.size());
for (const Part &P : Obj.Parts) {
Offsets.push_back(ObjectSize);
assert(P.Name.size() == 4 &&
"Valid DXIL Part name consists of 4 characters");
ObjectSize += 4 + sizeof(uint32_t) + P.Data.size();
}
return ObjectSize;
}
Error DXContainerWriter::write() {
size_t TotalSize = finalize();
Out.reserveExtraSpace(TotalSize);
Out.write(reinterpret_cast<const char *>(&Obj.Header), sizeof(dxbc::Header));
Out.write(reinterpret_cast<const char *>(Offsets.data()),
Offsets.size() * sizeof(uint32_t));
for (const Part &P : Obj.Parts) {
Out.write(reinterpret_cast<const char *>(P.Name.data()), P.Name.size());
uint32_t Size = P.Data.size();
Out.write(reinterpret_cast<const char *>(&Size), sizeof(uint32_t));
Out.write(reinterpret_cast<const char *>(P.Data.data()), P.Data.size());
}
return Error::success();
}
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm

View File

@ -0,0 +1,39 @@
//===- DXContainerWriter.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERWRITER_H
#define LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERWRITER_H
#include "DXContainerObject.h"
namespace llvm {
namespace objcopy {
namespace dxc {
using namespace object;
class DXContainerWriter {
public:
explicit DXContainerWriter(const Object &Obj, raw_ostream &Out)
: Obj(Obj), Out(Out) {}
Error write();
private:
const Object &Obj;
raw_ostream &Out;
SmallVector<uint32_t> Offsets;
size_t finalize();
};
} // end namespace dxc
} // end namespace objcopy
} // end namespace llvm
#endif // LLVM_LIB_OBJCOPY_DXCONTAINER_DXCONTAINERWRITER_H

View File

@ -9,6 +9,8 @@
#include "llvm/ObjCopy/ObjCopy.h"
#include "llvm/ObjCopy/COFF/COFFConfig.h"
#include "llvm/ObjCopy/COFF/COFFObjcopy.h"
#include "llvm/ObjCopy/DXContainer/DXContainerConfig.h"
#include "llvm/ObjCopy/DXContainer/DXContainerObjcopy.h"
#include "llvm/ObjCopy/ELF/ELFConfig.h"
#include "llvm/ObjCopy/ELF/ELFObjcopy.h"
#include "llvm/ObjCopy/MachO/MachOConfig.h"
@ -19,6 +21,7 @@
#include "llvm/ObjCopy/wasm/WasmConfig.h"
#include "llvm/ObjCopy/wasm/WasmObjcopy.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/DXContainer.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachO.h"
@ -78,6 +81,15 @@ Error objcopy::executeObjcopyOnBinary(const MultiFormatConfig &Config,
return xcoff::executeObjcopyOnBinary(Config.getCommonConfig(), *XCOFFConfig,
*XCOFFBinary, Out);
}
if (auto *DXContainerBinary = dyn_cast<object::DXContainerObjectFile>(&In)) {
Expected<const DXContainerConfig &> DXContainerConfig =
Config.getDXContainerConfig();
if (!DXContainerConfig)
return DXContainerConfig.takeError();
return dxc::executeObjcopyOnBinary(
Config.getCommonConfig(), *DXContainerConfig, *DXContainerBinary, Out);
}
return createStringError(object_error::invalid_file_type,
"unsupported object file format");
}