//===- CodeObject.hpp - ELF object file implementation ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file declares the HSA Code Object file class. // //===----------------------------------------------------------------------===// #ifndef AMDGPU_DISASSEMBLER_HSA_CODE_OBJECT_HPP #define AMDGPU_DISASSEMBLER_HSA_CODE_OBJECT_HPP #include "AMDKernelCodeT.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Endian.h" namespace llvm { //===----------------------------------------------------------------------===// // ELFNote //===----------------------------------------------------------------------===// struct amdgpu_hsa_code_object_version { support::ulittle32_t major_version; support::ulittle32_t minor_version; }; struct amdgpu_hsa_isa { support::ulittle16_t vendor_name_size; support::ulittle16_t architecture_name_size; support::ulittle32_t major; support::ulittle32_t minor; support::ulittle32_t stepping; char names[1]; StringRef getVendorName() const { return StringRef(names, vendor_name_size - 1); } StringRef getArchitectureName() const { return StringRef(names + vendor_name_size, architecture_name_size - 1); } }; struct ELFNote { support::ulittle32_t namesz; support::ulittle32_t descsz; support::ulittle32_t type; enum {ALIGN = 4}; ELFNote() = delete; ELFNote(const ELFNote&) = delete; ELFNote& operator =(const ELFNote&) = delete; StringRef getName() const { return StringRef(reinterpret_cast(this) + sizeof(*this), namesz); } StringRef getDesc() const { return StringRef(getName().data() + alignTo(namesz, ALIGN), descsz); } size_t getSize() const { return sizeof(*this) + alignTo(namesz, ALIGN) + alignTo(descsz, ALIGN); } template Expected as() const { if (descsz < sizeof(D)) { return make_error("invalid descsz", object::object_error::parse_failed); } return reinterpret_cast(getDesc().data()); } }; const ELFNote* getNext(const ELFNote &N); template class const_varsize_item_iterator { using iterator_catagory = std::forward_iterator_tag; using value_type = const Item; using difference_type = std::ptrdiff_t; using pointer = const Item *; using reference = const Item &; ArrayRef Ref; const Item *item() const { return reinterpret_cast(Ref.data()); } size_t getItemPadSize() const { assert(Ref.size() >= sizeof(Item)); return (const uint8_t*)getNext(*item()) - (const uint8_t*)item(); } public: const_varsize_item_iterator() {} const_varsize_item_iterator(ArrayRef Ref_) : Ref(Ref_) {} bool valid() const { return Ref.size() >= sizeof(Item) && Ref.size() >= getItemPadSize(); } Expected operator*() const { if (!valid()) { return make_error("invalid item", object::object_error::parse_failed); } return *item(); } bool operator==(const const_varsize_item_iterator &Other) const { return (Ref.size() == Other.Ref.size()) && (Ref.empty() || Ref.data() == Other.Ref.data()); } bool operator!=(const const_varsize_item_iterator &Other) const { return !(*this == Other); } const_varsize_item_iterator &operator++() { // preincrement Ref = Ref.size() >= sizeof(Item) ? Ref.slice((std::min)(getItemPadSize(), Ref.size())) : decltype(Ref)(); return *this; } }; //===----------------------------------------------------------------------===// // FunctionSym //===----------------------------------------------------------------------===// class HSACodeObject; class FunctionSym : public object::ELF64LEObjectFile::Elf_Sym { public: Expected getAddress(const HSACodeObject *CodeObject) const; Expected getAddress( const HSACodeObject *CodeObject, const object::ELF64LEObjectFile::Elf_Shdr *Text) const; Expected getSectionOffset(const HSACodeObject *CodeObject) const; Expected getSectionOffset( const HSACodeObject *CodeObject, const object::ELF64LEObjectFile::Elf_Shdr *Text) const; Expected getCodeOffset( const HSACodeObject *CodeObject, const object::ELF64LEObjectFile::Elf_Shdr *Text) const; static Expected asFunctionSym(Expected Sym); }; class KernelSym : public FunctionSym { public: Expected getCodeOffset(const HSACodeObject *CodeObject, const object::ELF64LEObjectFile::Elf_Shdr *Text) const; Expected getAmdKernelCodeT(const HSACodeObject *CodeObject) const; Expected getAmdKernelCodeT(const HSACodeObject *CodeObject, const object::ELF64LEObjectFile::Elf_Shdr *Text) const; static Expected asKernelSym(const FunctionSym *Sym); }; template class conditional_iterator : public iterator_adaptor_base< conditional_iterator, BaseIterator, std::forward_iterator_tag> { public: typedef std::function< bool(const typename conditional_iterator::iterator_adaptor_base::value_type&) > PredicateTy; protected: BaseIterator End; PredicateTy Predicate; public: conditional_iterator(BaseIterator BI, BaseIterator E, PredicateTy P) : conditional_iterator::iterator_adaptor_base(BI), End(E), Predicate(P) { while (this->I != End && !Predicate(*this->I)) { ++this->I; } } conditional_iterator &operator++() { do { ++this->I; } while (this->I != End && !Predicate(*this->I)); return *this; } }; class function_sym_iterator : public conditional_iterator { public: function_sym_iterator(object::elf_symbol_iterator It, object::elf_symbol_iterator End, PredicateTy P) : conditional_iterator(It, End, P) {} const object::ELFSymbolRef &operator*() const { return *I; } }; //===----------------------------------------------------------------------===// // HSACodeObject //===----------------------------------------------------------------------===// class HSACodeObject : public object::ELF64LEObjectFile { private: mutable SmallVector FunctionMarkers; void InitMarkers() const; HSACodeObject(object::ELF64LEObjectFile &&Obj) : object::ELF64LEObjectFile(std::move(Obj)) { InitMarkers(); } public: static Expected> create(MemoryBufferRef Wrapper) { auto Obj = object::ELF64LEObjectFile::create(Wrapper); if (auto E = Obj.takeError()) return std::move(E); std::unique_ptr Ret(new HSACodeObject(std::move(*Obj))); return std::move(Ret); } typedef const_varsize_item_iterator note_iterator; note_iterator notes_begin() const; note_iterator notes_end() const; iterator_range notes() const; function_sym_iterator functions_begin() const; function_sym_iterator functions_end() const; iterator_range functions() const; Expected> getCode(const FunctionSym *Function) const; Expected getSectionByName(StringRef Name) const; Expected getSectionIdxByName(StringRef) const; Expected getTextSectionIdx() const; Expected getNoteSectionIdx() const; Expected getTextSection() const; Expected getNoteSection() const; friend class FunctionSym; friend class KernelSym; }; } // namespace llvm #endif