如何从内部获取指向程序的特定可执行文件部分的指针? (也许和libelf一起)

我在Linux环境中,我需要创建一个程序来检索放置在其可执行文件的一个部分中的一些数据。 那么,如何从内部获取指向程序某一部分(通过其名称)的指针?

我知道可以使用elf_getdata()传递section的索引作为get和Elf_Data结构的参数,这个结构的一个字段是d_buf ,它是指向实际数据的指针。 但是,似乎elf_getdata()函数将段数据的副本从文件复制到内存中,这不是我想要的。 我想要一个指向加载时加载到内存中的数据的指针。

伙计们,任何想法?

实际上,使用libelf ,可以使用Elf64_Shdr结构(对于64位系统)来获取指向节的指针,因为sh_addr字段确实指向将在运行时加载节的实际地址。 因此,它可以用作指针。 这样,甚至不需要使用elf_getdata()函数来检索Elf_Data结构。

因为我想要做的是一个可以链接其他目标文件的库,我的代码可能有一个函数可以打开可执行文件本身以利用一些libelffunction,这样它就可以从主文件部分读取数据,如下:

 // A global variable which stores the executable file name extern const char *__progname; void retrieve_data() { int fd; // File descriptor for the executable ELF file char *section_name, path[256]; size_t shstrndx; Elf *e; // ELF struct Elf_Scn *scn; // Section index struct Elf64_Shdr *shdr; // Section struct // Create the full path of the executable getcwd(path, 255); strcat(path, "/"); strcat(path, __progname); if(elf_version(EV_CURRENT)==EV_NONE) errx(EXIT_FAILURE, "ELF library iinitialization failed: %s", elf_errmsg(-1)); if((fd = open(path, O_RDONLY, 0))<0) err(EXIT_FAILURE, "open \"%s\" failed", path); if((e = elf_begin(fd, ELF_C_READ, NULL))==NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s.", elf_errmsg(-1)); // Retrieve the section index of the ELF section containing the string table of section names if(elf_getshdrstrndx(e, &shstrndx)!=0) errx(EXIT_FAILURE, "elf_getshdrstrndx() failed: %s.", elf_errmsg(-1)); scn = NULL; // Loop over all sections in the ELF object while((scn = elf_nextscn(e, scn))!=NULL) { // Given a Elf Scn pointer, retrieve the associated section header if((shdr = elf64_getshdr(scn))!=shdr) errx(EXIT_FAILURE, "getshdr() failed: %s.", elf_errmsg(-1)); // Retrieve the name of the section name if((name = elf_strptr(e, shstrndx, shdr->sh_name))==NULL) errx(EXIT_FAILURE, "elf_strptr() failed: %s.", elf_errmsg(-1)); // If the section is the one we want... (in my case, it is one of the main file sections) if(!strcmp(section_name, "Section name")) { // We can use the section adress as a pointer, since it corresponds to the actual // adress where the section is placed in the virtual memory struct data_t * section_data = (struct data_t *) shdr->sh_addr; // Do whatever we want // End the loop (if we only need this section) break; } } elf_end(e); close(fd); } 

ELF标头不一定映射到内存中,因此依赖它可能有点冒险。 这是一种不需要任何API的方法:

  1. 声明两个符号,表示相关部分的开头和结尾。
  2. 使用__attribute__ ((section ("")))将它们放在具有已知名称的部分中
  3. 使用自定义链接描述文件,在两个变量的部分之间放置所需的部分。

或者,您可以使用链接器生成的符号 ,就像_etext / _edata / _end所做的那样 。