772 return false; |
772 return false; |
773 } |
773 } |
774 |
774 |
775 // process segments from interpreter (ld.so or ld-linux.so) |
775 // process segments from interpreter (ld.so or ld-linux.so) |
776 static bool read_interp_segments(struct ps_prochandle* ph) { |
776 static bool read_interp_segments(struct ps_prochandle* ph) { |
777 ELF_EHDR interp_ehdr; |
777 ELF_EHDR interp_ehdr; |
778 |
778 |
779 if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { |
779 if (read_elf_header(ph->core->interp_fd, &interp_ehdr) != true) { |
780 print_debug("interpreter is not a valid ELF file\n"); |
780 print_debug("interpreter is not a valid ELF file\n"); |
781 return false; |
781 return false; |
782 } |
782 } |
783 |
783 |
784 if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { |
784 if (read_lib_segments(ph, ph->core->interp_fd, &interp_ehdr, ph->core->ld_base_addr) != true) { |
785 print_debug("can't read segments of interpreter\n"); |
785 print_debug("can't read segments of interpreter\n"); |
786 return false; |
786 return false; |
787 } |
787 } |
788 |
788 |
789 return true; |
789 return true; |
790 } |
790 } |
791 |
791 |
792 // process segments of a a.out |
792 // process segments of a a.out |
793 static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) { |
793 static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) { |
794 int i = 0; |
794 int i = 0; |
795 ELF_PHDR* phbuf = NULL; |
795 ELF_PHDR* phbuf = NULL; |
796 ELF_PHDR* exec_php = NULL; |
796 ELF_PHDR* exec_php = NULL; |
797 |
797 |
798 if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) |
798 if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) { |
799 return false; |
799 return false; |
800 |
800 } |
801 for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) { |
801 |
802 switch (exec_php->p_type) { |
802 for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) { |
803 |
803 switch (exec_php->p_type) { |
804 // add mappings for PT_LOAD segments |
804 |
805 case PT_LOAD: { |
805 // add mappings for PT_LOAD segments |
806 // add only non-writable segments of non-zero filesz |
806 case PT_LOAD: { |
807 if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { |
807 // add only non-writable segments of non-zero filesz |
808 if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err; |
808 if (!(exec_php->p_flags & PF_W) && exec_php->p_filesz != 0) { |
809 } |
809 if (add_map_info(ph, ph->core->exec_fd, exec_php->p_offset, exec_php->p_vaddr, exec_php->p_filesz) == NULL) goto err; |
810 break; |
810 } |
811 } |
811 break; |
812 |
812 } |
813 // read the interpreter and it's segments |
813 |
814 case PT_INTERP: { |
814 // read the interpreter and it's segments |
815 char interp_name[BUF_SIZE]; |
815 case PT_INTERP: { |
816 |
816 char interp_name[BUF_SIZE + 1]; |
817 pread(ph->core->exec_fd, interp_name, MIN(exec_php->p_filesz, BUF_SIZE), exec_php->p_offset); |
817 |
818 print_debug("ELF interpreter %s\n", interp_name); |
818 // BUF_SIZE is PATH_MAX + NAME_MAX + 1. |
819 // read interpreter segments as well |
819 if (exec_php->p_filesz > BUF_SIZE) { |
820 if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { |
820 goto err; |
821 print_debug("can't open runtime loader\n"); |
821 } |
822 goto err; |
822 pread(ph->core->exec_fd, interp_name, exec_php->p_filesz, exec_php->p_offset); |
823 } |
823 interp_name[exec_php->p_filesz] = '\0'; |
824 break; |
824 print_debug("ELF interpreter %s\n", interp_name); |
825 } |
825 // read interpreter segments as well |
826 |
826 if ((ph->core->interp_fd = pathmap_open(interp_name)) < 0) { |
827 // from PT_DYNAMIC we want to read address of first link_map addr |
827 print_debug("can't open runtime loader\n"); |
828 case PT_DYNAMIC: { |
828 goto err; |
829 ph->core->dynamic_addr = exec_php->p_vaddr; |
829 } |
830 print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr); |
830 break; |
831 break; |
831 } |
832 } |
832 |
833 |
833 // from PT_DYNAMIC we want to read address of first link_map addr |
834 } // switch |
834 case PT_DYNAMIC: { |
835 exec_php++; |
835 ph->core->dynamic_addr = exec_php->p_vaddr; |
836 } // for |
836 print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr); |
837 |
837 break; |
838 free(phbuf); |
838 } |
839 return true; |
839 |
840 err: |
840 } // switch |
841 free(phbuf); |
841 exec_php++; |
842 return false; |
842 } // for |
|
843 |
|
844 free(phbuf); |
|
845 return true; |
|
846 err: |
|
847 free(phbuf); |
|
848 return false; |
843 } |
849 } |
844 |
850 |
845 |
851 |
846 #define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug, r_map) |
852 #define FIRST_LINK_MAP_OFFSET offsetof(struct r_debug, r_map) |
847 #define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase) |
853 #define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase) |