Get the start and end address of text section in an executable

后端 未结 4 1752
[愿得一人]
[愿得一人] 2020-12-01 09:28

I need to get the start and end address of an executable\'s text section. How can I get it?

I can get the starting address from the _init symbol or the

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-01 10:27

    It's incorrect to speak of "the" text segment, since there may be more than one (guaranteed for the usual case when you have shared libraries, but it's still possible for a single ELF binary to have multiple PT_LOAD sections with the same flags anyway).

    The following sample program dumps out all the information returned by dl_iterate_phr. You're interested in any segment of type PT_LOAD with the PF_X flag (note that PT_GNU_STACK will include the flag if -z execstack is passed to the linker, so you really do have to check both).

    #define _GNU_SOURCE
    #include 
    #include 
    #include 
    #include 
    
    const char *type_str(ElfW(Word) type)
    {
        switch (type)
        {
        case PT_NULL:
            return "PT_NULL"; // should not be seen at runtime, only in the file!
        case PT_LOAD:
            return "PT_LOAD";
        case PT_DYNAMIC:
            return "PT_DYNAMIC";
        case PT_INTERP:
            return "PT_INTERP";
        case PT_NOTE:
            return "PT_NOTE";
        case PT_SHLIB:
            return "PT_SHLIB";
        case PT_PHDR:
            return "PT_PHDR";
        case PT_TLS:
            return "PT_TLS";
        case PT_GNU_EH_FRAME:
            return "PT_GNU_EH_FRAME";
        case PT_GNU_STACK:
            return "PT_GNU_STACK";
        case PT_GNU_RELRO:
            return "PT_GNU_RELRO";
        case PT_SUNWBSS:
            return "PT_SUNWBSS";
        case PT_SUNWSTACK:
            return "PT_SUNWSTACK";
        default:
            if (PT_LOOS <= type && type <= PT_HIOS)
            {
                return "Unknown OS-specific";
            }
            if (PT_LOPROC <= type && type <= PT_HIPROC)
            {
                return "Unknown processor-specific";
            }
            return "Unknown";
        }
    }
    
    const char *flags_str(ElfW(Word) flags)
    {
        switch (flags & (PF_R | PF_W | PF_X))
        {
        case 0 | 0 | 0:
            return "none";
        case 0 | 0 | PF_X:
            return "x";
        case 0 | PF_W | 0:
            return "w";
        case 0 | PF_W | PF_X:
            return "wx";
        case PF_R | 0 | 0:
            return "r";
        case PF_R | 0 | PF_X:
            return "rx";
        case PF_R | PF_W | 0:
            return "rw";
        case PF_R | PF_W | PF_X:
            return "rwx";
        }
        __builtin_unreachable();
    }
    
    static int callback(struct dl_phdr_info *info, size_t size, void *data)
    {
        int j;
        (void)data;
    
        printf("object \"%s\"\n", info->dlpi_name);
        printf("  base address: %p\n", (void *)info->dlpi_addr);
        if (size > offsetof(struct dl_phdr_info, dlpi_adds))
        {
            printf("  adds: %lld\n", info->dlpi_adds);
        }
        if (size > offsetof(struct dl_phdr_info, dlpi_subs))
        {
            printf("  subs: %lld\n", info->dlpi_subs);
        }
        if (size > offsetof(struct dl_phdr_info, dlpi_tls_modid))
        {
            printf("  tls modid: %zu\n", info->dlpi_tls_modid);
        }
        if (size > offsetof(struct dl_phdr_info, dlpi_tls_data))
        {
            printf("  tls data: %p\n", info->dlpi_tls_data);
        }
        printf("  segments: %d\n", info->dlpi_phnum);
    
        for (j = 0; j < info->dlpi_phnum; j++)
        {
            const ElfW(Phdr) *hdr = &info->dlpi_phdr[j];
            printf("    segment %2d\n", j);
            printf("      type: 0x%08X (%s)\n", hdr->p_type, type_str(hdr->p_type));
            printf("      file offset: 0x%08zX\n", hdr->p_offset);
            printf("      virtual addr: %p\n", (void *)hdr->p_vaddr);
            printf("      physical addr: %p\n", (void *)hdr->p_paddr);
            printf("      file size: 0x%08zX\n", hdr->p_filesz);
            printf("      memory size: 0x%08zX\n", hdr->p_memsz);
            printf("      flags: 0x%08X (%s)\n", hdr->p_flags, flags_str(hdr->p_flags));
            printf("      align: %zd\n", hdr->p_align);
            if (hdr->p_memsz)
            {
                printf("      derived address range: %p to %p\n",
                    (void *) (info->dlpi_addr + hdr->p_vaddr),
                    (void *) (info->dlpi_addr + hdr->p_vaddr + hdr->p_memsz));
            }
        }
        return 0;
    }
    
    int main(void)
    {
        dl_iterate_phdr(callback, NULL);
    
        exit(EXIT_SUCCESS);
    }
    

提交回复
热议问题