1*9712c20fSFrederick Mayle // Copyright 2012 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
30*9712c20fSFrederick Mayle #include <config.h> // Must come first
31*9712c20fSFrederick Mayle #endif
32*9712c20fSFrederick Mayle
33*9712c20fSFrederick Mayle #include "common/linux/elfutils.h"
34*9712c20fSFrederick Mayle
35*9712c20fSFrederick Mayle #include <assert.h>
36*9712c20fSFrederick Mayle #include <string.h>
37*9712c20fSFrederick Mayle
38*9712c20fSFrederick Mayle #include "common/linux/linux_libc_support.h"
39*9712c20fSFrederick Mayle #include "common/linux/elfutils-inl.h"
40*9712c20fSFrederick Mayle
41*9712c20fSFrederick Mayle namespace google_breakpad {
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle namespace {
44*9712c20fSFrederick Mayle
45*9712c20fSFrederick Mayle template<typename ElfClass>
FindElfClassSection(const char * elf_base,const char * section_name,typename ElfClass::Word section_type,const void ** section_start,size_t * section_size)46*9712c20fSFrederick Mayle void FindElfClassSection(const char* elf_base,
47*9712c20fSFrederick Mayle const char* section_name,
48*9712c20fSFrederick Mayle typename ElfClass::Word section_type,
49*9712c20fSFrederick Mayle const void** section_start,
50*9712c20fSFrederick Mayle size_t* section_size) {
51*9712c20fSFrederick Mayle typedef typename ElfClass::Ehdr Ehdr;
52*9712c20fSFrederick Mayle typedef typename ElfClass::Shdr Shdr;
53*9712c20fSFrederick Mayle
54*9712c20fSFrederick Mayle assert(elf_base);
55*9712c20fSFrederick Mayle assert(section_start);
56*9712c20fSFrederick Mayle assert(section_size);
57*9712c20fSFrederick Mayle
58*9712c20fSFrederick Mayle assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
59*9712c20fSFrederick Mayle
60*9712c20fSFrederick Mayle const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
61*9712c20fSFrederick Mayle assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
62*9712c20fSFrederick Mayle
63*9712c20fSFrederick Mayle if (elf_header->e_shoff == 0) {
64*9712c20fSFrederick Mayle *section_start = NULL;
65*9712c20fSFrederick Mayle *section_size = 0;
66*9712c20fSFrederick Mayle return;
67*9712c20fSFrederick Mayle }
68*9712c20fSFrederick Mayle
69*9712c20fSFrederick Mayle const Shdr* sections =
70*9712c20fSFrederick Mayle GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
71*9712c20fSFrederick Mayle const Shdr* section_names = sections + elf_header->e_shstrndx;
72*9712c20fSFrederick Mayle const char* names =
73*9712c20fSFrederick Mayle GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
74*9712c20fSFrederick Mayle const char* names_end = names + section_names->sh_size;
75*9712c20fSFrederick Mayle
76*9712c20fSFrederick Mayle const Shdr* section =
77*9712c20fSFrederick Mayle FindElfSectionByName<ElfClass>(section_name, section_type,
78*9712c20fSFrederick Mayle sections, names, names_end,
79*9712c20fSFrederick Mayle elf_header->e_shnum);
80*9712c20fSFrederick Mayle
81*9712c20fSFrederick Mayle if (section != NULL && section->sh_size > 0) {
82*9712c20fSFrederick Mayle *section_start = elf_base + section->sh_offset;
83*9712c20fSFrederick Mayle *section_size = section->sh_size;
84*9712c20fSFrederick Mayle }
85*9712c20fSFrederick Mayle }
86*9712c20fSFrederick Mayle
87*9712c20fSFrederick Mayle template<typename ElfClass>
FindElfClassSegment(const char * elf_base,typename ElfClass::Word segment_type,wasteful_vector<ElfSegment> * segments)88*9712c20fSFrederick Mayle void FindElfClassSegment(const char* elf_base,
89*9712c20fSFrederick Mayle typename ElfClass::Word segment_type,
90*9712c20fSFrederick Mayle wasteful_vector<ElfSegment>* segments) {
91*9712c20fSFrederick Mayle typedef typename ElfClass::Ehdr Ehdr;
92*9712c20fSFrederick Mayle typedef typename ElfClass::Phdr Phdr;
93*9712c20fSFrederick Mayle
94*9712c20fSFrederick Mayle assert(elf_base);
95*9712c20fSFrederick Mayle assert(segments);
96*9712c20fSFrederick Mayle
97*9712c20fSFrederick Mayle assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
98*9712c20fSFrederick Mayle
99*9712c20fSFrederick Mayle const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
100*9712c20fSFrederick Mayle assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
101*9712c20fSFrederick Mayle
102*9712c20fSFrederick Mayle const Phdr* phdrs =
103*9712c20fSFrederick Mayle GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
104*9712c20fSFrederick Mayle
105*9712c20fSFrederick Mayle for (int i = 0; i < elf_header->e_phnum; ++i) {
106*9712c20fSFrederick Mayle if (phdrs[i].p_type == segment_type) {
107*9712c20fSFrederick Mayle ElfSegment seg = {};
108*9712c20fSFrederick Mayle seg.start = elf_base + phdrs[i].p_offset;
109*9712c20fSFrederick Mayle seg.size = phdrs[i].p_filesz;
110*9712c20fSFrederick Mayle segments->push_back(seg);
111*9712c20fSFrederick Mayle }
112*9712c20fSFrederick Mayle }
113*9712c20fSFrederick Mayle }
114*9712c20fSFrederick Mayle
115*9712c20fSFrederick Mayle } // namespace
116*9712c20fSFrederick Mayle
IsValidElf(const void * elf_base)117*9712c20fSFrederick Mayle bool IsValidElf(const void* elf_base) {
118*9712c20fSFrederick Mayle return my_strncmp(reinterpret_cast<const char*>(elf_base),
119*9712c20fSFrederick Mayle ELFMAG, SELFMAG) == 0;
120*9712c20fSFrederick Mayle }
121*9712c20fSFrederick Mayle
ElfClass(const void * elf_base)122*9712c20fSFrederick Mayle int ElfClass(const void* elf_base) {
123*9712c20fSFrederick Mayle const ElfW(Ehdr)* elf_header =
124*9712c20fSFrederick Mayle reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
125*9712c20fSFrederick Mayle
126*9712c20fSFrederick Mayle return elf_header->e_ident[EI_CLASS];
127*9712c20fSFrederick Mayle }
128*9712c20fSFrederick Mayle
FindElfSection(const void * elf_mapped_base,const char * section_name,uint32_t section_type,const void ** section_start,size_t * section_size)129*9712c20fSFrederick Mayle bool FindElfSection(const void* elf_mapped_base,
130*9712c20fSFrederick Mayle const char* section_name,
131*9712c20fSFrederick Mayle uint32_t section_type,
132*9712c20fSFrederick Mayle const void** section_start,
133*9712c20fSFrederick Mayle size_t* section_size) {
134*9712c20fSFrederick Mayle assert(elf_mapped_base);
135*9712c20fSFrederick Mayle assert(section_start);
136*9712c20fSFrederick Mayle assert(section_size);
137*9712c20fSFrederick Mayle
138*9712c20fSFrederick Mayle *section_start = NULL;
139*9712c20fSFrederick Mayle *section_size = 0;
140*9712c20fSFrederick Mayle
141*9712c20fSFrederick Mayle if (!IsValidElf(elf_mapped_base))
142*9712c20fSFrederick Mayle return false;
143*9712c20fSFrederick Mayle
144*9712c20fSFrederick Mayle int cls = ElfClass(elf_mapped_base);
145*9712c20fSFrederick Mayle const char* elf_base =
146*9712c20fSFrederick Mayle static_cast<const char*>(elf_mapped_base);
147*9712c20fSFrederick Mayle
148*9712c20fSFrederick Mayle if (cls == ELFCLASS32) {
149*9712c20fSFrederick Mayle FindElfClassSection<ElfClass32>(elf_base, section_name, section_type,
150*9712c20fSFrederick Mayle section_start, section_size);
151*9712c20fSFrederick Mayle return *section_start != NULL;
152*9712c20fSFrederick Mayle } else if (cls == ELFCLASS64) {
153*9712c20fSFrederick Mayle FindElfClassSection<ElfClass64>(elf_base, section_name, section_type,
154*9712c20fSFrederick Mayle section_start, section_size);
155*9712c20fSFrederick Mayle return *section_start != NULL;
156*9712c20fSFrederick Mayle }
157*9712c20fSFrederick Mayle
158*9712c20fSFrederick Mayle return false;
159*9712c20fSFrederick Mayle }
160*9712c20fSFrederick Mayle
FindElfSegments(const void * elf_mapped_base,uint32_t segment_type,wasteful_vector<ElfSegment> * segments)161*9712c20fSFrederick Mayle bool FindElfSegments(const void* elf_mapped_base,
162*9712c20fSFrederick Mayle uint32_t segment_type,
163*9712c20fSFrederick Mayle wasteful_vector<ElfSegment>* segments) {
164*9712c20fSFrederick Mayle assert(elf_mapped_base);
165*9712c20fSFrederick Mayle assert(segments);
166*9712c20fSFrederick Mayle
167*9712c20fSFrederick Mayle if (!IsValidElf(elf_mapped_base))
168*9712c20fSFrederick Mayle return false;
169*9712c20fSFrederick Mayle
170*9712c20fSFrederick Mayle int cls = ElfClass(elf_mapped_base);
171*9712c20fSFrederick Mayle const char* elf_base =
172*9712c20fSFrederick Mayle static_cast<const char*>(elf_mapped_base);
173*9712c20fSFrederick Mayle
174*9712c20fSFrederick Mayle if (cls == ELFCLASS32) {
175*9712c20fSFrederick Mayle FindElfClassSegment<ElfClass32>(elf_base, segment_type, segments);
176*9712c20fSFrederick Mayle return true;
177*9712c20fSFrederick Mayle } else if (cls == ELFCLASS64) {
178*9712c20fSFrederick Mayle FindElfClassSegment<ElfClass64>(elf_base, segment_type, segments);
179*9712c20fSFrederick Mayle return true;
180*9712c20fSFrederick Mayle }
181*9712c20fSFrederick Mayle
182*9712c20fSFrederick Mayle return false;
183*9712c20fSFrederick Mayle }
184*9712c20fSFrederick Mayle
185*9712c20fSFrederick Mayle template <typename ElfClass>
FindElfSoNameFromDynamicSection(const void * section_start,size_t section_size,const void * dynstr_start,size_t dynstr_size,char * soname,size_t soname_size)186*9712c20fSFrederick Mayle bool FindElfSoNameFromDynamicSection(const void* section_start,
187*9712c20fSFrederick Mayle size_t section_size,
188*9712c20fSFrederick Mayle const void* dynstr_start,
189*9712c20fSFrederick Mayle size_t dynstr_size,
190*9712c20fSFrederick Mayle char* soname,
191*9712c20fSFrederick Mayle size_t soname_size) {
192*9712c20fSFrederick Mayle typedef typename ElfClass::Dyn Dyn;
193*9712c20fSFrederick Mayle
194*9712c20fSFrederick Mayle auto* dynamic = static_cast<const Dyn*>(section_start);
195*9712c20fSFrederick Mayle size_t dcount = section_size / sizeof(Dyn);
196*9712c20fSFrederick Mayle for (const Dyn* dyn = dynamic; dyn < dynamic + dcount; ++dyn) {
197*9712c20fSFrederick Mayle if (dyn->d_tag == DT_SONAME) {
198*9712c20fSFrederick Mayle const char* dynstr = static_cast<const char*>(dynstr_start);
199*9712c20fSFrederick Mayle if (dyn->d_un.d_val >= dynstr_size) {
200*9712c20fSFrederick Mayle // Beyond the end of the dynstr section
201*9712c20fSFrederick Mayle return false;
202*9712c20fSFrederick Mayle }
203*9712c20fSFrederick Mayle const char* str = dynstr + dyn->d_un.d_val;
204*9712c20fSFrederick Mayle const size_t maxsize = dynstr_size - dyn->d_un.d_val;
205*9712c20fSFrederick Mayle my_strlcpy(soname, str, maxsize < soname_size ? maxsize : soname_size);
206*9712c20fSFrederick Mayle return true;
207*9712c20fSFrederick Mayle }
208*9712c20fSFrederick Mayle }
209*9712c20fSFrederick Mayle
210*9712c20fSFrederick Mayle return false;
211*9712c20fSFrederick Mayle }
212*9712c20fSFrederick Mayle
ElfFileSoNameFromMappedFile(const void * elf_base,char * soname,size_t soname_size)213*9712c20fSFrederick Mayle bool ElfFileSoNameFromMappedFile(const void* elf_base,
214*9712c20fSFrederick Mayle char* soname,
215*9712c20fSFrederick Mayle size_t soname_size) {
216*9712c20fSFrederick Mayle if (!IsValidElf(elf_base)) {
217*9712c20fSFrederick Mayle // Not ELF
218*9712c20fSFrederick Mayle return false;
219*9712c20fSFrederick Mayle }
220*9712c20fSFrederick Mayle
221*9712c20fSFrederick Mayle const void* segment_start;
222*9712c20fSFrederick Mayle size_t segment_size;
223*9712c20fSFrederick Mayle if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC, &segment_start,
224*9712c20fSFrederick Mayle &segment_size)) {
225*9712c20fSFrederick Mayle // No dynamic section
226*9712c20fSFrederick Mayle return false;
227*9712c20fSFrederick Mayle }
228*9712c20fSFrederick Mayle
229*9712c20fSFrederick Mayle const void* dynstr_start;
230*9712c20fSFrederick Mayle size_t dynstr_size;
231*9712c20fSFrederick Mayle if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB, &dynstr_start,
232*9712c20fSFrederick Mayle &dynstr_size)) {
233*9712c20fSFrederick Mayle // No dynstr section
234*9712c20fSFrederick Mayle return false;
235*9712c20fSFrederick Mayle }
236*9712c20fSFrederick Mayle
237*9712c20fSFrederick Mayle int cls = ElfClass(elf_base);
238*9712c20fSFrederick Mayle return cls == ELFCLASS32 ? FindElfSoNameFromDynamicSection<ElfClass32>(
239*9712c20fSFrederick Mayle segment_start, segment_size, dynstr_start,
240*9712c20fSFrederick Mayle dynstr_size, soname, soname_size)
241*9712c20fSFrederick Mayle : FindElfSoNameFromDynamicSection<ElfClass64>(
242*9712c20fSFrederick Mayle segment_start, segment_size, dynstr_start,
243*9712c20fSFrederick Mayle dynstr_size, soname, soname_size);
244*9712c20fSFrederick Mayle }
245*9712c20fSFrederick Mayle
246*9712c20fSFrederick Mayle } // namespace google_breakpad
247