disassembler_elf.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  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 "components/zucchini/disassembler_elf.h"
  5. #include <stddef.h>
  6. #include <utility>
  7. #include "base/logging.h"
  8. #include "base/numerics/checked_math.h"
  9. #include "base/numerics/safe_conversions.h"
  10. #include "components/zucchini/abs32_utils.h"
  11. #include "components/zucchini/algorithm.h"
  12. #include "components/zucchini/arm_utils.h"
  13. #include "components/zucchini/buffer_source.h"
  14. namespace zucchini {
  15. namespace {
  16. constexpr uint64_t kElfImageBase = 0;
  17. constexpr size_t kSizeBound = 0x7FFF0000;
  18. // Threshold value for heuristics to detect THUMB2 code.
  19. constexpr double kAArch32BitCondAlwaysDensityThreshold = 0.4;
  20. // Bit fields for JudgeSection() return value.
  21. enum SectionJudgement : int {
  22. // Bit: Section does not invalidate ELF, but may or may not be useful.
  23. SECTION_BIT_SAFE = 1 << 0,
  24. // Bit: Section useful for AddressTranslator, to map between offsets and RVAs.
  25. SECTION_BIT_USEFUL_FOR_ADDRESS_TRANSLATOR = 1 << 1,
  26. // Bit: Section useful for |offset_bound|, to estimate ELF size.
  27. SECTION_BIT_USEFUL_FOR_OFFSET_BOUND = 1 << 2,
  28. // Bit: Section potentially useful for pointer extraction.
  29. SECTION_BIT_MAYBE_USEFUL_FOR_POINTERS = 1 << 3,
  30. // The following are verdicts from combining bits, to improve semantics.
  31. // Default value: A section is malformed and invalidates ELF.
  32. SECTION_IS_MALFORMED = 0,
  33. // Section does not invalidate ELF, but is also not used for anything.
  34. SECTION_IS_USELESS = SECTION_BIT_SAFE,
  35. };
  36. // Decides how a section affects ELF parsing, and returns a bit field composed
  37. // from SectionJudgement values.
  38. template <class TRAITS>
  39. int JudgeSection(size_t image_size, const typename TRAITS::Elf_Shdr* section) {
  40. // BufferRegion uses |size_t| this can be 32-bit in some cases. For Elf64
  41. // |sh_addr|, |sh_offset| and |sh_size| are 64-bit this can result in
  42. // overflows in the subsequent validation steps.
  43. if (!base::IsValueInRangeForNumericType<size_t>(section->sh_addr) ||
  44. !base::IsValueInRangeForNumericType<size_t>(section->sh_offset) ||
  45. !base::IsValueInRangeForNumericType<size_t>(section->sh_size)) {
  46. return SECTION_IS_MALFORMED;
  47. }
  48. // Examine RVA range: Reject if numerical overflow may happen.
  49. if (!BufferRegion{static_cast<size_t>(section->sh_addr),
  50. static_cast<size_t>(section->sh_size)}
  51. .FitsIn(kSizeBound))
  52. return SECTION_IS_MALFORMED;
  53. // Examine offset range: If section takes up |image| data then be stricter.
  54. size_t offset_bound =
  55. (section->sh_type == elf::SHT_NOBITS) ? kSizeBound : image_size;
  56. if (!BufferRegion{static_cast<size_t>(section->sh_offset),
  57. static_cast<size_t>(section->sh_size)}
  58. .FitsIn(offset_bound))
  59. return SECTION_IS_MALFORMED;
  60. // Empty sections don't contribute to offset-RVA mapping. For consistency, it
  61. // should also not affect |offset_bounds|.
  62. if (section->sh_size == 0)
  63. return SECTION_IS_USELESS;
  64. // Sections with |sh_addr == 0| are ignored because these tend to duplicates
  65. // (can cause problems for lookup) and uninteresting. For consistency, it
  66. // should also not affect |offset_bounds|.
  67. if (section->sh_addr == 0)
  68. return SECTION_IS_USELESS;
  69. if (section->sh_type == elf::SHT_NOBITS) {
  70. // Special case for .tbss sections: These should be ignored because they may
  71. // have offset-RVA map that don't match other sections.
  72. if (section->sh_flags & elf::SHF_TLS)
  73. return SECTION_IS_USELESS;
  74. // Section is useful for offset-RVA translation, but does not affect
  75. // |offset_bounds| since it can have large virtual size (e.g., .bss).
  76. return SECTION_BIT_SAFE | SECTION_BIT_USEFUL_FOR_ADDRESS_TRANSLATOR;
  77. }
  78. return SECTION_BIT_SAFE | SECTION_BIT_USEFUL_FOR_ADDRESS_TRANSLATOR |
  79. SECTION_BIT_USEFUL_FOR_OFFSET_BOUND |
  80. SECTION_BIT_MAYBE_USEFUL_FOR_POINTERS;
  81. }
  82. // Determines whether |section| is a reloc section.
  83. template <class TRAITS>
  84. bool IsRelocSection(const typename TRAITS::Elf_Shdr& section) {
  85. DCHECK_GT(section.sh_size, 0U);
  86. if (section.sh_type == elf::SHT_REL) {
  87. // Also validate |section.sh_entsize|, which gets used later.
  88. return section.sh_entsize == sizeof(typename TRAITS::Elf_Rel);
  89. }
  90. if (section.sh_type == elf::SHT_RELA)
  91. return section.sh_entsize == sizeof(typename TRAITS::Elf_Rela);
  92. return false;
  93. }
  94. // Determines whether |section| is a section with executable code.
  95. template <class TRAITS>
  96. bool IsExecSection(const typename TRAITS::Elf_Shdr& section) {
  97. DCHECK_GT(section.sh_size, 0U);
  98. return section.sh_type == elf::SHT_PROGBITS &&
  99. (section.sh_flags & elf::SHF_EXECINSTR) != 0;
  100. }
  101. } // namespace
  102. /******** Elf32Traits ********/
  103. // static
  104. constexpr Bitness Elf32Traits::kBitness;
  105. constexpr elf::FileClass Elf32Traits::kIdentificationClass;
  106. /******** Elf32IntelTraits ********/
  107. // static
  108. constexpr ExecutableType Elf32IntelTraits::kExeType;
  109. const char Elf32IntelTraits::kExeTypeString[] = "ELF x86";
  110. constexpr elf::MachineArchitecture Elf32IntelTraits::kMachineValue;
  111. constexpr uint32_t Elf32IntelTraits::kRelType;
  112. /******** ElfAArch32Traits ********/
  113. // static
  114. constexpr ExecutableType ElfAArch32Traits::kExeType;
  115. const char ElfAArch32Traits::kExeTypeString[] = "ELF ARM";
  116. constexpr elf::MachineArchitecture ElfAArch32Traits::kMachineValue;
  117. constexpr uint32_t ElfAArch32Traits::kRelType;
  118. /******** Elf64Traits ********/
  119. // static
  120. constexpr Bitness Elf64Traits::kBitness;
  121. constexpr elf::FileClass Elf64Traits::kIdentificationClass;
  122. /******** Elf64IntelTraits ********/
  123. // static
  124. constexpr ExecutableType Elf64IntelTraits::kExeType;
  125. const char Elf64IntelTraits::kExeTypeString[] = "ELF x64";
  126. constexpr elf::MachineArchitecture Elf64IntelTraits::kMachineValue;
  127. constexpr uint32_t Elf64IntelTraits::kRelType;
  128. /******** ElfAArch64Traits ********/
  129. // static
  130. constexpr ExecutableType ElfAArch64Traits::kExeType;
  131. const char ElfAArch64Traits::kExeTypeString[] = "ELF ARM64";
  132. constexpr elf::MachineArchitecture ElfAArch64Traits::kMachineValue;
  133. constexpr uint32_t ElfAArch64Traits::kRelType;
  134. /******** DisassemblerElf ********/
  135. // static.
  136. template <class TRAITS>
  137. bool DisassemblerElf<TRAITS>::QuickDetect(ConstBufferView image) {
  138. BufferSource source(image);
  139. // Do not consume the bytes for the magic value, as they are part of the
  140. // header.
  141. if (!source.CheckNextBytes({0x7F, 'E', 'L', 'F'}))
  142. return false;
  143. auto* header = source.GetPointer<typename Traits::Elf_Ehdr>();
  144. if (!header)
  145. return false;
  146. if (header->e_ident[elf::EI_CLASS] != Traits::kIdentificationClass)
  147. return false;
  148. if (header->e_ident[elf::EI_DATA] != 1) // Only ELFDATA2LSB is supported.
  149. return false;
  150. if (header->e_type != elf::ET_EXEC && header->e_type != elf::ET_DYN)
  151. return false;
  152. if (header->e_version != 1 || header->e_ident[elf::EI_VERSION] != 1)
  153. return false;
  154. if (header->e_machine != supported_architecture())
  155. return false;
  156. if (header->e_shentsize != sizeof(typename Traits::Elf_Shdr))
  157. return false;
  158. return true;
  159. }
  160. template <class TRAITS>
  161. DisassemblerElf<TRAITS>::~DisassemblerElf() = default;
  162. template <class TRAITS>
  163. ExecutableType DisassemblerElf<TRAITS>::GetExeType() const {
  164. return Traits::kExeType;
  165. }
  166. template <class TRAITS>
  167. std::string DisassemblerElf<TRAITS>::GetExeTypeString() const {
  168. return Traits::kExeTypeString;
  169. }
  170. // |num_equivalence_iterations_| = 2 for reloc -> abs32.
  171. template <class TRAITS>
  172. DisassemblerElf<TRAITS>::DisassemblerElf() : Disassembler(2) {}
  173. template <class TRAITS>
  174. bool DisassemblerElf<TRAITS>::Parse(ConstBufferView image) {
  175. image_ = image;
  176. if (!ParseHeader())
  177. return false;
  178. ParseSections();
  179. return true;
  180. }
  181. template <class TRAITS>
  182. std::unique_ptr<ReferenceReader> DisassemblerElf<TRAITS>::MakeReadRelocs(
  183. offset_t lo,
  184. offset_t hi) {
  185. DCHECK_LE(lo, hi);
  186. DCHECK_LE(hi, image_.size());
  187. if (reloc_section_dims_.empty())
  188. return std::make_unique<EmptyReferenceReader>();
  189. return std::make_unique<RelocReaderElf>(
  190. image_, Traits::kBitness, reloc_section_dims_,
  191. supported_relocation_type(), lo, hi, translator_);
  192. }
  193. template <class TRAITS>
  194. std::unique_ptr<ReferenceWriter> DisassemblerElf<TRAITS>::MakeWriteRelocs(
  195. MutableBufferView image) {
  196. return std::make_unique<RelocWriterElf>(image, Traits::kBitness, translator_);
  197. }
  198. template <class TRAITS>
  199. bool DisassemblerElf<TRAITS>::ParseHeader() {
  200. BufferSource source(image_);
  201. // Ensure any offsets will fit within the |image_|'s bounds.
  202. if (!base::IsValueInRangeForNumericType<offset_t>(image_.size()))
  203. return false;
  204. // Ensures |header_| is valid later on.
  205. if (!QuickDetect(image_))
  206. return false;
  207. header_ = source.GetPointer<typename Traits::Elf_Ehdr>();
  208. sections_count_ = header_->e_shnum;
  209. source = std::move(BufferSource(image_).Skip(header_->e_shoff));
  210. sections_ = source.GetArray<typename Traits::Elf_Shdr>(sections_count_);
  211. if (!sections_)
  212. return false;
  213. offset_t section_table_end =
  214. base::checked_cast<offset_t>(source.begin() - image_.begin());
  215. segments_count_ = header_->e_phnum;
  216. source = std::move(BufferSource(image_).Skip(header_->e_phoff));
  217. segments_ = source.GetArray<typename Traits::Elf_Phdr>(segments_count_);
  218. if (!segments_)
  219. return false;
  220. offset_t segment_table_end =
  221. base::checked_cast<offset_t>(source.begin() - image_.begin());
  222. // Check string section -- even though we've stopped using them.
  223. elf::Elf32_Half string_section_id = header_->e_shstrndx;
  224. if (string_section_id >= sections_count_)
  225. return false;
  226. size_t section_names_size = sections_[string_section_id].sh_size;
  227. if (section_names_size > 0) {
  228. // If nonempty, then last byte of string section must be null.
  229. const char* section_names = nullptr;
  230. source = std::move(
  231. BufferSource(image_).Skip(sections_[string_section_id].sh_offset));
  232. section_names = source.GetArray<char>(section_names_size);
  233. if (!section_names || section_names[section_names_size - 1] != '\0')
  234. return false;
  235. }
  236. // Establish bound on encountered offsets.
  237. offset_t offset_bound = std::max(section_table_end, segment_table_end);
  238. // Visits |segments_| to get estimate on |offset_bound|.
  239. for (const typename Traits::Elf_Phdr* segment = segments_;
  240. segment != segments_ + segments_count_; ++segment) {
  241. // |image_.covers()| is a sufficient check except when size_t is 32 bit and
  242. // parsing ELF64. In such cases a value-in-range check is needed on the
  243. // segment. This fixes crbug/1035603.
  244. offset_t segment_end;
  245. base::CheckedNumeric<offset_t> checked_segment_end = segment->p_offset;
  246. checked_segment_end += segment->p_filesz;
  247. if (!checked_segment_end.AssignIfValid(&segment_end) ||
  248. !image_.covers({static_cast<size_t>(segment->p_offset),
  249. static_cast<size_t>(segment->p_filesz)})) {
  250. return false;
  251. }
  252. offset_bound = std::max(offset_bound, segment_end);
  253. }
  254. // Visit and validate each section; add address translation data to |units|.
  255. std::vector<AddressTranslator::Unit> units;
  256. units.reserve(sections_count_);
  257. section_judgements_.reserve(sections_count_);
  258. for (int i = 0; i < sections_count_; ++i) {
  259. const typename Traits::Elf_Shdr* section = &sections_[i];
  260. int judgement = JudgeSection<Traits>(image_.size(), section);
  261. section_judgements_.push_back(judgement);
  262. if ((judgement & SECTION_BIT_SAFE) == 0)
  263. return false;
  264. uint32_t sh_size = base::checked_cast<uint32_t>(section->sh_size);
  265. offset_t sh_offset = base::checked_cast<offset_t>(section->sh_offset);
  266. rva_t sh_addr = base::checked_cast<rva_t>(section->sh_addr);
  267. if ((judgement & SECTION_BIT_USEFUL_FOR_ADDRESS_TRANSLATOR) != 0) {
  268. // Store mappings between RVA and offset.
  269. units.push_back({sh_offset, sh_size, sh_addr, sh_size});
  270. }
  271. if ((judgement & SECTION_BIT_USEFUL_FOR_OFFSET_BOUND) != 0) {
  272. offset_t section_end = base::checked_cast<offset_t>(sh_offset + sh_size);
  273. offset_bound = std::max(offset_bound, section_end);
  274. }
  275. }
  276. // Initialize |translator_| for offset-RVA translations. Any inconsistency
  277. // (e.g., 2 offsets correspond to the same RVA) would invalidate the ELF file.
  278. if (translator_.Initialize(std::move(units)) != AddressTranslator::kSuccess)
  279. return false;
  280. DCHECK_LE(offset_bound, image_.size());
  281. image_.shrink(offset_bound);
  282. return true;
  283. }
  284. template <class TRAITS>
  285. void DisassemblerElf<TRAITS>::ExtractInterestingSectionHeaders() {
  286. DCHECK(reloc_section_dims_.empty());
  287. DCHECK(exec_headers_.empty());
  288. for (elf::Elf32_Half i = 0; i < sections_count_; ++i) {
  289. const typename Traits::Elf_Shdr* section = sections_ + i;
  290. if ((section_judgements_[i] & SECTION_BIT_MAYBE_USEFUL_FOR_POINTERS) != 0) {
  291. if (IsRelocSection<Traits>(*section))
  292. reloc_section_dims_.emplace_back(*section);
  293. else if (IsExecSection<Traits>(*section))
  294. exec_headers_.push_back(section);
  295. }
  296. }
  297. auto comp = [](const typename Traits::Elf_Shdr* a,
  298. const typename Traits::Elf_Shdr* b) {
  299. return a->sh_offset < b->sh_offset;
  300. };
  301. std::sort(reloc_section_dims_.begin(), reloc_section_dims_.end());
  302. std::sort(exec_headers_.begin(), exec_headers_.end(), comp);
  303. }
  304. template <class TRAITS>
  305. void DisassemblerElf<TRAITS>::GetAbs32FromRelocSections() {
  306. constexpr int kAbs32Width = Traits::kVAWidth;
  307. DCHECK(abs32_locations_.empty());
  308. // Read reloc targets to get preliminary abs32 locations.
  309. std::unique_ptr<ReferenceReader> relocs = MakeReadRelocs(0, offset_t(size()));
  310. for (auto ref = relocs->GetNext(); ref.has_value(); ref = relocs->GetNext())
  311. abs32_locations_.push_back(ref->target);
  312. std::sort(abs32_locations_.begin(), abs32_locations_.end());
  313. // Abs32 references must have targets translatable to offsets. Remove those
  314. // that are unable to do so.
  315. size_t num_untranslatable =
  316. RemoveUntranslatableAbs32(image_, {Traits::kBitness, kElfImageBase},
  317. translator_, &abs32_locations_);
  318. LOG_IF(WARNING, num_untranslatable) << "Removed " << num_untranslatable
  319. << " untranslatable abs32 references.";
  320. // Abs32 reference bodies must not overlap. If found, simply remove them.
  321. size_t num_overlapping =
  322. RemoveOverlappingAbs32Locations(kAbs32Width, &abs32_locations_);
  323. LOG_IF(WARNING, num_overlapping)
  324. << "Removed " << num_overlapping
  325. << " abs32 references with overlapping bodies.";
  326. abs32_locations_.shrink_to_fit();
  327. }
  328. template <class TRAITS>
  329. void DisassemblerElf<TRAITS>::GetRel32FromCodeSections() {
  330. for (const typename Traits::Elf_Shdr* section : exec_headers_)
  331. ParseExecSection(*section);
  332. PostProcessRel32();
  333. }
  334. template <class TRAITS>
  335. void DisassemblerElf<TRAITS>::ParseSections() {
  336. ExtractInterestingSectionHeaders();
  337. GetAbs32FromRelocSections();
  338. GetRel32FromCodeSections();
  339. }
  340. /******** DisassemblerElfIntel ********/
  341. template <class TRAITS>
  342. DisassemblerElfIntel<TRAITS>::DisassemblerElfIntel() = default;
  343. template <class TRAITS>
  344. DisassemblerElfIntel<TRAITS>::~DisassemblerElfIntel() = default;
  345. template <class TRAITS>
  346. std::vector<ReferenceGroup> DisassemblerElfIntel<TRAITS>::MakeReferenceGroups()
  347. const {
  348. return {
  349. {ReferenceTypeTraits{sizeof(TRAITS::Elf_Rel::r_offset), TypeTag(kReloc),
  350. PoolTag(kReloc)},
  351. &DisassemblerElfIntel<TRAITS>::MakeReadRelocs,
  352. &DisassemblerElfIntel<TRAITS>::MakeWriteRelocs},
  353. {ReferenceTypeTraits{Traits::kVAWidth, TypeTag(kAbs32), PoolTag(kAbs32)},
  354. &DisassemblerElfIntel<TRAITS>::MakeReadAbs32,
  355. &DisassemblerElfIntel<TRAITS>::MakeWriteAbs32},
  356. // N.B.: Rel32 |width| is 4 bytes, even for x64.
  357. {ReferenceTypeTraits{4, TypeTag(kRel32), PoolTag(kRel32)},
  358. &DisassemblerElfIntel<TRAITS>::MakeReadRel32,
  359. &DisassemblerElfIntel<TRAITS>::MakeWriteRel32}};
  360. }
  361. template <class TRAITS>
  362. void DisassemblerElfIntel<TRAITS>::ParseExecSection(
  363. const typename TRAITS::Elf_Shdr& section) {
  364. constexpr int kAbs32Width = Traits::kVAWidth;
  365. // |this->| is needed to access protected members of templated base class. To
  366. // reduce noise, use local references for these.
  367. ConstBufferView& image_ = this->image_;
  368. const AddressTranslator& translator_ = this->translator_;
  369. auto& abs32_locations_ = this->abs32_locations_;
  370. // Range of values was ensured in ParseHeader().
  371. rva_t start_rva = base::checked_cast<rva_t>(section.sh_addr);
  372. rva_t end_rva = base::checked_cast<rva_t>(start_rva + section.sh_size);
  373. AddressTranslator::RvaToOffsetCache target_rva_checker(translator_);
  374. ConstBufferView region(image_.begin() + section.sh_offset, section.sh_size);
  375. Abs32GapFinder gap_finder(image_, region, abs32_locations_, kAbs32Width);
  376. typename TRAITS::Rel32FinderUse rel_finder(image_, translator_);
  377. // Iterate over gaps between abs32 references, to avoid collision.
  378. while (gap_finder.FindNext()) {
  379. rel_finder.SetRegion(gap_finder.GetGap());
  380. while (rel_finder.FindNext()) {
  381. auto rel32 = rel_finder.GetRel32();
  382. if (target_rva_checker.IsValid(rel32.target_rva) &&
  383. (rel32.can_point_outside_section ||
  384. (start_rva <= rel32.target_rva && rel32.target_rva < end_rva))) {
  385. rel_finder.Accept();
  386. rel32_locations_.push_back(rel32.location);
  387. }
  388. }
  389. }
  390. }
  391. template <class TRAITS>
  392. void DisassemblerElfIntel<TRAITS>::PostProcessRel32() {
  393. rel32_locations_.shrink_to_fit();
  394. std::sort(rel32_locations_.begin(), rel32_locations_.end());
  395. }
  396. template <class TRAITS>
  397. std::unique_ptr<ReferenceReader> DisassemblerElfIntel<TRAITS>::MakeReadAbs32(
  398. offset_t lo,
  399. offset_t hi) {
  400. // TODO(huangs): Don't use Abs32RvaExtractorWin32 here; use new class that
  401. // caters to different ELF architectures.
  402. Abs32RvaExtractorWin32 abs_rva_extractor(
  403. this->image_, AbsoluteAddress(TRAITS::kBitness, kElfImageBase),
  404. this->abs32_locations_, lo, hi);
  405. return std::make_unique<Abs32ReaderWin32>(std::move(abs_rva_extractor),
  406. this->translator_);
  407. }
  408. template <class TRAITS>
  409. std::unique_ptr<ReferenceWriter> DisassemblerElfIntel<TRAITS>::MakeWriteAbs32(
  410. MutableBufferView image) {
  411. return std::make_unique<Abs32WriterWin32>(
  412. image, AbsoluteAddress(TRAITS::kBitness, kElfImageBase),
  413. this->translator_);
  414. }
  415. template <class TRAITS>
  416. std::unique_ptr<ReferenceReader> DisassemblerElfIntel<TRAITS>::MakeReadRel32(
  417. offset_t lo,
  418. offset_t hi) {
  419. return std::make_unique<Rel32ReaderX86>(this->image_, lo, hi,
  420. &rel32_locations_, this->translator_);
  421. }
  422. template <class TRAITS>
  423. std::unique_ptr<ReferenceWriter> DisassemblerElfIntel<TRAITS>::MakeWriteRel32(
  424. MutableBufferView image) {
  425. return std::make_unique<Rel32WriterX86>(image, this->translator_);
  426. }
  427. // Explicit instantiation for supported classes.
  428. template class DisassemblerElfIntel<Elf32IntelTraits>;
  429. template class DisassemblerElfIntel<Elf64IntelTraits>;
  430. template bool DisassemblerElf<Elf32IntelTraits>::QuickDetect(
  431. ConstBufferView image);
  432. template bool DisassemblerElf<Elf64IntelTraits>::QuickDetect(
  433. ConstBufferView image);
  434. /******** DisassemblerElfArm ********/
  435. template <class Traits>
  436. DisassemblerElfArm<Traits>::DisassemblerElfArm() = default;
  437. template <class Traits>
  438. DisassemblerElfArm<Traits>::~DisassemblerElfArm() = default;
  439. template <class Traits>
  440. bool DisassemblerElfArm<Traits>::IsTargetOffsetInExecSection(
  441. offset_t offset) const {
  442. // Executable sections can appear in large numbers in .o files and in
  443. // pathological cases. Since this function may be called for each reference
  444. // candidate, linear search may be too slow (so use binary search).
  445. return IsTargetOffsetInElfSectionList(this->exec_headers_, offset);
  446. }
  447. template <class Traits>
  448. void DisassemblerElfArm<Traits>::ParseExecSection(
  449. const typename Traits::Elf_Shdr& section) {
  450. ConstBufferView& image_ = this->image_;
  451. const AddressTranslator& translator_ = this->translator_;
  452. auto& abs32_locations_ = this->abs32_locations_;
  453. ConstBufferView region(image_.begin() + section.sh_offset, section.sh_size);
  454. Abs32GapFinder gap_finder(image_, region, abs32_locations_, Traits::kVAWidth);
  455. std::unique_ptr<typename Traits::Rel32FinderUse> rel_finder =
  456. MakeRel32Finder(section);
  457. AddressTranslator::RvaToOffsetCache rva_to_offset(translator_);
  458. while (gap_finder.FindNext()) {
  459. rel_finder->SetRegion(gap_finder.GetGap());
  460. while (rel_finder->FindNext()) {
  461. auto rel32 = rel_finder->GetRel32();
  462. offset_t target_offset = rva_to_offset.Convert(rel32.target_rva);
  463. if (target_offset != kInvalidOffset) {
  464. // For robustness, reject illegal offsets, which can arise from, e.g.,
  465. // misidentify ARM vs. THUMB2 mode, or even misidentifying data as code!
  466. if (IsTargetOffsetInExecSection(target_offset)) {
  467. rel_finder->Accept();
  468. rel32_locations_table_[rel32.type].push_back(rel32.location);
  469. }
  470. }
  471. }
  472. }
  473. }
  474. template <class Traits>
  475. void DisassemblerElfArm<Traits>::PostProcessRel32() {
  476. for (int type = 0; type < AArch32Rel32Translator::NUM_ADDR_TYPE; ++type) {
  477. std::sort(rel32_locations_table_[type].begin(),
  478. rel32_locations_table_[type].end());
  479. rel32_locations_table_[type].shrink_to_fit();
  480. }
  481. }
  482. template <class Traits>
  483. std::unique_ptr<ReferenceReader> DisassemblerElfArm<Traits>::MakeReadAbs32(
  484. offset_t lo,
  485. offset_t hi) {
  486. // TODO(huangs): Reconcile the use of Win32-specific classes in ARM code!
  487. Abs32RvaExtractorWin32 abs_rva_extractor(this->image_,
  488. AbsoluteAddress(Traits::kBitness, 0),
  489. this->abs32_locations_, lo, hi);
  490. return std::make_unique<Abs32ReaderWin32>(std::move(abs_rva_extractor),
  491. this->translator_);
  492. }
  493. template <class Traits>
  494. std::unique_ptr<ReferenceWriter> DisassemblerElfArm<Traits>::MakeWriteAbs32(
  495. MutableBufferView image) {
  496. return std::make_unique<Abs32WriterWin32>(
  497. image, AbsoluteAddress(Traits::kBitness, 0), this->translator_);
  498. }
  499. template <class TRAITS>
  500. template <class ADDR_TRAITS>
  501. std::unique_ptr<ReferenceReader> DisassemblerElfArm<TRAITS>::MakeReadRel32(
  502. offset_t lower,
  503. offset_t upper) {
  504. return std::make_unique<Rel32ReaderArm<ADDR_TRAITS>>(
  505. this->translator_, this->image_,
  506. this->rel32_locations_table_[ADDR_TRAITS::addr_type], lower, upper);
  507. }
  508. template <class TRAITS>
  509. template <class ADDR_TRAITS>
  510. std::unique_ptr<ReferenceWriter> DisassemblerElfArm<TRAITS>::MakeWriteRel32(
  511. MutableBufferView image) {
  512. return std::make_unique<Rel32WriterArm<ADDR_TRAITS>>(this->translator_,
  513. image);
  514. }
  515. template <class TRAITS>
  516. template <class ADDR_TRAITS>
  517. std::unique_ptr<ReferenceMixer> DisassemblerElfArm<TRAITS>::MakeMixRel32(
  518. ConstBufferView src_image,
  519. ConstBufferView dst_image) {
  520. return std::make_unique<Rel32MixerArm<ADDR_TRAITS>>(src_image, dst_image);
  521. }
  522. /******** DisassemblerElfAArch32 ********/
  523. DisassemblerElfAArch32::DisassemblerElfAArch32() = default;
  524. DisassemblerElfAArch32::~DisassemblerElfAArch32() = default;
  525. std::vector<ReferenceGroup> DisassemblerElfAArch32::MakeReferenceGroups()
  526. const {
  527. return {
  528. {ReferenceTypeTraits{sizeof(Traits::Elf_Rel::r_offset),
  529. TypeTag(AArch32ReferenceType::kReloc),
  530. PoolTag(ArmReferencePool::kPoolReloc)},
  531. &DisassemblerElfAArch32::MakeReadRelocs,
  532. &DisassemblerElfAArch32::MakeWriteRelocs},
  533. {ReferenceTypeTraits{Traits::kVAWidth,
  534. TypeTag(AArch32ReferenceType::kAbs32),
  535. PoolTag(ArmReferencePool::kPoolAbs32)},
  536. &DisassemblerElfAArch32::MakeReadAbs32,
  537. &DisassemblerElfAArch32::MakeWriteAbs32},
  538. {ReferenceTypeTraits{4, TypeTag(AArch32ReferenceType::kRel32_A24),
  539. PoolTag(ArmReferencePool::kPoolRel32)},
  540. &DisassemblerElfAArch32::MakeReadRel32<
  541. AArch32Rel32Translator::AddrTraits_A24>,
  542. &DisassemblerElfAArch32::MakeWriteRel32<
  543. AArch32Rel32Translator::AddrTraits_A24>,
  544. &DisassemblerElfAArch32::MakeMixRel32<
  545. AArch32Rel32Translator::AddrTraits_A24>},
  546. {ReferenceTypeTraits{2, TypeTag(AArch32ReferenceType::kRel32_T8),
  547. PoolTag(ArmReferencePool::kPoolRel32)},
  548. &DisassemblerElfAArch32::MakeReadRel32<
  549. AArch32Rel32Translator::AddrTraits_T8>,
  550. &DisassemblerElfAArch32::MakeWriteRel32<
  551. AArch32Rel32Translator::AddrTraits_T8>,
  552. &DisassemblerElfAArch32::MakeMixRel32<
  553. AArch32Rel32Translator::AddrTraits_T8>},
  554. {ReferenceTypeTraits{2, TypeTag(AArch32ReferenceType::kRel32_T11),
  555. PoolTag(ArmReferencePool::kPoolRel32)},
  556. &DisassemblerElfAArch32::MakeReadRel32<
  557. AArch32Rel32Translator::AddrTraits_T11>,
  558. &DisassemblerElfAArch32::MakeWriteRel32<
  559. AArch32Rel32Translator::AddrTraits_T11>,
  560. &DisassemblerElfAArch32::MakeMixRel32<
  561. AArch32Rel32Translator::AddrTraits_T11>},
  562. {ReferenceTypeTraits{4, TypeTag(AArch32ReferenceType::kRel32_T20),
  563. PoolTag(ArmReferencePool::kPoolRel32)},
  564. &DisassemblerElfAArch32::MakeReadRel32<
  565. AArch32Rel32Translator::AddrTraits_T20>,
  566. &DisassemblerElfAArch32::MakeWriteRel32<
  567. AArch32Rel32Translator::AddrTraits_T20>,
  568. &DisassemblerElfAArch32::MakeMixRel32<
  569. AArch32Rel32Translator::AddrTraits_T20>},
  570. {ReferenceTypeTraits{4, TypeTag(AArch32ReferenceType::kRel32_T24),
  571. PoolTag(ArmReferencePool::kPoolRel32)},
  572. &DisassemblerElfAArch32::MakeReadRel32<
  573. AArch32Rel32Translator::AddrTraits_T24>,
  574. &DisassemblerElfAArch32::MakeWriteRel32<
  575. AArch32Rel32Translator::AddrTraits_T24>,
  576. &DisassemblerElfAArch32::MakeMixRel32<
  577. AArch32Rel32Translator::AddrTraits_T24>},
  578. };
  579. }
  580. std::unique_ptr<DisassemblerElfAArch32::Traits::Rel32FinderUse>
  581. DisassemblerElfAArch32::MakeRel32Finder(
  582. const typename Traits::Elf_Shdr& section) {
  583. return std::make_unique<Rel32FinderAArch32>(image_, translator_,
  584. IsExecSectionThumb2(section));
  585. }
  586. bool DisassemblerElfAArch32::IsExecSectionThumb2(
  587. const typename Traits::Elf_Shdr& section) const {
  588. // ARM mode requires 4-byte alignment.
  589. if (section.sh_addr % 4 != 0 || section.sh_size % 4 != 0)
  590. return true;
  591. const uint8_t* first = image_.begin() + section.sh_offset;
  592. const uint8_t* end = first + section.sh_size;
  593. // Each instruction in 32-bit ARM (little-endian) looks like
  594. // ?? ?? ?? X?,
  595. // where X specifies conditional execution. X = 0xE represents AL = "ALways
  596. // execute", and tends to appear very often. We use this as our main indicator
  597. // to discern 32-bit ARM mode from THUMB2 mode.
  598. size_t num = 0;
  599. size_t den = 0;
  600. for (const uint8_t* cur = first; cur < end; cur += 4) {
  601. // |cur[3]| is within bounds because |end - cur| is a multiple of 4.
  602. uint8_t maybe_cond = cur[3] & 0xF0;
  603. if (maybe_cond == 0xE0)
  604. ++num;
  605. ++den;
  606. }
  607. if (den > 0) {
  608. LOG(INFO) << "Section scan: " << num << " / " << den << " => "
  609. << base::StringPrintf("%.2f", num * 100.0 / den) << "%";
  610. }
  611. return num < den * kAArch32BitCondAlwaysDensityThreshold;
  612. }
  613. /******** DisassemblerElfAArch64 ********/
  614. DisassemblerElfAArch64::DisassemblerElfAArch64() = default;
  615. DisassemblerElfAArch64::~DisassemblerElfAArch64() = default;
  616. std::vector<ReferenceGroup> DisassemblerElfAArch64::MakeReferenceGroups()
  617. const {
  618. return {
  619. {ReferenceTypeTraits{sizeof(Traits::Elf_Rel::r_offset),
  620. TypeTag(AArch64ReferenceType::kReloc),
  621. PoolTag(ArmReferencePool::kPoolReloc)},
  622. &DisassemblerElfAArch64::MakeReadRelocs,
  623. &DisassemblerElfAArch64::MakeWriteRelocs},
  624. {ReferenceTypeTraits{Traits::kVAWidth,
  625. TypeTag(AArch64ReferenceType::kAbs32),
  626. PoolTag(ArmReferencePool::kPoolAbs32)},
  627. &DisassemblerElfAArch64::MakeReadAbs32,
  628. &DisassemblerElfAArch64::MakeWriteAbs32},
  629. {ReferenceTypeTraits{4, TypeTag(AArch64ReferenceType::kRel32_Immd14),
  630. PoolTag(ArmReferencePool::kPoolRel32)},
  631. &DisassemblerElfAArch64::MakeReadRel32<
  632. AArch64Rel32Translator::AddrTraits_Immd14>,
  633. &DisassemblerElfAArch64::MakeWriteRel32<
  634. AArch64Rel32Translator::AddrTraits_Immd14>,
  635. &DisassemblerElfAArch32::MakeMixRel32<
  636. AArch64Rel32Translator::AddrTraits_Immd14>},
  637. {ReferenceTypeTraits{4, TypeTag(AArch64ReferenceType::kRel32_Immd19),
  638. PoolTag(ArmReferencePool::kPoolRel32)},
  639. &DisassemblerElfAArch64::MakeReadRel32<
  640. AArch64Rel32Translator::AddrTraits_Immd19>,
  641. &DisassemblerElfAArch64::MakeWriteRel32<
  642. AArch64Rel32Translator::AddrTraits_Immd19>,
  643. &DisassemblerElfAArch32::MakeMixRel32<
  644. AArch64Rel32Translator::AddrTraits_Immd19>},
  645. {ReferenceTypeTraits{4, TypeTag(AArch64ReferenceType::kRel32_Immd26),
  646. PoolTag(ArmReferencePool::kPoolRel32)},
  647. &DisassemblerElfAArch64::MakeReadRel32<
  648. AArch64Rel32Translator::AddrTraits_Immd26>,
  649. &DisassemblerElfAArch64::MakeWriteRel32<
  650. AArch64Rel32Translator::AddrTraits_Immd26>,
  651. &DisassemblerElfAArch32::MakeMixRel32<
  652. AArch64Rel32Translator::AddrTraits_Immd26>},
  653. };
  654. }
  655. std::unique_ptr<DisassemblerElfAArch64::Traits::Rel32FinderUse>
  656. DisassemblerElfAArch64::MakeRel32Finder(
  657. const typename Traits::Elf_Shdr& section) {
  658. return std::make_unique<Rel32FinderAArch64>(image_, translator_);
  659. }
  660. // Explicit instantiation for supported classes.
  661. template class DisassemblerElfArm<ElfAArch32Traits>;
  662. template class DisassemblerElfArm<ElfAArch64Traits>;
  663. template bool DisassemblerElf<ElfAArch32Traits>::QuickDetect(
  664. ConstBufferView image);
  665. template bool DisassemblerElf<ElfAArch64Traits>::QuickDetect(
  666. ConstBufferView image);
  667. } // namespace zucchini