Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableELFObject.h @@ -0,0 +1,199 @@ +//===-- 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 "llvm/ADT/ArrayRef.h" +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MutableObject.h" + +namespace llvm { +namespace object { + +template class MutableELFObject; + +template +static inline DataRefImpl toDataRef(T Ptr) { + DataRefImpl Ref; + Ref.p = reinterpret_cast(Ptr); + return Ref; +} + +template class MutableELFSection { +public: + Elf_Shdr_Impl Header; + std::string Name; + OwningArrayRef Data; + + MutableELFSection(uintptr_t ToCopy, const MutableELFObject *ObjFile) + : Header(*ObjFile->getSection(toDataRef(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; + + MutableRange> Sections; + +protected: + using MappingType = + typename MutableRange>::MappingType; + + void moveSectionNext(DataRefImpl &Sec) const override; + Expected getSectionName(DataRefImpl Sec) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionIndex(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; + Expected> + getSectionContents(DataRefImpl Sec) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionCompressed(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool isBerkeleyText(DataRefImpl Sec) const override; + bool isBerkeleyData(DataRefImpl Sec) const override; + +public: + MutableELFObject(ELFObjectFile &B) + : ELFObjectFile(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(0UL), this)); + } + + section_iterator section_end() const override { + return section_iterator(SectionRef(toDataRef(Sections.size()), this)); + } + + MutableELFSection *getMutableSection(section_iterator Sec) { + uintptr_t Index = Sec->getRawDataRefImpl().p; + return Sections.makeMutable(Index, this); + } +}; + +template +void MutableELFObject::moveSectionNext(DataRefImpl &Sec) const { + ++Sec.p; +} + +template +Expected +MutableELFObject::getSectionName(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + if (Mapping.New) { + const MutableELFSection *NewSec = Sections.getNew(Mapping.Ptr); + return NewSec->Name; + } + return ELFObjectFile::getSectionName(toDataRef(Mapping.Ptr)); +} + +template +uint64_t MutableELFObject::getSectionAddress(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::getSectionAddress(Ref); +} + +template +uint64_t MutableELFObject::getSectionIndex(DataRefImpl Sec) const { + return Sec.p; +} + +template +uint64_t MutableELFObject::getSectionSize(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::getSectionSize(Ref); +} + +template +Expected> +MutableELFObject::getSectionContents(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::getSectionContents(Ref); +} + +template +uint64_t MutableELFObject::getSectionAlignment(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::getSectionAlignment(Ref); +} + +template +bool MutableELFObject::isSectionCompressed(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isSectionCompressed(Ref); +} + +template +bool MutableELFObject::isSectionText(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isSectionText(Ref); +} + +template +bool MutableELFObject::isSectionData(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isSectionData(Ref); +} + +template +bool MutableELFObject::isSectionBSS(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isSectionBSS(Ref); +} + +template +bool MutableELFObject::isSectionVirtual(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isSectionVirtual(Ref); +} + +template +bool MutableELFObject::isBerkeleyText(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isBerkeleyText(Ref); +} + +template +bool MutableELFObject::isBerkeleyData(DataRefImpl Sec) const { + MappingType Mapping = Sections[Sec.p]; + DataRefImpl Ref = Mapping.New ? toDataRef(Sections.getNew(Mapping.Ptr)) + : toDataRef(Mapping.Ptr); + return ELFObjectFile::isBerkeleyData(Ref); +} + +} // 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,78 @@ +//===-- 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 LLVM_OBJECT_MUTABLEOBJECT_H + +namespace llvm { +namespace object { + +// T is a wrapper type around Iterable::value_type and must have a constructor +// taking an Iterable::value_type. +template class MutableRange { +public: + 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 value_type = MappingType; + +private: + std::vector Mappings; + std::vector NewValues; + +public: + template + MutableRange( + Iterable Range, + function_ref Extract) + : MutableRange(Range.begin(), Range.end(), Extract) {} + + template + MutableRange(Iter Begin, Iter End, + function_ref Extract) { + std::transform(Begin, End, std::back_inserter(Mappings), + [&Extract](typename Iter::value_type Value) -> MappingType { + uintptr_t Extracted = Extract(Value); + assert(Extracted <= (UINT64_MAX >> 1) && + "returned type too large"); + return MappingType(false, 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