xref: /aosp_15_r20/art/runtime/oat/elf_file.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "elf_file.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <inttypes.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>  // For the PROT_* and MAP_* constants.
21*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
22*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
25*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "elf/elf_utils.h"
33*795d594fSAndroid Build Coastguard Worker #include "elf_file_impl.h"
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
ElfFileImpl(File * file,bool writable,bool program_header_only)40*795d594fSAndroid Build Coastguard Worker ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable, bool program_header_only)
41*795d594fSAndroid Build Coastguard Worker   : writable_(writable),
42*795d594fSAndroid Build Coastguard Worker     program_header_only_(program_header_only),
43*795d594fSAndroid Build Coastguard Worker     header_(nullptr),
44*795d594fSAndroid Build Coastguard Worker     base_address_(nullptr),
45*795d594fSAndroid Build Coastguard Worker     program_headers_start_(nullptr),
46*795d594fSAndroid Build Coastguard Worker     section_headers_start_(nullptr),
47*795d594fSAndroid Build Coastguard Worker     dynamic_program_header_(nullptr),
48*795d594fSAndroid Build Coastguard Worker     dynamic_section_start_(nullptr),
49*795d594fSAndroid Build Coastguard Worker     symtab_section_start_(nullptr),
50*795d594fSAndroid Build Coastguard Worker     dynsym_section_start_(nullptr),
51*795d594fSAndroid Build Coastguard Worker     strtab_section_start_(nullptr),
52*795d594fSAndroid Build Coastguard Worker     dynstr_section_start_(nullptr),
53*795d594fSAndroid Build Coastguard Worker     hash_section_start_(nullptr),
54*795d594fSAndroid Build Coastguard Worker     symtab_symbol_table_(nullptr),
55*795d594fSAndroid Build Coastguard Worker     dynsym_symbol_table_(nullptr) {
56*795d594fSAndroid Build Coastguard Worker   CHECK(file != nullptr);
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
Open(File * file,bool writable,bool program_header_only,bool low_4gb,std::string * error_msg)60*795d594fSAndroid Build Coastguard Worker ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
61*795d594fSAndroid Build Coastguard Worker                                                    bool writable,
62*795d594fSAndroid Build Coastguard Worker                                                    bool program_header_only,
63*795d594fSAndroid Build Coastguard Worker                                                    bool low_4gb,
64*795d594fSAndroid Build Coastguard Worker                                                    std::string* error_msg) {
65*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(
66*795d594fSAndroid Build Coastguard Worker       new ElfFileImpl<ElfTypes>(file, writable, program_header_only));
67*795d594fSAndroid Build Coastguard Worker   int prot;
68*795d594fSAndroid Build Coastguard Worker   int flags;
69*795d594fSAndroid Build Coastguard Worker   if (writable) {
70*795d594fSAndroid Build Coastguard Worker     prot = PROT_READ | PROT_WRITE;
71*795d594fSAndroid Build Coastguard Worker     flags = MAP_SHARED;
72*795d594fSAndroid Build Coastguard Worker   } else {
73*795d594fSAndroid Build Coastguard Worker     prot = PROT_READ;
74*795d594fSAndroid Build Coastguard Worker     flags = MAP_PRIVATE;
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker   if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
77*795d594fSAndroid Build Coastguard Worker     return nullptr;
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker   return elf_file.release();
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
Open(File * file,int prot,int flags,bool low_4gb,std::string * error_msg)83*795d594fSAndroid Build Coastguard Worker ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file,
84*795d594fSAndroid Build Coastguard Worker                                                    int prot,
85*795d594fSAndroid Build Coastguard Worker                                                    int flags,
86*795d594fSAndroid Build Coastguard Worker                                                    bool low_4gb,
87*795d594fSAndroid Build Coastguard Worker                                                    std::string* error_msg) {
88*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(
89*795d594fSAndroid Build Coastguard Worker       new ElfFileImpl<ElfTypes>(file, (prot & PROT_WRITE) != 0, /* program_header_only= */ false));
90*795d594fSAndroid Build Coastguard Worker   if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) {
91*795d594fSAndroid Build Coastguard Worker     return nullptr;
92*795d594fSAndroid Build Coastguard Worker   }
93*795d594fSAndroid Build Coastguard Worker   return elf_file.release();
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
Setup(File * file,int prot,int flags,bool low_4gb,std::string * error_msg)97*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::Setup(File* file,
98*795d594fSAndroid Build Coastguard Worker                                   int prot,
99*795d594fSAndroid Build Coastguard Worker                                   int flags,
100*795d594fSAndroid Build Coastguard Worker                                   bool low_4gb,
101*795d594fSAndroid Build Coastguard Worker                                   std::string* error_msg) {
102*795d594fSAndroid Build Coastguard Worker   int64_t temp_file_length = file->GetLength();
103*795d594fSAndroid Build Coastguard Worker   if (temp_file_length < 0) {
104*795d594fSAndroid Build Coastguard Worker     errno = -temp_file_length;
105*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
106*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(), file->Fd(), strerror(errno));
107*795d594fSAndroid Build Coastguard Worker     return false;
108*795d594fSAndroid Build Coastguard Worker   }
109*795d594fSAndroid Build Coastguard Worker   size_t file_length = static_cast<size_t>(temp_file_length);
110*795d594fSAndroid Build Coastguard Worker   if (file_length < sizeof(Elf_Ehdr)) {
111*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF header of "
112*795d594fSAndroid Build Coastguard Worker                               "%zd bytes: '%s'", file_length, sizeof(Elf_Ehdr),
113*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
114*795d594fSAndroid Build Coastguard Worker     return false;
115*795d594fSAndroid Build Coastguard Worker   }
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker   if (program_header_only_) {
118*795d594fSAndroid Build Coastguard Worker     // first just map ELF header to get program header size information
119*795d594fSAndroid Build Coastguard Worker     size_t elf_header_size = sizeof(Elf_Ehdr);
120*795d594fSAndroid Build Coastguard Worker     if (!SetMap(file,
121*795d594fSAndroid Build Coastguard Worker                 MemMap::MapFile(elf_header_size,
122*795d594fSAndroid Build Coastguard Worker                                 prot,
123*795d594fSAndroid Build Coastguard Worker                                 flags,
124*795d594fSAndroid Build Coastguard Worker                                 file->Fd(),
125*795d594fSAndroid Build Coastguard Worker                                 0,
126*795d594fSAndroid Build Coastguard Worker                                 low_4gb,
127*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str(),
128*795d594fSAndroid Build Coastguard Worker                                 error_msg),
129*795d594fSAndroid Build Coastguard Worker                 error_msg)) {
130*795d594fSAndroid Build Coastguard Worker       return false;
131*795d594fSAndroid Build Coastguard Worker     }
132*795d594fSAndroid Build Coastguard Worker     // then remap to cover program header
133*795d594fSAndroid Build Coastguard Worker     size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum);
134*795d594fSAndroid Build Coastguard Worker     if (file_length < program_header_size) {
135*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program "
136*795d594fSAndroid Build Coastguard Worker                                 "header of %zd bytes: '%s'", file_length,
137*795d594fSAndroid Build Coastguard Worker                                 sizeof(Elf_Ehdr), file->GetPath().c_str());
138*795d594fSAndroid Build Coastguard Worker       return false;
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker     if (!SetMap(file,
141*795d594fSAndroid Build Coastguard Worker                 MemMap::MapFile(program_header_size,
142*795d594fSAndroid Build Coastguard Worker                                 prot,
143*795d594fSAndroid Build Coastguard Worker                                 flags,
144*795d594fSAndroid Build Coastguard Worker                                 file->Fd(),
145*795d594fSAndroid Build Coastguard Worker                                 0,
146*795d594fSAndroid Build Coastguard Worker                                 low_4gb,
147*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str(),
148*795d594fSAndroid Build Coastguard Worker                                 error_msg),
149*795d594fSAndroid Build Coastguard Worker                 error_msg)) {
150*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str());
151*795d594fSAndroid Build Coastguard Worker       return false;
152*795d594fSAndroid Build Coastguard Worker     }
153*795d594fSAndroid Build Coastguard Worker   } else {
154*795d594fSAndroid Build Coastguard Worker     // otherwise map entire file
155*795d594fSAndroid Build Coastguard Worker     if (!SetMap(file,
156*795d594fSAndroid Build Coastguard Worker                 MemMap::MapFile(file->GetLength(),
157*795d594fSAndroid Build Coastguard Worker                                 prot,
158*795d594fSAndroid Build Coastguard Worker                                 flags,
159*795d594fSAndroid Build Coastguard Worker                                 file->Fd(),
160*795d594fSAndroid Build Coastguard Worker                                 0,
161*795d594fSAndroid Build Coastguard Worker                                 low_4gb,
162*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str(),
163*795d594fSAndroid Build Coastguard Worker                                 error_msg),
164*795d594fSAndroid Build Coastguard Worker                 error_msg)) {
165*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str());
166*795d594fSAndroid Build Coastguard Worker       return false;
167*795d594fSAndroid Build Coastguard Worker     }
168*795d594fSAndroid Build Coastguard Worker   }
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   if (program_header_only_) {
171*795d594fSAndroid Build Coastguard Worker     program_headers_start_ = Begin() + GetHeader().e_phoff;
172*795d594fSAndroid Build Coastguard Worker   } else {
173*795d594fSAndroid Build Coastguard Worker     if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) {
174*795d594fSAndroid Build Coastguard Worker       return false;
175*795d594fSAndroid Build Coastguard Worker     }
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker     // Setup section headers.
178*795d594fSAndroid Build Coastguard Worker     if (!CheckAndSet(GetHeader().e_shoff, "section headers", &section_headers_start_, error_msg)) {
179*795d594fSAndroid Build Coastguard Worker       return false;
180*795d594fSAndroid Build Coastguard Worker     }
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker     // Find shstrtab.
183*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection();
184*795d594fSAndroid Build Coastguard Worker     if (shstrtab_section_header == nullptr) {
185*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'",
186*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
187*795d594fSAndroid Build Coastguard Worker       return false;
188*795d594fSAndroid Build Coastguard Worker     }
189*795d594fSAndroid Build Coastguard Worker 
190*795d594fSAndroid Build Coastguard Worker     // Find .dynamic section info from program header
191*795d594fSAndroid Build Coastguard Worker     dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC);
192*795d594fSAndroid Build Coastguard Worker     if (dynamic_program_header_ == nullptr) {
193*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
194*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
195*795d594fSAndroid Build Coastguard Worker       return false;
196*795d594fSAndroid Build Coastguard Worker     }
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker     if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section",
199*795d594fSAndroid Build Coastguard Worker                      reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) {
200*795d594fSAndroid Build Coastguard Worker       return false;
201*795d594fSAndroid Build Coastguard Worker     }
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker     // Find other sections from section headers
204*795d594fSAndroid Build Coastguard Worker     for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
205*795d594fSAndroid Build Coastguard Worker       Elf_Shdr* section_header = GetSectionHeader(i);
206*795d594fSAndroid Build Coastguard Worker       if (section_header == nullptr) {
207*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'",
208*795d594fSAndroid Build Coastguard Worker                                   i, file->GetPath().c_str());
209*795d594fSAndroid Build Coastguard Worker         return false;
210*795d594fSAndroid Build Coastguard Worker       }
211*795d594fSAndroid Build Coastguard Worker       switch (section_header->sh_type) {
212*795d594fSAndroid Build Coastguard Worker         case SHT_SYMTAB: {
213*795d594fSAndroid Build Coastguard Worker           if (!CheckAndSet(section_header->sh_offset, "symtab",
214*795d594fSAndroid Build Coastguard Worker                            reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) {
215*795d594fSAndroid Build Coastguard Worker             return false;
216*795d594fSAndroid Build Coastguard Worker           }
217*795d594fSAndroid Build Coastguard Worker           break;
218*795d594fSAndroid Build Coastguard Worker         }
219*795d594fSAndroid Build Coastguard Worker         case SHT_DYNSYM: {
220*795d594fSAndroid Build Coastguard Worker           if (!CheckAndSet(section_header->sh_offset, "dynsym",
221*795d594fSAndroid Build Coastguard Worker                            reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) {
222*795d594fSAndroid Build Coastguard Worker             return false;
223*795d594fSAndroid Build Coastguard Worker           }
224*795d594fSAndroid Build Coastguard Worker           break;
225*795d594fSAndroid Build Coastguard Worker         }
226*795d594fSAndroid Build Coastguard Worker         case SHT_STRTAB: {
227*795d594fSAndroid Build Coastguard Worker           // TODO: base these off of sh_link from .symtab and .dynsym above
228*795d594fSAndroid Build Coastguard Worker           if ((section_header->sh_flags & SHF_ALLOC) != 0) {
229*795d594fSAndroid Build Coastguard Worker             // Check that this is named ".dynstr" and ignore otherwise.
230*795d594fSAndroid Build Coastguard Worker             const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
231*795d594fSAndroid Build Coastguard Worker             if (strncmp(".dynstr", header_name, 8) == 0) {
232*795d594fSAndroid Build Coastguard Worker               if (!CheckAndSet(section_header->sh_offset, "dynstr",
233*795d594fSAndroid Build Coastguard Worker                                reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) {
234*795d594fSAndroid Build Coastguard Worker                 return false;
235*795d594fSAndroid Build Coastguard Worker               }
236*795d594fSAndroid Build Coastguard Worker             }
237*795d594fSAndroid Build Coastguard Worker           } else {
238*795d594fSAndroid Build Coastguard Worker             // Check that this is named ".strtab" and ignore otherwise.
239*795d594fSAndroid Build Coastguard Worker             const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name);
240*795d594fSAndroid Build Coastguard Worker             if (strncmp(".strtab", header_name, 8) == 0) {
241*795d594fSAndroid Build Coastguard Worker               if (!CheckAndSet(section_header->sh_offset, "strtab",
242*795d594fSAndroid Build Coastguard Worker                                reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) {
243*795d594fSAndroid Build Coastguard Worker                 return false;
244*795d594fSAndroid Build Coastguard Worker               }
245*795d594fSAndroid Build Coastguard Worker             }
246*795d594fSAndroid Build Coastguard Worker           }
247*795d594fSAndroid Build Coastguard Worker           break;
248*795d594fSAndroid Build Coastguard Worker         }
249*795d594fSAndroid Build Coastguard Worker         case SHT_DYNAMIC: {
250*795d594fSAndroid Build Coastguard Worker           if (reinterpret_cast<uint8_t*>(dynamic_section_start_) !=
251*795d594fSAndroid Build Coastguard Worker               Begin() + section_header->sh_offset) {
252*795d594fSAndroid Build Coastguard Worker             LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in "
253*795d594fSAndroid Build Coastguard Worker                          << file->GetPath() << ": " << std::hex
254*795d594fSAndroid Build Coastguard Worker                          << reinterpret_cast<void*>(dynamic_section_start_)
255*795d594fSAndroid Build Coastguard Worker                          << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset);
256*795d594fSAndroid Build Coastguard Worker             return false;
257*795d594fSAndroid Build Coastguard Worker           }
258*795d594fSAndroid Build Coastguard Worker           break;
259*795d594fSAndroid Build Coastguard Worker         }
260*795d594fSAndroid Build Coastguard Worker         case SHT_HASH: {
261*795d594fSAndroid Build Coastguard Worker           if (!CheckAndSet(section_header->sh_offset, "hash section",
262*795d594fSAndroid Build Coastguard Worker                            reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) {
263*795d594fSAndroid Build Coastguard Worker             return false;
264*795d594fSAndroid Build Coastguard Worker           }
265*795d594fSAndroid Build Coastguard Worker           break;
266*795d594fSAndroid Build Coastguard Worker         }
267*795d594fSAndroid Build Coastguard Worker       }
268*795d594fSAndroid Build Coastguard Worker     }
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker     // Check for the existence of some sections.
271*795d594fSAndroid Build Coastguard Worker     if (!CheckSectionsExist(file, error_msg)) {
272*795d594fSAndroid Build Coastguard Worker       return false;
273*795d594fSAndroid Build Coastguard Worker     }
274*795d594fSAndroid Build Coastguard Worker   }
275*795d594fSAndroid Build Coastguard Worker 
276*795d594fSAndroid Build Coastguard Worker   return true;
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
~ElfFileImpl()280*795d594fSAndroid Build Coastguard Worker ElfFileImpl<ElfTypes>::~ElfFileImpl() {
281*795d594fSAndroid Build Coastguard Worker   delete symtab_symbol_table_;
282*795d594fSAndroid Build Coastguard Worker   delete dynsym_symbol_table_;
283*795d594fSAndroid Build Coastguard Worker }
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
CheckAndSet(Elf32_Off offset,const char * label,uint8_t ** target,std::string * error_msg)286*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label,
287*795d594fSAndroid Build Coastguard Worker                                         uint8_t** target, std::string* error_msg) {
288*795d594fSAndroid Build Coastguard Worker   if (Begin() + offset >= End()) {
289*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label,
290*795d594fSAndroid Build Coastguard Worker                               file_path_.c_str());
291*795d594fSAndroid Build Coastguard Worker     return false;
292*795d594fSAndroid Build Coastguard Worker   }
293*795d594fSAndroid Build Coastguard Worker   *target = Begin() + offset;
294*795d594fSAndroid Build Coastguard Worker   return true;
295*795d594fSAndroid Build Coastguard Worker }
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
CheckSectionsLinked(const uint8_t * source,const uint8_t * target) const298*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source,
299*795d594fSAndroid Build Coastguard Worker                                                 const uint8_t* target) const {
300*795d594fSAndroid Build Coastguard Worker   // Only works in whole-program mode, as we need to iterate over the sections.
301*795d594fSAndroid Build Coastguard Worker   // Note that we normally can't search by type, as duplicates are allowed for most section types.
302*795d594fSAndroid Build Coastguard Worker   if (program_header_only_) {
303*795d594fSAndroid Build Coastguard Worker     return true;
304*795d594fSAndroid Build Coastguard Worker   }
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker   Elf_Shdr* source_section = nullptr;
307*795d594fSAndroid Build Coastguard Worker   Elf_Word target_index = 0;
308*795d594fSAndroid Build Coastguard Worker   bool target_found = false;
309*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
310*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* section_header = GetSectionHeader(i);
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker     if (Begin() + section_header->sh_offset == source) {
313*795d594fSAndroid Build Coastguard Worker       // Found the source.
314*795d594fSAndroid Build Coastguard Worker       source_section = section_header;
315*795d594fSAndroid Build Coastguard Worker       if (target_index) {
316*795d594fSAndroid Build Coastguard Worker         break;
317*795d594fSAndroid Build Coastguard Worker       }
318*795d594fSAndroid Build Coastguard Worker     } else if (Begin() + section_header->sh_offset == target) {
319*795d594fSAndroid Build Coastguard Worker       target_index = i;
320*795d594fSAndroid Build Coastguard Worker       target_found = true;
321*795d594fSAndroid Build Coastguard Worker       if (source_section != nullptr) {
322*795d594fSAndroid Build Coastguard Worker         break;
323*795d594fSAndroid Build Coastguard Worker       }
324*795d594fSAndroid Build Coastguard Worker     }
325*795d594fSAndroid Build Coastguard Worker   }
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   return target_found && source_section != nullptr && source_section->sh_link == target_index;
328*795d594fSAndroid Build Coastguard Worker }
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
CheckSectionsExist(File * file,std::string * error_msg) const331*795d594fSAndroid Build Coastguard Worker   bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const {
332*795d594fSAndroid Build Coastguard Worker   if (!program_header_only_) {
333*795d594fSAndroid Build Coastguard Worker     // If in full mode, need section headers.
334*795d594fSAndroid Build Coastguard Worker     if (section_headers_start_ == nullptr) {
335*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str());
336*795d594fSAndroid Build Coastguard Worker       return false;
337*795d594fSAndroid Build Coastguard Worker     }
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker   // This is redundant, but defensive.
341*795d594fSAndroid Build Coastguard Worker   if (dynamic_program_header_ == nullptr) {
342*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'",
343*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
344*795d594fSAndroid Build Coastguard Worker     return false;
345*795d594fSAndroid Build Coastguard Worker   }
346*795d594fSAndroid Build Coastguard Worker 
347*795d594fSAndroid Build Coastguard Worker   // Need a dynamic section. This is redundant, but defensive.
348*795d594fSAndroid Build Coastguard Worker   if (dynamic_section_start_ == nullptr) {
349*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find dynamic section in ELF file: '%s'",
350*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
351*795d594fSAndroid Build Coastguard Worker     return false;
352*795d594fSAndroid Build Coastguard Worker   }
353*795d594fSAndroid Build Coastguard Worker 
354*795d594fSAndroid Build Coastguard Worker   // Symtab validation. These is not really a hard failure, as we are currently not using the
355*795d594fSAndroid Build Coastguard Worker   // symtab internally, but it's nice to be defensive.
356*795d594fSAndroid Build Coastguard Worker   if (symtab_section_start_ != nullptr) {
357*795d594fSAndroid Build Coastguard Worker     // When there's a symtab, there should be a strtab.
358*795d594fSAndroid Build Coastguard Worker     if (strtab_section_start_ == nullptr) {
359*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str());
360*795d594fSAndroid Build Coastguard Worker       return false;
361*795d594fSAndroid Build Coastguard Worker     }
362*795d594fSAndroid Build Coastguard Worker 
363*795d594fSAndroid Build Coastguard Worker     // The symtab should link to the strtab.
364*795d594fSAndroid Build Coastguard Worker     if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_),
365*795d594fSAndroid Build Coastguard Worker                              reinterpret_cast<const uint8_t*>(strtab_section_start_))) {
366*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'",
367*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
368*795d594fSAndroid Build Coastguard Worker       return false;
369*795d594fSAndroid Build Coastguard Worker     }
370*795d594fSAndroid Build Coastguard Worker   }
371*795d594fSAndroid Build Coastguard Worker 
372*795d594fSAndroid Build Coastguard Worker   // We always need a dynstr & dynsym.
373*795d594fSAndroid Build Coastguard Worker   if (dynstr_section_start_ == nullptr) {
374*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("No dynstr in ELF file: '%s'", file->GetPath().c_str());
375*795d594fSAndroid Build Coastguard Worker     return false;
376*795d594fSAndroid Build Coastguard Worker   }
377*795d594fSAndroid Build Coastguard Worker   if (dynsym_section_start_ == nullptr) {
378*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("No dynsym in ELF file: '%s'", file->GetPath().c_str());
379*795d594fSAndroid Build Coastguard Worker     return false;
380*795d594fSAndroid Build Coastguard Worker   }
381*795d594fSAndroid Build Coastguard Worker 
382*795d594fSAndroid Build Coastguard Worker   // Need a hash section for dynamic symbol lookup.
383*795d594fSAndroid Build Coastguard Worker   if (hash_section_start_ == nullptr) {
384*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find hash section in ELF file: '%s'",
385*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
386*795d594fSAndroid Build Coastguard Worker     return false;
387*795d594fSAndroid Build Coastguard Worker   }
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker   // And the hash section should be linking to the dynsym.
390*795d594fSAndroid Build Coastguard Worker   if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_),
391*795d594fSAndroid Build Coastguard Worker                            reinterpret_cast<const uint8_t*>(dynsym_section_start_))) {
392*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'",
393*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
394*795d594fSAndroid Build Coastguard Worker     return false;
395*795d594fSAndroid Build Coastguard Worker   }
396*795d594fSAndroid Build Coastguard Worker 
397*795d594fSAndroid Build Coastguard Worker   // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for
398*795d594fSAndroid Build Coastguard Worker   // us). This is usually the last in an oat file, and a good indicator of whether writing was
399*795d594fSAndroid Build Coastguard Worker   // successful (or the process crashed and left garbage).
400*795d594fSAndroid Build Coastguard Worker   if (program_header_only_) {
401*795d594fSAndroid Build Coastguard Worker     // It might not be mapped, but we can compare against the file size.
402*795d594fSAndroid Build Coastguard Worker     int64_t offset = static_cast<int64_t>(GetHeader().e_shoff +
403*795d594fSAndroid Build Coastguard Worker                                           (GetHeader().e_shstrndx * GetHeader().e_shentsize));
404*795d594fSAndroid Build Coastguard Worker     if (offset >= file->GetLength()) {
405*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'",
406*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
407*795d594fSAndroid Build Coastguard Worker       return false;
408*795d594fSAndroid Build Coastguard Worker     }
409*795d594fSAndroid Build Coastguard Worker   }
410*795d594fSAndroid Build Coastguard Worker 
411*795d594fSAndroid Build Coastguard Worker   return true;
412*795d594fSAndroid Build Coastguard Worker }
413*795d594fSAndroid Build Coastguard Worker 
414*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
SetMap(File * file,MemMap && map,std::string * error_msg)415*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap&& map, std::string* error_msg) {
416*795d594fSAndroid Build Coastguard Worker   if (!map.IsValid()) {
417*795d594fSAndroid Build Coastguard Worker     // MemMap::Open should have already set an error.
418*795d594fSAndroid Build Coastguard Worker     DCHECK(!error_msg->empty());
419*795d594fSAndroid Build Coastguard Worker     return false;
420*795d594fSAndroid Build Coastguard Worker   }
421*795d594fSAndroid Build Coastguard Worker   map_ = std::move(map);
422*795d594fSAndroid Build Coastguard Worker   CHECK(map_.IsValid()) << file->GetPath();
423*795d594fSAndroid Build Coastguard Worker   CHECK(map_.Begin() != nullptr) << file->GetPath();
424*795d594fSAndroid Build Coastguard Worker 
425*795d594fSAndroid Build Coastguard Worker   header_ = reinterpret_cast<Elf_Ehdr*>(map_.Begin());
426*795d594fSAndroid Build Coastguard Worker   if ((ELFMAG0 != header_->e_ident[EI_MAG0])
427*795d594fSAndroid Build Coastguard Worker       || (ELFMAG1 != header_->e_ident[EI_MAG1])
428*795d594fSAndroid Build Coastguard Worker       || (ELFMAG2 != header_->e_ident[EI_MAG2])
429*795d594fSAndroid Build Coastguard Worker       || (ELFMAG3 != header_->e_ident[EI_MAG3])) {
430*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find ELF magic value %d %d %d %d in %s, found %d %d %d %d",
431*795d594fSAndroid Build Coastguard Worker                               ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
432*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
433*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_MAG0],
434*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_MAG1],
435*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_MAG2],
436*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_MAG3]);
437*795d594fSAndroid Build Coastguard Worker     return false;
438*795d594fSAndroid Build Coastguard Worker   }
439*795d594fSAndroid Build Coastguard Worker   uint8_t elf_class = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) ? ELFCLASS64 : ELFCLASS32;
440*795d594fSAndroid Build Coastguard Worker   if (elf_class != header_->e_ident[EI_CLASS]) {
441*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d in %s, found %d",
442*795d594fSAndroid Build Coastguard Worker                               elf_class,
443*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
444*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_CLASS]);
445*795d594fSAndroid Build Coastguard Worker     return false;
446*795d594fSAndroid Build Coastguard Worker   }
447*795d594fSAndroid Build Coastguard Worker   if (ELFDATA2LSB != header_->e_ident[EI_DATA]) {
448*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected EI_DATA value %d in %s, found %d",
449*795d594fSAndroid Build Coastguard Worker                               ELFDATA2LSB,
450*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
451*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_CLASS]);
452*795d594fSAndroid Build Coastguard Worker     return false;
453*795d594fSAndroid Build Coastguard Worker   }
454*795d594fSAndroid Build Coastguard Worker   if (EV_CURRENT != header_->e_ident[EI_VERSION]) {
455*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected EI_VERSION value %d in %s, found %d",
456*795d594fSAndroid Build Coastguard Worker                               EV_CURRENT,
457*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
458*795d594fSAndroid Build Coastguard Worker                               header_->e_ident[EI_CLASS]);
459*795d594fSAndroid Build Coastguard Worker     return false;
460*795d594fSAndroid Build Coastguard Worker   }
461*795d594fSAndroid Build Coastguard Worker   if (ET_DYN != header_->e_type) {
462*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected e_type value %d in %s, found %d",
463*795d594fSAndroid Build Coastguard Worker                               ET_DYN,
464*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
465*795d594fSAndroid Build Coastguard Worker                               header_->e_type);
466*795d594fSAndroid Build Coastguard Worker     return false;
467*795d594fSAndroid Build Coastguard Worker   }
468*795d594fSAndroid Build Coastguard Worker   if (EV_CURRENT != header_->e_version) {
469*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected e_version value %d in %s, found %d",
470*795d594fSAndroid Build Coastguard Worker                               EV_CURRENT,
471*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
472*795d594fSAndroid Build Coastguard Worker                               header_->e_version);
473*795d594fSAndroid Build Coastguard Worker     return false;
474*795d594fSAndroid Build Coastguard Worker   }
475*795d594fSAndroid Build Coastguard Worker   if (0 != header_->e_entry) {
476*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected e_entry value %d in %s, found %d",
477*795d594fSAndroid Build Coastguard Worker                               0,
478*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
479*795d594fSAndroid Build Coastguard Worker                               static_cast<int32_t>(header_->e_entry));
480*795d594fSAndroid Build Coastguard Worker     return false;
481*795d594fSAndroid Build Coastguard Worker   }
482*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_phoff) {
483*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_phoff value in %s",
484*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
485*795d594fSAndroid Build Coastguard Worker     return false;
486*795d594fSAndroid Build Coastguard Worker   }
487*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_shoff) {
488*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_shoff value in %s",
489*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
490*795d594fSAndroid Build Coastguard Worker     return false;
491*795d594fSAndroid Build Coastguard Worker   }
492*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_ehsize) {
493*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_ehsize value in %s",
494*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
495*795d594fSAndroid Build Coastguard Worker     return false;
496*795d594fSAndroid Build Coastguard Worker   }
497*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_phentsize) {
498*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_phentsize value in %s",
499*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
500*795d594fSAndroid Build Coastguard Worker     return false;
501*795d594fSAndroid Build Coastguard Worker   }
502*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_phnum) {
503*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_phnum value in %s",
504*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
505*795d594fSAndroid Build Coastguard Worker     return false;
506*795d594fSAndroid Build Coastguard Worker   }
507*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_shentsize) {
508*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_shentsize value in %s",
509*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
510*795d594fSAndroid Build Coastguard Worker     return false;
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_shnum) {
513*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_shnum value in %s",
514*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
515*795d594fSAndroid Build Coastguard Worker     return false;
516*795d594fSAndroid Build Coastguard Worker   }
517*795d594fSAndroid Build Coastguard Worker   if (0 == header_->e_shstrndx) {
518*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find non-zero e_shstrndx value in %s",
519*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
520*795d594fSAndroid Build Coastguard Worker     return false;
521*795d594fSAndroid Build Coastguard Worker   }
522*795d594fSAndroid Build Coastguard Worker   if (header_->e_shstrndx >= header_->e_shnum) {
523*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find e_shnum value %d less than %d in %s",
524*795d594fSAndroid Build Coastguard Worker                               header_->e_shstrndx,
525*795d594fSAndroid Build Coastguard Worker                               header_->e_shnum,
526*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
527*795d594fSAndroid Build Coastguard Worker     return false;
528*795d594fSAndroid Build Coastguard Worker   }
529*795d594fSAndroid Build Coastguard Worker 
530*795d594fSAndroid Build Coastguard Worker   if (!program_header_only_) {
531*795d594fSAndroid Build Coastguard Worker     if (header_->e_phoff >= Size()) {
532*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s",
533*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(header_->e_phoff),
534*795d594fSAndroid Build Coastguard Worker                                 Size(),
535*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
536*795d594fSAndroid Build Coastguard Worker       return false;
537*795d594fSAndroid Build Coastguard Worker     }
538*795d594fSAndroid Build Coastguard Worker     if (header_->e_shoff >= Size()) {
539*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s",
540*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(header_->e_shoff),
541*795d594fSAndroid Build Coastguard Worker                                 Size(),
542*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
543*795d594fSAndroid Build Coastguard Worker       return false;
544*795d594fSAndroid Build Coastguard Worker     }
545*795d594fSAndroid Build Coastguard Worker   }
546*795d594fSAndroid Build Coastguard Worker   return true;
547*795d594fSAndroid Build Coastguard Worker }
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHeader() const550*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Ehdr& ElfFileImpl<ElfTypes>::GetHeader() const {
551*795d594fSAndroid Build Coastguard Worker   CHECK(header_ != nullptr);  // Header has been checked in SetMap
552*795d594fSAndroid Build Coastguard Worker   return *header_;
553*795d594fSAndroid Build Coastguard Worker }
554*795d594fSAndroid Build Coastguard Worker 
555*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetProgramHeadersStart() const556*795d594fSAndroid Build Coastguard Worker uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const {
557*795d594fSAndroid Build Coastguard Worker   CHECK(program_headers_start_ != nullptr);  // Header has been set in Setup
558*795d594fSAndroid Build Coastguard Worker   return program_headers_start_;
559*795d594fSAndroid Build Coastguard Worker }
560*795d594fSAndroid Build Coastguard Worker 
561*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSectionHeadersStart() const562*795d594fSAndroid Build Coastguard Worker uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const {
563*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_);              // Only used in "full" mode.
564*795d594fSAndroid Build Coastguard Worker   CHECK(section_headers_start_ != nullptr);  // Is checked in CheckSectionsExist
565*795d594fSAndroid Build Coastguard Worker   return section_headers_start_;
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker 
568*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetDynamicProgramHeader() const569*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const {
570*795d594fSAndroid Build Coastguard Worker   CHECK(dynamic_program_header_ != nullptr);  // Is checked in CheckSectionsExist
571*795d594fSAndroid Build Coastguard Worker   return *dynamic_program_header_;
572*795d594fSAndroid Build Coastguard Worker }
573*795d594fSAndroid Build Coastguard Worker 
574*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetDynamicSectionStart() const575*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::GetDynamicSectionStart() const {
576*795d594fSAndroid Build Coastguard Worker   CHECK(dynamic_section_start_ != nullptr);  // Is checked in CheckSectionsExist
577*795d594fSAndroid Build Coastguard Worker   return dynamic_section_start_;
578*795d594fSAndroid Build Coastguard Worker }
579*795d594fSAndroid Build Coastguard Worker 
580*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSymbolSectionStart(Elf_Word section_type) const581*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbolSectionStart(
582*795d594fSAndroid Build Coastguard Worker     Elf_Word section_type) const {
583*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
584*795d594fSAndroid Build Coastguard Worker   switch (section_type) {
585*795d594fSAndroid Build Coastguard Worker     case SHT_SYMTAB: {
586*795d594fSAndroid Build Coastguard Worker       return symtab_section_start_;
587*795d594fSAndroid Build Coastguard Worker       break;
588*795d594fSAndroid Build Coastguard Worker     }
589*795d594fSAndroid Build Coastguard Worker     case SHT_DYNSYM: {
590*795d594fSAndroid Build Coastguard Worker       return dynsym_section_start_;
591*795d594fSAndroid Build Coastguard Worker       break;
592*795d594fSAndroid Build Coastguard Worker     }
593*795d594fSAndroid Build Coastguard Worker     default: {
594*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << section_type;
595*795d594fSAndroid Build Coastguard Worker       return nullptr;
596*795d594fSAndroid Build Coastguard Worker     }
597*795d594fSAndroid Build Coastguard Worker   }
598*795d594fSAndroid Build Coastguard Worker }
599*795d594fSAndroid Build Coastguard Worker 
600*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetStringSectionStart(Elf_Word section_type) const601*795d594fSAndroid Build Coastguard Worker const char* ElfFileImpl<ElfTypes>::GetStringSectionStart(
602*795d594fSAndroid Build Coastguard Worker     Elf_Word section_type) const {
603*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
604*795d594fSAndroid Build Coastguard Worker   switch (section_type) {
605*795d594fSAndroid Build Coastguard Worker     case SHT_SYMTAB: {
606*795d594fSAndroid Build Coastguard Worker       return strtab_section_start_;
607*795d594fSAndroid Build Coastguard Worker     }
608*795d594fSAndroid Build Coastguard Worker     case SHT_DYNSYM: {
609*795d594fSAndroid Build Coastguard Worker       return dynstr_section_start_;
610*795d594fSAndroid Build Coastguard Worker     }
611*795d594fSAndroid Build Coastguard Worker     default: {
612*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << section_type;
613*795d594fSAndroid Build Coastguard Worker       return nullptr;
614*795d594fSAndroid Build Coastguard Worker     }
615*795d594fSAndroid Build Coastguard Worker   }
616*795d594fSAndroid Build Coastguard Worker }
617*795d594fSAndroid Build Coastguard Worker 
618*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetString(Elf_Word section_type,Elf_Word i) const619*795d594fSAndroid Build Coastguard Worker const char* ElfFileImpl<ElfTypes>::GetString(Elf_Word section_type,
620*795d594fSAndroid Build Coastguard Worker                                              Elf_Word i) const {
621*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
622*795d594fSAndroid Build Coastguard Worker   if (i == 0) {
623*795d594fSAndroid Build Coastguard Worker     return nullptr;
624*795d594fSAndroid Build Coastguard Worker   }
625*795d594fSAndroid Build Coastguard Worker   const char* string_section_start = GetStringSectionStart(section_type);
626*795d594fSAndroid Build Coastguard Worker   if (string_section_start == nullptr) {
627*795d594fSAndroid Build Coastguard Worker     return nullptr;
628*795d594fSAndroid Build Coastguard Worker   }
629*795d594fSAndroid Build Coastguard Worker   return string_section_start + i;
630*795d594fSAndroid Build Coastguard Worker }
631*795d594fSAndroid Build Coastguard Worker 
632*795d594fSAndroid Build Coastguard Worker // WARNING: The following methods do not check for an error condition (non-existent hash section).
633*795d594fSAndroid Build Coastguard Worker //          It is the caller's job to do this.
634*795d594fSAndroid Build Coastguard Worker 
635*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHashSectionStart() const636*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word* ElfFileImpl<ElfTypes>::GetHashSectionStart() const {
637*795d594fSAndroid Build Coastguard Worker   return hash_section_start_;
638*795d594fSAndroid Build Coastguard Worker }
639*795d594fSAndroid Build Coastguard Worker 
640*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHashBucketNum() const641*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucketNum() const {
642*795d594fSAndroid Build Coastguard Worker   return GetHashSectionStart()[0];
643*795d594fSAndroid Build Coastguard Worker }
644*795d594fSAndroid Build Coastguard Worker 
645*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHashChainNum() const646*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChainNum() const {
647*795d594fSAndroid Build Coastguard Worker   return GetHashSectionStart()[1];
648*795d594fSAndroid Build Coastguard Worker }
649*795d594fSAndroid Build Coastguard Worker 
650*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHashBucket(size_t i,bool * ok) const651*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashBucket(size_t i, bool* ok) const {
652*795d594fSAndroid Build Coastguard Worker   if (i >= GetHashBucketNum()) {
653*795d594fSAndroid Build Coastguard Worker     *ok = false;
654*795d594fSAndroid Build Coastguard Worker     return 0;
655*795d594fSAndroid Build Coastguard Worker   }
656*795d594fSAndroid Build Coastguard Worker   *ok = true;
657*795d594fSAndroid Build Coastguard Worker   // 0 is nbucket, 1 is nchain
658*795d594fSAndroid Build Coastguard Worker   return GetHashSectionStart()[2 + i];
659*795d594fSAndroid Build Coastguard Worker }
660*795d594fSAndroid Build Coastguard Worker 
661*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetHashChain(size_t i,bool * ok) const662*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetHashChain(size_t i, bool* ok) const {
663*795d594fSAndroid Build Coastguard Worker   if (i >= GetHashChainNum()) {
664*795d594fSAndroid Build Coastguard Worker     *ok = false;
665*795d594fSAndroid Build Coastguard Worker     return 0;
666*795d594fSAndroid Build Coastguard Worker   }
667*795d594fSAndroid Build Coastguard Worker   *ok = true;
668*795d594fSAndroid Build Coastguard Worker   // 0 is nbucket, 1 is nchain, & chains are after buckets
669*795d594fSAndroid Build Coastguard Worker   return GetHashSectionStart()[2 + GetHashBucketNum() + i];
670*795d594fSAndroid Build Coastguard Worker }
671*795d594fSAndroid Build Coastguard Worker 
672*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetProgramHeaderNum() const673*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetProgramHeaderNum() const {
674*795d594fSAndroid Build Coastguard Worker   return GetHeader().e_phnum;
675*795d594fSAndroid Build Coastguard Worker }
676*795d594fSAndroid Build Coastguard Worker 
677*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetProgramHeader(Elf_Word i) const678*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::GetProgramHeader(Elf_Word i) const {
679*795d594fSAndroid Build Coastguard Worker   CHECK_LT(i, GetProgramHeaderNum()) << file_path_;  // Validity check for caller.
680*795d594fSAndroid Build Coastguard Worker   uint8_t* program_header = GetProgramHeadersStart() + (i * GetHeader().e_phentsize);
681*795d594fSAndroid Build Coastguard Worker   CHECK_LT(program_header, End());
682*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<Elf_Phdr*>(program_header);
683*795d594fSAndroid Build Coastguard Worker }
684*795d594fSAndroid Build Coastguard Worker 
685*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindProgamHeaderByType(Elf_Word type) const686*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Phdr* ElfFileImpl<ElfTypes>::FindProgamHeaderByType(Elf_Word type) const {
687*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
688*795d594fSAndroid Build Coastguard Worker     Elf_Phdr* program_header = GetProgramHeader(i);
689*795d594fSAndroid Build Coastguard Worker     if (program_header->p_type == type) {
690*795d594fSAndroid Build Coastguard Worker       return program_header;
691*795d594fSAndroid Build Coastguard Worker     }
692*795d594fSAndroid Build Coastguard Worker   }
693*795d594fSAndroid Build Coastguard Worker   return nullptr;
694*795d594fSAndroid Build Coastguard Worker }
695*795d594fSAndroid Build Coastguard Worker 
696*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSectionHeaderNum() const697*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const {
698*795d594fSAndroid Build Coastguard Worker   return GetHeader().e_shnum;
699*795d594fSAndroid Build Coastguard Worker }
700*795d594fSAndroid Build Coastguard Worker 
701*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSectionHeader(Elf_Word i) const702*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const {
703*795d594fSAndroid Build Coastguard Worker   // Can only access arbitrary sections when we have the whole file, not just program header.
704*795d594fSAndroid Build Coastguard Worker   // Even if we Load(), it doesn't bring in all the sections.
705*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_) << file_path_;
706*795d594fSAndroid Build Coastguard Worker   if (i >= GetSectionHeaderNum()) {
707*795d594fSAndroid Build Coastguard Worker     return nullptr;  // Failure condition.
708*795d594fSAndroid Build Coastguard Worker   }
709*795d594fSAndroid Build Coastguard Worker   uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize);
710*795d594fSAndroid Build Coastguard Worker   if (section_header >= End()) {
711*795d594fSAndroid Build Coastguard Worker     return nullptr;  // Failure condition.
712*795d594fSAndroid Build Coastguard Worker   }
713*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<Elf_Shdr*>(section_header);
714*795d594fSAndroid Build Coastguard Worker }
715*795d594fSAndroid Build Coastguard Worker 
716*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindSectionByType(Elf_Word type) const717*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const {
718*795d594fSAndroid Build Coastguard Worker   // Can only access arbitrary sections when we have the whole file, not just program header.
719*795d594fSAndroid Build Coastguard Worker   // We could change this to switch on known types if they were detected during loading.
720*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_) << file_path_;
721*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
722*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* section_header = GetSectionHeader(i);
723*795d594fSAndroid Build Coastguard Worker     if (section_header->sh_type == type) {
724*795d594fSAndroid Build Coastguard Worker       return section_header;
725*795d594fSAndroid Build Coastguard Worker     }
726*795d594fSAndroid Build Coastguard Worker   }
727*795d594fSAndroid Build Coastguard Worker   return nullptr;
728*795d594fSAndroid Build Coastguard Worker }
729*795d594fSAndroid Build Coastguard Worker 
730*795d594fSAndroid Build Coastguard Worker // from bionic
elfhash(const char * _name)731*795d594fSAndroid Build Coastguard Worker static unsigned elfhash(const char *_name) {
732*795d594fSAndroid Build Coastguard Worker   const unsigned char *name = (const unsigned char *) _name;
733*795d594fSAndroid Build Coastguard Worker   unsigned h = 0, g;
734*795d594fSAndroid Build Coastguard Worker 
735*795d594fSAndroid Build Coastguard Worker   while (*name) {
736*795d594fSAndroid Build Coastguard Worker     h = (h << 4) + *name++;
737*795d594fSAndroid Build Coastguard Worker     g = h & 0xf0000000;
738*795d594fSAndroid Build Coastguard Worker     h ^= g;
739*795d594fSAndroid Build Coastguard Worker     h ^= g >> 24;
740*795d594fSAndroid Build Coastguard Worker   }
741*795d594fSAndroid Build Coastguard Worker   return h;
742*795d594fSAndroid Build Coastguard Worker }
743*795d594fSAndroid Build Coastguard Worker 
744*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSectionNameStringSection() const745*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const {
746*795d594fSAndroid Build Coastguard Worker   return GetSectionHeader(GetHeader().e_shstrndx);
747*795d594fSAndroid Build Coastguard Worker }
748*795d594fSAndroid Build Coastguard Worker 
749*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindDynamicSymbolAddress(const std::string & symbol_name) const750*795d594fSAndroid Build Coastguard Worker const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress(
751*795d594fSAndroid Build Coastguard Worker     const std::string& symbol_name) const {
752*795d594fSAndroid Build Coastguard Worker   // Check that we have a hash section.
753*795d594fSAndroid Build Coastguard Worker   if (GetHashSectionStart() == nullptr) {
754*795d594fSAndroid Build Coastguard Worker     return nullptr;  // Failure condition.
755*795d594fSAndroid Build Coastguard Worker   }
756*795d594fSAndroid Build Coastguard Worker   const Elf_Sym* sym = FindDynamicSymbol(symbol_name);
757*795d594fSAndroid Build Coastguard Worker   if (sym != nullptr) {
758*795d594fSAndroid Build Coastguard Worker     // TODO: we need to change this to calculate base_address_ in ::Open,
759*795d594fSAndroid Build Coastguard Worker     // otherwise it will be wrongly 0 if ::Load has not yet been called.
760*795d594fSAndroid Build Coastguard Worker     return base_address_ + sym->st_value;
761*795d594fSAndroid Build Coastguard Worker   } else {
762*795d594fSAndroid Build Coastguard Worker     return nullptr;
763*795d594fSAndroid Build Coastguard Worker   }
764*795d594fSAndroid Build Coastguard Worker }
765*795d594fSAndroid Build Coastguard Worker 
766*795d594fSAndroid Build Coastguard Worker // WARNING: Only called from FindDynamicSymbolAddress. Elides check for hash section.
767*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindDynamicSymbol(const std::string & symbol_name) const768*795d594fSAndroid Build Coastguard Worker const typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindDynamicSymbol(
769*795d594fSAndroid Build Coastguard Worker     const std::string& symbol_name) const {
770*795d594fSAndroid Build Coastguard Worker   if (GetHashBucketNum() == 0) {
771*795d594fSAndroid Build Coastguard Worker     // No dynamic symbols at all.
772*795d594fSAndroid Build Coastguard Worker     return nullptr;
773*795d594fSAndroid Build Coastguard Worker   }
774*795d594fSAndroid Build Coastguard Worker   Elf_Word hash = elfhash(symbol_name.c_str());
775*795d594fSAndroid Build Coastguard Worker   Elf_Word bucket_index = hash % GetHashBucketNum();
776*795d594fSAndroid Build Coastguard Worker   bool ok;
777*795d594fSAndroid Build Coastguard Worker   Elf_Word symbol_and_chain_index = GetHashBucket(bucket_index, &ok);
778*795d594fSAndroid Build Coastguard Worker   if (!ok) {
779*795d594fSAndroid Build Coastguard Worker     return nullptr;
780*795d594fSAndroid Build Coastguard Worker   }
781*795d594fSAndroid Build Coastguard Worker   while (symbol_and_chain_index != 0 /* STN_UNDEF */) {
782*795d594fSAndroid Build Coastguard Worker     Elf_Sym* symbol = GetSymbol(SHT_DYNSYM, symbol_and_chain_index);
783*795d594fSAndroid Build Coastguard Worker     if (symbol == nullptr) {
784*795d594fSAndroid Build Coastguard Worker       return nullptr;  // Failure condition.
785*795d594fSAndroid Build Coastguard Worker     }
786*795d594fSAndroid Build Coastguard Worker     const char* name = GetString(SHT_DYNSYM, symbol->st_name);
787*795d594fSAndroid Build Coastguard Worker     if (symbol_name == name) {
788*795d594fSAndroid Build Coastguard Worker       return symbol;
789*795d594fSAndroid Build Coastguard Worker     }
790*795d594fSAndroid Build Coastguard Worker     symbol_and_chain_index = GetHashChain(symbol_and_chain_index, &ok);
791*795d594fSAndroid Build Coastguard Worker     if (!ok) {
792*795d594fSAndroid Build Coastguard Worker       return nullptr;
793*795d594fSAndroid Build Coastguard Worker     }
794*795d594fSAndroid Build Coastguard Worker   }
795*795d594fSAndroid Build Coastguard Worker   return nullptr;
796*795d594fSAndroid Build Coastguard Worker }
797*795d594fSAndroid Build Coastguard Worker 
798*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
IsSymbolSectionType(Elf_Word section_type)799*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::IsSymbolSectionType(Elf_Word section_type) {
800*795d594fSAndroid Build Coastguard Worker   return ((section_type == SHT_SYMTAB) || (section_type == SHT_DYNSYM));
801*795d594fSAndroid Build Coastguard Worker }
802*795d594fSAndroid Build Coastguard Worker 
803*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSymbolNum(Elf_Shdr & section_header) const804*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSymbolNum(Elf_Shdr& section_header) const {
805*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_header.sh_type))
806*795d594fSAndroid Build Coastguard Worker       << file_path_ << " " << section_header.sh_type;
807*795d594fSAndroid Build Coastguard Worker   CHECK_NE(0U, section_header.sh_entsize) << file_path_;
808*795d594fSAndroid Build Coastguard Worker   return section_header.sh_size / section_header.sh_entsize;
809*795d594fSAndroid Build Coastguard Worker }
810*795d594fSAndroid Build Coastguard Worker 
811*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetSymbol(Elf_Word section_type,Elf_Word i) const812*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, Elf_Word i) const {
813*795d594fSAndroid Build Coastguard Worker   Elf_Sym* sym_start = GetSymbolSectionStart(section_type);
814*795d594fSAndroid Build Coastguard Worker   if (sym_start == nullptr) {
815*795d594fSAndroid Build Coastguard Worker     return nullptr;
816*795d594fSAndroid Build Coastguard Worker   }
817*795d594fSAndroid Build Coastguard Worker   return sym_start + i;
818*795d594fSAndroid Build Coastguard Worker }
819*795d594fSAndroid Build Coastguard Worker 
820*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
821*795d594fSAndroid Build Coastguard Worker typename ElfFileImpl<ElfTypes>::SymbolTable**
GetSymbolTable(Elf_Word section_type)822*795d594fSAndroid Build Coastguard Worker ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) {
823*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
824*795d594fSAndroid Build Coastguard Worker   switch (section_type) {
825*795d594fSAndroid Build Coastguard Worker     case SHT_SYMTAB: {
826*795d594fSAndroid Build Coastguard Worker       return &symtab_symbol_table_;
827*795d594fSAndroid Build Coastguard Worker     }
828*795d594fSAndroid Build Coastguard Worker     case SHT_DYNSYM: {
829*795d594fSAndroid Build Coastguard Worker       return &dynsym_symbol_table_;
830*795d594fSAndroid Build Coastguard Worker     }
831*795d594fSAndroid Build Coastguard Worker     default: {
832*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << section_type;
833*795d594fSAndroid Build Coastguard Worker       return nullptr;
834*795d594fSAndroid Build Coastguard Worker     }
835*795d594fSAndroid Build Coastguard Worker   }
836*795d594fSAndroid Build Coastguard Worker }
837*795d594fSAndroid Build Coastguard Worker 
838*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindSymbolByName(Elf_Word section_type,const std::string & symbol_name,bool build_map)839*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName(
840*795d594fSAndroid Build Coastguard Worker     Elf_Word section_type, const std::string& symbol_name, bool build_map) {
841*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_) << file_path_;
842*795d594fSAndroid Build Coastguard Worker   CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type;
843*795d594fSAndroid Build Coastguard Worker 
844*795d594fSAndroid Build Coastguard Worker   SymbolTable** symbol_table = GetSymbolTable(section_type);
845*795d594fSAndroid Build Coastguard Worker   if (*symbol_table != nullptr || build_map) {
846*795d594fSAndroid Build Coastguard Worker     if (*symbol_table == nullptr) {
847*795d594fSAndroid Build Coastguard Worker       DCHECK(build_map);
848*795d594fSAndroid Build Coastguard Worker       *symbol_table = new SymbolTable;
849*795d594fSAndroid Build Coastguard Worker       Elf_Shdr* symbol_section = FindSectionByType(section_type);
850*795d594fSAndroid Build Coastguard Worker       if (symbol_section == nullptr) {
851*795d594fSAndroid Build Coastguard Worker         return nullptr;  // Failure condition.
852*795d594fSAndroid Build Coastguard Worker       }
853*795d594fSAndroid Build Coastguard Worker       Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
854*795d594fSAndroid Build Coastguard Worker       if (string_section == nullptr) {
855*795d594fSAndroid Build Coastguard Worker         return nullptr;  // Failure condition.
856*795d594fSAndroid Build Coastguard Worker       }
857*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
858*795d594fSAndroid Build Coastguard Worker         Elf_Sym* symbol = GetSymbol(section_type, i);
859*795d594fSAndroid Build Coastguard Worker         if (symbol == nullptr) {
860*795d594fSAndroid Build Coastguard Worker           return nullptr;  // Failure condition.
861*795d594fSAndroid Build Coastguard Worker         }
862*795d594fSAndroid Build Coastguard Worker         unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr))
863*795d594fSAndroid Build Coastguard Worker                              ? ELF64_ST_TYPE(symbol->st_info)
864*795d594fSAndroid Build Coastguard Worker                              : ELF32_ST_TYPE(symbol->st_info);
865*795d594fSAndroid Build Coastguard Worker         if (type == STT_NOTYPE) {
866*795d594fSAndroid Build Coastguard Worker           continue;
867*795d594fSAndroid Build Coastguard Worker         }
868*795d594fSAndroid Build Coastguard Worker         const char* name = GetString(*string_section, symbol->st_name);
869*795d594fSAndroid Build Coastguard Worker         if (name == nullptr) {
870*795d594fSAndroid Build Coastguard Worker           continue;
871*795d594fSAndroid Build Coastguard Worker         }
872*795d594fSAndroid Build Coastguard Worker         std::pair<typename SymbolTable::iterator, bool> result =
873*795d594fSAndroid Build Coastguard Worker             (*symbol_table)->insert(std::make_pair(name, symbol));
874*795d594fSAndroid Build Coastguard Worker         if (!result.second) {
875*795d594fSAndroid Build Coastguard Worker           // If a duplicate, make sure it has the same logical value. Seen on x86.
876*795d594fSAndroid Build Coastguard Worker           if ((symbol->st_value != result.first->second->st_value) ||
877*795d594fSAndroid Build Coastguard Worker               (symbol->st_size != result.first->second->st_size) ||
878*795d594fSAndroid Build Coastguard Worker               (symbol->st_info != result.first->second->st_info) ||
879*795d594fSAndroid Build Coastguard Worker               (symbol->st_other != result.first->second->st_other) ||
880*795d594fSAndroid Build Coastguard Worker               (symbol->st_shndx != result.first->second->st_shndx)) {
881*795d594fSAndroid Build Coastguard Worker             return nullptr;  // Failure condition.
882*795d594fSAndroid Build Coastguard Worker           }
883*795d594fSAndroid Build Coastguard Worker         }
884*795d594fSAndroid Build Coastguard Worker       }
885*795d594fSAndroid Build Coastguard Worker     }
886*795d594fSAndroid Build Coastguard Worker     CHECK(*symbol_table != nullptr);
887*795d594fSAndroid Build Coastguard Worker     typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name);
888*795d594fSAndroid Build Coastguard Worker     if (it == (*symbol_table)->end()) {
889*795d594fSAndroid Build Coastguard Worker       return nullptr;
890*795d594fSAndroid Build Coastguard Worker     }
891*795d594fSAndroid Build Coastguard Worker     return it->second;
892*795d594fSAndroid Build Coastguard Worker   }
893*795d594fSAndroid Build Coastguard Worker 
894*795d594fSAndroid Build Coastguard Worker   // Fall back to linear search
895*795d594fSAndroid Build Coastguard Worker   Elf_Shdr* symbol_section = FindSectionByType(section_type);
896*795d594fSAndroid Build Coastguard Worker   if (symbol_section == nullptr) {
897*795d594fSAndroid Build Coastguard Worker     return nullptr;
898*795d594fSAndroid Build Coastguard Worker   }
899*795d594fSAndroid Build Coastguard Worker   Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link);
900*795d594fSAndroid Build Coastguard Worker   if (string_section == nullptr) {
901*795d594fSAndroid Build Coastguard Worker     return nullptr;
902*795d594fSAndroid Build Coastguard Worker   }
903*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) {
904*795d594fSAndroid Build Coastguard Worker     Elf_Sym* symbol = GetSymbol(section_type, i);
905*795d594fSAndroid Build Coastguard Worker     if (symbol == nullptr) {
906*795d594fSAndroid Build Coastguard Worker       return nullptr;  // Failure condition.
907*795d594fSAndroid Build Coastguard Worker     }
908*795d594fSAndroid Build Coastguard Worker     const char* name = GetString(*string_section, symbol->st_name);
909*795d594fSAndroid Build Coastguard Worker     if (name == nullptr) {
910*795d594fSAndroid Build Coastguard Worker       continue;
911*795d594fSAndroid Build Coastguard Worker     }
912*795d594fSAndroid Build Coastguard Worker     if (symbol_name == name) {
913*795d594fSAndroid Build Coastguard Worker       return symbol;
914*795d594fSAndroid Build Coastguard Worker     }
915*795d594fSAndroid Build Coastguard Worker   }
916*795d594fSAndroid Build Coastguard Worker   return nullptr;
917*795d594fSAndroid Build Coastguard Worker }
918*795d594fSAndroid Build Coastguard Worker 
919*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindSymbolAddress(Elf_Word section_type,const std::string & symbol_name,bool build_map)920*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress(
921*795d594fSAndroid Build Coastguard Worker     Elf_Word section_type, const std::string& symbol_name, bool build_map) {
922*795d594fSAndroid Build Coastguard Worker   Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map);
923*795d594fSAndroid Build Coastguard Worker   if (symbol == nullptr) {
924*795d594fSAndroid Build Coastguard Worker     return 0;
925*795d594fSAndroid Build Coastguard Worker   }
926*795d594fSAndroid Build Coastguard Worker   return symbol->st_value;
927*795d594fSAndroid Build Coastguard Worker }
928*795d594fSAndroid Build Coastguard Worker 
929*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetString(Elf_Shdr & string_section,Elf_Word i) const930*795d594fSAndroid Build Coastguard Worker const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section,
931*795d594fSAndroid Build Coastguard Worker                                              Elf_Word i) const {
932*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_) << file_path_;
933*795d594fSAndroid Build Coastguard Worker   // TODO: remove this static_cast from enum when using -std=gnu++0x
934*795d594fSAndroid Build Coastguard Worker   if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) {
935*795d594fSAndroid Build Coastguard Worker     return nullptr;  // Failure condition.
936*795d594fSAndroid Build Coastguard Worker   }
937*795d594fSAndroid Build Coastguard Worker   if (i >= string_section.sh_size) {
938*795d594fSAndroid Build Coastguard Worker     return nullptr;
939*795d594fSAndroid Build Coastguard Worker   }
940*795d594fSAndroid Build Coastguard Worker   if (i == 0) {
941*795d594fSAndroid Build Coastguard Worker     return nullptr;
942*795d594fSAndroid Build Coastguard Worker   }
943*795d594fSAndroid Build Coastguard Worker   uint8_t* strings = Begin() + string_section.sh_offset;
944*795d594fSAndroid Build Coastguard Worker   uint8_t* string = strings + i;
945*795d594fSAndroid Build Coastguard Worker   if (string >= End()) {
946*795d594fSAndroid Build Coastguard Worker     return nullptr;
947*795d594fSAndroid Build Coastguard Worker   }
948*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const char*>(string);
949*795d594fSAndroid Build Coastguard Worker }
950*795d594fSAndroid Build Coastguard Worker 
951*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetDynamicNum() const952*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const {
953*795d594fSAndroid Build Coastguard Worker   return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn);
954*795d594fSAndroid Build Coastguard Worker }
955*795d594fSAndroid Build Coastguard Worker 
956*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetDynamic(Elf_Word i) const957*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Dyn& ElfFileImpl<ElfTypes>::GetDynamic(Elf_Word i) const {
958*795d594fSAndroid Build Coastguard Worker   CHECK_LT(i, GetDynamicNum()) << file_path_;
959*795d594fSAndroid Build Coastguard Worker   return *(GetDynamicSectionStart() + i);
960*795d594fSAndroid Build Coastguard Worker }
961*795d594fSAndroid Build Coastguard Worker 
962*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindDynamicByType(Elf_Sword type) const963*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Dyn* ElfFileImpl<ElfTypes>::FindDynamicByType(Elf_Sword type) const {
964*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
965*795d594fSAndroid Build Coastguard Worker     Elf_Dyn* dyn = &GetDynamic(i);
966*795d594fSAndroid Build Coastguard Worker     if (dyn->d_tag == type) {
967*795d594fSAndroid Build Coastguard Worker       return dyn;
968*795d594fSAndroid Build Coastguard Worker     }
969*795d594fSAndroid Build Coastguard Worker   }
970*795d594fSAndroid Build Coastguard Worker   return nullptr;
971*795d594fSAndroid Build Coastguard Worker }
972*795d594fSAndroid Build Coastguard Worker 
973*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindDynamicValueByType(Elf_Sword type) const974*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::FindDynamicValueByType(Elf_Sword type) const {
975*795d594fSAndroid Build Coastguard Worker   Elf_Dyn* dyn = FindDynamicByType(type);
976*795d594fSAndroid Build Coastguard Worker   if (dyn == nullptr) {
977*795d594fSAndroid Build Coastguard Worker     return 0;
978*795d594fSAndroid Build Coastguard Worker   } else {
979*795d594fSAndroid Build Coastguard Worker     return dyn->d_un.d_val;
980*795d594fSAndroid Build Coastguard Worker   }
981*795d594fSAndroid Build Coastguard Worker }
982*795d594fSAndroid Build Coastguard Worker 
983*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRelSectionStart(Elf_Shdr & section_header) const984*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Rel* ElfFileImpl<ElfTypes>::GetRelSectionStart(Elf_Shdr& section_header) const {
985*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
986*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<Elf_Rel*>(Begin() + section_header.sh_offset);
987*795d594fSAndroid Build Coastguard Worker }
988*795d594fSAndroid Build Coastguard Worker 
989*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRelNum(Elf_Shdr & section_header) const990*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelNum(Elf_Shdr& section_header) const {
991*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
992*795d594fSAndroid Build Coastguard Worker   CHECK_NE(0U, section_header.sh_entsize) << file_path_;
993*795d594fSAndroid Build Coastguard Worker   return section_header.sh_size / section_header.sh_entsize;
994*795d594fSAndroid Build Coastguard Worker }
995*795d594fSAndroid Build Coastguard Worker 
996*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRel(Elf_Shdr & section_header,Elf_Word i) const997*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Rel& ElfFileImpl<ElfTypes>::GetRel(Elf_Shdr& section_header, Elf_Word i) const {
998*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_REL == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
999*795d594fSAndroid Build Coastguard Worker   CHECK_LT(i, GetRelNum(section_header)) << file_path_;
1000*795d594fSAndroid Build Coastguard Worker   return *(GetRelSectionStart(section_header) + i);
1001*795d594fSAndroid Build Coastguard Worker }
1002*795d594fSAndroid Build Coastguard Worker 
1003*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRelaSectionStart(Elf_Shdr & section_header) const1004*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Rela* ElfFileImpl<ElfTypes>::GetRelaSectionStart(Elf_Shdr& section_header) const {
1005*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1006*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<Elf_Rela*>(Begin() + section_header.sh_offset);
1007*795d594fSAndroid Build Coastguard Worker }
1008*795d594fSAndroid Build Coastguard Worker 
1009*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRelaNum(Elf_Shdr & section_header) const1010*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetRelaNum(Elf_Shdr& section_header) const {
1011*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1012*795d594fSAndroid Build Coastguard Worker   return section_header.sh_size / section_header.sh_entsize;
1013*795d594fSAndroid Build Coastguard Worker }
1014*795d594fSAndroid Build Coastguard Worker 
1015*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetRela(Elf_Shdr & section_header,Elf_Word i) const1016*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Rela& ElfFileImpl<ElfTypes>::GetRela(Elf_Shdr& section_header, Elf_Word i) const {
1017*795d594fSAndroid Build Coastguard Worker   CHECK(SHT_RELA == section_header.sh_type) << file_path_ << " " << section_header.sh_type;
1018*795d594fSAndroid Build Coastguard Worker   CHECK_LT(i, GetRelaNum(section_header)) << file_path_;
1019*795d594fSAndroid Build Coastguard Worker   return *(GetRelaSectionStart(section_header) + i);
1020*795d594fSAndroid Build Coastguard Worker }
1021*795d594fSAndroid Build Coastguard Worker 
1022*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetLoadedSize(size_t * size,std::string * error_msg) const1023*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::GetLoadedSize(size_t* size, std::string* error_msg) const {
1024*795d594fSAndroid Build Coastguard Worker   uint8_t* vaddr_begin;
1025*795d594fSAndroid Build Coastguard Worker   return GetLoadedAddressRange(&vaddr_begin, size, error_msg);
1026*795d594fSAndroid Build Coastguard Worker }
1027*795d594fSAndroid Build Coastguard Worker 
1028*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetElfSegmentAlignmentFromFile() const1029*795d594fSAndroid Build Coastguard Worker size_t ElfFileImpl<ElfTypes>::GetElfSegmentAlignmentFromFile() const {
1030*795d594fSAndroid Build Coastguard Worker   // Return the alignment of the first loadable program segment.
1031*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1032*795d594fSAndroid Build Coastguard Worker     Elf_Phdr* program_header = GetProgramHeader(i);
1033*795d594fSAndroid Build Coastguard Worker     if (program_header->p_type != PT_LOAD) {
1034*795d594fSAndroid Build Coastguard Worker       continue;
1035*795d594fSAndroid Build Coastguard Worker     }
1036*795d594fSAndroid Build Coastguard Worker     return program_header->p_align;
1037*795d594fSAndroid Build Coastguard Worker   }
1038*795d594fSAndroid Build Coastguard Worker   LOG(ERROR) << "No loadable segment found in ELF file " << file_path_;
1039*795d594fSAndroid Build Coastguard Worker   return 0;
1040*795d594fSAndroid Build Coastguard Worker }
1041*795d594fSAndroid Build Coastguard Worker 
1042*795d594fSAndroid Build Coastguard Worker // Base on bionic phdr_table_get_load_size
1043*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
GetLoadedAddressRange(uint8_t ** vaddr_begin,size_t * vaddr_size,std::string * error_msg) const1044*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::GetLoadedAddressRange(/*out*/uint8_t** vaddr_begin,
1045*795d594fSAndroid Build Coastguard Worker                                                   /*out*/size_t* vaddr_size,
1046*795d594fSAndroid Build Coastguard Worker                                                   /*out*/std::string* error_msg) const {
1047*795d594fSAndroid Build Coastguard Worker   Elf_Addr min_vaddr = static_cast<Elf_Addr>(-1);
1048*795d594fSAndroid Build Coastguard Worker   Elf_Addr max_vaddr = 0u;
1049*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1050*795d594fSAndroid Build Coastguard Worker     Elf_Phdr* program_header = GetProgramHeader(i);
1051*795d594fSAndroid Build Coastguard Worker     if (program_header->p_type != PT_LOAD) {
1052*795d594fSAndroid Build Coastguard Worker       continue;
1053*795d594fSAndroid Build Coastguard Worker     }
1054*795d594fSAndroid Build Coastguard Worker     Elf_Addr begin_vaddr = program_header->p_vaddr;
1055*795d594fSAndroid Build Coastguard Worker     if (begin_vaddr < min_vaddr) {
1056*795d594fSAndroid Build Coastguard Worker        min_vaddr = begin_vaddr;
1057*795d594fSAndroid Build Coastguard Worker     }
1058*795d594fSAndroid Build Coastguard Worker     Elf_Addr end_vaddr = program_header->p_vaddr + program_header->p_memsz;
1059*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(begin_vaddr > end_vaddr)) {
1060*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
1061*795d594fSAndroid Build Coastguard Worker       oss << "Program header #" << i << " has overflow in p_vaddr+p_memsz: 0x" << std::hex
1062*795d594fSAndroid Build Coastguard Worker           << program_header->p_vaddr << "+0x" << program_header->p_memsz << "=0x" << end_vaddr
1063*795d594fSAndroid Build Coastguard Worker           << " in ELF file \"" << file_path_ << "\"";
1064*795d594fSAndroid Build Coastguard Worker       *error_msg = oss.str();
1065*795d594fSAndroid Build Coastguard Worker       *vaddr_begin = nullptr;
1066*795d594fSAndroid Build Coastguard Worker       *vaddr_size = static_cast<size_t>(-1);
1067*795d594fSAndroid Build Coastguard Worker       return false;
1068*795d594fSAndroid Build Coastguard Worker     }
1069*795d594fSAndroid Build Coastguard Worker     if (end_vaddr > max_vaddr) {
1070*795d594fSAndroid Build Coastguard Worker       max_vaddr = end_vaddr;
1071*795d594fSAndroid Build Coastguard Worker     }
1072*795d594fSAndroid Build Coastguard Worker   }
1073*795d594fSAndroid Build Coastguard Worker   min_vaddr = RoundDown(min_vaddr, kElfSegmentAlignment);
1074*795d594fSAndroid Build Coastguard Worker   max_vaddr = RoundUp(max_vaddr, kElfSegmentAlignment);
1075*795d594fSAndroid Build Coastguard Worker   CHECK_LT(min_vaddr, max_vaddr) << file_path_;
1076*795d594fSAndroid Build Coastguard Worker   // Check that the range fits into the runtime address space.
1077*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(max_vaddr - 1u > std::numeric_limits<size_t>::max())) {
1078*795d594fSAndroid Build Coastguard Worker     std::ostringstream oss;
1079*795d594fSAndroid Build Coastguard Worker     oss << "Loaded range is 0x" << std::hex << min_vaddr << "-0x" << max_vaddr
1080*795d594fSAndroid Build Coastguard Worker         << " but maximum size_t is 0x" << std::numeric_limits<size_t>::max()
1081*795d594fSAndroid Build Coastguard Worker         << " for ELF file \"" << file_path_ << "\"";
1082*795d594fSAndroid Build Coastguard Worker     *error_msg = oss.str();
1083*795d594fSAndroid Build Coastguard Worker     *vaddr_begin = nullptr;
1084*795d594fSAndroid Build Coastguard Worker     *vaddr_size = static_cast<size_t>(-1);
1085*795d594fSAndroid Build Coastguard Worker     return false;
1086*795d594fSAndroid Build Coastguard Worker   }
1087*795d594fSAndroid Build Coastguard Worker   *vaddr_begin = reinterpret_cast<uint8_t*>(min_vaddr);
1088*795d594fSAndroid Build Coastguard Worker   *vaddr_size = dchecked_integral_cast<size_t>(max_vaddr - min_vaddr);
1089*795d594fSAndroid Build Coastguard Worker   return true;
1090*795d594fSAndroid Build Coastguard Worker }
1091*795d594fSAndroid Build Coastguard Worker 
GetInstructionSetFromELF(uint16_t e_machine,uint32_t e_flags)1092*795d594fSAndroid Build Coastguard Worker static InstructionSet GetInstructionSetFromELF(uint16_t e_machine,
1093*795d594fSAndroid Build Coastguard Worker                                                [[maybe_unused]] uint32_t e_flags) {
1094*795d594fSAndroid Build Coastguard Worker   switch (e_machine) {
1095*795d594fSAndroid Build Coastguard Worker     case EM_ARM:
1096*795d594fSAndroid Build Coastguard Worker       return InstructionSet::kArm;
1097*795d594fSAndroid Build Coastguard Worker     case EM_AARCH64:
1098*795d594fSAndroid Build Coastguard Worker       return InstructionSet::kArm64;
1099*795d594fSAndroid Build Coastguard Worker     case EM_RISCV:
1100*795d594fSAndroid Build Coastguard Worker       return InstructionSet::kRiscv64;
1101*795d594fSAndroid Build Coastguard Worker     case EM_386:
1102*795d594fSAndroid Build Coastguard Worker       return InstructionSet::kX86;
1103*795d594fSAndroid Build Coastguard Worker     case EM_X86_64:
1104*795d594fSAndroid Build Coastguard Worker       return InstructionSet::kX86_64;
1105*795d594fSAndroid Build Coastguard Worker   }
1106*795d594fSAndroid Build Coastguard Worker   return InstructionSet::kNone;
1107*795d594fSAndroid Build Coastguard Worker }
1108*795d594fSAndroid Build Coastguard Worker 
1109*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
Load(File * file,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1110*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::Load(File* file,
1111*795d594fSAndroid Build Coastguard Worker                                  bool executable,
1112*795d594fSAndroid Build Coastguard Worker                                  bool low_4gb,
1113*795d594fSAndroid Build Coastguard Worker                                  /*inout*/MemMap* reservation,
1114*795d594fSAndroid Build Coastguard Worker                                  /*out*/std::string* error_msg) {
1115*795d594fSAndroid Build Coastguard Worker   CHECK(program_header_only_) << file->GetPath();
1116*795d594fSAndroid Build Coastguard Worker 
1117*795d594fSAndroid Build Coastguard Worker   if (executable) {
1118*795d594fSAndroid Build Coastguard Worker     InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags);
1119*795d594fSAndroid Build Coastguard Worker     if (elf_ISA != kRuntimeQuickCodeISA) {
1120*795d594fSAndroid Build Coastguard Worker       std::ostringstream oss;
1121*795d594fSAndroid Build Coastguard Worker       oss << "Expected ISA " << kRuntimeQuickCodeISA << " but found " << elf_ISA;
1122*795d594fSAndroid Build Coastguard Worker       *error_msg = oss.str();
1123*795d594fSAndroid Build Coastguard Worker       return false;
1124*795d594fSAndroid Build Coastguard Worker     }
1125*795d594fSAndroid Build Coastguard Worker   }
1126*795d594fSAndroid Build Coastguard Worker 
1127*795d594fSAndroid Build Coastguard Worker   bool reserved = false;
1128*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetProgramHeaderNum(); i++) {
1129*795d594fSAndroid Build Coastguard Worker     Elf_Phdr* program_header = GetProgramHeader(i);
1130*795d594fSAndroid Build Coastguard Worker 
1131*795d594fSAndroid Build Coastguard Worker     // Record .dynamic header information for later use
1132*795d594fSAndroid Build Coastguard Worker     if (program_header->p_type == PT_DYNAMIC) {
1133*795d594fSAndroid Build Coastguard Worker       dynamic_program_header_ = program_header;
1134*795d594fSAndroid Build Coastguard Worker       continue;
1135*795d594fSAndroid Build Coastguard Worker     }
1136*795d594fSAndroid Build Coastguard Worker 
1137*795d594fSAndroid Build Coastguard Worker     // Not something to load, move on.
1138*795d594fSAndroid Build Coastguard Worker     if (program_header->p_type != PT_LOAD) {
1139*795d594fSAndroid Build Coastguard Worker       continue;
1140*795d594fSAndroid Build Coastguard Worker     }
1141*795d594fSAndroid Build Coastguard Worker 
1142*795d594fSAndroid Build Coastguard Worker     // Found something to load.
1143*795d594fSAndroid Build Coastguard Worker 
1144*795d594fSAndroid Build Coastguard Worker     // Before load the actual segments, reserve a contiguous chunk
1145*795d594fSAndroid Build Coastguard Worker     // of required size and address for all segments, but with no
1146*795d594fSAndroid Build Coastguard Worker     // permissions. We'll then carve that up with the proper
1147*795d594fSAndroid Build Coastguard Worker     // permissions as we load the actual segments. If p_vaddr is
1148*795d594fSAndroid Build Coastguard Worker     // non-zero, the segments require the specific address specified,
1149*795d594fSAndroid Build Coastguard Worker     // which either was specified in the file because we already set
1150*795d594fSAndroid Build Coastguard Worker     // base_address_ after the first zero segment).
1151*795d594fSAndroid Build Coastguard Worker     int64_t temp_file_length = file->GetLength();
1152*795d594fSAndroid Build Coastguard Worker     if (temp_file_length < 0) {
1153*795d594fSAndroid Build Coastguard Worker       errno = -temp_file_length;
1154*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to get length of file: '%s' fd=%d: %s",
1155*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str(), file->Fd(), strerror(errno));
1156*795d594fSAndroid Build Coastguard Worker       return false;
1157*795d594fSAndroid Build Coastguard Worker     }
1158*795d594fSAndroid Build Coastguard Worker     size_t file_length = static_cast<size_t>(temp_file_length);
1159*795d594fSAndroid Build Coastguard Worker     if (!reserved) {
1160*795d594fSAndroid Build Coastguard Worker       uint8_t* vaddr_begin;
1161*795d594fSAndroid Build Coastguard Worker       size_t vaddr_size;
1162*795d594fSAndroid Build Coastguard Worker       if (!GetLoadedAddressRange(&vaddr_begin, &vaddr_size, error_msg)) {
1163*795d594fSAndroid Build Coastguard Worker         DCHECK(!error_msg->empty());
1164*795d594fSAndroid Build Coastguard Worker         return false;
1165*795d594fSAndroid Build Coastguard Worker       }
1166*795d594fSAndroid Build Coastguard Worker       std::string reservation_name = "ElfFile reservation for " + file->GetPath();
1167*795d594fSAndroid Build Coastguard Worker       MemMap local_reservation = MemMap::MapAnonymous(
1168*795d594fSAndroid Build Coastguard Worker           reservation_name.c_str(),
1169*795d594fSAndroid Build Coastguard Worker           (reservation != nullptr) ? reservation->Begin() : nullptr,
1170*795d594fSAndroid Build Coastguard Worker           vaddr_size,
1171*795d594fSAndroid Build Coastguard Worker           PROT_NONE,
1172*795d594fSAndroid Build Coastguard Worker           low_4gb,
1173*795d594fSAndroid Build Coastguard Worker           /* reuse= */ false,
1174*795d594fSAndroid Build Coastguard Worker           reservation,
1175*795d594fSAndroid Build Coastguard Worker           error_msg);
1176*795d594fSAndroid Build Coastguard Worker       if (!local_reservation.IsValid()) {
1177*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to allocate %s: %s",
1178*795d594fSAndroid Build Coastguard Worker                                   reservation_name.c_str(),
1179*795d594fSAndroid Build Coastguard Worker                                   error_msg->c_str());
1180*795d594fSAndroid Build Coastguard Worker         return false;
1181*795d594fSAndroid Build Coastguard Worker       }
1182*795d594fSAndroid Build Coastguard Worker       reserved = true;
1183*795d594fSAndroid Build Coastguard Worker 
1184*795d594fSAndroid Build Coastguard Worker       // Base address is the difference of actual mapped location and the vaddr_begin.
1185*795d594fSAndroid Build Coastguard Worker       base_address_ = reinterpret_cast<uint8_t*>(
1186*795d594fSAndroid Build Coastguard Worker           static_cast<uintptr_t>(local_reservation.Begin() - vaddr_begin));
1187*795d594fSAndroid Build Coastguard Worker       // By adding the p_vaddr of a section/symbol to base_address_ we will always get the
1188*795d594fSAndroid Build Coastguard Worker       // dynamic memory address of where that object is actually mapped
1189*795d594fSAndroid Build Coastguard Worker       //
1190*795d594fSAndroid Build Coastguard Worker       // TODO: base_address_ needs to be calculated in ::Open, otherwise
1191*795d594fSAndroid Build Coastguard Worker       // FindDynamicSymbolAddress returns the wrong values until Load is called.
1192*795d594fSAndroid Build Coastguard Worker       segments_.push_back(std::move(local_reservation));
1193*795d594fSAndroid Build Coastguard Worker     }
1194*795d594fSAndroid Build Coastguard Worker     // empty segment, nothing to map
1195*795d594fSAndroid Build Coastguard Worker     if (program_header->p_memsz == 0) {
1196*795d594fSAndroid Build Coastguard Worker       continue;
1197*795d594fSAndroid Build Coastguard Worker     }
1198*795d594fSAndroid Build Coastguard Worker     uint8_t* p_vaddr = base_address_ + program_header->p_vaddr;
1199*795d594fSAndroid Build Coastguard Worker     int prot = 0;
1200*795d594fSAndroid Build Coastguard Worker     if (executable && ((program_header->p_flags & PF_X) != 0)) {
1201*795d594fSAndroid Build Coastguard Worker       prot |= PROT_EXEC;
1202*795d594fSAndroid Build Coastguard Worker     }
1203*795d594fSAndroid Build Coastguard Worker     if ((program_header->p_flags & PF_W) != 0) {
1204*795d594fSAndroid Build Coastguard Worker       prot |= PROT_WRITE;
1205*795d594fSAndroid Build Coastguard Worker     }
1206*795d594fSAndroid Build Coastguard Worker     if ((program_header->p_flags & PF_R) != 0) {
1207*795d594fSAndroid Build Coastguard Worker       prot |= PROT_READ;
1208*795d594fSAndroid Build Coastguard Worker     }
1209*795d594fSAndroid Build Coastguard Worker     int flags = 0;
1210*795d594fSAndroid Build Coastguard Worker     if (writable_) {
1211*795d594fSAndroid Build Coastguard Worker       prot |= PROT_WRITE;
1212*795d594fSAndroid Build Coastguard Worker       flags |= MAP_SHARED;
1213*795d594fSAndroid Build Coastguard Worker     } else {
1214*795d594fSAndroid Build Coastguard Worker       flags |= MAP_PRIVATE;
1215*795d594fSAndroid Build Coastguard Worker     }
1216*795d594fSAndroid Build Coastguard Worker     if (program_header->p_filesz > program_header->p_memsz) {
1217*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s",
1218*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(program_header->p_filesz),
1219*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(program_header->p_memsz),
1220*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
1221*795d594fSAndroid Build Coastguard Worker       return false;
1222*795d594fSAndroid Build Coastguard Worker     }
1223*795d594fSAndroid Build Coastguard Worker     if (program_header->p_filesz < program_header->p_memsz &&
1224*795d594fSAndroid Build Coastguard Worker         !IsAligned<kElfSegmentAlignment>(program_header->p_filesz)) {
1225*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Unsupported unaligned p_filesz < p_memsz (%" PRIu64
1226*795d594fSAndroid Build Coastguard Worker                                 " < %" PRIu64 "): %s",
1227*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(program_header->p_filesz),
1228*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(program_header->p_memsz),
1229*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
1230*795d594fSAndroid Build Coastguard Worker       return false;
1231*795d594fSAndroid Build Coastguard Worker     }
1232*795d594fSAndroid Build Coastguard Worker     if (file_length < (program_header->p_offset + program_header->p_filesz)) {
1233*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF segment "
1234*795d594fSAndroid Build Coastguard Worker                                 "%d of %" PRIu64 " bytes: '%s'", file_length, i,
1235*795d594fSAndroid Build Coastguard Worker                                 static_cast<uint64_t>(program_header->p_offset + program_header->p_filesz),
1236*795d594fSAndroid Build Coastguard Worker                                 file->GetPath().c_str());
1237*795d594fSAndroid Build Coastguard Worker       return false;
1238*795d594fSAndroid Build Coastguard Worker     }
1239*795d594fSAndroid Build Coastguard Worker     if (program_header->p_filesz != 0u) {
1240*795d594fSAndroid Build Coastguard Worker       MemMap segment =
1241*795d594fSAndroid Build Coastguard Worker           MemMap::MapFileAtAddress(p_vaddr,
1242*795d594fSAndroid Build Coastguard Worker                                    program_header->p_filesz,
1243*795d594fSAndroid Build Coastguard Worker                                    prot,
1244*795d594fSAndroid Build Coastguard Worker                                    flags,
1245*795d594fSAndroid Build Coastguard Worker                                    file->Fd(),
1246*795d594fSAndroid Build Coastguard Worker                                    program_header->p_offset,
1247*795d594fSAndroid Build Coastguard Worker                                    /* low_4gb= */ false,
1248*795d594fSAndroid Build Coastguard Worker                                    file->GetPath().c_str(),
1249*795d594fSAndroid Build Coastguard Worker                                    /* reuse= */ true,  // implies MAP_FIXED
1250*795d594fSAndroid Build Coastguard Worker                                    /* reservation= */ nullptr,
1251*795d594fSAndroid Build Coastguard Worker                                    error_msg);
1252*795d594fSAndroid Build Coastguard Worker       if (!segment.IsValid()) {
1253*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s",
1254*795d594fSAndroid Build Coastguard Worker                                   i, file->GetPath().c_str(), error_msg->c_str());
1255*795d594fSAndroid Build Coastguard Worker         return false;
1256*795d594fSAndroid Build Coastguard Worker       }
1257*795d594fSAndroid Build Coastguard Worker       if (segment.Begin() != p_vaddr) {
1258*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to map ELF file segment %d from %s at expected address %p, "
1259*795d594fSAndroid Build Coastguard Worker                                   "instead mapped to %p",
1260*795d594fSAndroid Build Coastguard Worker                                   i, file->GetPath().c_str(), p_vaddr, segment.Begin());
1261*795d594fSAndroid Build Coastguard Worker         return false;
1262*795d594fSAndroid Build Coastguard Worker       }
1263*795d594fSAndroid Build Coastguard Worker       segments_.push_back(std::move(segment));
1264*795d594fSAndroid Build Coastguard Worker     }
1265*795d594fSAndroid Build Coastguard Worker     if (program_header->p_filesz < program_header->p_memsz) {
1266*795d594fSAndroid Build Coastguard Worker       std::string name = StringPrintf("Zero-initialized segment %" PRIu64 " of ELF file %s",
1267*795d594fSAndroid Build Coastguard Worker                                       static_cast<uint64_t>(i), file->GetPath().c_str());
1268*795d594fSAndroid Build Coastguard Worker       MemMap segment = MemMap::MapAnonymous(name.c_str(),
1269*795d594fSAndroid Build Coastguard Worker                                             p_vaddr + program_header->p_filesz,
1270*795d594fSAndroid Build Coastguard Worker                                             program_header->p_memsz - program_header->p_filesz,
1271*795d594fSAndroid Build Coastguard Worker                                             prot,
1272*795d594fSAndroid Build Coastguard Worker                                             /* low_4gb= */ false,
1273*795d594fSAndroid Build Coastguard Worker                                             /* reuse= */ true,
1274*795d594fSAndroid Build Coastguard Worker                                             /* reservation= */ nullptr,
1275*795d594fSAndroid Build Coastguard Worker                                             error_msg);
1276*795d594fSAndroid Build Coastguard Worker       if (!segment.IsValid()) {
1277*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s",
1278*795d594fSAndroid Build Coastguard Worker                                   i, file->GetPath().c_str(), error_msg->c_str());
1279*795d594fSAndroid Build Coastguard Worker         return false;
1280*795d594fSAndroid Build Coastguard Worker       }
1281*795d594fSAndroid Build Coastguard Worker       if (segment.Begin() != p_vaddr) {
1282*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s "
1283*795d594fSAndroid Build Coastguard Worker                                   "at expected address %p, instead mapped to %p",
1284*795d594fSAndroid Build Coastguard Worker                                   i, file->GetPath().c_str(), p_vaddr, segment.Begin());
1285*795d594fSAndroid Build Coastguard Worker         return false;
1286*795d594fSAndroid Build Coastguard Worker       }
1287*795d594fSAndroid Build Coastguard Worker       segments_.push_back(std::move(segment));
1288*795d594fSAndroid Build Coastguard Worker     }
1289*795d594fSAndroid Build Coastguard Worker   }
1290*795d594fSAndroid Build Coastguard Worker 
1291*795d594fSAndroid Build Coastguard Worker   // Now that we are done loading, .dynamic should be in memory to find .dynstr, .dynsym, .hash
1292*795d594fSAndroid Build Coastguard Worker   uint8_t* dsptr = base_address_ + GetDynamicProgramHeader().p_vaddr;
1293*795d594fSAndroid Build Coastguard Worker   if ((dsptr < Begin() || dsptr >= End()) && !ValidPointer(dsptr)) {
1294*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("dynamic section address invalid in ELF file %s",
1295*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
1296*795d594fSAndroid Build Coastguard Worker     return false;
1297*795d594fSAndroid Build Coastguard Worker   }
1298*795d594fSAndroid Build Coastguard Worker   dynamic_section_start_ = reinterpret_cast<Elf_Dyn*>(dsptr);
1299*795d594fSAndroid Build Coastguard Worker 
1300*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetDynamicNum(); i++) {
1301*795d594fSAndroid Build Coastguard Worker     Elf_Dyn& elf_dyn = GetDynamic(i);
1302*795d594fSAndroid Build Coastguard Worker     uint8_t* d_ptr = base_address_ + elf_dyn.d_un.d_ptr;
1303*795d594fSAndroid Build Coastguard Worker     switch (elf_dyn.d_tag) {
1304*795d594fSAndroid Build Coastguard Worker       case DT_HASH: {
1305*795d594fSAndroid Build Coastguard Worker         if (!ValidPointer(d_ptr)) {
1306*795d594fSAndroid Build Coastguard Worker           *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1307*795d594fSAndroid Build Coastguard Worker                                     d_ptr, file->GetPath().c_str());
1308*795d594fSAndroid Build Coastguard Worker           return false;
1309*795d594fSAndroid Build Coastguard Worker         }
1310*795d594fSAndroid Build Coastguard Worker         hash_section_start_ = reinterpret_cast<Elf_Word*>(d_ptr);
1311*795d594fSAndroid Build Coastguard Worker         break;
1312*795d594fSAndroid Build Coastguard Worker       }
1313*795d594fSAndroid Build Coastguard Worker       case DT_STRTAB: {
1314*795d594fSAndroid Build Coastguard Worker         if (!ValidPointer(d_ptr)) {
1315*795d594fSAndroid Build Coastguard Worker           *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1316*795d594fSAndroid Build Coastguard Worker                                     d_ptr, file->GetPath().c_str());
1317*795d594fSAndroid Build Coastguard Worker           return false;
1318*795d594fSAndroid Build Coastguard Worker         }
1319*795d594fSAndroid Build Coastguard Worker         dynstr_section_start_ = reinterpret_cast<char*>(d_ptr);
1320*795d594fSAndroid Build Coastguard Worker         break;
1321*795d594fSAndroid Build Coastguard Worker       }
1322*795d594fSAndroid Build Coastguard Worker       case DT_SYMTAB: {
1323*795d594fSAndroid Build Coastguard Worker         if (!ValidPointer(d_ptr)) {
1324*795d594fSAndroid Build Coastguard Worker           *error_msg = StringPrintf("DT_HASH value %p does not refer to a loaded ELF segment of %s",
1325*795d594fSAndroid Build Coastguard Worker                                     d_ptr, file->GetPath().c_str());
1326*795d594fSAndroid Build Coastguard Worker           return false;
1327*795d594fSAndroid Build Coastguard Worker         }
1328*795d594fSAndroid Build Coastguard Worker         dynsym_section_start_ = reinterpret_cast<Elf_Sym*>(d_ptr);
1329*795d594fSAndroid Build Coastguard Worker         break;
1330*795d594fSAndroid Build Coastguard Worker       }
1331*795d594fSAndroid Build Coastguard Worker       case DT_NULL: {
1332*795d594fSAndroid Build Coastguard Worker         if (GetDynamicNum() != i+1) {
1333*795d594fSAndroid Build Coastguard Worker           *error_msg = StringPrintf("DT_NULL found after %d .dynamic entries, "
1334*795d594fSAndroid Build Coastguard Worker                                     "expected %d as implied by size of PT_DYNAMIC segment in %s",
1335*795d594fSAndroid Build Coastguard Worker                                     i + 1, GetDynamicNum(), file->GetPath().c_str());
1336*795d594fSAndroid Build Coastguard Worker           return false;
1337*795d594fSAndroid Build Coastguard Worker         }
1338*795d594fSAndroid Build Coastguard Worker         break;
1339*795d594fSAndroid Build Coastguard Worker       }
1340*795d594fSAndroid Build Coastguard Worker     }
1341*795d594fSAndroid Build Coastguard Worker   }
1342*795d594fSAndroid Build Coastguard Worker 
1343*795d594fSAndroid Build Coastguard Worker   // Check for the existence of some sections.
1344*795d594fSAndroid Build Coastguard Worker   if (!CheckSectionsExist(file, error_msg)) {
1345*795d594fSAndroid Build Coastguard Worker     return false;
1346*795d594fSAndroid Build Coastguard Worker   }
1347*795d594fSAndroid Build Coastguard Worker 
1348*795d594fSAndroid Build Coastguard Worker   return true;
1349*795d594fSAndroid Build Coastguard Worker }
1350*795d594fSAndroid Build Coastguard Worker 
1351*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
ValidPointer(const uint8_t * start) const1352*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const {
1353*795d594fSAndroid Build Coastguard Worker   for (const MemMap& segment : segments_) {
1354*795d594fSAndroid Build Coastguard Worker     if (segment.Begin() <= start && start < segment.End()) {
1355*795d594fSAndroid Build Coastguard Worker       return true;
1356*795d594fSAndroid Build Coastguard Worker     }
1357*795d594fSAndroid Build Coastguard Worker   }
1358*795d594fSAndroid Build Coastguard Worker   return false;
1359*795d594fSAndroid Build Coastguard Worker }
1360*795d594fSAndroid Build Coastguard Worker 
1361*795d594fSAndroid Build Coastguard Worker 
1362*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
FindSectionByName(const std::string & name) const1363*795d594fSAndroid Build Coastguard Worker typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName(
1364*795d594fSAndroid Build Coastguard Worker     const std::string& name) const {
1365*795d594fSAndroid Build Coastguard Worker   CHECK(!program_header_only_);
1366*795d594fSAndroid Build Coastguard Worker   Elf_Shdr* shstrtab_sec = GetSectionNameStringSection();
1367*795d594fSAndroid Build Coastguard Worker   if (shstrtab_sec == nullptr) {
1368*795d594fSAndroid Build Coastguard Worker     return nullptr;
1369*795d594fSAndroid Build Coastguard Worker   }
1370*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) {
1371*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* shdr = GetSectionHeader(i);
1372*795d594fSAndroid Build Coastguard Worker     if (shdr == nullptr) {
1373*795d594fSAndroid Build Coastguard Worker       return nullptr;
1374*795d594fSAndroid Build Coastguard Worker     }
1375*795d594fSAndroid Build Coastguard Worker     const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name);
1376*795d594fSAndroid Build Coastguard Worker     if (sec_name == nullptr) {
1377*795d594fSAndroid Build Coastguard Worker       continue;
1378*795d594fSAndroid Build Coastguard Worker     }
1379*795d594fSAndroid Build Coastguard Worker     if (name == sec_name) {
1380*795d594fSAndroid Build Coastguard Worker       return shdr;
1381*795d594fSAndroid Build Coastguard Worker     }
1382*795d594fSAndroid Build Coastguard Worker   }
1383*795d594fSAndroid Build Coastguard Worker   return nullptr;
1384*795d594fSAndroid Build Coastguard Worker }
1385*795d594fSAndroid Build Coastguard Worker 
1386*795d594fSAndroid Build Coastguard Worker template <typename ElfTypes>
Strip(File * file,std::string * error_msg)1387*795d594fSAndroid Build Coastguard Worker bool ElfFileImpl<ElfTypes>::Strip(File* file, std::string* error_msg) {
1388*795d594fSAndroid Build Coastguard Worker   // ELF files produced by MCLinker look roughly like this
1389*795d594fSAndroid Build Coastguard Worker   //
1390*795d594fSAndroid Build Coastguard Worker   // +------------+
1391*795d594fSAndroid Build Coastguard Worker   // | Elf_Ehdr   | contains number of Elf_Shdr and offset to first
1392*795d594fSAndroid Build Coastguard Worker   // +------------+
1393*795d594fSAndroid Build Coastguard Worker   // | Elf_Phdr   | program headers
1394*795d594fSAndroid Build Coastguard Worker   // | Elf_Phdr   |
1395*795d594fSAndroid Build Coastguard Worker   // | ...        |
1396*795d594fSAndroid Build Coastguard Worker   // | Elf_Phdr   |
1397*795d594fSAndroid Build Coastguard Worker   // +------------+
1398*795d594fSAndroid Build Coastguard Worker   // | section    | mixture of needed and unneeded sections
1399*795d594fSAndroid Build Coastguard Worker   // +------------+
1400*795d594fSAndroid Build Coastguard Worker   // | section    |
1401*795d594fSAndroid Build Coastguard Worker   // +------------+
1402*795d594fSAndroid Build Coastguard Worker   // | ...        |
1403*795d594fSAndroid Build Coastguard Worker   // +------------+
1404*795d594fSAndroid Build Coastguard Worker   // | section    |
1405*795d594fSAndroid Build Coastguard Worker   // +------------+
1406*795d594fSAndroid Build Coastguard Worker   // | Elf_Shdr   | section headers
1407*795d594fSAndroid Build Coastguard Worker   // | Elf_Shdr   |
1408*795d594fSAndroid Build Coastguard Worker   // | ...        | contains offset to section start
1409*795d594fSAndroid Build Coastguard Worker   // | Elf_Shdr   |
1410*795d594fSAndroid Build Coastguard Worker   // +------------+
1411*795d594fSAndroid Build Coastguard Worker   //
1412*795d594fSAndroid Build Coastguard Worker   // To strip:
1413*795d594fSAndroid Build Coastguard Worker   // - leave the Elf_Ehdr and Elf_Phdr values in place.
1414*795d594fSAndroid Build Coastguard Worker   // - walk the sections making a new set of Elf_Shdr section headers for what we want to keep
1415*795d594fSAndroid Build Coastguard Worker   // - move the sections are keeping up to fill in gaps of sections we want to strip
1416*795d594fSAndroid Build Coastguard Worker   // - write new Elf_Shdr section headers to end of file, updating Elf_Ehdr
1417*795d594fSAndroid Build Coastguard Worker   // - truncate rest of file
1418*795d594fSAndroid Build Coastguard Worker   //
1419*795d594fSAndroid Build Coastguard Worker 
1420*795d594fSAndroid Build Coastguard Worker   std::vector<Elf_Shdr> section_headers;
1421*795d594fSAndroid Build Coastguard Worker   std::vector<Elf_Word> section_headers_original_indexes;
1422*795d594fSAndroid Build Coastguard Worker   section_headers.reserve(GetSectionHeaderNum());
1423*795d594fSAndroid Build Coastguard Worker 
1424*795d594fSAndroid Build Coastguard Worker 
1425*795d594fSAndroid Build Coastguard Worker   Elf_Shdr* string_section = GetSectionNameStringSection();
1426*795d594fSAndroid Build Coastguard Worker   CHECK(string_section != nullptr);
1427*795d594fSAndroid Build Coastguard Worker   for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) {
1428*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* sh = GetSectionHeader(i);
1429*795d594fSAndroid Build Coastguard Worker     CHECK(sh != nullptr);
1430*795d594fSAndroid Build Coastguard Worker     const char* name = GetString(*string_section, sh->sh_name);
1431*795d594fSAndroid Build Coastguard Worker     if (name == nullptr) {
1432*795d594fSAndroid Build Coastguard Worker       CHECK_EQ(0U, i);
1433*795d594fSAndroid Build Coastguard Worker       section_headers.push_back(*sh);
1434*795d594fSAndroid Build Coastguard Worker       section_headers_original_indexes.push_back(0);
1435*795d594fSAndroid Build Coastguard Worker       continue;
1436*795d594fSAndroid Build Coastguard Worker     }
1437*795d594fSAndroid Build Coastguard Worker     std::string_view name_sv(name);
1438*795d594fSAndroid Build Coastguard Worker     if (name_sv.starts_with(".debug") || (name_sv == ".strtab") || (name_sv == ".symtab")) {
1439*795d594fSAndroid Build Coastguard Worker       continue;
1440*795d594fSAndroid Build Coastguard Worker     }
1441*795d594fSAndroid Build Coastguard Worker     section_headers.push_back(*sh);
1442*795d594fSAndroid Build Coastguard Worker     section_headers_original_indexes.push_back(i);
1443*795d594fSAndroid Build Coastguard Worker   }
1444*795d594fSAndroid Build Coastguard Worker   CHECK_NE(0U, section_headers.size());
1445*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());
1446*795d594fSAndroid Build Coastguard Worker 
1447*795d594fSAndroid Build Coastguard Worker   // section 0 is the null section, sections start at offset of first section
1448*795d594fSAndroid Build Coastguard Worker   CHECK(GetSectionHeader(1) != nullptr);
1449*795d594fSAndroid Build Coastguard Worker   Elf_Off offset = GetSectionHeader(1)->sh_offset;
1450*795d594fSAndroid Build Coastguard Worker   for (size_t i = 1; i < section_headers.size(); i++) {
1451*795d594fSAndroid Build Coastguard Worker     Elf_Shdr& new_sh = section_headers[i];
1452*795d594fSAndroid Build Coastguard Worker     Elf_Shdr* old_sh = GetSectionHeader(section_headers_original_indexes[i]);
1453*795d594fSAndroid Build Coastguard Worker     CHECK(old_sh != nullptr);
1454*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(new_sh.sh_name, old_sh->sh_name);
1455*795d594fSAndroid Build Coastguard Worker     if (old_sh->sh_addralign > 1) {
1456*795d594fSAndroid Build Coastguard Worker       offset = RoundUp(offset, old_sh->sh_addralign);
1457*795d594fSAndroid Build Coastguard Worker     }
1458*795d594fSAndroid Build Coastguard Worker     if (old_sh->sh_offset == offset) {
1459*795d594fSAndroid Build Coastguard Worker       // already in place
1460*795d594fSAndroid Build Coastguard Worker       offset += old_sh->sh_size;
1461*795d594fSAndroid Build Coastguard Worker       continue;
1462*795d594fSAndroid Build Coastguard Worker     }
1463*795d594fSAndroid Build Coastguard Worker     // shift section earlier
1464*795d594fSAndroid Build Coastguard Worker     memmove(Begin() + offset,
1465*795d594fSAndroid Build Coastguard Worker             Begin() + old_sh->sh_offset,
1466*795d594fSAndroid Build Coastguard Worker             old_sh->sh_size);
1467*795d594fSAndroid Build Coastguard Worker     new_sh.sh_offset = offset;
1468*795d594fSAndroid Build Coastguard Worker     offset += old_sh->sh_size;
1469*795d594fSAndroid Build Coastguard Worker   }
1470*795d594fSAndroid Build Coastguard Worker 
1471*795d594fSAndroid Build Coastguard Worker   Elf_Off shoff = offset;
1472*795d594fSAndroid Build Coastguard Worker   size_t section_headers_size_in_bytes = section_headers.size() * sizeof(Elf_Shdr);
1473*795d594fSAndroid Build Coastguard Worker   memcpy(Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
1474*795d594fSAndroid Build Coastguard Worker   offset += section_headers_size_in_bytes;
1475*795d594fSAndroid Build Coastguard Worker 
1476*795d594fSAndroid Build Coastguard Worker   GetHeader().e_shnum = section_headers.size();
1477*795d594fSAndroid Build Coastguard Worker   GetHeader().e_shoff = shoff;
1478*795d594fSAndroid Build Coastguard Worker   int result = ftruncate(file->Fd(), offset);
1479*795d594fSAndroid Build Coastguard Worker   if (result != 0) {
1480*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to truncate while stripping ELF file: '%s': %s",
1481*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(), strerror(errno));
1482*795d594fSAndroid Build Coastguard Worker     return false;
1483*795d594fSAndroid Build Coastguard Worker   }
1484*795d594fSAndroid Build Coastguard Worker   return true;
1485*795d594fSAndroid Build Coastguard Worker }
1486*795d594fSAndroid Build Coastguard Worker 
1487*795d594fSAndroid Build Coastguard Worker // Explicit instantiations
1488*795d594fSAndroid Build Coastguard Worker template class ElfFileImpl<ElfTypes32>;
1489*795d594fSAndroid Build Coastguard Worker template class ElfFileImpl<ElfTypes64>;
1490*795d594fSAndroid Build Coastguard Worker 
ElfFile(ElfFileImpl32 * elf32)1491*795d594fSAndroid Build Coastguard Worker ElfFile::ElfFile(ElfFileImpl32* elf32) : elf32_(elf32), elf64_(nullptr) {
1492*795d594fSAndroid Build Coastguard Worker }
1493*795d594fSAndroid Build Coastguard Worker 
ElfFile(ElfFileImpl64 * elf64)1494*795d594fSAndroid Build Coastguard Worker ElfFile::ElfFile(ElfFileImpl64* elf64) : elf32_(nullptr), elf64_(elf64) {
1495*795d594fSAndroid Build Coastguard Worker }
1496*795d594fSAndroid Build Coastguard Worker 
~ElfFile()1497*795d594fSAndroid Build Coastguard Worker ElfFile::~ElfFile() {
1498*795d594fSAndroid Build Coastguard Worker   // Should never have 32 and 64-bit impls.
1499*795d594fSAndroid Build Coastguard Worker   CHECK_NE(elf32_.get() == nullptr, elf64_.get() == nullptr);
1500*795d594fSAndroid Build Coastguard Worker }
1501*795d594fSAndroid Build Coastguard Worker 
Open(File * file,bool writable,bool program_header_only,bool low_4gb,std::string * error_msg)1502*795d594fSAndroid Build Coastguard Worker ElfFile* ElfFile::Open(File* file,
1503*795d594fSAndroid Build Coastguard Worker                        bool writable,
1504*795d594fSAndroid Build Coastguard Worker                        bool program_header_only,
1505*795d594fSAndroid Build Coastguard Worker                        bool low_4gb,
1506*795d594fSAndroid Build Coastguard Worker                        /*out*/std::string* error_msg) {
1507*795d594fSAndroid Build Coastguard Worker   if (file->GetLength() < EI_NIDENT) {
1508*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1509*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
1510*795d594fSAndroid Build Coastguard Worker     return nullptr;
1511*795d594fSAndroid Build Coastguard Worker   }
1512*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapFile(EI_NIDENT,
1513*795d594fSAndroid Build Coastguard Worker                                PROT_READ,
1514*795d594fSAndroid Build Coastguard Worker                                MAP_PRIVATE,
1515*795d594fSAndroid Build Coastguard Worker                                file->Fd(),
1516*795d594fSAndroid Build Coastguard Worker                                0,
1517*795d594fSAndroid Build Coastguard Worker                                low_4gb,
1518*795d594fSAndroid Build Coastguard Worker                                file->GetPath().c_str(),
1519*795d594fSAndroid Build Coastguard Worker                                error_msg);
1520*795d594fSAndroid Build Coastguard Worker   if (!map.IsValid() || map.Size() != EI_NIDENT) {
1521*795d594fSAndroid Build Coastguard Worker     return nullptr;
1522*795d594fSAndroid Build Coastguard Worker   }
1523*795d594fSAndroid Build Coastguard Worker   uint8_t* header = map.Begin();
1524*795d594fSAndroid Build Coastguard Worker   if (header[EI_CLASS] == ELFCLASS64) {
1525*795d594fSAndroid Build Coastguard Worker     ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1526*795d594fSAndroid Build Coastguard Worker                                                        writable,
1527*795d594fSAndroid Build Coastguard Worker                                                        program_header_only,
1528*795d594fSAndroid Build Coastguard Worker                                                        low_4gb,
1529*795d594fSAndroid Build Coastguard Worker                                                        error_msg);
1530*795d594fSAndroid Build Coastguard Worker     if (elf_file_impl == nullptr) {
1531*795d594fSAndroid Build Coastguard Worker       return nullptr;
1532*795d594fSAndroid Build Coastguard Worker     }
1533*795d594fSAndroid Build Coastguard Worker     return new ElfFile(elf_file_impl);
1534*795d594fSAndroid Build Coastguard Worker   } else if (header[EI_CLASS] == ELFCLASS32) {
1535*795d594fSAndroid Build Coastguard Worker     ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1536*795d594fSAndroid Build Coastguard Worker                                                        writable,
1537*795d594fSAndroid Build Coastguard Worker                                                        program_header_only,
1538*795d594fSAndroid Build Coastguard Worker                                                        low_4gb,
1539*795d594fSAndroid Build Coastguard Worker                                                        error_msg);
1540*795d594fSAndroid Build Coastguard Worker     if (elf_file_impl == nullptr) {
1541*795d594fSAndroid Build Coastguard Worker       return nullptr;
1542*795d594fSAndroid Build Coastguard Worker     }
1543*795d594fSAndroid Build Coastguard Worker     return new ElfFile(elf_file_impl);
1544*795d594fSAndroid Build Coastguard Worker   } else {
1545*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1546*795d594fSAndroid Build Coastguard Worker                               ELFCLASS32, ELFCLASS64,
1547*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
1548*795d594fSAndroid Build Coastguard Worker                               header[EI_CLASS]);
1549*795d594fSAndroid Build Coastguard Worker     return nullptr;
1550*795d594fSAndroid Build Coastguard Worker   }
1551*795d594fSAndroid Build Coastguard Worker }
1552*795d594fSAndroid Build Coastguard Worker 
Open(File * file,int mmap_prot,int mmap_flags,std::string * error_msg)1553*795d594fSAndroid Build Coastguard Worker ElfFile* ElfFile::Open(File* file, int mmap_prot, int mmap_flags, /*out*/std::string* error_msg) {
1554*795d594fSAndroid Build Coastguard Worker   // low_4gb support not required for this path.
1555*795d594fSAndroid Build Coastguard Worker   constexpr bool low_4gb = false;
1556*795d594fSAndroid Build Coastguard Worker   if (file->GetLength() < EI_NIDENT) {
1557*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("File %s is too short to be a valid ELF file",
1558*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str());
1559*795d594fSAndroid Build Coastguard Worker     return nullptr;
1560*795d594fSAndroid Build Coastguard Worker   }
1561*795d594fSAndroid Build Coastguard Worker   MemMap map = MemMap::MapFile(EI_NIDENT,
1562*795d594fSAndroid Build Coastguard Worker                                PROT_READ,
1563*795d594fSAndroid Build Coastguard Worker                                MAP_PRIVATE,
1564*795d594fSAndroid Build Coastguard Worker                                file->Fd(),
1565*795d594fSAndroid Build Coastguard Worker                                /* start= */ 0,
1566*795d594fSAndroid Build Coastguard Worker                                low_4gb,
1567*795d594fSAndroid Build Coastguard Worker                                file->GetPath().c_str(),
1568*795d594fSAndroid Build Coastguard Worker                                error_msg);
1569*795d594fSAndroid Build Coastguard Worker   if (!map.IsValid() || map.Size() != EI_NIDENT) {
1570*795d594fSAndroid Build Coastguard Worker     return nullptr;
1571*795d594fSAndroid Build Coastguard Worker   }
1572*795d594fSAndroid Build Coastguard Worker   uint8_t* header = map.Begin();
1573*795d594fSAndroid Build Coastguard Worker   if (header[EI_CLASS] == ELFCLASS64) {
1574*795d594fSAndroid Build Coastguard Worker     ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file,
1575*795d594fSAndroid Build Coastguard Worker                                                        mmap_prot,
1576*795d594fSAndroid Build Coastguard Worker                                                        mmap_flags,
1577*795d594fSAndroid Build Coastguard Worker                                                        low_4gb,
1578*795d594fSAndroid Build Coastguard Worker                                                        error_msg);
1579*795d594fSAndroid Build Coastguard Worker     if (elf_file_impl == nullptr) {
1580*795d594fSAndroid Build Coastguard Worker       return nullptr;
1581*795d594fSAndroid Build Coastguard Worker     }
1582*795d594fSAndroid Build Coastguard Worker     return new ElfFile(elf_file_impl);
1583*795d594fSAndroid Build Coastguard Worker   } else if (header[EI_CLASS] == ELFCLASS32) {
1584*795d594fSAndroid Build Coastguard Worker     ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file,
1585*795d594fSAndroid Build Coastguard Worker                                                        mmap_prot,
1586*795d594fSAndroid Build Coastguard Worker                                                        mmap_flags,
1587*795d594fSAndroid Build Coastguard Worker                                                        low_4gb,
1588*795d594fSAndroid Build Coastguard Worker                                                        error_msg);
1589*795d594fSAndroid Build Coastguard Worker     if (elf_file_impl == nullptr) {
1590*795d594fSAndroid Build Coastguard Worker       return nullptr;
1591*795d594fSAndroid Build Coastguard Worker     }
1592*795d594fSAndroid Build Coastguard Worker     return new ElfFile(elf_file_impl);
1593*795d594fSAndroid Build Coastguard Worker   } else {
1594*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find expected EI_CLASS value %d or %d in %s, found %d",
1595*795d594fSAndroid Build Coastguard Worker                               ELFCLASS32, ELFCLASS64,
1596*795d594fSAndroid Build Coastguard Worker                               file->GetPath().c_str(),
1597*795d594fSAndroid Build Coastguard Worker                               header[EI_CLASS]);
1598*795d594fSAndroid Build Coastguard Worker     return nullptr;
1599*795d594fSAndroid Build Coastguard Worker   }
1600*795d594fSAndroid Build Coastguard Worker }
1601*795d594fSAndroid Build Coastguard Worker 
1602*795d594fSAndroid Build Coastguard Worker #define DELEGATE_TO_IMPL(func, ...) \
1603*795d594fSAndroid Build Coastguard Worker   if (elf64_.get() != nullptr) { \
1604*795d594fSAndroid Build Coastguard Worker     return elf64_->func(__VA_ARGS__); \
1605*795d594fSAndroid Build Coastguard Worker   } else { \
1606*795d594fSAndroid Build Coastguard Worker     DCHECK(elf32_.get() != nullptr); \
1607*795d594fSAndroid Build Coastguard Worker     return elf32_->func(__VA_ARGS__); \
1608*795d594fSAndroid Build Coastguard Worker   }
1609*795d594fSAndroid Build Coastguard Worker 
Load(File * file,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1610*795d594fSAndroid Build Coastguard Worker bool ElfFile::Load(File* file,
1611*795d594fSAndroid Build Coastguard Worker                    bool executable,
1612*795d594fSAndroid Build Coastguard Worker                    bool low_4gb,
1613*795d594fSAndroid Build Coastguard Worker                    /*inout*/MemMap* reservation,
1614*795d594fSAndroid Build Coastguard Worker                    /*out*/std::string* error_msg) {
1615*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(Load, file, executable, low_4gb, reservation, error_msg);
1616*795d594fSAndroid Build Coastguard Worker }
1617*795d594fSAndroid Build Coastguard Worker 
FindDynamicSymbolAddress(const std::string & symbol_name) const1618*795d594fSAndroid Build Coastguard Worker const uint8_t* ElfFile::FindDynamicSymbolAddress(const std::string& symbol_name) const {
1619*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(FindDynamicSymbolAddress, symbol_name);
1620*795d594fSAndroid Build Coastguard Worker }
1621*795d594fSAndroid Build Coastguard Worker 
Size() const1622*795d594fSAndroid Build Coastguard Worker size_t ElfFile::Size() const {
1623*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(Size);
1624*795d594fSAndroid Build Coastguard Worker }
1625*795d594fSAndroid Build Coastguard Worker 
Begin() const1626*795d594fSAndroid Build Coastguard Worker uint8_t* ElfFile::Begin() const {
1627*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(Begin);
1628*795d594fSAndroid Build Coastguard Worker }
1629*795d594fSAndroid Build Coastguard Worker 
End() const1630*795d594fSAndroid Build Coastguard Worker uint8_t* ElfFile::End() const {
1631*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(End);
1632*795d594fSAndroid Build Coastguard Worker }
1633*795d594fSAndroid Build Coastguard Worker 
GetFilePath() const1634*795d594fSAndroid Build Coastguard Worker const std::string& ElfFile::GetFilePath() const {
1635*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(GetFilePath);
1636*795d594fSAndroid Build Coastguard Worker }
1637*795d594fSAndroid Build Coastguard Worker 
GetSectionOffsetAndSize(const char * section_name,uint64_t * offset,uint64_t * size) const1638*795d594fSAndroid Build Coastguard Worker bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset,
1639*795d594fSAndroid Build Coastguard Worker                                       uint64_t* size) const {
1640*795d594fSAndroid Build Coastguard Worker   if (elf32_.get() == nullptr) {
1641*795d594fSAndroid Build Coastguard Worker     CHECK(elf64_.get() != nullptr);
1642*795d594fSAndroid Build Coastguard Worker 
1643*795d594fSAndroid Build Coastguard Worker     Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name);
1644*795d594fSAndroid Build Coastguard Worker     if (shdr == nullptr) {
1645*795d594fSAndroid Build Coastguard Worker       return false;
1646*795d594fSAndroid Build Coastguard Worker     }
1647*795d594fSAndroid Build Coastguard Worker     if (offset != nullptr) {
1648*795d594fSAndroid Build Coastguard Worker       *offset = shdr->sh_offset;
1649*795d594fSAndroid Build Coastguard Worker     }
1650*795d594fSAndroid Build Coastguard Worker     if (size != nullptr) {
1651*795d594fSAndroid Build Coastguard Worker       *size = shdr->sh_size;
1652*795d594fSAndroid Build Coastguard Worker     }
1653*795d594fSAndroid Build Coastguard Worker     return true;
1654*795d594fSAndroid Build Coastguard Worker   } else {
1655*795d594fSAndroid Build Coastguard Worker     Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name);
1656*795d594fSAndroid Build Coastguard Worker     if (shdr == nullptr) {
1657*795d594fSAndroid Build Coastguard Worker       return false;
1658*795d594fSAndroid Build Coastguard Worker     }
1659*795d594fSAndroid Build Coastguard Worker     if (offset != nullptr) {
1660*795d594fSAndroid Build Coastguard Worker       *offset = shdr->sh_offset;
1661*795d594fSAndroid Build Coastguard Worker     }
1662*795d594fSAndroid Build Coastguard Worker     if (size != nullptr) {
1663*795d594fSAndroid Build Coastguard Worker       *size = shdr->sh_size;
1664*795d594fSAndroid Build Coastguard Worker     }
1665*795d594fSAndroid Build Coastguard Worker     return true;
1666*795d594fSAndroid Build Coastguard Worker   }
1667*795d594fSAndroid Build Coastguard Worker }
1668*795d594fSAndroid Build Coastguard Worker 
HasSection(const std::string & name) const1669*795d594fSAndroid Build Coastguard Worker bool ElfFile::HasSection(const std::string& name) const {
1670*795d594fSAndroid Build Coastguard Worker   if (elf64_.get() != nullptr) {
1671*795d594fSAndroid Build Coastguard Worker     return elf64_->FindSectionByName(name) != nullptr;
1672*795d594fSAndroid Build Coastguard Worker   } else {
1673*795d594fSAndroid Build Coastguard Worker     return elf32_->FindSectionByName(name) != nullptr;
1674*795d594fSAndroid Build Coastguard Worker   }
1675*795d594fSAndroid Build Coastguard Worker }
1676*795d594fSAndroid Build Coastguard Worker 
FindSymbolAddress(unsigned section_type,const std::string & symbol_name,bool build_map)1677*795d594fSAndroid Build Coastguard Worker uint64_t ElfFile::FindSymbolAddress(unsigned section_type,
1678*795d594fSAndroid Build Coastguard Worker                                     const std::string& symbol_name,
1679*795d594fSAndroid Build Coastguard Worker                                     bool build_map) {
1680*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map);
1681*795d594fSAndroid Build Coastguard Worker }
1682*795d594fSAndroid Build Coastguard Worker 
GetLoadedSize(size_t * size,std::string * error_msg) const1683*795d594fSAndroid Build Coastguard Worker bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const {
1684*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg);
1685*795d594fSAndroid Build Coastguard Worker }
1686*795d594fSAndroid Build Coastguard Worker 
GetElfSegmentAlignmentFromFile() const1687*795d594fSAndroid Build Coastguard Worker size_t ElfFile::GetElfSegmentAlignmentFromFile() const {
1688*795d594fSAndroid Build Coastguard Worker   DELEGATE_TO_IMPL(GetElfSegmentAlignmentFromFile);
1689*795d594fSAndroid Build Coastguard Worker }
1690*795d594fSAndroid Build Coastguard Worker 
GetBaseAddress() const1691*795d594fSAndroid Build Coastguard Worker const uint8_t* ElfFile::GetBaseAddress() const { DELEGATE_TO_IMPL(GetBaseAddress); }
1692*795d594fSAndroid Build Coastguard Worker 
Strip(File * file,std::string * error_msg)1693*795d594fSAndroid Build Coastguard Worker bool ElfFile::Strip(File* file, std::string* error_msg) {
1694*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file, true, false, /*low_4gb=*/false, error_msg));
1695*795d594fSAndroid Build Coastguard Worker   if (elf_file.get() == nullptr) {
1696*795d594fSAndroid Build Coastguard Worker     return false;
1697*795d594fSAndroid Build Coastguard Worker   }
1698*795d594fSAndroid Build Coastguard Worker 
1699*795d594fSAndroid Build Coastguard Worker   if (elf_file->elf64_.get() != nullptr) {
1700*795d594fSAndroid Build Coastguard Worker     return elf_file->elf64_->Strip(file, error_msg);
1701*795d594fSAndroid Build Coastguard Worker   } else {
1702*795d594fSAndroid Build Coastguard Worker     return elf_file->elf32_->Strip(file, error_msg);
1703*795d594fSAndroid Build Coastguard Worker   }
1704*795d594fSAndroid Build Coastguard Worker }
1705*795d594fSAndroid Build Coastguard Worker 
1706*795d594fSAndroid Build Coastguard Worker }  // namespace art
1707