• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <elf.h>
18 #include <stdint.h>
19 
20 #include <memory>
21 #include <string>
22 #include <utility>
23 
24 #include <7zCrc.h>
25 #include <Xz.h>
26 #include <XzCrc64.h>
27 
28 #include <unwindstack/DwarfError.h>
29 #include <unwindstack/DwarfSection.h>
30 #include <unwindstack/ElfInterface.h>
31 #include <unwindstack/Log.h>
32 #include <unwindstack/Memory.h>
33 #include <unwindstack/Regs.h>
34 
35 #include "DwarfDebugFrame.h"
36 #include "DwarfEhFrame.h"
37 #include "DwarfEhFrameWithHdr.h"
38 #include "Symbols.h"
39 
40 namespace unwindstack {
41 
~ElfInterface()42 ElfInterface::~ElfInterface() {
43   for (auto symbol : symbols_) {
44     delete symbol;
45   }
46 }
47 
IsValidPc(uint64_t pc)48 bool ElfInterface::IsValidPc(uint64_t pc) {
49   if (!pt_loads_.empty()) {
50     for (auto& entry : pt_loads_) {
51       uint64_t start = entry.second.table_offset;
52       uint64_t end = start + entry.second.table_size;
53       if (pc >= start && pc < end) {
54         return true;
55       }
56     }
57     return false;
58   }
59 
60   // No PT_LOAD data, look for a fde for this pc in the section data.
61   if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) {
62     return true;
63   }
64 
65   if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) {
66     return true;
67   }
68 
69   return false;
70 }
71 
CreateGnuDebugdataMemory()72 Memory* ElfInterface::CreateGnuDebugdataMemory() {
73   if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) {
74     return nullptr;
75   }
76 
77   // TODO: Only call these initialization functions once.
78   CrcGenerateTable();
79   Crc64GenerateTable();
80 
81   std::vector<uint8_t> src(gnu_debugdata_size_);
82   if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
83     gnu_debugdata_offset_ = 0;
84     gnu_debugdata_size_ = static_cast<uint64_t>(-1);
85     return nullptr;
86   }
87 
88   ISzAlloc alloc;
89   CXzUnpacker state;
90   alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
91   alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
92 
93   XzUnpacker_Construct(&state, &alloc);
94 
95   std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
96   int return_val;
97   size_t src_offset = 0;
98   size_t dst_offset = 0;
99   ECoderStatus status;
100   dst->Resize(5 * gnu_debugdata_size_);
101   do {
102     size_t src_remaining = src.size() - src_offset;
103     size_t dst_remaining = dst->Size() - dst_offset;
104     if (dst_remaining < 2 * gnu_debugdata_size_) {
105       dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
106       dst_remaining += 2 * gnu_debugdata_size_;
107     }
108     return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
109                                  &src_remaining, true, CODER_FINISH_ANY, &status);
110     src_offset += src_remaining;
111     dst_offset += dst_remaining;
112   } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
113   XzUnpacker_Free(&state);
114   if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
115     gnu_debugdata_offset_ = 0;
116     gnu_debugdata_size_ = static_cast<uint64_t>(-1);
117     return nullptr;
118   }
119 
120   // Shrink back down to the exact size.
121   dst->Resize(dst_offset);
122 
123   return dst.release();
124 }
125 
126 template <typename AddressType>
InitHeadersWithTemplate(uint64_t load_bias)127 void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
128   if (eh_frame_hdr_offset_ != 0) {
129     eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
130     if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, load_bias)) {
131       eh_frame_.reset(nullptr);
132     }
133   }
134 
135   if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) {
136     // If there is an eh_frame section without an eh_frame_hdr section,
137     // or using the frame hdr object failed to init.
138     eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
139     if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, load_bias)) {
140       eh_frame_.reset(nullptr);
141     }
142   }
143 
144   if (eh_frame_.get() == nullptr) {
145     eh_frame_hdr_offset_ = 0;
146     eh_frame_hdr_size_ = static_cast<uint64_t>(-1);
147     eh_frame_offset_ = 0;
148     eh_frame_size_ = static_cast<uint64_t>(-1);
149   }
150 
151   if (debug_frame_offset_ != 0) {
152     debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
153     if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, load_bias)) {
154       debug_frame_.reset(nullptr);
155       debug_frame_offset_ = 0;
156       debug_frame_size_ = static_cast<uint64_t>(-1);
157     }
158   }
159 }
160 
161 template <typename EhdrType, typename PhdrType, typename ShdrType>
ReadAllHeaders(uint64_t * load_bias)162 bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
163   EhdrType ehdr;
164   if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
165     last_error_.code = ERROR_MEMORY_INVALID;
166     last_error_.address = 0;
167     return false;
168   }
169 
170   // If we have enough information that this is an elf file, then allow
171   // malformed program and section headers.
172   ReadProgramHeaders<EhdrType, PhdrType>(ehdr, load_bias);
173   ReadSectionHeaders<EhdrType, ShdrType>(ehdr);
174   return true;
175 }
176 
177 template <typename EhdrType, typename PhdrType>
GetLoadBias(Memory * memory)178 uint64_t ElfInterface::GetLoadBias(Memory* memory) {
179   EhdrType ehdr;
180   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
181     return false;
182   }
183 
184   uint64_t offset = ehdr.e_phoff;
185   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
186     PhdrType phdr;
187     if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
188       return 0;
189     }
190     if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
191       return phdr.p_vaddr;
192     }
193   }
194   return 0;
195 }
196 
197 template <typename EhdrType, typename PhdrType>
ReadProgramHeaders(const EhdrType & ehdr,uint64_t * load_bias)198 void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias) {
199   uint64_t offset = ehdr.e_phoff;
200   for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
201     PhdrType phdr;
202     if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) {
203       return;
204     }
205 
206     switch (phdr.p_type) {
207     case PT_LOAD:
208     {
209       if ((phdr.p_flags & PF_X) == 0) {
210         continue;
211       }
212 
213       pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
214                                           static_cast<size_t>(phdr.p_memsz)};
215       if (phdr.p_offset == 0) {
216         *load_bias = phdr.p_vaddr;
217       }
218       break;
219     }
220 
221     case PT_GNU_EH_FRAME:
222       // This is really the pointer to the .eh_frame_hdr section.
223       eh_frame_hdr_offset_ = phdr.p_offset;
224       eh_frame_hdr_size_ = phdr.p_memsz;
225       break;
226 
227     case PT_DYNAMIC:
228       dynamic_offset_ = phdr.p_offset;
229       dynamic_vaddr_ = phdr.p_vaddr;
230       dynamic_size_ = phdr.p_memsz;
231       break;
232 
233     default:
234       HandleUnknownType(phdr.p_type, phdr.p_offset, phdr.p_filesz);
235       break;
236     }
237   }
238 }
239 
240 template <typename NhdrType>
ReadBuildID()241 std::string ElfInterface::ReadBuildID() {
242   // Ensure there is no overflow in any of the calulations below.
243   uint64_t tmp;
244   if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) {
245     return "";
246   }
247 
248   uint64_t offset = 0;
249   while (offset < gnu_build_id_size_) {
250     if (gnu_build_id_size_ - offset < sizeof(NhdrType)) {
251       return "";
252     }
253     NhdrType hdr;
254     if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) {
255       return "";
256     }
257     offset += sizeof(hdr);
258 
259     if (gnu_build_id_size_ - offset < hdr.n_namesz) {
260       return "";
261     }
262     if (hdr.n_namesz > 0) {
263       std::string name(hdr.n_namesz, '\0');
264       if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) {
265         return "";
266       }
267 
268       // Trim trailing \0 as GNU is stored as a C string in the ELF file.
269       if (name.back() == '\0')
270         name.resize(name.size() - 1);
271 
272       // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
273       offset += (hdr.n_namesz + 3) & ~3;
274 
275       if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
276         if (gnu_build_id_size_ - offset < hdr.n_descsz || hdr.n_descsz == 0) {
277           return "";
278         }
279         std::string build_id(hdr.n_descsz, '\0');
280         if (memory_->ReadFully(gnu_build_id_offset_ + offset, &build_id[0], hdr.n_descsz)) {
281           return build_id;
282         }
283         return "";
284       }
285     }
286     // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
287     offset += (hdr.n_descsz + 3) & ~3;
288   }
289   return "";
290 }
291 
292 template <typename EhdrType, typename ShdrType>
ReadSectionHeaders(const EhdrType & ehdr)293 void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
294   uint64_t offset = ehdr.e_shoff;
295   uint64_t sec_offset = 0;
296   uint64_t sec_size = 0;
297 
298   // Get the location of the section header names.
299   // If something is malformed in the header table data, we aren't going
300   // to terminate, we'll simply ignore this part.
301   ShdrType shdr;
302   if (ehdr.e_shstrndx < ehdr.e_shnum) {
303     uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
304     if (memory_->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
305       sec_offset = shdr.sh_offset;
306       sec_size = shdr.sh_size;
307     }
308   }
309 
310   // Skip the first header, it's always going to be NULL.
311   offset += ehdr.e_shentsize;
312   for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
313     if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
314       return;
315     }
316 
317     if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
318       // Need to go get the information about the section that contains
319       // the string terminated names.
320       ShdrType str_shdr;
321       if (shdr.sh_link >= ehdr.e_shnum) {
322         continue;
323       }
324       uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
325       if (!memory_->ReadFully(str_offset, &str_shdr, sizeof(str_shdr))) {
326         continue;
327       }
328       if (str_shdr.sh_type != SHT_STRTAB) {
329         continue;
330       }
331       symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
332                                      str_shdr.sh_offset, str_shdr.sh_size));
333     } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
334       // Look for the .debug_frame and .gnu_debugdata.
335       if (shdr.sh_name < sec_size) {
336         std::string name;
337         if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
338           uint64_t* offset_ptr = nullptr;
339           uint64_t* size_ptr = nullptr;
340           if (name == ".debug_frame") {
341             offset_ptr = &debug_frame_offset_;
342             size_ptr = &debug_frame_size_;
343           } else if (name == ".gnu_debugdata") {
344             offset_ptr = &gnu_debugdata_offset_;
345             size_ptr = &gnu_debugdata_size_;
346           } else if (name == ".eh_frame") {
347             offset_ptr = &eh_frame_offset_;
348             size_ptr = &eh_frame_size_;
349           } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") {
350             offset_ptr = &eh_frame_hdr_offset_;
351             size_ptr = &eh_frame_hdr_size_;
352           }
353           if (offset_ptr != nullptr) {
354             *offset_ptr = shdr.sh_offset;
355             *size_ptr = shdr.sh_size;
356           }
357         }
358       }
359     } else if (shdr.sh_type == SHT_STRTAB) {
360       // In order to read soname, keep track of address to offset mapping.
361       strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
362                                                             static_cast<uint64_t>(shdr.sh_offset)));
363     } else if (shdr.sh_type == SHT_NOTE) {
364       if (shdr.sh_name < sec_size) {
365         std::string name;
366         if (memory_->ReadString(sec_offset + shdr.sh_name, &name) &&
367             name == ".note.gnu.build-id") {
368           gnu_build_id_offset_ = shdr.sh_offset;
369           gnu_build_id_size_ = shdr.sh_size;
370         }
371       }
372     }
373   }
374 }
375 
376 template <typename DynType>
GetSonameWithTemplate()377 std::string ElfInterface::GetSonameWithTemplate() {
378   if (soname_type_ == SONAME_INVALID) {
379     return "";
380   }
381   if (soname_type_ == SONAME_VALID) {
382     return soname_;
383   }
384 
385   soname_type_ = SONAME_INVALID;
386 
387   uint64_t soname_offset = 0;
388   uint64_t strtab_addr = 0;
389   uint64_t strtab_size = 0;
390 
391   // Find the soname location from the dynamic headers section.
392   DynType dyn;
393   uint64_t offset = dynamic_offset_;
394   uint64_t max_offset = offset + dynamic_size_;
395   for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
396     if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
397       last_error_.code = ERROR_MEMORY_INVALID;
398       last_error_.address = offset;
399       return "";
400     }
401 
402     if (dyn.d_tag == DT_STRTAB) {
403       strtab_addr = dyn.d_un.d_ptr;
404     } else if (dyn.d_tag == DT_STRSZ) {
405       strtab_size = dyn.d_un.d_val;
406     } else if (dyn.d_tag == DT_SONAME) {
407       soname_offset = dyn.d_un.d_val;
408     } else if (dyn.d_tag == DT_NULL) {
409       break;
410     }
411   }
412 
413   // Need to map the strtab address to the real offset.
414   for (const auto& entry : strtabs_) {
415     if (entry.first == strtab_addr) {
416       soname_offset = entry.second + soname_offset;
417       if (soname_offset >= entry.second + strtab_size) {
418         return "";
419       }
420       if (!memory_->ReadString(soname_offset, &soname_)) {
421         return "";
422       }
423       soname_type_ = SONAME_VALID;
424       return soname_;
425     }
426   }
427   return "";
428 }
429 
430 template <typename SymType>
GetFunctionNameWithTemplate(uint64_t addr,std::string * name,uint64_t * func_offset)431 bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name,
432                                                uint64_t* func_offset) {
433   if (symbols_.empty()) {
434     return false;
435   }
436 
437   for (const auto symbol : symbols_) {
438     if (symbol->GetName<SymType>(addr, memory_, name, func_offset)) {
439       return true;
440     }
441   }
442   return false;
443 }
444 
445 template <typename SymType>
GetGlobalVariableWithTemplate(const std::string & name,uint64_t * memory_address)446 bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) {
447   if (symbols_.empty()) {
448     return false;
449   }
450 
451   for (const auto symbol : symbols_) {
452     if (symbol->GetGlobal<SymType>(memory_, name, memory_address)) {
453       return true;
454     }
455   }
456   return false;
457 }
458 
Step(uint64_t pc,Regs * regs,Memory * process_memory,bool * finished)459 bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
460   last_error_.code = ERROR_NONE;
461   last_error_.address = 0;
462 
463   // Try the debug_frame first since it contains the most specific unwind
464   // information.
465   DwarfSection* debug_frame = debug_frame_.get();
466   if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) {
467     return true;
468   }
469 
470   // Try the eh_frame next.
471   DwarfSection* eh_frame = eh_frame_.get();
472   if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) {
473     return true;
474   }
475 
476   if (gnu_debugdata_interface_ != nullptr &&
477       gnu_debugdata_interface_->Step(pc, regs, process_memory, finished)) {
478     return true;
479   }
480 
481   // Set the error code based on the first error encountered.
482   DwarfSection* section = nullptr;
483   if (debug_frame_ != nullptr) {
484     section = debug_frame_.get();
485   } else if (eh_frame_ != nullptr) {
486     section = eh_frame_.get();
487   } else if (gnu_debugdata_interface_ != nullptr) {
488     last_error_ = gnu_debugdata_interface_->last_error();
489     return false;
490   } else {
491     return false;
492   }
493 
494   // Convert the DWARF ERROR to an external error.
495   DwarfErrorCode code = section->LastErrorCode();
496   switch (code) {
497     case DWARF_ERROR_NONE:
498       last_error_.code = ERROR_NONE;
499       break;
500 
501     case DWARF_ERROR_MEMORY_INVALID:
502       last_error_.code = ERROR_MEMORY_INVALID;
503       last_error_.address = section->LastErrorAddress();
504       break;
505 
506     case DWARF_ERROR_ILLEGAL_VALUE:
507     case DWARF_ERROR_ILLEGAL_STATE:
508     case DWARF_ERROR_STACK_INDEX_NOT_VALID:
509     case DWARF_ERROR_TOO_MANY_ITERATIONS:
510     case DWARF_ERROR_CFA_NOT_DEFINED:
511     case DWARF_ERROR_NO_FDES:
512       last_error_.code = ERROR_UNWIND_INFO;
513       break;
514 
515     case DWARF_ERROR_NOT_IMPLEMENTED:
516     case DWARF_ERROR_UNSUPPORTED_VERSION:
517       last_error_.code = ERROR_UNSUPPORTED;
518       break;
519   }
520   return false;
521 }
522 
523 // This is an estimation of the size of the elf file using the location
524 // of the section headers and size. This assumes that the section headers
525 // are at the end of the elf file. If the elf has a load bias, the size
526 // will be too large, but this is acceptable.
527 template <typename EhdrType>
GetMaxSizeWithTemplate(Memory * memory,uint64_t * size)528 void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
529   EhdrType ehdr;
530   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
531     return;
532   }
533   if (ehdr.e_shnum == 0) {
534     return;
535   }
536   *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
537 }
538 
539 template <typename EhdrType, typename ShdrType>
GetBuildIDInfo(Memory * memory,uint64_t * build_id_offset,uint64_t * build_id_size)540 bool GetBuildIDInfo(Memory* memory, uint64_t* build_id_offset, uint64_t* build_id_size) {
541   EhdrType ehdr;
542   if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
543     return false;
544   }
545 
546   uint64_t offset = ehdr.e_shoff;
547   uint64_t sec_offset;
548   uint64_t sec_size;
549   ShdrType shdr;
550   if (ehdr.e_shstrndx >= ehdr.e_shnum) {
551     return false;
552   }
553 
554   uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
555   if (!memory->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
556     return false;
557   }
558   sec_offset = shdr.sh_offset;
559   sec_size = shdr.sh_size;
560 
561   // Skip the first header, it's always going to be NULL.
562   offset += ehdr.e_shentsize;
563   for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
564     if (!memory->ReadFully(offset, &shdr, sizeof(shdr))) {
565       return false;
566     }
567     std::string name;
568     if (shdr.sh_type == SHT_NOTE && shdr.sh_name < sec_size &&
569         memory->ReadString(sec_offset + shdr.sh_name, &name) && name == ".note.gnu.build-id") {
570       *build_id_offset = shdr.sh_offset;
571       *build_id_size = shdr.sh_size;
572       return true;
573     }
574   }
575 
576   return false;
577 }
578 
579 template <typename EhdrType, typename ShdrType, typename NhdrType>
ReadBuildIDFromMemory(Memory * memory)580 std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) {
581   uint64_t note_offset;
582   uint64_t note_size;
583   if (!GetBuildIDInfo<EhdrType, ShdrType>(memory, &note_offset, &note_size)) {
584     return "";
585   }
586 
587   // Ensure there is no overflow in any of the calculations below.
588   uint64_t tmp;
589   if (__builtin_add_overflow(note_offset, note_size, &tmp)) {
590     return "";
591   }
592 
593   uint64_t offset = 0;
594   while (offset < note_size) {
595     if (note_size - offset < sizeof(NhdrType)) {
596       return "";
597     }
598     NhdrType hdr;
599     if (!memory->ReadFully(note_offset + offset, &hdr, sizeof(hdr))) {
600       return "";
601     }
602     offset += sizeof(hdr);
603 
604     if (note_size - offset < hdr.n_namesz) {
605       return "";
606     }
607     if (hdr.n_namesz > 0) {
608       std::string name(hdr.n_namesz, '\0');
609       if (!memory->ReadFully(note_offset + offset, &(name[0]), hdr.n_namesz)) {
610         return "";
611       }
612 
613       // Trim trailing \0 as GNU is stored as a C string in the ELF file.
614       if (name.back() == '\0') name.resize(name.size() - 1);
615 
616       // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
617       offset += (hdr.n_namesz + 3) & ~3;
618 
619       if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
620         if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) {
621           return "";
622         }
623         std::string build_id(hdr.n_descsz - 1, '\0');
624         if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) {
625           return build_id;
626         }
627         return "";
628       }
629     }
630     // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
631     offset += (hdr.n_descsz + 3) & ~3;
632   }
633   return "";
634 }
635 
636 // Instantiate all of the needed template functions.
637 template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
638 template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
639 
640 template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
641 template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
642 
643 template void ElfInterface::ReadProgramHeaders<Elf32_Ehdr, Elf32_Phdr>(const Elf32_Ehdr&,
644                                                                        uint64_t*);
645 template void ElfInterface::ReadProgramHeaders<Elf64_Ehdr, Elf64_Phdr>(const Elf64_Ehdr&,
646                                                                        uint64_t*);
647 
648 template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
649 template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
650 
651 template std::string ElfInterface::ReadBuildID<Elf32_Nhdr>();
652 template std::string ElfInterface::ReadBuildID<Elf64_Nhdr>();
653 
654 template std::string ElfInterface::GetSonameWithTemplate<Elf32_Dyn>();
655 template std::string ElfInterface::GetSonameWithTemplate<Elf64_Dyn>();
656 
657 template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
658                                                                    uint64_t*);
659 template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
660                                                                    uint64_t*);
661 
662 template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
663 template bool ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(const std::string&, uint64_t*);
664 
665 template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
666 template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
667 
668 template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
669 template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
670 
671 template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
672     Memory*);
673 template std::string ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(
674     Memory*);
675 
676 }  // namespace unwindstack
677