Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableELFObject.h @@ -0,0 +1,84 @@ +//===-- MutableELFObject.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_OBJECT_MUTABLEELFOBJECT_H +#define LLVM_OBJECT_MUTABLEELFOBJECT_H + +#include "ELFObjectFile.h" +#include "MutableObject.h" +#include "llvm/ADT/ArrayRef.h" + +namespace llvm { +namespace object { + +template class MutableELFObject; + +static DataRefImpl toDataRef(uintptr_t Num) { + DataRefImpl Ref; + Ref.p = Num; + return Ref; +} + +template +class MutableELFSection { +public: + Elf_Shdr_Impl Header; + std::string Name; + OwningArrayRef Data; + + MutableELFSection(uintptr_t ToCopy, const MutableELFObject *ObjFile) + : MutableELFSection(toDataRef(ToCopy), ObjFile) {} + MutableELFSection(DataRefImpl ToCopy, const MutableELFObject *ObjFile) + : Header(*ObjFile->getSection(ToCopy)), + Data(OwningArrayRef(Header.sh_size)) { + ::memcpy(Data.data(), ObjFile->base() + Header.sh_offset, Header.sh_size); + } +}; + +template class MutableELFObject : public ELFObjectFile { + friend class MutableELFSection; + using Base = ELFObjectFile; + + MutableRange> Sections; + + void moveSectionNext(DataRefImpl &Sec) const override { ++Sec.p; } + + Expected getSectionName(DataRefImpl Sec) const override { + auto Mapping = Sections[Sec.p]; + if (Mapping.New) { + auto *MutSec = Sections.getNew(Mapping.Ptr); + return MutSec->Name; + } + return ELFObjectFile::getSectionName(toDataRef(Mapping.Ptr)); + } + +public: + MutableELFObject(Base &B) + : Base(std::move(B)), + Sections(B.section_begin(), B.section_end(), [&](SectionRef Ref) { + return Ref.getRawDataRefImpl().p; + }) {} + + section_iterator section_begin() const override { + return section_iterator(SectionRef(toDataRef(0), this)); + } + + section_iterator section_end() const override { + return section_iterator(SectionRef(toDataRef(Sections.size()), this)); + } + + MutableELFSection *mutateSection(section_iterator Sec) { + auto Index = Sec->getRawDataRefImpl().p; + return Sections.makeMutable(Index, this); + } +}; + +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_MUTABLEELFOBJECT_H Index: llvm/include/llvm/Object/MutableObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableObject.h @@ -0,0 +1,81 @@ +//===-- MutableObject.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_OBJECT_MUTABLEOBJECT_H +#define LVM_OBJECT_MUTABLEOBJECT_H + +#include "ELFObjectFile.h" +#include "ObjectFile.h" + +namespace llvm { +namespace object { + +// T is a wrapper type around Iterable::value_type and must have an conversion +// operator and a constructor taking a Iterable::value_type. +template class MutableRange { +public: + // The second variant of the union cannot be T because T might be non + // trivally copyable. + struct MappingType { + bool New : 1; + uintptr_t Ptr : sizeof(void *) * 8 - 1; + + MappingType(bool New, uintptr_t Ptr) : New(New), Ptr(Ptr) {} + + uintptr_t getPtr() const { return Ptr; } + }; + + using iterator = typename std::vector::iterator; + using const_iterator = iterator; + using value_type = MappingType; + +private: + std::vector Mappings; + std::vector NewValues; + +public: + template + MutableRange(Iterable Range, Extractor Extract) + : MutableRange(Range.begin(), Range.end(), Extract) {} + + template + MutableRange(Iter Begin, Iter End, Extractor Extract) { + std::transform( + Begin, End, std::back_inserter(Mappings), + [&Extract](typename Iter::value_type Value) -> MappingType { + auto Extracted = Extract(Value); + assert(Extracted <= (UINT64_MAX >> 1) && "returned type too large"); + return MappingType(false, reinterpret_cast(Extracted)); + }); + } + + MappingType operator[](uint64_t Index) const { return Mappings[Index]; } + + size_t size() const { return Mappings.size(); } + + iterator begin() { return Mappings.begin(); } + iterator end() { return Mappings.end(); } + + const T *getNew(uint64_t Index) const { return &NewValues[Index]; } + T *getNew(uint64_t Index) { return &NewValues[Index]; } + + template + T *makeMutable(uint64_t Index, Args &&... Arguments) { + MappingType Mapping = Mappings[Index]; + if (Mapping.New) + return &NewValues[reinterpret_cast(Mapping.Ptr)]; + NewValues.emplace_back(Mapping.getPtr(), Arguments...); + Mappings[Index] = MappingType(true, NewValues.size() - 1); + return &NewValues.back(); + } +}; + +} // namespace object +} // namespace llvm + +#endif // LVM_OBJECT_MUTABLEOBJECT_H