Print this page
    
5261 libm should stop using synonyms.h
5298 fabs is 0-sized, confuses dis(1) and others
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Approved by: Gordon Ross <gwr@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libm/common/m9x/__fex_sym.c
          +++ new/usr/src/lib/libm/common/m9x/__fex_sym.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  
    | 
      ↓ open down ↓ | 
    19 lines elided | 
    
      ↑ open up ↑ | 
  
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  /*
  26   26   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27   27   * Use is subject to license terms.
  28   28   */
  29   29  
  30      -#include "fenv_synonyms.h"
  31   30  #include <elf.h>
  32   31  #include <stdio.h>
  33   32  #include <stdlib.h>
  34   33  #include <unistd.h>
  35   34  #include <fcntl.h>
  36   35  #include <procfs.h>
  37   36  #include <string.h>
  38   37  #include <sys/stat.h>
  39   38  
  40   39  #if defined(__sparcv9) || defined(__amd64)
  41   40  
  42   41  #define Elf_Ehdr        Elf64_Ehdr
  43   42  #define Elf_Phdr        Elf64_Phdr
  44   43  #define Elf_Shdr        Elf64_Shdr
  45   44  #define Elf_Sym         Elf64_Sym
  46   45  #define ELF_ST_BIND     ELF64_ST_BIND
  47   46  #define ELF_ST_TYPE     ELF64_ST_TYPE
  48   47  
  49   48  #else
  50   49  
  51   50  #define Elf_Ehdr        Elf32_Ehdr
  52   51  #define Elf_Phdr        Elf32_Phdr
  53   52  #define Elf_Shdr        Elf32_Shdr
  54   53  #define Elf_Sym         Elf32_Sym
  55   54  #define ELF_ST_BIND     ELF32_ST_BIND
  56   55  #define ELF_ST_TYPE     ELF32_ST_TYPE
  57   56  
  58   57  #endif  /* __sparcv9 */
  59   58  
  60   59  /* semi-permanent data established by __fex_sym_init */
  61   60  static  prmap_t         *pm = NULL;             /* prmap_t array */
  62   61  static  int                     npm = 0;                /* number of entries in pm */
  63   62  
  64   63  /* transient data modified by __fex_sym */
  65   64  static  prmap_t         *lpm = NULL;    /* prmap_t found in last call */
  66   65  static  Elf_Phdr        *ph = NULL;             /* program header array */
  67   66  static  int                     phsize = 0;             /* size of ph */
  68   67  static  int                     nph;                    /* number of entries in ph */
  69   68  static  char            *stbuf = NULL;  /* symbol and string table buffer */
  70   69  static  int                     stbufsize = 0;  /* size of stbuf */
  71   70  static  int                     stoffset;               /* offset of string table in stbuf */
  72   71  static  int                     nsyms;                  /* number of symbols in stbuf */
  73   72  
  74   73  /* get a current prmap_t list (must call this before each stack trace) */
  75   74  void
  76   75  __fex_sym_init()
  77   76  {
  78   77          struct stat     statbuf;
  79   78          long            n;
  80   79          int                     i;
  81   80  
  82   81          /* clear out the previous prmap_t list */
  83   82          if (pm != NULL)
  84   83                  free(pm);
  85   84          pm = lpm = NULL;
  86   85          npm = 0;
  87   86  
  88   87          /* get the current prmap_t list */
  89   88          if (stat("/proc/self/map", &statbuf) < 0 || statbuf.st_size <= 0 ||
  90   89                  (pm = (prmap_t*)malloc(statbuf.st_size)) == NULL)
  91   90                  return;
  92   91          if ((i = open("/proc/self/map", O_RDONLY)) < 0)
  93   92          {
  94   93                  free(pm);
  95   94                  pm = NULL;
  96   95                  return;
  97   96          }
  98   97          n = read(i, pm, statbuf.st_size);
  99   98          close(i);
 100   99          if (n != statbuf.st_size)
 101  100          {
 102  101                  free(pm);
 103  102                  pm = NULL;
 104  103          }
 105  104          else
 106  105                  npm = (int) (n / sizeof(prmap_t));
 107  106  }
 108  107  
 109  108  /* read ELF program headers and symbols; return -1 on error, 0 otherwise */
 110  109  static int
 111  110  __fex_read_syms(int fd)
 112  111  {
 113  112          Elf_Ehdr        h;
 114  113          Elf_Shdr        *sh;
 115  114          int                     i, size;
 116  115  
 117  116          /* read the ELF header */
 118  117          if (read(fd, &h, sizeof(h)) != sizeof(h))
 119  118                  return -1;
 120  119          if (h.e_ident[EI_MAG0] != ELFMAG0 ||
 121  120                  h.e_ident[EI_MAG1] != ELFMAG1 ||
 122  121                  h.e_ident[EI_MAG2] != ELFMAG2 ||
 123  122                  h.e_ident[EI_MAG3] != ELFMAG3 ||
 124  123                  h.e_phentsize != sizeof(Elf_Phdr) ||
 125  124                  h.e_shentsize != sizeof(Elf_Shdr))
 126  125                  return -1;
 127  126  
 128  127          /* get space for the program headers */
 129  128          size = h.e_phnum * h.e_phentsize;
 130  129          if (size > phsize)
 131  130          {
 132  131                  if (ph)
 133  132                          free(ph);
 134  133                  phsize = nph = 0;
 135  134                  if ((ph = (Elf_Phdr*)malloc(size)) == NULL)
 136  135                          return -1;
 137  136                  phsize = size;
 138  137          }
 139  138  
 140  139          /* read the program headers */
 141  140          if (lseek(fd, h.e_phoff, SEEK_SET) != h.e_phoff ||
 142  141                  read(fd, ph, size) != (ssize_t)size)
 143  142          {
 144  143                  nph = 0;
 145  144                  return -1;
 146  145          }
 147  146          nph = h.e_phnum;
 148  147  
 149  148          /* read the section headers */
 150  149          size = h.e_shnum * h.e_shentsize;
 151  150          if ((sh = (Elf_Shdr*)malloc(size)) == NULL)
 152  151                  return -1;
 153  152          if (lseek(fd, h.e_shoff, SEEK_SET) != h.e_shoff ||
 154  153                  read(fd, sh, size) != (ssize_t)size)
 155  154          {
 156  155                  free(sh);
 157  156                  return -1;
 158  157          }
 159  158  
 160  159          /* find the symtab section header */
 161  160          for (i = 0; i < h.e_shnum; i++)
 162  161          {
 163  162                  if (sh[i].sh_type == SHT_SYMTAB)
 164  163                          break; /* assume there is only one */
 165  164          }
 166  165          if (i == h.e_shnum || sh[i].sh_size == 0 ||
 167  166                  sh[i].sh_entsize != sizeof(Elf_Sym) ||
 168  167                  sh[i].sh_link < 1 || sh[i].sh_link >= h.e_shnum ||
 169  168                  sh[sh[i].sh_link].sh_type != SHT_STRTAB ||
 170  169                  sh[sh[i].sh_link].sh_size == 0)
 171  170          {
 172  171                  free(sh);
 173  172                  return -1;
 174  173          }
 175  174  
 176  175          /* get space for the symbol and string tables */
 177  176          size = (int) (sh[i].sh_size + sh[sh[i].sh_link].sh_size);
 178  177          if (size > stbufsize)
 179  178          {
 180  179                  if (stbuf)
 181  180                          free(stbuf);
 182  181                  stbufsize = nsyms = 0;
 183  182                  if ((stbuf = (char*)malloc(size)) == NULL)
 184  183                  {
 185  184                          free(sh);
 186  185                          return -1;
 187  186                  }
 188  187                  stbufsize = size;
 189  188          }
 190  189  
 191  190          /* read the symbol and string tables */
 192  191          if (lseek(fd, sh[i].sh_offset, SEEK_SET) != sh[i].sh_offset ||
 193  192                  read(fd, stbuf, sh[i].sh_size) != sh[i].sh_size ||
 194  193                  lseek(fd, sh[sh[i].sh_link].sh_offset, SEEK_SET) !=
 195  194                          sh[sh[i].sh_link].sh_offset ||
 196  195                  read(fd, stbuf + sh[i].sh_size, sh[sh[i].sh_link].sh_size) !=
 197  196                          sh[sh[i].sh_link].sh_size)
 198  197          {
 199  198                  free(sh);
 200  199                  return (-1);
 201  200          }
 202  201          nsyms = (int) (sh[i].sh_size / sh[i].sh_entsize);
 203  202          stoffset = (int) sh[i].sh_size;
 204  203  
 205  204          free(sh);
 206  205          return (0);
 207  206  }
 208  207  
 209  208  /* find the symbol corresponding to the given text address;
 210  209     return NULL on error, symbol address otherwise */
 211  210  char *
 212  211  __fex_sym(char *a, char **name)
 213  212  {
 214  213          Elf_Sym                 *s;
 215  214          unsigned long   fo, va, value;
 216  215          int                             fd, i, j, nm;
 217  216          char                    fname[PRMAPSZ+20];
 218  217  
 219  218          /* see if the last prmap_t found contains the indicated address */
 220  219          if (lpm)
 221  220          {
 222  221                  if (a >= (char*)lpm->pr_vaddr && a < (char*)lpm->pr_vaddr +
 223  222                          lpm->pr_size)
 224  223                          goto cont;
 225  224          }
 226  225  
 227  226          /* look for a prmap_t that contains the indicated address */
 228  227          for (i = 0; i < npm; i++)
 229  228          {
 230  229                  if (a >= (char*)pm[i].pr_vaddr && a < (char*)pm[i].pr_vaddr +
 231  230                          pm[i].pr_size)
 232  231                          break;
 233  232          }
 234  233          if (i == npm)
 235  234                  return NULL;
 236  235  
 237  236          /* get an open file descriptor for the mapped object */
 238  237          if (pm[i].pr_mapname[0] == '\0')
 239  238                  return NULL;
 240  239          strcpy(fname, "/proc/self/object/");
 241  240          strncat(fname, pm[i].pr_mapname, PRMAPSZ);
 242  241          fd = open(fname, O_RDONLY);
 243  242          if (fd < 0)
 244  243                  return NULL;
 245  244  
 246  245          /* read the program headers and symbols */
 247  246          lpm = NULL;
 248  247          j = __fex_read_syms(fd);
 249  248          close(fd);
 250  249          if (j < 0)
 251  250                  return NULL;
 252  251          lpm = &pm[i];
 253  252  
 254  253  cont:
 255  254          /* compute the file offset corresponding to the mapped address */
 256  255          fo = (a - (char*)lpm->pr_vaddr) + lpm->pr_offset;
 257  256  
 258  257          /* find the program header containing the file offset */
 259  258          for (i = 0; i < nph; i++)
 260  259          {
 261  260                  if (ph[i].p_type == PT_LOAD && fo >= ph[i].p_offset &&
 262  261                          fo < ph[i].p_offset + ph[i].p_filesz)
 263  262                          break;
 264  263          }
 265  264          if (i == nph)
 266  265                  return NULL;
 267  266  
 268  267          /* compute the virtual address corresponding to the file offset */
 269  268          va = (fo - ph[i].p_offset) + ph[i].p_vaddr;
 270  269  
 271  270          /* find the symbol in this segment with the highest value
 272  271             less than or equal to the virtual address */
 273  272          s = (Elf_Sym*)stbuf;
 274  273          value = nm = 0;
 275  274          for (j = 0; j < nsyms; j++)
 276  275          {
 277  276                  if (s[j].st_name == 0 || s[j].st_shndx == SHN_UNDEF ||
 278  277                          (ELF_ST_BIND(s[j].st_info) != STB_LOCAL &&
 279  278                          ELF_ST_BIND(s[j].st_info) != STB_GLOBAL &&
 280  279                          ELF_ST_BIND(s[j].st_info) != STB_WEAK) ||
 281  280                          (ELF_ST_TYPE(s[j].st_info) != STT_NOTYPE &&
 282  281                          ELF_ST_TYPE(s[j].st_info) != STT_OBJECT &&
 283  282                          ELF_ST_TYPE(s[j].st_info) != STT_FUNC))
 284  283                  {
 285  284                          continue;
 286  285                  }
 287  286  
 288  287                  if (s[j].st_value < ph[i].p_vaddr || s[j].st_value >= ph[i].p_vaddr
 289  288                          + ph[i].p_memsz)
 290  289                  {
 291  290                          continue;
 292  291                  }
 293  292  
 294  293                  if (s[j].st_value < value || s[j].st_value > va)
 295  294                          continue;
 296  295  
 297  296                  value = s[j].st_value;
 298  297                  nm = s[j].st_name;
 299  298          }
 300  299          if (nm == 0)
 301  300                  return NULL;
 302  301  
 303  302          /* pass back the name and return the mapped address of the symbol */
 304  303          *name = stbuf + stoffset + nm;
 305  304          fo = (value - ph[i].p_vaddr) + ph[i].p_offset;
 306  305          return (char*)lpm->pr_vaddr + (fo - lpm->pr_offset);
 307  306  }
  
    | 
      ↓ open down ↓ | 
    267 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX