DynamicLoader.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (c) 2019-2020, Andrew Kaster <akaster@serenityos.org>
  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/DeprecatedString.h>
  10. #include <AK/OwnPtr.h>
  11. #include <AK/RefCounted.h>
  12. #include <LibC/elf.h>
  13. #include <LibELF/DynamicObject.h>
  14. #include <LibELF/Image.h>
  15. #include <bits/dlfcn_integration.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. extern "C" FlatPtr _fixup_plt_entry(DynamicObject* object, u32 relocation_offset);
  36. class DynamicLoader : public RefCounted<DynamicLoader> {
  37. public:
  38. static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> try_create(int fd, DeprecatedString filepath);
  39. ~DynamicLoader();
  40. DeprecatedString const& filepath() const { return m_filepath; }
  41. bool is_valid() const { return m_valid; }
  42. // Load a full ELF image from file into the current process and create an DynamicObject
  43. // from the SHT_DYNAMIC in the file.
  44. // Note that the DynamicObject will not be linked yet. Callers are responsible for calling link() to finish it.
  45. RefPtr<DynamicObject> map();
  46. bool link(unsigned flags);
  47. // Stage 2 of loading: dynamic object loading and primary relocations
  48. bool load_stage_2(unsigned flags);
  49. // Stage 3 of loading: lazy relocations
  50. Result<NonnullRefPtr<DynamicObject>, DlErrorMessage> load_stage_3(unsigned flags);
  51. // Stage 4 of loading: initializers
  52. void load_stage_4();
  53. void set_tls_offset(size_t offset) { m_tls_offset = offset; };
  54. size_t tls_size_of_current_object() const { return m_tls_size_of_current_object; }
  55. size_t tls_alignment_of_current_object() const { return m_tls_alignment_of_current_object; }
  56. size_t tls_offset() const { return m_tls_offset; }
  57. const ELF::Image& image() const { return *m_elf_image; }
  58. template<typename F>
  59. void for_each_needed_library(F) const;
  60. VirtualAddress base_address() const { return m_base_address; }
  61. Vector<LoadedSegment> const text_segments() const { return m_text_segments; }
  62. bool is_dynamic() const { return image().is_dynamic(); }
  63. static Optional<DynamicObject::SymbolLookupResult> lookup_symbol(const ELF::DynamicObject::Symbol&);
  64. void copy_initial_tls_data_into(ByteBuffer& buffer) const;
  65. DynamicObject const& dynamic_object() const;
  66. bool is_fully_relocated() const { return m_fully_relocated; }
  67. bool is_fully_initialized() const { return m_fully_initialized; }
  68. private:
  69. DynamicLoader(int fd, DeprecatedString filepath, void* file_data, size_t file_size);
  70. class ProgramHeaderRegion {
  71. public:
  72. void set_program_header(const ElfW(Phdr) & header) { m_program_header = header; }
  73. // Information from ELF Program header
  74. u32 type() const { return m_program_header.p_type; }
  75. u32 flags() const { return m_program_header.p_flags; }
  76. u32 offset() const { return m_program_header.p_offset; }
  77. VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
  78. u32 size_in_memory() const { return m_program_header.p_memsz; }
  79. u32 size_in_image() const { return m_program_header.p_filesz; }
  80. u32 alignment() const { return m_program_header.p_align; }
  81. bool is_readable() const { return flags() & PF_R; }
  82. bool is_writable() const { return flags() & PF_W; }
  83. bool is_executable() const { return flags() & PF_X; }
  84. bool is_tls_template() const { return type() == PT_TLS; }
  85. bool is_load() const { return type() == PT_LOAD; }
  86. bool is_dynamic() const { return type() == PT_DYNAMIC; }
  87. bool is_relro() const { return type() == PT_GNU_RELRO; }
  88. private:
  89. ElfW(Phdr) m_program_header; // Explicitly a copy of the PHDR in the image
  90. };
  91. friend FlatPtr _fixup_plt_entry(DynamicObject*, u32);
  92. // Stage 1
  93. void load_program_headers();
  94. // Stage 2
  95. void do_main_relocations();
  96. // Stage 3
  97. void do_lazy_relocations();
  98. void setup_plt_trampoline();
  99. // Stage 4
  100. void call_object_init_functions();
  101. bool validate();
  102. enum class RelocationResult : uint8_t {
  103. Failed = 0,
  104. Success = 1,
  105. ResolveLater = 2,
  106. };
  107. RelocationResult do_direct_relocation(DynamicObject::Relocation const&, ShouldInitializeWeak);
  108. static RelocationResult do_plt_relocation(DynamicObject::Relocation const&);
  109. void do_relr_relocations();
  110. void find_tls_size_and_alignment();
  111. DeprecatedString m_filepath;
  112. size_t m_file_size { 0 };
  113. int m_image_fd { -1 };
  114. void* m_file_data { nullptr };
  115. OwnPtr<ELF::Image> m_elf_image;
  116. bool m_valid { true };
  117. RefPtr<DynamicObject> m_dynamic_object;
  118. VirtualAddress m_base_address;
  119. Vector<LoadedSegment> m_text_segments;
  120. VirtualAddress m_relro_segment_address;
  121. size_t m_relro_segment_size { 0 };
  122. VirtualAddress m_dynamic_section_address;
  123. ssize_t m_tls_offset { 0 };
  124. size_t m_tls_size_of_current_object { 0 };
  125. size_t m_tls_alignment_of_current_object { 0 };
  126. Vector<DynamicObject::Relocation> m_unresolved_relocations;
  127. mutable RefPtr<DynamicObject> m_cached_dynamic_object;
  128. bool m_fully_relocated { false };
  129. bool m_fully_initialized { false };
  130. };
  131. template<typename F>
  132. void DynamicLoader::for_each_needed_library(F func) const
  133. {
  134. dynamic_object().for_each_needed_library(move(func));
  135. }
  136. } // end namespace ELF