DynamicLoader.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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/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);
  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_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. void copy_initial_tls_data_into(ByteBuffer& buffer) const;
  63. private:
  64. DynamicLoader(int fd, String filename, void* file_data, size_t file_size);
  65. class ProgramHeaderRegion {
  66. public:
  67. void set_program_header(const ElfW(Phdr) & header) { m_program_header = header; }
  68. // Information from ELF Program header
  69. u32 type() const { return m_program_header.p_type; }
  70. u32 flags() const { return m_program_header.p_flags; }
  71. u32 offset() const { return m_program_header.p_offset; }
  72. VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
  73. u32 size_in_memory() const { return m_program_header.p_memsz; }
  74. u32 size_in_image() const { return m_program_header.p_filesz; }
  75. u32 alignment() const { return m_program_header.p_align; }
  76. bool is_readable() const { return flags() & PF_R; }
  77. bool is_writable() const { return flags() & PF_W; }
  78. bool is_executable() const { return flags() & PF_X; }
  79. bool is_tls_template() const { return type() == PT_TLS; }
  80. bool is_load() const { return type() == PT_LOAD; }
  81. bool is_dynamic() const { return type() == PT_DYNAMIC; }
  82. bool is_relro() const { return type() == PT_GNU_RELRO; }
  83. private:
  84. ElfW(Phdr) m_program_header; // Explicitly a copy of the PHDR in the image
  85. };
  86. const DynamicObject& dynamic_object() const;
  87. // Stage 1
  88. void load_program_headers();
  89. // Stage 2
  90. void do_main_relocations();
  91. // Stage 3
  92. void do_lazy_relocations();
  93. void setup_plt_trampoline();
  94. // Stage 4
  95. void call_object_init_functions();
  96. bool validate();
  97. enum class RelocationResult : uint8_t {
  98. Failed = 0,
  99. Success = 1,
  100. ResolveLater = 2,
  101. };
  102. RelocationResult do_relocation(const DynamicObject::Relocation&, ShouldInitializeWeak should_initialize_weak);
  103. size_t calculate_tls_size() const;
  104. ssize_t negative_offset_from_tls_block_end(ssize_t tls_offset, size_t value_of_symbol) const;
  105. String m_filename;
  106. String m_program_interpreter;
  107. size_t m_file_size { 0 };
  108. int m_image_fd { -1 };
  109. void* m_file_data { nullptr };
  110. ELF::Image m_elf_image;
  111. bool m_valid { true };
  112. RefPtr<DynamicObject> m_dynamic_object;
  113. VirtualAddress m_base_address;
  114. Vector<LoadedSegment> m_text_segments;
  115. VirtualAddress m_relro_segment_address;
  116. size_t m_relro_segment_size { 0 };
  117. VirtualAddress m_dynamic_section_address;
  118. ssize_t m_tls_offset { 0 };
  119. size_t m_tls_size_of_current_object { 0 };
  120. Vector<DynamicObject::Relocation> m_unresolved_relocations;
  121. mutable RefPtr<DynamicObject> m_cached_dynamic_object;
  122. };
  123. template<typename F>
  124. void DynamicLoader::for_each_needed_library(F func) const
  125. {
  126. dynamic_object().for_each_needed_library(move(func));
  127. }
  128. } // end namespace ELF