9

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?

WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • Curious why you want to detect this at runtime? – Martin York Feb 28 '11 at 18:31
  • I'm not clear on why you need to know if the executable has been stripped. But whatever you're using to process the executable at runtime should also have the ability to tell you if things have been stripped. – Max Lybbert Feb 28 '11 at 18:27
  • @Martin York To trigger an alert message when executing the application to reduce the chance that a non-stripped version is inadvertently given to a customer. – WilliamKF Feb 28 '11 at 19:51
  • 3
    It would be more appropriate to make this part of your build processes so that you can't ship outstripped apps to you client. – Martin York Feb 28 '11 at 21:39
  • @Martin York It is part of the build process, but sometimes a customer gets a special build for temporary purposes of debugging or checking a fix. Such builds are not intended for long term production use and we wish that they self identify themselves programmatically. – WilliamKF Mar 01 '11 at 17:17

5 Answers5

12

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

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 5
    A stripped [ELF](http://en.wikipedia.org/wiki/Executable_and_Linkable_Format) 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*. – jschmier Feb 28 '11 at 17:03
8

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);
}
Community
  • 1
  • 1
jschmier
  • 15,458
  • 6
  • 54
  • 72
2

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.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64
1

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.

Tosha
  • 998
  • 1
  • 10
  • 22
1

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
Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426