ELFDynamicObject.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #pragma once
  2. #include <LibELF/ELFImage.h>
  3. #include <LibELF/exec_elf.h>
  4. #include <dlfcn.h>
  5. #include <mman.h>
  6. #include <AK/OwnPtr.h>
  7. #include <AK/RefCounted.h>
  8. #include <AK/String.h>
  9. #define ALIGN_ROUND_UP(x, align) ((((size_t)(x)) + align - 1) & (~(align - 1)))
  10. class ELFDynamicObject : public RefCounted<ELFDynamicObject> {
  11. public:
  12. static NonnullRefPtr<ELFDynamicObject> construct(const char* filename, int fd, size_t file_size);
  13. ~ELFDynamicObject();
  14. bool is_valid() const { return m_valid; }
  15. // FIXME: How can we resolve all of the symbols without having the original elf image for our process?
  16. // RTLD_LAZY only at first probably... though variables ('objects') need resolved at load time every time
  17. bool load(unsigned flags);
  18. // Intended for use by dlsym or other internal methods
  19. void* symbol_for_name(const char*);
  20. void dump();
  21. private:
  22. class ProgramHeaderRegion {
  23. public:
  24. ProgramHeaderRegion(const Elf32_Phdr& header)
  25. : m_program_header(header)
  26. {
  27. }
  28. VirtualAddress load_address() const { return m_load_address; }
  29. VirtualAddress base_address() const { return m_image_base_address; }
  30. void set_load_address(VirtualAddress addr) { m_load_address = addr; }
  31. void set_base_address(VirtualAddress addr) { m_image_base_address = addr; }
  32. // Information from ELF Program header
  33. u32 type() const { return m_program_header.p_type; }
  34. u32 flags() const { return m_program_header.p_flags; }
  35. u32 offset() const { return m_program_header.p_offset; }
  36. VirtualAddress desired_load_address() const { return VirtualAddress(m_program_header.p_vaddr); }
  37. u32 size_in_memory() const { return m_program_header.p_memsz; }
  38. u32 size_in_image() const { return m_program_header.p_filesz; }
  39. u32 alignment() const { return m_program_header.p_align; }
  40. u32 mmap_prot() const;
  41. bool is_readable() const { return flags() & PF_R; }
  42. bool is_writable() const { return flags() & PF_W; }
  43. bool is_executable() const { return flags() & PF_X; }
  44. bool is_tls_template() const { return type() == PT_TLS; }
  45. bool is_load() const { return type() == PT_LOAD; }
  46. bool is_dynamic() const { return type() == PT_DYNAMIC; }
  47. u32 required_load_size() { return ALIGN_ROUND_UP(m_program_header.p_memsz, m_program_header.p_align); }
  48. private:
  49. Elf32_Phdr m_program_header; // Explictly a copy of the PHDR in the image
  50. VirtualAddress m_load_address { 0 };
  51. VirtualAddress m_image_base_address { 0 };
  52. };
  53. explicit ELFDynamicObject(const char* filename, int fd, size_t file_size);
  54. String m_filename;
  55. size_t m_file_size { 0 };
  56. int m_image_fd { -1 };
  57. void* m_file_mapping { nullptr };
  58. bool m_valid { false };
  59. OwnPtr<ELFImage> m_image;
  60. void parse_dynamic_section();
  61. void do_relocations();
  62. static void patch_plt_entry(u32 got_offset, void* dso_got_tag);
  63. Vector<ProgramHeaderRegion> m_program_header_regions;
  64. ProgramHeaderRegion* m_text_region { nullptr };
  65. ProgramHeaderRegion* m_data_region { nullptr };
  66. ProgramHeaderRegion* m_tls_region { nullptr };
  67. // Begin Section information collected from DT_* entries
  68. uintptr_t m_init_offset { 0 };
  69. uintptr_t m_fini_offset { 0 };
  70. uintptr_t m_init_array_offset { 0 };
  71. size_t m_init_array_size { 0 };
  72. uintptr_t m_hash_table_offset { 0 };
  73. uintptr_t m_string_table_offset { 0 };
  74. uintptr_t m_symbol_table_offset { 0 };
  75. size_t m_size_of_string_table { 0 };
  76. size_t m_size_of_symbol_table_entry { 0 };
  77. Elf32_Sword m_procedure_linkage_table_relocation_type { -1 };
  78. uintptr_t m_plt_relocation_offset_location { 0 }; // offset of PLT relocations, at end of relocations
  79. size_t m_size_of_plt_relocation_entry_list { 0 };
  80. uintptr_t m_procedure_linkage_table_offset { 0 };
  81. // NOTE: We'll only ever either RELA or REL entries, not both (thank god)
  82. size_t m_number_of_relocations { 0 };
  83. size_t m_size_of_relocation_entry { 0 };
  84. size_t m_size_of_relocation_table { 0 };
  85. uintptr_t m_relocation_table_offset { 0 };
  86. // DT_FLAGS
  87. bool m_should_process_origin = false;
  88. bool m_requires_symbolic_symbol_resolution = false;
  89. // Text relocations meaning: we need to edit the .text section which is normally mapped PROT_READ
  90. bool m_has_text_relocations = false;
  91. bool m_must_bind_now = false; // FIXME: control with an environment var as well?
  92. bool m_has_static_thread_local_storage = false;
  93. // End Section information from DT_* entries
  94. };