xref: /aosp_15_r20/external/cronet/base/debug/test_elf_image_builder.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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