如何从自身内部获取指向程序的特定可执行文件部分的指针? (也许与libelf) [英] How to get a pointer to a specific executable file's section of a program from within itself? (Maybe with libelf)

查看:137
本文介绍了如何从自身内部获取指向程序的特定可执行文件部分的指针? (也许与libelf)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Linux环境中,我需要制作一个程序来检索放置在其可执行文件部分之一中的某些数据.那么,如何从自身内部获取指向程序部分的指针(按其名称)?

I'm on a Linux environment and I need to make a program that retrieves some data that is placed in one of the sections of its executable file. So, how to get a pointer to a section of a program (by its name) from within itself?

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

I know it's possible to use elf_getdata() passing the index of the section as argument to get and Elf_Data struct and one of the fields of this struct is d_buf, which is a pointer to the actual data. However, it seems the elf_getdata() function makes a copy of the section data from the file to the memory and that's not what I want. I want a pointer to the data the has been loaded to the memory in loading time.

那么,伙计们,有什么主意吗?

So, guys, any idea?

推荐答案

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

Actually, using libelf, it's possible to use the Elf64_Shdr struct (for 64-bit systems) to get a pointer to a section, because the sh_addr field do points to the actual adress where the section will be loaded in runtime. So, it can be used as a pointer. This way, it's not even necessary to use the elf_getdata() function to retrieve a Elf_Data struct.

因为我要做的是可以链接其他目标文件的库,所以我的代码可能具有一个函数,该函数可以打开可执行文件本身以利用某些libelf功能,以便可以从中读取数据.主要文件部分,如下所示:

Since what I want to do is a library which other object files can be linked against, my code may have a function which opens the executable file itself to make use of some libelf features, so that it can read data from the main file sections, as follows:

// 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[384];
  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, "/");
  strncat(path, __progname, 127);

  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
    if ((section_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);
}

这篇关于如何从自身内部获取指向程序的特定可执行文件部分的指针? (也许与libelf)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆