elf_reader.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/debug/elf_reader.h"
  5. #include <arpa/inet.h>
  6. #include <elf.h>
  7. #include <string.h>
  8. #include "base/bits.h"
  9. #include "base/containers/span.h"
  10. #include "base/hash/sha1.h"
  11. #include "base/strings/safe_sprintf.h"
  12. #include "build/build_config.h"
  13. #include "third_party/abseil-cpp/absl/types/optional.h"
  14. // NOTE: This code may be used in crash handling code, so the implementation
  15. // must avoid dynamic memory allocation or using data structures which rely on
  16. // dynamic allocation.
  17. namespace base {
  18. namespace debug {
  19. namespace {
  20. // See https://refspecs.linuxbase.org/elf/elf.pdf for the ELF specification.
  21. #if __SIZEOF_POINTER__ == 4
  22. using Ehdr = Elf32_Ehdr;
  23. using Dyn = Elf32_Dyn;
  24. using Half = Elf32_Half;
  25. using Nhdr = Elf32_Nhdr;
  26. using Word = Elf32_Word;
  27. using Xword = Elf32_Word;
  28. #else
  29. using Ehdr = Elf64_Ehdr;
  30. using Dyn = Elf64_Dyn;
  31. using Half = Elf64_Half;
  32. using Nhdr = Elf64_Nhdr;
  33. using Word = Elf64_Word;
  34. using Xword = Elf64_Xword;
  35. #endif
  36. constexpr char kGnuNoteName[] = "GNU";
  37. // Returns a pointer to the header of the ELF binary mapped into memory, or a
  38. // null pointer if the header is invalid. Here and below |elf_mapped_base| is a
  39. // pointer to the start of the ELF image.
  40. const Ehdr* GetElfHeader(const void* elf_mapped_base) {
  41. if (strncmp(reinterpret_cast<const char*>(elf_mapped_base), ELFMAG,
  42. SELFMAG) != 0)
  43. return nullptr;
  44. return reinterpret_cast<const Ehdr*>(elf_mapped_base);
  45. }
  46. } // namespace
  47. size_t ReadElfBuildId(const void* elf_mapped_base,
  48. bool uppercase,
  49. ElfBuildIdBuffer build_id) {
  50. // NOTE: Function should use async signal safe calls only.
  51. const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  52. if (!elf_header)
  53. return 0;
  54. const size_t relocation_offset = GetRelocationOffset(elf_mapped_base);
  55. for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) {
  56. if (header.p_type != PT_NOTE)
  57. continue;
  58. // Look for a NT_GNU_BUILD_ID note with name == "GNU".
  59. const char* current_section =
  60. reinterpret_cast<const char*>(header.p_vaddr + relocation_offset);
  61. const char* section_end = current_section + header.p_memsz;
  62. const Nhdr* current_note = nullptr;
  63. bool found = false;
  64. while (current_section < section_end) {
  65. current_note = reinterpret_cast<const Nhdr*>(current_section);
  66. if (current_note->n_type == NT_GNU_BUILD_ID) {
  67. StringPiece note_name(current_section + sizeof(Nhdr),
  68. current_note->n_namesz);
  69. // Explicit constructor is used to include the '\0' character.
  70. if (note_name == StringPiece(kGnuNoteName, sizeof(kGnuNoteName))) {
  71. found = true;
  72. break;
  73. }
  74. }
  75. size_t section_size = bits::AlignUp(current_note->n_namesz, 4u) +
  76. bits::AlignUp(current_note->n_descsz, 4u) +
  77. sizeof(Nhdr);
  78. if (section_size > static_cast<size_t>(section_end - current_section))
  79. return 0;
  80. current_section += section_size;
  81. }
  82. if (!found)
  83. continue;
  84. // Validate that the serialized build ID will fit inside |build_id|.
  85. size_t note_size = current_note->n_descsz;
  86. if ((note_size * 2) > kMaxBuildIdStringLength)
  87. continue;
  88. // Write out the build ID as a null-terminated hex string.
  89. const uint8_t* build_id_raw =
  90. reinterpret_cast<const uint8_t*>(current_note) + sizeof(Nhdr) +
  91. bits::AlignUp(current_note->n_namesz, 4u);
  92. size_t i = 0;
  93. for (i = 0; i < current_note->n_descsz; ++i) {
  94. strings::SafeSNPrintf(&build_id[i * 2], 3, (uppercase ? "%02X" : "%02x"),
  95. build_id_raw[i]);
  96. }
  97. build_id[i * 2] = '\0';
  98. // Return the length of the string.
  99. return i * 2;
  100. }
  101. return 0;
  102. }
  103. absl::optional<StringPiece> ReadElfLibraryName(const void* elf_mapped_base) {
  104. // NOTE: Function should use async signal safe calls only.
  105. const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  106. if (!elf_header)
  107. return {};
  108. const size_t relocation_offset = GetRelocationOffset(elf_mapped_base);
  109. for (const Phdr& header : GetElfProgramHeaders(elf_mapped_base)) {
  110. if (header.p_type != PT_DYNAMIC)
  111. continue;
  112. // Read through the ELF dynamic sections to find the string table and
  113. // SONAME offsets, which are used to compute the offset of the library
  114. // name string.
  115. const Dyn* dynamic_start =
  116. reinterpret_cast<const Dyn*>(header.p_vaddr + relocation_offset);
  117. const Dyn* dynamic_end = reinterpret_cast<const Dyn*>(
  118. header.p_vaddr + relocation_offset + header.p_memsz);
  119. Xword soname_strtab_offset = 0;
  120. const char* strtab_addr = 0;
  121. for (const Dyn* dynamic_iter = dynamic_start; dynamic_iter < dynamic_end;
  122. ++dynamic_iter) {
  123. if (dynamic_iter->d_tag == DT_STRTAB) {
  124. #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_ANDROID)
  125. // Fuchsia and Android do not relocate the symtab pointer on ELF load.
  126. strtab_addr = static_cast<size_t>(dynamic_iter->d_un.d_ptr) +
  127. reinterpret_cast<const char*>(relocation_offset);
  128. #else
  129. strtab_addr = reinterpret_cast<const char*>(dynamic_iter->d_un.d_ptr);
  130. #endif
  131. } else if (dynamic_iter->d_tag == DT_SONAME) {
  132. // The Android NDK wrongly defines `d_val` as an Elf32_Sword for 32 bits
  133. // and thus needs this cast.
  134. soname_strtab_offset = static_cast<Xword>(dynamic_iter->d_un.d_val);
  135. }
  136. }
  137. if (soname_strtab_offset && strtab_addr)
  138. return StringPiece(strtab_addr + soname_strtab_offset);
  139. }
  140. return absl::nullopt;
  141. }
  142. span<const Phdr> GetElfProgramHeaders(const void* elf_mapped_base) {
  143. // NOTE: Function should use async signal safe calls only.
  144. const Ehdr* elf_header = GetElfHeader(elf_mapped_base);
  145. if (!elf_header)
  146. return {};
  147. const char* phdr_start =
  148. reinterpret_cast<const char*>(elf_header) + elf_header->e_phoff;
  149. return span<const Phdr>(reinterpret_cast<const Phdr*>(phdr_start),
  150. elf_header->e_phnum);
  151. }
  152. // Returns the offset to add to virtual addresses in the image to compute the
  153. // mapped virtual address.
  154. size_t GetRelocationOffset(const void* elf_mapped_base) {
  155. span<const Phdr> headers = GetElfProgramHeaders(elf_mapped_base);
  156. for (const Phdr& header : headers) {
  157. if (header.p_type == PT_LOAD) {
  158. // |elf_mapped_base| + |header.p_offset| is the mapped address of this
  159. // segment. |header.p_vaddr| is the specified virtual address within the
  160. // ELF image.
  161. const char* const mapped_address =
  162. reinterpret_cast<const char*>(elf_mapped_base) + header.p_offset;
  163. return reinterpret_cast<uintptr_t>(mapped_address) - header.p_vaddr;
  164. }
  165. }
  166. // Assume the virtual addresses in the image start at 0, so the offset is
  167. // from 0 to the actual mapped base address.
  168. return static_cast<size_t>(reinterpret_cast<uintptr_t>(elf_mapped_base) -
  169. reinterpret_cast<uintptr_t>(nullptr));
  170. }
  171. } // namespace debug
  172. } // namespace base