DynamicLoader.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com>
  3. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Assertions.h>
  9. #include <AK/OwnPtr.h>
  10. #include <AK/RefCounted.h>
  11. #include <AK/String.h>
  12. #include <LibC/elf.h>
  13. #include <LibDl/dlfcn_integration.h>
  14. #include <LibELF/DynamicObject.h>
  15. #include <LibELF/Image.h>
  16. #include <sys/mman.h>
  17. namespace ELF {
  18. class LoadedSegment {
  19. public:
  20. LoadedSegment(VirtualAddress address, size_t size)
  21. : m_address(address)
  22. , m_size(size)
  23. {
  24. }
  25. VirtualAddress address() const { return m_address; }
  26. size_t size() const { return m_size; }
  27. private:
  28. VirtualAddress m_address;
  29. size_t m_size;
  30. };
  31. enum class ShouldInitializeWeak {
  32. Yes,
  33. No
  34. };
  35. class DynamicLoader : public RefCounted<DynamicLoader> {
  36. public:
  37. static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> try_create(int fd, String filename);
  38. ~DynamicLoader();
  39. const String& filename() const { return m_filename; }
  40. bool is_valid() const { return m_valid; }
  41. // Load a full ELF image from file into the current process and create an DynamicObject
  42. // from the SHT_DYNAMIC in the file.
  43. // Note that the DynamicObject will not be linked yet. Callers are responsible for calling link() to finish it.
  44. RefPtr<DynamicObject> map();
  45. bool link(unsigned flags, size_t total_tls_size);
  46. // Stage 2 of loading: dynamic object loading and primary relocations
  47. bool load_stage_2(unsigned flags, size_t total_tls_size);
  48. // Stage 3 of loading: lazy relocations
  49. Result<NonnullRefPtr<DynamicObject>, DlErrorMessage> load_stage_3(unsigned flags, size_t total_tls_size);
  50. // Stage 4 of loading: initializers
  51. void load_stage_4();
  52. void set_tls_offset(size_t offset) { m_tls_offset = offset; };
  53. size_t tls_size_of_current_object() const { return m_tls_size_of_current_object; }
  54. size_t tls_offset() const { return m_tls_offset; }
  55. const ELF::Image& image() const { return m_elf_image; }
  56. template<typename F>
  57. void for_each_needed_library(F) const;
  58. VirtualAddress base_address() const { return m_base_address; }
  59. const Vector<LoadedSegment> text_segments() const { return m_text_segments; }
  60. bool is_dynamic() const { return m_elf_image.is_dynamic(); }
  61. static Optional<DynamicObject::SymbolLookupResult> lookup_symbol(const ELF::DynamicObject::Symbol&);
  62. private:
  63. DynamicLoader(int fd, String filename, void* file_data, size_t file_size);
  64. class ProgramHeaderRegion {
  65. public:
  66. void set_program_header(const Elf32_Phdr& header) { m_program_header = header; }
  67. // Information from ELF Program header
  68. u32 type() const { return m_program_header.p_type; }
  69. u32 flags() const { return m_program_header.p_flags; }
  70. u32 offset() const { return m_program_header.p_offset; }
  71. VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
  72. u32 size_in_memory() const { return m_program_header.p_memsz; }
  73. u32 size_in_image() const { return m_program_header.p_filesz; }
  74. u32 alignment() const { return m_program_header.p_align; }
  75. bool is_readable() const { return flags() & PF_R; }
  76. bool is_writable() const { return flags() & PF_W; }
  77. bool is_executable() const { return flags() & PF_X; }
  78. bool is_tls_template() const { return type() == PT_TLS; }
  79. bool is_load() const { return type() == PT_LOAD; }
  80. bool is_dynamic() const { return type() == PT_DYNAMIC; }
  81. bool is_relro() const { return type() == PT_GNU_RELRO; }
  82. private:
  83. Elf32_Phdr m_program_header; // Explicitly a copy of the PHDR in the image
  84. };
  85. const DynamicObject& dynamic_object() const;
  86. // Stage 1
  87. void load_program_headers();
  88. // Stage 2
  89. void do_main_relocations(size_t total_tls_size);
  90. // Stage 3
  91. void do_lazy_relocations(size_t total_tls_size);
  92. void setup_plt_trampoline();
  93. // Stage 4
  94. void call_object_init_functions();
  95. bool validate();
  96. enum class RelocationResult : uint8_t {
  97. Failed = 0,
  98. Success = 1,
  99. ResolveLater = 2,
  100. };
  101. RelocationResult do_relocation(size_t total_tls_size, const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
  102. size_t calculate_tls_size() const;
  103. ssize_t negative_offset_from_tls_block_end(size_t value_of_symbol, size_t tls_offset, size_t total_tls_size) const;
  104. String m_filename;
  105. String m_program_interpreter;
  106. size_t m_file_size { 0 };
  107. int m_image_fd { -1 };
  108. void* m_file_data { nullptr };
  109. ELF::Image m_elf_image;
  110. bool m_valid { true };
  111. RefPtr<DynamicObject> m_dynamic_object;
  112. VirtualAddress m_base_address;
  113. Vector<LoadedSegment> m_text_segments;
  114. VirtualAddress m_relro_segment_address;
  115. size_t m_relro_segment_size { 0 };
  116. VirtualAddress m_dynamic_section_address;
  117. size_t m_tls_offset { 0 };
  118. size_t m_tls_size_of_current_object { 0 };
  119. Vector<DynamicObject::Relocation> m_unresolved_relocations;
  120. mutable RefPtr<DynamicObject> m_cached_dynamic_object;
  121. };
  122. template<typename F>
  123. void DynamicLoader::for_each_needed_library(F func) const
  124. {
  125. dynamic_object().for_each_needed_library(move(func));
  126. }
  127. } // end namespace ELF