簡體   English   中英

如何從自身內部獲取指向程序的特定可執行文件部分的指針? (也許與libelf)

[英]How to get a pointer to a specific executable file's section of a program from within itself? (Maybe with libelf)

我在Linux環境中,需要創建一個程序來檢索放置在其可執行文件部分之一中的某些數據。 那么,如何從自身內部獲取指向程序部分的指針(按其名稱)?

我知道有可能使用elf_getdata()傳遞節的索引作為get和Elf_Data結構的參數,而Elf_Data結構的字段之一是d_buf ,它是指向實際數據的指針。 但是,似乎elf_getdata()函數將節數據從文件復制到內存中,這不是我想要的。 我想要一個指向在加載時已加載到內存的數據的指針。

那么,伙計們,有什么主意嗎?

實際上,使用libelf ,可以使用Elf64_Shdr結構(對於64位系統)獲取指向節的指針,因為sh_addr字段確實指向將在運行時加載該節的實際地址。 因此,它可用作指針。 這樣,甚至不需要使用elf_getdata()函數來檢索Elf_Data結構。

由於我想做的是一個可以鏈接其他目標文件的庫,因此我的代碼可能具有打開可執行文件本身的功能,以利用某些libelf功能,以便它可以從主文件部分讀取數據,如下:

// 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);
}

ELF標頭不一定映射到內存中,因此依賴它可能會有些冒險。 這是一種不需要任何API的方法:

  1. 聲明兩個符號,分別表示相關部分的開頭和結尾。
  2. 使用__attribute__ ((section ("")))放置在名稱已知的部分中
  3. 使用自定義鏈接描述文件,該腳本將您需要的部分放在兩個變量的部分之間。

另外,您也可以使用鏈接器生成的符號 ,就像_etext / _edata / _end一樣

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM