Print this page
5688 ELF tools need to be more careful with dwarf data

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/sgs/tools/common/leb128.c
          +++ new/usr/src/cmd/sgs/tools/common/leb128.c
↓ open down ↓ 91 lines elided ↑ open up ↑
  92   92   * DW_EH_PE_datarel        0x30 Value is reletive to the beginning of the
  93   93   *                              eh_frame_hdr segment ( segment type
  94   94   *                              PT_GNU_EH_FRAME )
  95   95   * DW_EH_PE_funcrel        0x40
  96   96   * DW_EH_PE_aligned        0x50 value is an aligned void*
  97   97   * DW_EH_PE_indirect       0x80 bit to signal indirection after relocation
  98   98   * DW_EH_PE_omit           0xff No value is present.
  99   99   *
 100  100   */
 101  101  
 102      -uint64_t
 103      -uleb_extract(unsigned char *data, uint64_t *dotp)
      102 +dwarf_error_t
      103 +uleb_extract(unsigned char *data, uint64_t *dotp, size_t len, uint64_t *ret)
 104  104  {
 105  105          uint64_t        dot = *dotp;
 106  106          uint64_t        res = 0;
 107  107          int             more = 1;
 108  108          int             shift = 0;
 109  109          int             val;
 110  110  
 111  111          data += dot;
 112  112  
 113  113          while (more) {
      114 +                if (dot > len)
      115 +                        return (DW_OVERFLOW);
      116 +
 114  117                  /*
 115  118                   * Pull off lower 7 bits
 116  119                   */
 117  120                  val = (*data) & 0x7f;
 118  121  
 119  122                  /*
 120  123                   * Add prepend value to head of number.
 121  124                   */
 122  125                  res = res | (val << shift);
 123  126  
↓ open down ↓ 3 lines elided ↑ open up ↑
 127  130                  shift += 7;
 128  131                  dot++;
 129  132  
 130  133                  /*
 131  134                   * Check to see if hi bit is set - if not, this
 132  135                   * is the last byte.
 133  136                   */
 134  137                  more = ((*data++) & 0x80) >> 7;
 135  138          }
 136  139          *dotp = dot;
 137      -        return (res);
      140 +        *ret = res;
      141 +        return (DW_SUCCESS);
 138  142  }
 139  143  
 140      -int64_t
 141      -sleb_extract(unsigned char *data, uint64_t *dotp)
      144 +dwarf_error_t
      145 +sleb_extract(unsigned char *data, uint64_t *dotp, size_t len, int64_t *ret)
 142  146  {
 143  147          uint64_t        dot = *dotp;
 144  148          int64_t         res = 0;
 145  149          int             more = 1;
 146  150          int             shift = 0;
 147  151          int             val;
 148  152  
 149  153          data += dot;
 150  154  
 151  155          while (more) {
      156 +                if (dot > len)
      157 +                        return (DW_OVERFLOW);
      158 +
 152  159                  /*
 153  160                   * Pull off lower 7 bits
 154  161                   */
 155  162                  val = (*data) & 0x7f;
 156  163  
 157  164                  /*
 158  165                   * Add prepend value to head of number.
 159  166                   */
 160  167                  res = res | (val << shift);
 161  168  
↓ open down ↓ 8 lines elided ↑ open up ↑
 170  177                   * is the last byte.
 171  178                   */
 172  179                  more = ((*data++) & 0x80) >> 7;
 173  180          }
 174  181          *dotp = dot;
 175  182  
 176  183          /*
 177  184           * Make sure value is properly sign extended.
 178  185           */
 179  186          res = (res << (64 - shift)) >> (64 - shift);
 180      -
 181      -        return (res);
      187 +        *ret = res;
      188 +        return (DW_SUCCESS);
 182  189  }
 183  190  
 184  191  /*
 185  192   * Extract a DWARF encoded datum
 186  193   *
 187  194   * entry:
 188  195   *      data - Base of data buffer containing encoded bytes
 189  196   *      dotp - Address of variable containing index within data
 190  197   *              at which the desired datum starts.
 191  198   *      ehe_flags - DWARF encoding
 192  199   *      eident - ELF header e_ident[] array for object being processed
 193  200   *      frame_hdr - Boolean, true if we're extracting from .eh_frame_hdr
 194  201   *      sh_base - Base address of ELF section containing desired datum
 195  202   *      sh_offset - Offset relative to sh_base of desired datum.
 196  203   *      dbase - The base address to which DW_EH_PE_datarel is relative
 197  204   *              (if frame_hdr is false)
 198  205   */
 199      -uint64_t
 200      -dwarf_ehe_extract(unsigned char *data, uint64_t *dotp, uint_t ehe_flags,
 201      -    unsigned char *eident, boolean_t frame_hdr, uint64_t sh_base,
 202      -    uint64_t sh_offset, uint64_t dbase)
      206 +dwarf_error_t
      207 +dwarf_ehe_extract(unsigned char *data, size_t len, uint64_t *dotp,
      208 +    uint64_t *ret, uint_t ehe_flags, unsigned char *eident,
      209 +    boolean_t frame_hdr, uint64_t sh_base, uint64_t sh_offset,
      210 +    uint64_t dbase)
 203  211  {
 204  212          uint64_t    dot = *dotp;
 205  213          uint_t      lsb;
 206  214          uint_t      wordsize;
 207  215          uint_t      fsize;
 208  216          uint64_t    result;
 209  217  
 210  218          if (eident[EI_DATA] == ELFDATA2LSB)
 211  219                  lsb = 1;
 212  220          else
 213  221                  lsb = 0;
 214  222  
 215  223          if (eident[EI_CLASS] == ELFCLASS64)
 216  224                  wordsize = 8;
 217  225          else
 218  226                  wordsize = 4;
 219  227  
 220  228          switch (ehe_flags & 0x0f) {
 221  229          case DW_EH_PE_omit:
 222      -                return (0);
      230 +                *ret = 0;
      231 +                return (DW_SUCCESS);
 223  232          case DW_EH_PE_absptr:
 224  233                  fsize = wordsize;
 225  234                  break;
 226  235          case DW_EH_PE_udata8:
 227  236          case DW_EH_PE_sdata8:
 228  237                  fsize = 8;
 229  238                  break;
 230  239          case DW_EH_PE_udata4:
 231  240          case DW_EH_PE_sdata4:
 232  241                  fsize = 4;
 233  242                  break;
 234  243          case DW_EH_PE_udata2:
 235  244          case DW_EH_PE_sdata2:
 236  245                  fsize = 2;
 237  246                  break;
 238  247          case DW_EH_PE_uleb128:
 239      -                return (uleb_extract(data, dotp));
      248 +                return (uleb_extract(data, dotp, len, ret));
 240  249          case DW_EH_PE_sleb128:
 241      -                return ((uint64_t)sleb_extract(data, dotp));
      250 +                return (sleb_extract(data, dotp, len, (int64_t *)ret));
 242  251          default:
 243      -                return (0);
      252 +                *ret = 0;
      253 +                return (DW_BAD_ENCODING);
 244  254          }
 245  255  
 246  256          if (lsb) {
 247  257                  /*
 248  258                   * Extract unaligned LSB formated data
 249  259                   */
 250  260                  uint_t  cnt;
 251  261  
 252  262                  result = 0;
 253  263                  for (cnt = 0; cnt < fsize;
 254  264                      cnt++, dot++) {
 255  265                          uint64_t val;
      266 +
      267 +                        if (dot > len)
      268 +                                return (DW_OVERFLOW);
 256  269                          val = data[dot];
 257  270                          result |= val << (cnt * 8);
 258  271                  }
 259  272          } else {
 260  273                  /*
 261  274                   * Extract unaligned MSB formated data
 262  275                   */
 263  276                  uint_t  cnt;
 264  277                  result = 0;
 265  278                  for (cnt = 0; cnt < fsize;
 266  279                      cnt++, dot++) {
 267      -                        uint64_t        val;
      280 +                        uint64_t val;
      281 +
      282 +                        if (dot > len)
      283 +                                return (DW_OVERFLOW);
 268  284                          val = data[dot];
 269  285                          result |= val << ((fsize - cnt - 1) * 8);
 270  286                  }
 271  287          }
 272  288          /*
 273  289           * perform sign extension
 274  290           */
 275  291          if ((ehe_flags & DW_EH_PE_signed) &&
 276  292              (fsize < sizeof (uint64_t))) {
 277  293                  int64_t sresult;
↓ open down ↓ 22 lines elided ↑ open up ↑
 300  316                  else
 301  317                          result += dbase;
 302  318                  break;
 303  319          }
 304  320  
 305  321          /* Truncate the result to its specified size */
 306  322          result = (result << ((sizeof (uint64_t) - fsize) * 8)) >>
 307  323              ((sizeof (uint64_t) - fsize) * 8);
 308  324  
 309  325          *dotp = dot;
 310      -        return (result);
      326 +        *ret = result;
      327 +        return (DW_SUCCESS);
 311  328  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX