* @brief Map ELF segments into memory. * * This function maps the loadable segments of an ELF file into the process's address space. * It handles both executable and shared library files, manages BSS sections, and sets up * the load address and base address for dynamic libraries. * * @param load_info Pointer to the structure containing ELF loading context. * @param elf_info Pointer to the s
| 617 | * @return -ENOMEM if memory allocation fails. |
| 618 | */ |
| 619 | static int elf_file_mmap(elf_load_info_t *load_info, elf_info_t *elf_info, rt_ubase_t *elfload_addr, |
| 620 | rt_uint32_t map_size, rt_ubase_t *load_base) |
| 621 | { |
| 622 | int ret, i; |
| 623 | rt_ubase_t map_va, bss_start, bss_end; |
| 624 | Elf_Ehdr *ehdr = &elf_info->ehdr; /* ELF header */ |
| 625 | Elf_Phdr *phdr = elf_info->phdr; /* Program header array */ |
| 626 | const Elf_Phdr *tmp_phdr = phdr; /* Current program header */ |
| 627 | int fd = elf_info->fd; /* File descriptor for ELF file */ |
| 628 | rt_ubase_t load_addr; /* Calculated load address */ |
| 629 | size_t prot = PROT_READ | PROT_WRITE; /* Memory protection flags */ |
| 630 | size_t flags = MAP_FIXED | MAP_PRIVATE; /* Memory mapping flags */ |
| 631 | |
| 632 | /* Iterate through all program headers */ |
| 633 | for (i = 0; i < ehdr->e_phnum; ++i, ++tmp_phdr) |
| 634 | { |
| 635 | /* Only process PT_LOAD segments (loadable segments) */ |
| 636 | if (tmp_phdr->p_type != PT_LOAD) |
| 637 | { |
| 638 | continue; |
| 639 | } |
| 640 | |
| 641 | /* For executable files, validate the program header */ |
| 642 | if (ehdr->e_type == ET_EXEC) |
| 643 | { |
| 644 | if (elf_check_phdr(tmp_phdr) != RT_EOK) |
| 645 | { |
| 646 | LOG_E("%s : elf_check_phdr failed", __func__); |
| 647 | return -RT_ERROR; |
| 648 | } |
| 649 | } |
| 650 | |
| 651 | load_addr = tmp_phdr->p_vaddr + *load_base; |
| 652 | LOG_D("%s : p_vaddr : 0x%x, load_addr : 0x%x", __func__, tmp_phdr->p_vaddr, load_addr); |
| 653 | |
| 654 | /* When both the segment's virtual address and the load base are 0, the segment is loaded at any available |
| 655 | address rather than a fixed one. This behavior is particularly useful for Position-Independent Code (PIC) |
| 656 | or shared libraries. */ |
| 657 | if ((tmp_phdr->p_vaddr == 0) && (*load_base == 0)) |
| 658 | { |
| 659 | flags &= ~MAP_FIXED; |
| 660 | } |
| 661 | |
| 662 | /* Map the segment into memory */ |
| 663 | map_va = elf_map(load_info->lwp, tmp_phdr, fd, load_addr, prot, flags, map_size); |
| 664 | if (!map_va) |
| 665 | { |
| 666 | LOG_E("%s : elf_map failed", __func__); |
| 667 | return -ENOMEM; |
| 668 | } |
| 669 | |
| 670 | map_size = 0; |
| 671 | |
| 672 | elf_user_dump(load_info->lwp, (void *)load_addr, 64); |
| 673 | |
| 674 | /* Handle BSS section (zero-initialized data) */ |
| 675 | if ((tmp_phdr->p_memsz > tmp_phdr->p_filesz) && (tmp_phdr->p_flags & PF_W)) |
| 676 | { |
no test coverage detected