実際には、 をlibelf
使用すると、Elf64_Shdr
構造体 (64 ビット システムの場合) を使用してセクションへのポインターを取得できます。これは、sh_addr
フィールド do が実行時にセクションがロードされる実際のアドレスを指しているためです。したがって、ポインターとして使用できます。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);
}