xref: /aosp_15_r20/external/google-breakpad/src/common/linux/elfutils.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2012 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 // elfutils.h: Utilities for dealing with ELF files.
30 //
31 
32 #ifndef COMMON_LINUX_ELFUTILS_H_
33 #define COMMON_LINUX_ELFUTILS_H_
34 
35 #include <elf.h>
36 #include <link.h>
37 #include <stdint.h>
38 
39 #include "common/memory_allocator.h"
40 
41 namespace google_breakpad {
42 
43 typedef struct Elf32_Chdr {
44   typedef Elf32_Word Type;
45   typedef Elf32_Word Size;
46   typedef Elf32_Addr Addr;
47 
48   static_assert(sizeof (Type) == 4);
49   static_assert(sizeof (Size) == 4);
50   static_assert(sizeof (Addr) == 4);
51 
52   Type ch_type;       // Compression type
53   Size ch_size;       // Uncompressed data size in bytes
54   Addr ch_addralign;  // Uncompressed data alignment
55 } Elf32_Chdr;
56 
57 static_assert(sizeof (Elf32_Chdr) == 12);
58 
59 typedef struct Elf64_Chdr {
60   typedef Elf64_Word  Type;
61   typedef Elf64_Xword Size;
62   typedef Elf64_Addr  Addr;
63 
64   static_assert(sizeof (Type) == 4);
65   static_assert(sizeof (Size) == 8);
66   static_assert(sizeof (Addr) == 8);
67 
68   Type ch_type;       // Compression type
69   Type ch_reserved;   // Padding
70   Size ch_size;       // Uncompressed data size in bytes
71   Addr ch_addralign;  // Uncompressed data alignment
72 } Elf64_Chdr;
73 
74 static_assert(sizeof (Elf64_Chdr) == 24);
75 
76 // Traits classes so consumers can write templatized code to deal
77 // with specific ELF bits.
78 struct ElfClass32 {
79   typedef Elf32_Addr Addr;
80   typedef Elf32_Dyn Dyn;
81   typedef Elf32_Ehdr Ehdr;
82   typedef Elf32_Nhdr Nhdr;
83   typedef Elf32_Phdr Phdr;
84   typedef Elf32_Shdr Shdr;
85   typedef Elf32_Chdr Chdr;
86   typedef Elf32_Half Half;
87   typedef Elf32_Off Off;
88   typedef Elf32_Sym Sym;
89   typedef Elf32_Word Word;
90 
91   static const int kClass = ELFCLASS32;
92   static const uint16_t kMachine = EM_386;
93   static const size_t kAddrSize = sizeof(Elf32_Addr);
94   static constexpr const char* kMachineName = "x86";
95 };
96 
97 struct ElfClass64 {
98   typedef Elf64_Addr Addr;
99   typedef Elf64_Dyn Dyn;
100   typedef Elf64_Ehdr Ehdr;
101   typedef Elf64_Nhdr Nhdr;
102   typedef Elf64_Phdr Phdr;
103   typedef Elf64_Shdr Shdr;
104   typedef Elf64_Chdr Chdr;
105   typedef Elf64_Half Half;
106   typedef Elf64_Off Off;
107   typedef Elf64_Sym Sym;
108   typedef Elf64_Word Word;
109 
110   static const int kClass = ELFCLASS64;
111   static const uint16_t kMachine = EM_X86_64;
112   static const size_t kAddrSize = sizeof(Elf64_Addr);
113   static constexpr const char* kMachineName = "x86_64";
114 };
115 
116 bool IsValidElf(const void* elf_header);
117 int ElfClass(const void* elf_base);
118 
119 // Attempt to find a section named |section_name| of type |section_type|
120 // in the ELF binary data at |elf_mapped_base|. On success, returns true
121 // and sets |*section_start| to point to the start of the section data,
122 // and |*section_size| to the size of the section's data.
123 bool FindElfSection(const void* elf_mapped_base,
124                     const char* section_name,
125                     uint32_t section_type,
126                     const void** section_start,
127                     size_t* section_size);
128 
129 // Internal helper method, exposed for convenience for callers
130 // that already have more info.
131 template<typename ElfClass>
132 const typename ElfClass::Shdr*
133 FindElfSectionByName(const char* name,
134                      typename ElfClass::Word section_type,
135                      const typename ElfClass::Shdr* sections,
136                      const char* section_names,
137                      const char* names_end,
138                      int nsection);
139 
140 struct ElfSegment {
141   const void* start;
142   size_t size;
143 };
144 
145 // Attempt to find all segments of type |segment_type| in the ELF
146 // binary data at |elf_mapped_base|. On success, returns true and fills
147 // |*segments| with a list of segments of the given type.
148 bool FindElfSegments(const void* elf_mapped_base,
149                      uint32_t segment_type,
150                      wasteful_vector<ElfSegment>* segments);
151 
152 // Convert an offset from an Elf header into a pointer to the mapped
153 // address in the current process. Takes an extra template parameter
154 // to specify the return type to avoid having to dynamic_cast the
155 // result.
156 template<typename ElfClass, typename T>
157 const T*
158 GetOffset(const typename ElfClass::Ehdr* elf_header,
159           typename ElfClass::Off offset);
160 
161 // Read the value of DT_SONAME from the elf file mapped at |elf_base|. Returns
162 // true and fills |soname| with the result if found.
163 bool ElfFileSoNameFromMappedFile(const void* elf_base,
164                                  char* soname,
165                                  size_t soname_size);
166 
167 }  // namespace google_breakpad
168 
169 #endif  // COMMON_LINUX_ELFUTILS_H_
170