linker: map large portion of ELF file to read its fragments

ElfReader::Read() maps ELF file fragments separately to read their
data, which leads to at least 4 separate mmap() syscalls and additional
mmap() call for every PT_NOTE section. This can be replaced with one
mmap() syscall which covers large enough address space to include all
required areas in majority of cases and use the old approach for a few
outliers. Local testing on a Pixel 7 device reveals that 1MB is enough
to cover 97.5% of the cases, therefore we map the first 1MB of the Elf
file (which starts at file_offset_). pread64() syscall in ReadElfHeader()
can also be eliminated since it's always at the beginning of the Elf
file and will be included in this large mapping.
This reduction in syscalls should benefit app launch time since
ElfReader::Read() is used by load_library(), which is one of the heavily
used functions during application launch.

Bug: 322132947
Test: atest -c linker-unit-tests
Change-Id: I7b25151aba52da4116c2b6afd8a254646d0b622c
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index aab9018..dc1ca99 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -73,6 +73,7 @@
   [[nodiscard]] bool FindGnuPropertySection();
   [[nodiscard]] bool CheckPhdr(ElfW(Addr));
   [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
+  [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offs, off64_t size);
 
   bool did_read_;
   bool did_load_;
@@ -81,6 +82,8 @@
   off64_t file_offset_;
   off64_t file_size_;
 
+  MappedFileFragment file_fragment_;
+
   ElfW(Ehdr) header_;
   size_t phdr_num_;