Back to index

glibc  2.9
Defines | Functions
readelflib.c File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define check_ptr(ptr)
#define ROUND(len)   (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))

Functions

int process_elf_file (const char *file_name, const char *lib, int *flag, unsigned int *osversion, char **soname, void *file_contents, size_t file_length)

Define Documentation

#define check_ptr (   ptr)
Value:
do                                                      \
  {                                                     \
    if ((void *)(ptr) < file_contents                          \
       || (void *)(ptr) > (file_contents+file_length))         \
      {                                                        \
       error (0, 0, _("file %s is truncated\n"), file_name);   \
       return 1;                                        \
      }                                                        \
  }                                                     \
 while (0);

Definition at line 29 of file readelflib.c.

#define ROUND (   len)    (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))

Function Documentation

int process_elf_file ( const char *  file_name,
const char *  lib,
int flag,
unsigned int osversion,
char **  soname,
void *  file_contents,
size_t  file_length 
)

Definition at line 43 of file readelflib.c.

{
  int i;
  unsigned int j;
  ElfW(Addr) loadaddr;
  unsigned int dynamic_addr;
  size_t dynamic_size;
  char *program_interpreter;

  ElfW(Ehdr) *elf_header;
  ElfW(Phdr) *elf_pheader, *segment;
  ElfW(Dyn) *dynamic_segment, *dyn_entry;
  char *dynamic_strings;

  elf_header = (ElfW(Ehdr) *) file_contents;
  *osversion = 0;

  if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS))
    {
      if (opt_verbose)
       {
         if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
           error (0, 0, _("%s is a 32 bit ELF file.\n"), file_name);
         else if (elf_header->e_ident [EI_CLASS] == ELFCLASS64)
           error (0, 0, _("%s is a 64 bit ELF file.\n"), file_name);
         else
           error (0, 0, _("Unknown ELFCLASS in file %s.\n"), file_name);
       }
      return 1;
    }

  if (elf_header->e_type != ET_DYN)
    {
      error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name,
            elf_header->e_type);
      return 1;
    }

  /* Get information from elf program header.  */
  elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents);
  check_ptr (elf_pheader);

  /* The library is an elf library, now search for soname and
     libc5/libc6.  */
  *flag = FLAG_ELF;

  loadaddr = -1;
  dynamic_addr = 0;
  dynamic_size = 0;
  program_interpreter = NULL;
  for (i = 0, segment = elf_pheader;
       i < elf_header->e_phnum; i++, segment++)
    {
      check_ptr (segment);

      switch (segment->p_type)
       {
       case PT_LOAD:
         if (loadaddr == (ElfW(Addr)) -1)
           loadaddr = segment->p_vaddr - segment->p_offset;
         break;

       case PT_DYNAMIC:
         if (dynamic_addr)
           error (0, 0, _("more than one dynamic segment\n"));

         dynamic_addr = segment->p_offset;
         dynamic_size = segment->p_filesz;
         break;

       case PT_INTERP:
         program_interpreter = (char *) (file_contents + segment->p_offset);
         check_ptr (program_interpreter);

         /* Check if this is enough to classify the binary.  */
         for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]);
              ++j)
           if (strcmp (program_interpreter, interpreters[j].soname) == 0)
             {
              *flag = interpreters[j].flag;
              break;
             }
         break;

       case PT_NOTE:
         if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
           {
             ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
                                               + segment->p_offset);
             ElfW(Addr) size = segment->p_filesz;

             while (abi_note [0] != 4 || abi_note [1] != 16
                   || abi_note [2] != 1
                   || memcmp (abi_note + 3, "GNU", 4) != 0)
              {
#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
                ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
                                    + ROUND (abi_note[0])
                                    + ROUND (abi_note[1]);

                if (size - 32 < note_size || note_size == 0)
                  {
                    size = 0;
                    break;
                  }
                size -= note_size;
                abi_note = (void *) abi_note + note_size;
              }

             if (size == 0)
              break;

             *osversion = (abi_note [4] << 24) |
                        ((abi_note [5] & 0xff) << 16) |
                        ((abi_note [6] & 0xff) << 8) |
                        (abi_note [7] & 0xff);
           }
         break;

       default:
         break;
       }

    }
  if (loadaddr == (ElfW(Addr)) -1)
    {
      /* Very strange. */
      loadaddr = 0;
    }

  /* Now we can read the dynamic sections.  */
  if (dynamic_size == 0)
    return 1;

  dynamic_segment = (ElfW(Dyn) *) (file_contents + dynamic_addr);
  check_ptr (dynamic_segment);

  /* Find the string table.  */
  dynamic_strings = NULL;
  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
       ++dyn_entry)
    {
      check_ptr (dyn_entry);
      if (dyn_entry->d_tag == DT_STRTAB)
       {
         dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr);
         check_ptr (dynamic_strings);
         break;
       }
    }

  if (dynamic_strings == NULL)
    return 1;

  /* Now read the DT_NEEDED and DT_SONAME entries.  */
  for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
       ++dyn_entry)
    {
      if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
       {
         char *name = dynamic_strings + dyn_entry->d_un.d_val;
         check_ptr (name);

         if (dyn_entry->d_tag == DT_NEEDED)
           {

             if (*flag == FLAG_ELF)
              {
                /* Check if this is enough to classify the binary.  */
                for (j = 0;
                     j < sizeof (known_libs) / sizeof (known_libs [0]);
                     ++j)
                  if (strcmp (name, known_libs [j].soname) == 0)
                    {
                     *flag = known_libs [j].flag;
                     break;
                    }
              }
           }

         else if (dyn_entry->d_tag == DT_SONAME)
           *soname = xstrdup (name);

         /* Do we have everything we need?  */
         if (*soname && *flag != FLAG_ELF)
           return 0;
       }
    }

  return 0;
}