Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableELFObject.h @@ -0,0 +1,81 @@ +//===-- 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; + +static DataRefImpl toDataRef(uintptr_t Ptr) { + DataRefImpl Ref; + Ref.p = 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; + + void moveSectionNext(DataRefImpl &Sec) const override { ++Sec.p; } + + using MappingType = + typename MutableRange>::MappingType; + Expected getSectionName(DataRefImpl Sec) const override { + MappingType Mapping = Sections[Sec.p]; + if (Mapping.New) { + const MutableELFSection *NewSec = Sections.getNew(Mapping.Ptr); + return NewSec->Name; + } + return ELFObjectFile::getSectionName(toDataRef(Mapping.Ptr)); + } + +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(0), 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); + } +}; + +} // 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,77 @@ +//===-- 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 + +#include "llvm/Object/ELFObjectFile.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, 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