In my C++ program, how can I detect programmatically at runtime whether symbols have been stripped via the 'strip' gnu development tool on Linux?
I'd like a function definition which returns true if stripped, otherwise false.
Would using dlsym() on "main()" work to detect this reliably?
I know the file
command can tell the difference, so you could possibly look at its source to see what mechanism it uses.
From a comment left for another answer:
A stripped ELF will lack a .symtab
entry. The file
command traverses through all the ELF section headers until a symbol table section is found. If one cannot be found, the binary is considered stripped.
The libelf library allows a program to manipulate ELF object files, archive files, and archive members. The elf(3E) man pages provide documentation related to using the library. The following code provides an example on determining if the executable is stripped by looking for the existence of a symbol table section (.symtab
).
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
/* Include for ELF processing */
#include <libelf.h>
#include <gelf.h>
int main(int argc, char ** argv)
{
int fd;
const char *file = argv[0];
Elf *elf; /* ELF pointer for libelf */
Elf_Scn *scn; /* section descriptor pointer */
GElf_Shdr shdr; /* section header */
/* Open ELF file to obtain file descriptor */
if((fd = open(file, O_RDONLY)) < 0)
{
fprintf(stderr, "Error opening file %s\n", file);
exit(EXIT_FAILURE);
}
/* Protect program from using an older library */
if(elf_version(EV_CURRENT) == EV_NONE)
{
fprintf(stderr, "WARNING - ELF Library is out of date!\n");
exit(EXIT_FAILURE);
}
/* Initialize elf pointer for examining contents of file */
elf = elf_begin(fd, ELF_C_READ, NULL);
/* Initialize section descriptor pointer so that elf_nextscn()
* returns a pointer to the section descriptor at index 1. */
scn = NULL;
/* Iterate through ELF sections */
while((scn = elf_nextscn(elf, scn)) != NULL)
{
/* Retrieve section header */
gelf_getshdr(scn, &shdr);
/* If a section header holding a symbol table (.symtab)
* is found, this ELF file has not been stripped. */
if(shdr.sh_type == SHT_SYMTAB)
{
printf("NOT STRIPPED\n");
break;
}
}
elf_end(elf);
close(fd);
exit(EXIT_SUCCESS);
}
dlsym
looks at dynamic symbols, which aren't touched by strip. The static symbol table is contained in sections that are not loaded at runtime and thus do not appear in the segment table.
A pretty good heuristic would be to watch for the existence of a section table in the ELF header, which is usually mapped to your process memory, although the dynamic linker interfaces make it deliberately hard to find out where. On a typical system that has the dl_iterate_phdrs
function (which is an extension to the standard), you might be able to walk the PHDRS and check at the vaddr for each whether there is an ELF magic number there, but that is in no way, shape or form portable.
You could use popen() to execute nm
on the target application and then parse the output to figure if it's stripped or not.
nm: /bin/ls: no symbols
readelf --sections binary_path | grep debug_info
It is not trivial to say in general whether a binary was stripped or not, because there are different ways to strip a file. Essentially stripping removes some sections related to symbols and debugging. However, if you replace "debug_info" with "debug", you can see that there are still some debug-related sections left in standard binaries of Ubuntu distribution.