DynamicLoader.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. class DynamicLoader : public RefCounted<DynamicLoader> {
  36. public:
  37. static Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> try_create(int fd, DeprecatedString filepath);
  38. ~DynamicLoader();
  39. DeprecatedString const& filepath() const { return m_filepath; }
  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);
  46. // Stage 2 of loading: dynamic object loading and primary relocations
  47. bool load_stage_2(unsigned flags);
  48. // Stage 3 of loading: lazy relocations
  49. Result<NonnullRefPtr<DynamicObject>, DlErrorMessage> load_stage_3(unsigned flags);
  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_alignment_of_current_object() const { return m_tls_alignment_of_current_object; }
  55. size_t tls_offset() const { return m_tls_offset; }
  56. const ELF::Image& image() const { return *m_elf_image; }
  57. template<typename F>
  58. void for_each_needed_library(F) const;
  59. VirtualAddress base_address() const { return m_base_address; }
  60. Vector<LoadedSegment> const text_segments() const { return m_text_segments; }
  61. bool is_dynamic() const { return image().is_dynamic(); }
  62. static Optional<DynamicObject::SymbolLookupResult> lookup_symbol(const ELF::DynamicObject::Symbol&);
  63. void copy_initial_tls_data_into(ByteBuffer& buffer) const;
  64. DynamicObject const& dynamic_object() const;
  65. bool is_fully_relocated() const { return m_fully_relocated; }
  66. bool is_fully_initialized() const { return m_fully_initialized; }
  67. private:
  68. DynamicLoader(int fd, DeprecatedString filepath, void* file_data, size_t file_size);
  69. class ProgramHeaderRegion {
  70. public:
  71. void set_program_header(const ElfW(Phdr) & header) { m_program_header = header; }
  72. // Information from ELF Program header
  73. u32 type() const { return m_program_header.p_type; }
  74. u32 flags() const { return m_program_header.p_flags; }
  75. u32 offset() const { return m_program_header.p_offset; }
  76. VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
  77. u32 size_in_memory() const { return m_program_header.p_memsz; }
  78. u32 size_in_image() const { return m_program_header.p_filesz; }
  79. u32 alignment() const { return m_program_header.p_align; }
  80. bool is_readable() const { return flags() & PF_R; }
  81. bool is_writable() const { return flags() & PF_W; }
  82. bool is_executable() const { return flags() & PF_X; }
  83. bool is_tls_template() const { return type() == PT_TLS; }
  84. bool is_load() const { return type() == PT_LOAD; }
  85. bool is_dynamic() const { return type() == PT_DYNAMIC; }
  86. bool is_relro() const { return type() == PT_GNU_RELRO; }
  87. private:
  88. ElfW(Phdr) m_program_header; // Explicitly a copy of the PHDR in the image
  89. };
  90. // Stage 1
  91. void load_program_headers();
  92. // Stage 2
  93. void do_main_relocations();
  94. // Stage 3
  95. void do_lazy_relocations();
  96. void setup_plt_trampoline();
  97. // Stage 4
  98. void call_object_init_functions();
  99. bool validate();
  100. enum class RelocationResult : uint8_t {
  101. Failed = 0,
  102. Success = 1,
  103. ResolveLater = 2,
  104. };
  105. RelocationResult do_relocation(DynamicObject::Relocation const&, ShouldInitializeWeak should_initialize_weak);
  106. void do_relr_relocations();
  107. void find_tls_size_and_alignment();
  108. DeprecatedString m_filepath;
  109. size_t m_file_size { 0 };
  110. int m_image_fd { -1 };
  111. void* m_file_data { nullptr };
  112. OwnPtr<ELF::Image> m_elf_image;
  113. bool m_valid { true };
  114. RefPtr<DynamicObject> m_dynamic_object;
  115. VirtualAddress m_base_address;
  116. Vector<LoadedSegment> m_text_segments;
  117. VirtualAddress m_relro_segment_address;
  118. size_t m_relro_segment_size { 0 };
  119. VirtualAddress m_dynamic_section_address;
  120. ssize_t m_tls_offset { 0 };
  121. size_t m_tls_size_of_current_object { 0 };
  122. size_t m_tls_alignment_of_current_object { 0 };
  123. Vector<DynamicObject::Relocation> m_unresolved_relocations;
  124. mutable RefPtr<DynamicObject> m_cached_dynamic_object;
  125. bool m_fully_relocated { false };
  126. bool m_fully_initialized { false };
  127. };
  128. template<typename F>
  129. void DynamicLoader::for_each_needed_library(F func) const
  130. {
  131. dynamic_object().for_each_needed_library(move(func));
  132. }
  133. } // end namespace ELF