ELFBuild.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2023, Jesús Lapastora <cyber.gsuscode@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibELF/ELFBuild.h>
  7. namespace ELF {
  8. SectionTable::Index StringTable::emit_into_builder(u32 name_index, SectionTable& builder) const noexcept
  9. {
  10. return builder.append(emit_section(name_index));
  11. }
  12. Section StringTable::emit_section(u32 name_index) const noexcept
  13. {
  14. Elf64_Shdr header {};
  15. header.sh_name = name_index;
  16. header.sh_type = SHT_STRTAB;
  17. header.sh_flags = 0;
  18. header.sh_addr = 0;
  19. header.sh_link = 0;
  20. header.sh_info = 0;
  21. header.sh_entsize = 0;
  22. header.sh_addralign = 0;
  23. return Section(m_data.span(), header);
  24. }
  25. u32 StringTable::insert(StringView str) noexcept
  26. {
  27. // The offsets for sh_name and st_name are 32-bit unsigned integers, so it
  28. // won't make sense to address a string table bigger than what u32 can
  29. // provide.
  30. VERIFY(m_data.size() < NumericLimits<u32>::max());
  31. auto const offset = static_cast<u32>(m_data.size());
  32. auto const final_size = m_data.size() + str.length() + 1;
  33. VERIFY(final_size < NumericLimits<u32>::max());
  34. m_data.ensure_capacity(m_data.size() + str.length() + 1);
  35. for (auto ch : str) {
  36. VERIFY(ch != 0);
  37. m_data.unchecked_append(ch);
  38. }
  39. m_data.append(0);
  40. return offset;
  41. }
  42. FixedArray<u8> build_elf_image(u64 shstrndx, Elf64_Quarter image_type, ReadonlySpan<Section> sections)
  43. {
  44. Checked<u64> final_image_size = sizeof(Elf64_Ehdr);
  45. Vector<u64> section_offsets;
  46. section_offsets.ensure_capacity(sections.size());
  47. auto const sections_begin = final_image_size.value_unchecked();
  48. final_image_size += sizeof(Elf64_Shdr) * sections.size();
  49. for (auto const& section : sections) {
  50. auto const offset = final_image_size.value();
  51. section_offsets.unchecked_append(offset);
  52. if (section.data.has_value()) {
  53. final_image_size += section.data.value().size();
  54. }
  55. }
  56. auto image = MUST(FixedArray<u8>::create(final_image_size.value()));
  57. {
  58. auto section_headers = Span<Elf64_Shdr> {
  59. reinterpret_cast<Elf64_Shdr*>(image.span().offset_pointer(sections_begin)),
  60. sections.size(),
  61. };
  62. for (size_t i = 0; i < sections.size(); ++i) {
  63. section_headers[i] = sections[i].header;
  64. section_headers[i].sh_offset = section_offsets[i];
  65. if (sections[i].data.has_value()) {
  66. auto const data = sections[i].data.value();
  67. auto const data_in_elf = image.span().slice(section_offsets[i], data.size());
  68. data.copy_to(data_in_elf);
  69. section_headers[i].sh_size = data.size();
  70. }
  71. }
  72. }
  73. {
  74. auto* const final_elf_hdr = reinterpret_cast<Elf64_Ehdr*>(image.data());
  75. final_elf_hdr->e_ident[EI_MAG0] = 0x7f;
  76. final_elf_hdr->e_ident[EI_MAG1] = 'E';
  77. final_elf_hdr->e_ident[EI_MAG2] = 'L';
  78. final_elf_hdr->e_ident[EI_MAG3] = 'F';
  79. final_elf_hdr->e_ident[EI_CLASS] = ELFCLASS64;
  80. // FIXME: This is platform-dependent. Any big-endian host will write the
  81. // data in MSB format, so the EI_DATA field should be set to
  82. // ELFDATA2MSB.
  83. final_elf_hdr->e_ident[EI_DATA] = ELFDATA2LSB;
  84. final_elf_hdr->e_ident[EI_VERSION] = EV_CURRENT;
  85. // FIXME: This is platform-dependent. The host must set the OSABI to the
  86. // one of the image target.
  87. final_elf_hdr->e_ident[EI_OSABI] = ELFOSABI_SYSV;
  88. final_elf_hdr->e_ident[EI_ABIVERSION] = 0;
  89. auto padding = Bytes {
  90. &final_elf_hdr->e_ident[EI_PAD],
  91. EI_NIDENT - EI_PAD,
  92. };
  93. padding.fill(0);
  94. final_elf_hdr->e_type = image_type;
  95. // FIXME: This is platform-dependent. This must be set to the host
  96. // architecture.
  97. final_elf_hdr->e_machine = EM_AMD64;
  98. final_elf_hdr->e_version = EV_CURRENT;
  99. // Currently segments aren't supported, hence no program headers.
  100. // FIXME: Update program header info on ELF header when adding segment
  101. // information.
  102. final_elf_hdr->e_phoff = 0;
  103. final_elf_hdr->e_phnum = 0;
  104. final_elf_hdr->e_phentsize = 0;
  105. final_elf_hdr->e_shoff = sections_begin;
  106. final_elf_hdr->e_shnum = sections.size();
  107. final_elf_hdr->e_shentsize = sizeof(Section::header);
  108. // FIXME: This is platform-dependent. The flags field should be in sync
  109. // with the architecture flags assumed in the code sections, otherwise
  110. // instructions may be misinterpreted.
  111. final_elf_hdr->e_flags = 0;
  112. final_elf_hdr->e_ehsize = sizeof(*final_elf_hdr);
  113. final_elf_hdr->e_shstrndx = shstrndx;
  114. }
  115. return image;
  116. }
  117. };