Back to index

glibc  2.9
Defines | Functions
dl-sysdep.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define NEED_DL_SYSINFO_DSO   1
#define HAVE_DL_DISCOVER_OSVERSION   1

Functions

int _dl_discover_osversion (void) attribute_hidden

Define Documentation

Definition at line 33 of file dl-sysdep.h.

#define NEED_DL_SYSINFO_DSO   1

Definition at line 27 of file dl-sysdep.h.


Function Documentation

Definition at line 66 of file dl-sysdep.c.

{
#if (defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO) && defined SHARED
  if (GLRO(dl_sysinfo_map) != NULL)
    {
      /* If the kernel-supplied DSO contains a note indicating the kernel's
        version, we don't need to call uname or parse any strings.  */

      static const struct
      {
       ElfW(Nhdr) hdr;
       char vendor[8];
      } expected_note = { { sizeof "Linux", sizeof (ElfW(Word)), 0 }, "Linux" };
      const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
      const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
      for (uint_fast16_t i = 0; i < phnum; ++i)
       if (phdr[i].p_type == PT_NOTE)
         {
           const ElfW(Addr) start = (phdr[i].p_vaddr
                                  + GLRO(dl_sysinfo_map)->l_addr);
           const ElfW(Nhdr) *note = (const void *) start;
           while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
             {
              if (!memcmp (note, &expected_note, sizeof expected_note))
                return *(const ElfW(Word) *) ((const void *) note
                                          + sizeof expected_note);
#define ROUND(len) (((len) + sizeof note->n_type - 1) & -sizeof note->n_type)
              note = ((const void *) (note + 1)
                     + ROUND (note->n_namesz) + ROUND (note->n_descsz));
#undef ROUND
             }
         }
    }
#endif

  char bufmem[64];
  char *buf = bufmem;
  unsigned int version;
  int parts;
  char *cp;
  struct utsname uts;

  /* Try the uname system call.  */
  if (__uname (&uts))
    {
      /* This was not successful.  Now try reading the /proc filesystem.  */
      int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);
      if (fd < 0)
       return -1;
      ssize_t reslen = __read (fd, bufmem, sizeof (bufmem));
      __close (fd);
      if (reslen <= 0)
       /* This also didn't work.  We give up since we cannot
          make sure the library can actually work.  */
       return -1;
      buf[MIN (reslen, (ssize_t) sizeof (bufmem) - 1)] = '\0';
    }
  else
    buf = uts.release;

  /* Now convert it into a number.  The string consists of at most
     three parts.  */
  version = 0;
  parts = 0;
  cp = buf;
  while ((*cp >= '0') && (*cp <= '9'))
    {
      unsigned int here = *cp++ - '0';

      while ((*cp >= '0') && (*cp <= '9'))
       {
         here *= 10;
         here += *cp++ - '0';
       }

      ++parts;
      version <<= 8;
      version |= here;

      if (*cp++ != '.' || parts == 3)
       /* Another part following?  */
       break;
    }

  if (parts < 3)
    version <<= 8 * (3 - parts);

  return version;
}

Here is the call graph for this function: