How to detect at runtime whether symbols are stripped?

6.9k views Asked by At

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?

5

There are 5 answers

1
Mark B On BEST ANSWER

I know the file command can tell the difference, so you could possibly look at its source to see what mechanism it uses.

0
Simon Richter On

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.

0
karlphillip On

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
0
jschmier On

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);
}
0
Tosha On

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.