1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_ 6 #define BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_ 7 8 #include <elf.h> 9 10 #include <cstdint> 11 #include <optional> 12 #include <string> 13 #include <string_view> 14 #include <vector> 15 16 #include "base/containers/span.h" 17 #include "base/memory/raw_ptr.h" 18 19 #if __SIZEOF_POINTER__ == 4 20 using Addr = Elf32_Addr; 21 using Ehdr = Elf32_Ehdr; 22 using Half = Elf32_Half; 23 using Off = Elf32_Off; 24 using Phdr = Elf32_Phdr; 25 using Word = Elf32_Word; 26 #else 27 using Addr = Elf64_Addr; 28 using Ehdr = Elf64_Ehdr; 29 using Half = Elf64_Half; 30 using Off = Elf64_Off; 31 using Phdr = Elf64_Phdr; 32 using Word = Elf64_Word; 33 #endif 34 35 namespace base { 36 37 // In-memory ELF image constructed by TestElfImageBuilder. 38 class TestElfImage { 39 public: 40 // |buffer| is a memory buffer containing the ELF image. |elf_start| is the 41 // start address of the ELF image within the buffer. 42 TestElfImage(std::vector<uint8_t> buffer, const void* elf_start); 43 ~TestElfImage(); 44 45 TestElfImage(TestElfImage&&); 46 TestElfImage& operator=(TestElfImage&&); 47 48 // The start address of the ELF image. elf_start()49 const void* elf_start() const { return elf_start_; } 50 51 private: 52 std::vector<uint8_t> buffer_; 53 raw_ptr<const void> elf_start_; 54 }; 55 56 // Builds an in-memory image of an ELF file for testing. 57 class TestElfImageBuilder { 58 public: 59 // The type of mapping to use for virtual addresses in the ELF file. 60 enum MappingType { 61 RELOCATABLE, // Virtual address == file offset. 62 RELOCATABLE_WITH_BIAS, // Virtual address == file offset + load bias. 63 NON_RELOCATABLE, // Virtual address == mapped address. 64 }; 65 66 // The load bias to use for RELOCATABLE_WITH_BIAS. 0xc000 is a commonly used 67 // load bias for Android system ELF images. 68 static constexpr size_t kLoadBias = 0xc000; 69 70 explicit TestElfImageBuilder(MappingType mapping_type); 71 ~TestElfImageBuilder(); 72 73 TestElfImageBuilder(const TestElfImageBuilder&) = delete; 74 TestElfImageBuilder& operator=(const TestElfImageBuilder&) = delete; 75 76 // Add a PT_LOAD segment with the specified rwx |flags|. The contents will be 77 // filled with |size| bytes of zeros. 78 TestElfImageBuilder& AddLoadSegment(Word flags, size_t size); 79 80 // Add a PT_NOTE segment with the specified state. 81 TestElfImageBuilder& AddNoteSegment(Word type, 82 std::string_view name, 83 span<const uint8_t> desc); 84 85 // Adds a DT_SONAME dynamic section and the necessary state to support it. May 86 // be invoked at most once. 87 TestElfImageBuilder& AddSoName(std::string_view soname); 88 89 TestElfImage Build(); 90 91 private: 92 // Properties of a load segment to create. 93 struct LoadSegment; 94 95 // Computed sizing state for parts of the ELF image. 96 struct ImageMeasures; 97 98 // Gets the 'virtual address' corresponding to |offset| to write into the 99 // image, according to |mapping_type_|. Relocatable ELF images have virtual 100 // addresses equal to the offset with a possible constant load bias. 101 // Non-relocatable ELF images have virtual addresses equal to the actual 102 // memory address. 103 Addr GetVirtualAddressForOffset(Off offset, const uint8_t* elf_start) const; 104 105 // Measures sizes/start offset of segments in the image. 106 ImageMeasures MeasureSizesAndOffsets() const; 107 108 // Appends a header of type |T| at |loc|, a memory address within the ELF 109 // image being constructed, and returns the address past the header. 110 template <typename T> 111 static uint8_t* AppendHdr(const T& hdr, uint8_t* loc); 112 113 Ehdr CreateEhdr(Half phnum); 114 Phdr CreatePhdr(Word type, 115 Word flags, 116 size_t align, 117 Off offset, 118 Addr vaddr, 119 size_t size); 120 121 const MappingType mapping_type_; 122 std::vector<std::vector<uint8_t>> note_contents_; 123 std::vector<LoadSegment> load_segments_; 124 std::optional<std::string> soname_; 125 }; 126 127 } // namespace base 128 129 #endif // BASE_DEBUG_TEST_ELF_IMAGE_BUILDER_H_ 130