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?
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?
Advertisement
Answer
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.
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); }