LCOV - code coverage report
Current view: top level - libdw - dwarf_getsrclines.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 265 347 76.4 %
Date: 2017-01-05 09:15:16 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Return line number information of CU.
       2             :    Copyright (C) 2004-2010, 2013, 2014, 2015, 2016 Red Hat, Inc.
       3             :    This file is part of elfutils.
       4             :    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
       5             : 
       6             :    This file is free software; you can redistribute it and/or modify
       7             :    it under the terms of either
       8             : 
       9             :      * the GNU Lesser General Public License as published by the Free
      10             :        Software Foundation; either version 3 of the License, or (at
      11             :        your option) any later version
      12             : 
      13             :    or
      14             : 
      15             :      * the GNU General Public License as published by the Free
      16             :        Software Foundation; either version 2 of the License, or (at
      17             :        your option) any later version
      18             : 
      19             :    or both in parallel, as here.
      20             : 
      21             :    elfutils is distributed in the hope that it will be useful, but
      22             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      24             :    General Public License for more details.
      25             : 
      26             :    You should have received copies of the GNU General Public License and
      27             :    the GNU Lesser General Public License along with this program.  If
      28             :    not, see <http://www.gnu.org/licenses/>.  */
      29             : 
      30             : #ifdef HAVE_CONFIG_H
      31             : # include <config.h>
      32             : #endif
      33             : 
      34             : #include <assert.h>
      35             : #include <stdlib.h>
      36             : #include <string.h>
      37             : #include <search.h>
      38             : 
      39             : #include "dwarf.h"
      40             : #include "libdwP.h"
      41             : 
      42             : 
      43             : struct filelist
      44             : {
      45             :   Dwarf_Fileinfo info;
      46             :   struct filelist *next;
      47             : };
      48             : 
      49             : struct linelist
      50             : {
      51             :   Dwarf_Line line;
      52             :   struct linelist *next;
      53             :   size_t sequence;
      54             : };
      55             : 
      56             : 
      57             : /* Compare by Dwarf_Line.addr, given pointers into an array of pointers.  */
      58             : static int
      59     1387397 : compare_lines (const void *a, const void *b)
      60             : {
      61     1387397 :   struct linelist *const *p1 = a;
      62     1387397 :   struct linelist *const *p2 = b;
      63     1387397 :   struct linelist *list1 = *p1;
      64     1387397 :   struct linelist *list2 = *p2;
      65     1387397 :   Dwarf_Line *line1 = &list1->line;
      66     1387397 :   Dwarf_Line *line2 = &list2->line;
      67             : 
      68     1387397 :   if (line1->addr != line2->addr)
      69     1383979 :     return (line1->addr < line2->addr) ? -1 : 1;
      70             : 
      71             :   /* An end_sequence marker precedes a normal record at the same address.  */
      72        3418 :   if (line1->end_sequence != line2->end_sequence)
      73          13 :     return line2->end_sequence - line1->end_sequence;
      74             : 
      75             :   /* Otherwise, the linelist sequence maintains a stable sort.  */
      76        3405 :   return (list1->sequence < list2->sequence) ? -1
      77        3405 :     : (list1->sequence > list2->sequence) ? 1
      78           0 :     : 0;
      79             : }
      80             : 
      81             : struct line_state
      82             : {
      83             :   Dwarf_Word addr;
      84             :   unsigned int op_index;
      85             :   unsigned int file;
      86             :   int64_t line;
      87             :   unsigned int column;
      88             :   uint_fast8_t is_stmt;
      89             :   bool basic_block;
      90             :   bool prologue_end;
      91             :   bool epilogue_begin;
      92             :   unsigned int isa;
      93             :   unsigned int discriminator;
      94             :   struct linelist *linelist;
      95             :   size_t nlinelist;
      96             :   unsigned int end_sequence;
      97             : };
      98             : 
      99             : static inline void
     100             : run_advance_pc (struct line_state *state, unsigned int op_advance,
     101             :                 uint_fast8_t minimum_instr_len, uint_fast8_t max_ops_per_instr)
     102             : {
     103      900400 :   state->addr += minimum_instr_len * ((state->op_index + op_advance)
     104      450200 :                                       / max_ops_per_instr);
     105      450200 :   state->op_index = (state->op_index + op_advance) % max_ops_per_instr;
     106             : }
     107             : 
     108             : static inline bool
     109      367106 : add_new_line (struct line_state *state, struct linelist *new_line)
     110             : {
     111             :   /* Set the line information.  For some fields we use bitfields,
     112             :      so we would lose information if the encoded values are too large.
     113             :      Check just for paranoia, and call the data "invalid" if it
     114             :      violates our assumptions on reasonable limits for the values.  */
     115      367106 :   new_line->next = state->linelist;
     116      367106 :   new_line->sequence = state->nlinelist;
     117      367106 :   state->linelist = new_line;
     118      367106 :   ++(state->nlinelist);
     119             : 
     120             :   /* Set the line information.  For some fields we use bitfields,
     121             :      so we would lose information if the encoded values are too large.
     122             :      Check just for paranoia, and call the data "invalid" if it
     123             :      violates our assumptions on reasonable limits for the values.  */
     124             : #define SET(field)                                                    \
     125             :   do {                                                                \
     126             :      new_line->line.field = state->field;                       \
     127             :      if (unlikely (new_line->line.field != state->field))       \
     128             :        return true;                                                   \
     129             :    } while (0)
     130             : 
     131      367106 :   SET (addr);
     132      367106 :   SET (op_index);
     133      367106 :   SET (file);
     134      367106 :   SET (line);
     135      367106 :   SET (column);
     136      367106 :   SET (is_stmt);
     137      367106 :   SET (basic_block);
     138      367106 :   SET (end_sequence);
     139      367106 :   SET (prologue_end);
     140      367106 :   SET (epilogue_begin);
     141      367106 :   SET (isa);
     142      367106 :   SET (discriminator);
     143             : 
     144             : #undef SET
     145             : 
     146      367106 :   return false;
     147             : }
     148             : 
     149             : static int
     150        4338 : read_srclines (Dwarf *dbg,
     151             :                const unsigned char *linep, const unsigned char *lineendp,
     152             :                const char *comp_dir, unsigned address_size,
     153             :                Dwarf_Lines **linesp, Dwarf_Files **filesp)
     154             : {
     155        4338 :   int res = -1;
     156             : 
     157        4338 :   size_t nfilelist = 0;
     158        4338 :   unsigned int ndirlist = 0;
     159             : 
     160        4338 :   struct filelist null_file =
     161             :     {
     162             :       .info =
     163             :       {
     164             :         .name = "???",
     165             :         .mtime = 0,
     166             :         .length = 0
     167             :       },
     168             :       .next = NULL
     169             :     };
     170        4338 :   struct filelist *filelist = &null_file;
     171             : 
     172             :   /* If there are a large number of lines, files or dirs don't blow up
     173             :      the stack.  Stack allocate some entries, only dynamically malloc
     174             :      when more than MAX.  */
     175             : #define MAX_STACK_ALLOC 4096
     176             : #define MAX_STACK_LINES MAX_STACK_ALLOC
     177             : #define MAX_STACK_FILES (MAX_STACK_ALLOC / 4)
     178             : #define MAX_STACK_DIRS  (MAX_STACK_ALLOC / 16)
     179             : 
     180             :   struct dirlist
     181             :   {
     182             :     const char *dir;
     183             :     size_t len;
     184             :   };
     185             :   struct dirlist dirstack[MAX_STACK_DIRS];
     186        4338 :   struct dirlist *dirarray = dirstack;
     187             : 
     188             :   /* We are about to process the statement program.  Initialize the
     189             :      state machine registers (see 6.2.2 in the v2.1 specification).  */
     190        4338 :   struct line_state state =
     191             :     {
     192             :       .linelist = NULL,
     193             :       .nlinelist = 0,
     194             :       .addr = 0,
     195             :       .op_index = 0,
     196             :       .file = 1,
     197             :       /* We only store int but want to check for overflow (see SET above).  */
     198             :       .line = 1,
     199             :       .column = 0,
     200             :       .basic_block = false,
     201             :       .prologue_end = false,
     202             :       .epilogue_begin = false,
     203             :       .isa = 0,
     204             :       .discriminator = 0
     205             :     };
     206             : 
     207        4338 :   if (unlikely (linep + 4 > lineendp))
     208             :     {
     209             :     invalid_data:
     210           0 :       __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
     211           0 :       goto out;
     212             :     }
     213             : 
     214        4354 :   Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
     215        4338 :   unsigned int length = 4;
     216        4338 :   if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
     217             :     {
     218           0 :       if (unlikely (linep + 8 > lineendp))
     219             :         goto invalid_data;
     220           0 :       unit_length = read_8ubyte_unaligned_inc (dbg, linep);
     221           0 :       length = 8;
     222             :     }
     223             : 
     224             :   /* Check whether we have enough room in the section.  */
     225        4338 :   if (unlikely (unit_length > (size_t) (lineendp - linep)
     226             :       || unit_length < 2 + length + 5 * 1))
     227             :     goto invalid_data;
     228        4338 :   lineendp = linep + unit_length;
     229             : 
     230             :   /* The next element of the header is the version identifier.  */
     231        4338 :   uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
     232        4338 :   if (unlikely (version < 2) || unlikely (version > 4))
     233             :     {
     234           0 :       __libdw_seterrno (DWARF_E_VERSION);
     235           0 :       goto out;
     236             :     }
     237             : 
     238             :   /* Next comes the header length.  */
     239             :   Dwarf_Word header_length;
     240        4338 :   if (length == 4)
     241        4354 :     header_length = read_4ubyte_unaligned_inc (dbg, linep);
     242             :   else
     243           0 :     header_length = read_8ubyte_unaligned_inc (dbg, linep);
     244        4338 :   const unsigned char *header_start = linep;
     245             : 
     246             :   /* Next the minimum instruction length.  */
     247        4338 :   uint_fast8_t minimum_instr_len = *linep++;
     248             : 
     249             :   /* Next the maximum operations per instruction, in version 4 format.  */
     250        4338 :   uint_fast8_t max_ops_per_instr = 1;
     251        4338 :   if (version >= 4)
     252             :     {
     253           0 :       if (unlikely (lineendp - linep < 5))
     254             :         goto invalid_data;
     255           0 :       max_ops_per_instr = *linep++;
     256           0 :       if (unlikely (max_ops_per_instr == 0))
     257             :         goto invalid_data;
     258             :     }
     259             : 
     260             :   /* Then the flag determining the default value of the is_stmt
     261             :      register.  */
     262        4338 :   uint_fast8_t default_is_stmt = *linep++;
     263             : 
     264             :   /* Now the line base.  */
     265        4338 :   int_fast8_t line_base = (int8_t) *linep++;
     266             : 
     267             :   /* And the line range.  */
     268        4338 :   uint_fast8_t line_range = *linep++;
     269             : 
     270             :   /* The opcode base.  */
     271        4338 :   uint_fast8_t opcode_base = *linep++;
     272             : 
     273             :   /* Remember array with the standard opcode length (-1 to account for
     274             :      the opcode with value zero not being mentioned).  */
     275        4338 :   const uint8_t *standard_opcode_lengths = linep - 1;
     276        4338 :   if (unlikely (lineendp - linep < opcode_base - 1))
     277             :     goto invalid_data;
     278        4338 :   linep += opcode_base - 1;
     279             : 
     280             :   /* First comes the list of directories.  Add the compilation
     281             :      directory first since the index zero is used for it.  */
     282        8676 :   struct dirlist comp_dir_elem =
     283             :     {
     284             :       .dir = comp_dir,
     285        4338 :       .len = comp_dir ? strlen (comp_dir) : 0,
     286             :     };
     287        4338 :   ndirlist = 1;
     288             : 
     289             :   /* First count the entries.  */
     290        4338 :   const unsigned char *dirp = linep;
     291        4338 :   unsigned int ndirs = 0;
     292       33190 :   while (*dirp != 0)
     293             :     {
     294       24514 :       uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
     295       24514 :       if (endp == NULL)
     296             :         goto invalid_data;
     297       24514 :       ++ndirs;
     298       24514 :       dirp = endp + 1;
     299             :     }
     300        4338 :   ndirlist += ndirs;
     301             : 
     302             :   /* Arrange the list in array form.  */
     303        4338 :   if (ndirlist >= MAX_STACK_DIRS)
     304             :     {
     305           0 :       dirarray = (struct dirlist *) malloc (ndirlist * sizeof (*dirarray));
     306           0 :       if (unlikely (dirarray == NULL))
     307             :         {
     308             :         no_mem:
     309           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     310           0 :           goto out;
     311             :         }
     312             :     }
     313        4338 :   dirarray[0] = comp_dir_elem;
     314       28852 :   for (unsigned int n = 1; n < ndirlist; n++)
     315             :     {
     316       24514 :       dirarray[n].dir = (char *) linep;
     317       24514 :       uint8_t *endp = memchr (linep, '\0', lineendp - linep);
     318       24514 :       assert (endp != NULL);
     319       24514 :       dirarray[n].len = endp - linep;
     320       24514 :       linep = endp + 1;
     321             :     }
     322             :   /* Skip the final NUL byte.  */
     323        4338 :   ++linep;
     324             : 
     325             :   /* Allocate memory for a new file.  For the first MAX_STACK_FILES
     326             :      entries just return a slot in the preallocated stack array.  */
     327             :   struct filelist flstack[MAX_STACK_FILES];
     328             : #define NEW_FILE() ({                                                   \
     329             :   struct filelist *fl = (nfilelist < MAX_STACK_FILES                 \
     330             :                            ? &flstack[nfilelist]                    \
     331             :                            : malloc (sizeof (struct filelist)));        \
     332             :   if (unlikely (fl == NULL))                                            \
     333             :     goto no_mem;                                                        \
     334             :   ++nfilelist;                                                          \
     335             :   fl->next = filelist;                                                       \
     336             :   filelist = fl;                                                        \
     337             :   fl; })
     338             : 
     339             :   /* Now read the files.  */
     340        4338 :   nfilelist = 1;
     341             : 
     342        4338 :   if (unlikely (linep >= lineendp))
     343             :     goto invalid_data;
     344       72662 :   while (*linep != 0)
     345             :     {
     346       68324 :       struct filelist *new_file = NEW_FILE ();
     347             : 
     348             :       /* First comes the file name.  */
     349       68324 :       char *fname = (char *) linep;
     350       68324 :       uint8_t *endp = memchr (fname, '\0', lineendp - linep);
     351       68324 :       if (endp == NULL)
     352             :         goto invalid_data;
     353       68324 :       size_t fnamelen = endp - (uint8_t *) fname;
     354       68324 :       linep = endp + 1;
     355             : 
     356             :       /* Then the index.  */
     357             :       Dwarf_Word diridx;
     358       68324 :       if (unlikely (linep >= lineendp))
     359             :         goto invalid_data;
     360       68324 :       get_uleb128 (diridx, linep, lineendp);
     361       68324 :       if (unlikely (diridx >= ndirlist))
     362             :         {
     363           0 :           __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
     364           0 :           goto out;
     365             :         }
     366             : 
     367       68324 :       if (*fname == '/')
     368             :         /* It's an absolute path.  */
     369         302 :         new_file->info.name = fname;
     370             :       else
     371             :         {
     372       68022 :           new_file->info.name = libdw_alloc (dbg, char, 1,
     373             :                                              dirarray[diridx].len + 1
     374             :                                              + fnamelen + 1);
     375       68022 :           char *cp = new_file->info.name;
     376             : 
     377       68022 :           if (dirarray[diridx].dir != NULL)
     378             :             {
     379             :               /* This value could be NULL in case the DW_AT_comp_dir
     380             :                  was not present.  We cannot do much in this case.
     381             :                  The easiest thing is to convert the path in an
     382             :                  absolute path.  */
     383       68022 :               cp = stpcpy (cp, dirarray[diridx].dir);
     384             :             }
     385       68022 :           *cp++ = '/';
     386       68022 :           strcpy (cp, fname);
     387       68022 :           assert (strlen (new_file->info.name)
     388             :                   < dirarray[diridx].len + 1 + fnamelen + 1);
     389             :         }
     390             : 
     391             :       /* Next comes the modification time.  */
     392       68324 :       if (unlikely (linep >= lineendp))
     393             :         goto invalid_data;
     394       68324 :       get_uleb128 (new_file->info.mtime, linep, lineendp);
     395             : 
     396             :       /* Finally the length of the file.  */
     397       68324 :       if (unlikely (linep >= lineendp))
     398             :         goto invalid_data;
     399       68324 :       get_uleb128 (new_file->info.length, linep, lineendp);
     400             :     }
     401             :   /* Skip the final NUL byte.  */
     402        4338 :   ++linep;
     403             : 
     404             :   /* Consistency check.  */
     405        4338 :   if (unlikely (linep != header_start + header_length))
     406             :     {
     407           0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     408           0 :       goto out;
     409             :     }
     410             : 
     411        4338 :   state.is_stmt = default_is_stmt;
     412             : 
     413             :   /* Apply the "operation advance" from a special opcode or
     414             :      DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
     415             : #define advance_pc(op_advance) \
     416             :   run_advance_pc (&state, op_advance, minimum_instr_len, max_ops_per_instr)
     417             : 
     418             :   /* Process the instructions.  */
     419             : 
     420             :   /* Adds a new line to the matrix.  For the first MAX_STACK_LINES
     421             :      entries just return a slot in the preallocated stack array.  */
     422             :   struct linelist llstack[MAX_STACK_LINES];
     423             : #define NEW_LINE(end_seq)                                               \
     424             :   do {                                                          \
     425             :     struct linelist *ll = (state.nlinelist < MAX_STACK_LINES \
     426             :                            ? &llstack[state.nlinelist]              \
     427             :                            : malloc (sizeof (struct linelist)));        \
     428             :     if (unlikely (ll == NULL))                                  \
     429             :       goto no_mem;                                              \
     430             :     state.end_sequence = end_seq;                               \
     431             :     if (unlikely (add_new_line (&state, ll)))                       \
     432             :       goto invalid_data;                                                \
     433             :   } while (0)
     434             : 
     435      720177 :   while (linep < lineendp)
     436             :     {
     437             :       unsigned int opcode;
     438             :       unsigned int u128;
     439             :       int s128;
     440             : 
     441             :       /* Read the opcode.  */
     442      711501 :       opcode = *linep++;
     443             : 
     444             :       /* Is this a special opcode?  */
     445      711501 :       if (likely (opcode >= opcode_base))
     446             :         {
     447      340733 :           if (unlikely (line_range == 0))
     448             :             goto invalid_data;
     449             : 
     450             :           /* Yes.  Handling this is quite easy since the opcode value
     451             :              is computed with
     452             : 
     453             :              opcode = (desired line increment - line_base)
     454             :                        + (line_range * address advance) + opcode_base
     455             :           */
     456      340733 :           int line_increment = (line_base
     457      340733 :                                 + (opcode - opcode_base) % line_range);
     458             : 
     459             :           /* Perform the increments.  */
     460      340733 :           state.line += line_increment;
     461      681466 :           advance_pc ((opcode - opcode_base) / line_range);
     462             : 
     463             :           /* Add a new line with the current state machine values.  */
     464      340733 :           NEW_LINE (0);
     465             : 
     466             :           /* Reset the flags.  */
     467      340733 :           state.basic_block = false;
     468      340733 :           state.prologue_end = false;
     469      340733 :           state.epilogue_begin = false;
     470      340733 :           state.discriminator = 0;
     471             :         }
     472      370768 :       else if (opcode == 0)
     473             :         {
     474             :           /* This an extended opcode.  */
     475       46969 :           if (unlikely (lineendp - linep < 2))
     476             :             goto invalid_data;
     477             : 
     478             :           /* The length.  */
     479       46969 :           uint_fast8_t len = *linep++;
     480             : 
     481       46969 :           if (unlikely ((size_t) (lineendp - linep) < len))
     482             :             goto invalid_data;
     483             : 
     484             :           /* The sub-opcode.  */
     485       46969 :           opcode = *linep++;
     486             : 
     487       46969 :           switch (opcode)
     488             :             {
     489             :             case DW_LNE_end_sequence:
     490             :               /* Add a new line with the current state machine values.
     491             :                  The is the end of the sequence.  */
     492        4445 :               NEW_LINE (1);
     493             : 
     494             :               /* Reset the registers.  */
     495        4445 :               state.addr = 0;
     496        4445 :               state.op_index = 0;
     497        4445 :               state.file = 1;
     498        4445 :               state.line = 1;
     499        4445 :               state.column = 0;
     500        4445 :               state.is_stmt = default_is_stmt;
     501        4445 :               state.basic_block = false;
     502        4445 :               state.prologue_end = false;
     503        4445 :               state.epilogue_begin = false;
     504        4445 :               state.isa = 0;
     505        4445 :               state.discriminator = 0;
     506        4445 :               break;
     507             : 
     508             :             case DW_LNE_set_address:
     509             :               /* The value is an address.  The size is defined as
     510             :                  apporiate for the target machine.  We use the
     511             :                  address size field from the CU header.  */
     512        4630 :               state.op_index = 0;
     513        4630 :               if (unlikely (lineendp - linep < (uint8_t) address_size))
     514             :                 goto invalid_data;
     515        4630 :               if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
     516             :                                             address_size, &state.addr))
     517             :                 goto out;
     518             :               break;
     519             : 
     520             :             case DW_LNE_define_file:
     521             :               {
     522           0 :                 char *fname = (char *) linep;
     523           0 :                 uint8_t *endp = memchr (linep, '\0', lineendp - linep);
     524           0 :                 if (endp == NULL)
     525             :                   goto invalid_data;
     526           0 :                 size_t fnamelen = endp - linep;
     527           0 :                 linep = endp + 1;
     528             : 
     529             :                 unsigned int diridx;
     530           0 :                 if (unlikely (linep >= lineendp))
     531             :                   goto invalid_data;
     532           0 :                 get_uleb128 (diridx, linep, lineendp);
     533           0 :                 if (unlikely (diridx >= ndirlist))
     534             :                   {
     535           0 :                     __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
     536           0 :                     goto invalid_data;
     537             :                   }
     538             :                 Dwarf_Word mtime;
     539           0 :                 if (unlikely (linep >= lineendp))
     540             :                   goto invalid_data;
     541           0 :                 get_uleb128 (mtime, linep, lineendp);
     542             :                 Dwarf_Word filelength;
     543           0 :                 if (unlikely (linep >= lineendp))
     544             :                   goto invalid_data;
     545           0 :                 get_uleb128 (filelength, linep, lineendp);
     546             : 
     547           0 :                 struct filelist *new_file = NEW_FILE ();
     548           0 :                 if (fname[0] == '/')
     549           0 :                   new_file->info.name = fname;
     550             :                 else
     551             :                   {
     552           0 :                     new_file->info.name =
     553           0 :                       libdw_alloc (dbg, char, 1, (dirarray[diridx].len + 1
     554             :                                                   + fnamelen + 1));
     555           0 :                     char *cp = new_file->info.name;
     556             : 
     557           0 :                     if (dirarray[diridx].dir != NULL)
     558             :                       /* This value could be NULL in case the
     559             :                          DW_AT_comp_dir was not present.  We
     560             :                          cannot do much in this case.  The easiest
     561             :                          thing is to convert the path in an
     562             :                          absolute path.  */
     563           0 :                       cp = stpcpy (cp, dirarray[diridx].dir);
     564           0 :                     *cp++ = '/';
     565           0 :                     strcpy (cp, fname);
     566             :                   }
     567             : 
     568           0 :                 new_file->info.mtime = mtime;
     569           0 :                 new_file->info.length = filelength;
     570             :               }
     571           0 :               break;
     572             : 
     573             :             case DW_LNE_set_discriminator:
     574             :               /* Takes one ULEB128 parameter, the discriminator.  */
     575       37890 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     576             :                 goto invalid_data;
     577             : 
     578       37890 :               if (unlikely (linep >= lineendp))
     579             :                 goto invalid_data;
     580       37890 :               get_uleb128 (state.discriminator, linep, lineendp);
     581       37890 :               break;
     582             : 
     583             :             default:
     584             :               /* Unknown, ignore it.  */
     585             :               if (unlikely ((size_t) (lineendp - (linep - 1)) < len))
     586             :                 goto invalid_data;
     587           4 :               linep += len - 1;
     588           4 :               break;
     589             :             }
     590             :         }
     591      323799 :       else if (opcode <= DW_LNS_set_isa)
     592             :         {
     593             :           /* This is a known standard opcode.  */
     594      323799 :           switch (opcode)
     595             :             {
     596             :             case DW_LNS_copy:
     597             :               /* Takes no argument.  */
     598       21928 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     599             :                 goto invalid_data;
     600             : 
     601             :               /* Add a new line with the current state machine values.  */
     602       21928 :               NEW_LINE (0);
     603             : 
     604             :               /* Reset the flags.  */
     605       21928 :               state.basic_block = false;
     606       21928 :               state.prologue_end = false;
     607       21928 :               state.epilogue_begin = false;
     608       21928 :               state.discriminator = 0;
     609       21928 :               break;
     610             : 
     611             :             case DW_LNS_advance_pc:
     612             :               /* Takes one uleb128 parameter which is added to the
     613             :                  address.  */
     614       33537 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     615             :                 goto invalid_data;
     616             : 
     617       33537 :               if (unlikely (linep >= lineendp))
     618             :                 goto invalid_data;
     619       33537 :               get_uleb128 (u128, linep, lineendp);
     620       33537 :               advance_pc (u128);
     621             :               break;
     622             : 
     623             :             case DW_LNS_advance_line:
     624             :               /* Takes one sleb128 parameter which is added to the
     625             :                  line.  */
     626      136791 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     627             :                 goto invalid_data;
     628             : 
     629      136791 :               if (unlikely (linep >= lineendp))
     630             :                 goto invalid_data;
     631      136791 :               get_sleb128 (s128, linep, lineendp);
     632      136791 :               state.line += s128;
     633      136791 :               break;
     634             : 
     635             :             case DW_LNS_set_file:
     636             :               /* Takes one uleb128 parameter which is stored in file.  */
     637       39522 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     638             :                 goto invalid_data;
     639             : 
     640       39522 :               if (unlikely (linep >= lineendp))
     641             :                 goto invalid_data;
     642       39522 :               get_uleb128 (u128, linep, lineendp);
     643       39522 :               state.file = u128;
     644       39522 :               break;
     645             : 
     646             :             case DW_LNS_set_column:
     647             :               /* Takes one uleb128 parameter which is stored in column.  */
     648           0 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     649             :                 goto invalid_data;
     650             : 
     651           0 :               if (unlikely (linep >= lineendp))
     652             :                 goto invalid_data;
     653           0 :               get_uleb128 (u128, linep, lineendp);
     654           0 :               state.column = u128;
     655           0 :               break;
     656             : 
     657             :             case DW_LNS_negate_stmt:
     658             :               /* Takes no argument.  */
     659       16089 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     660             :                 goto invalid_data;
     661             : 
     662       16089 :               state.is_stmt = 1 - state.is_stmt;
     663       16089 :               break;
     664             : 
     665             :             case DW_LNS_set_basic_block:
     666             :               /* Takes no argument.  */
     667           0 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     668             :                 goto invalid_data;
     669             : 
     670           0 :               state.basic_block = true;
     671           0 :               break;
     672             : 
     673             :             case DW_LNS_const_add_pc:
     674             :               /* Takes no argument.  */
     675       75930 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     676             :                 goto invalid_data;
     677             : 
     678       75930 :               if (unlikely (line_range == 0))
     679             :                 goto invalid_data;
     680             : 
     681       75930 :               advance_pc ((255 - opcode_base) / line_range);
     682             :               break;
     683             : 
     684             :             case DW_LNS_fixed_advance_pc:
     685             :               /* Takes one 16 bit parameter which is added to the
     686             :                  address.  */
     687           0 :               if (unlikely (standard_opcode_lengths[opcode] != 1)
     688           0 :                   || unlikely (lineendp - linep < 2))
     689             :                 goto invalid_data;
     690             : 
     691           0 :               state.addr += read_2ubyte_unaligned_inc (dbg, linep);
     692           0 :               state.op_index = 0;
     693           0 :               break;
     694             : 
     695             :             case DW_LNS_set_prologue_end:
     696             :               /* Takes no argument.  */
     697           2 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     698             :                 goto invalid_data;
     699             : 
     700           2 :               state.prologue_end = true;
     701           2 :               break;
     702             : 
     703             :             case DW_LNS_set_epilogue_begin:
     704             :               /* Takes no argument.  */
     705           0 :               if (unlikely (standard_opcode_lengths[opcode] != 0))
     706             :                 goto invalid_data;
     707             : 
     708           0 :               state.epilogue_begin = true;
     709           0 :               break;
     710             : 
     711             :             case DW_LNS_set_isa:
     712             :               /* Takes one uleb128 parameter which is stored in isa.  */
     713           0 :               if (unlikely (standard_opcode_lengths[opcode] != 1))
     714             :                 goto invalid_data;
     715             : 
     716           0 :               if (unlikely (linep >= lineendp))
     717             :                 goto invalid_data;
     718           0 :               get_uleb128 (state.isa, linep, lineendp);
     719           0 :               break;
     720             :             }
     721             :         }
     722             :       else
     723             :         {
     724             :           /* This is a new opcode the generator but not we know about.
     725             :              Read the parameters associated with it but then discard
     726             :              everything.  Read all the parameters for this opcode.  */
     727           0 :           for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
     728             :             {
     729           0 :               if (unlikely (linep >= lineendp))
     730             :                 goto invalid_data;
     731           0 :               get_uleb128 (u128, linep, lineendp);
     732             :             }
     733             : 
     734             :           /* Next round, ignore this opcode.  */
     735           0 :           continue;
     736             :         }
     737             :     }
     738             : 
     739             :   /* Put all the files in an array.  */
     740        4338 :   Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
     741             :                                     sizeof (Dwarf_Files)
     742             :                                     + nfilelist * sizeof (Dwarf_Fileinfo)
     743             :                                     + (ndirlist + 1) * sizeof (char *),
     744             :                                     1);
     745        4338 :   const char **dirs = (void *) &files->info[nfilelist];
     746             : 
     747        4338 :   struct filelist *fileslist = filelist;
     748        4338 :   files->nfiles = nfilelist;
     749       77000 :   for (size_t n = nfilelist; n > 0; n--)
     750             :     {
     751       72662 :       files->info[n - 1] = fileslist->info;
     752       72662 :       fileslist = fileslist->next;
     753             :     }
     754        4338 :   assert (fileslist == NULL);
     755             : 
     756             :   /* Put all the directory strings in an array.  */
     757        4338 :   files->ndirs = ndirlist;
     758       33190 :   for (unsigned int i = 0; i < ndirlist; ++i)
     759       28852 :     dirs[i] = dirarray[i].dir;
     760        4338 :   dirs[ndirlist] = NULL;
     761             : 
     762             :   /* Pass the file data structure to the caller.  */
     763        4338 :   if (filesp != NULL)
     764        4338 :     *filesp = files;
     765             : 
     766        4338 :   size_t buf_size = (sizeof (Dwarf_Lines)
     767        4338 :                      + (sizeof (Dwarf_Line) * state.nlinelist));
     768        4338 :   void *buf = libdw_alloc (dbg, Dwarf_Lines, buf_size, 1);
     769             : 
     770             :   /* First use the buffer for the pointers, and sort the entries.
     771             :      We'll write the pointers in the end of the buffer, and then
     772             :      copy into the buffer from the beginning so the overlap works.  */
     773             :   assert (sizeof (Dwarf_Line) >= sizeof (struct linelist *));
     774        4338 :   struct linelist **sortlines = (buf + buf_size
     775        4338 :                                  - sizeof (struct linelist **) * state.nlinelist);
     776             : 
     777             :   /* The list is in LIFO order and usually they come in clumps with
     778             :      ascending addresses.  So fill from the back to probably start with
     779             :      runs already in order before we sort.  */
     780        4338 :   struct linelist *lineslist = state.linelist;
     781      375782 :   for (size_t i = state.nlinelist; i-- > 0; )
     782             :     {
     783      367106 :       sortlines[i] = lineslist;
     784      367106 :       lineslist = lineslist->next;
     785             :     }
     786        4338 :   assert (lineslist == NULL);
     787             : 
     788             :   /* Sort by ascending address.  */
     789        4338 :   qsort (sortlines, state.nlinelist, sizeof sortlines[0], &compare_lines);
     790             : 
     791             :   /* Now that they are sorted, put them in the final array.
     792             :      The buffers overlap, so we've clobbered the early elements
     793             :      of SORTLINES by the time we're reading the later ones.  */
     794        4338 :   Dwarf_Lines *lines = buf;
     795        4338 :   lines->nlines = state.nlinelist;
     796      371444 :   for (size_t i = 0; i < state.nlinelist; ++i)
     797             :     {
     798      367106 :       lines->info[i] = sortlines[i]->line;
     799      367106 :       lines->info[i].files = files;
     800             :     }
     801             : 
     802             :   /* Make sure the highest address for the CU is marked as end_sequence.
     803             :      This is required by the DWARF spec, but some compilers forget and
     804             :      dwfl_module_getsrc depends on it.  */
     805        4338 :   if (state.nlinelist > 0)
     806        4336 :     lines->info[state.nlinelist - 1].end_sequence = 1;
     807             : 
     808             :   /* Pass the line structure back to the caller.  */
     809        4338 :   if (linesp != NULL)
     810        4338 :     *linesp = lines;
     811             : 
     812             :   /* Success.  */
     813             :   res = 0;
     814             : 
     815             :  out:
     816             :   /* Free malloced line records, if any.  */
     817        7459 :   for (size_t i = MAX_STACK_LINES; i < state.nlinelist; i++)
     818             :     {
     819        3121 :       struct linelist *ll = state.linelist->next;
     820        3121 :       free (state.linelist);
     821        3121 :       state.linelist = ll;
     822             :     }
     823        4338 :   if (ndirlist >= MAX_STACK_DIRS)
     824           0 :     free (dirarray);
     825           0 :   for (size_t i = MAX_STACK_FILES; i < nfilelist; i++)
     826             :     {
     827           0 :       struct filelist *fl = filelist->next;
     828           0 :       free (filelist);
     829           0 :       filelist = fl;
     830             :     }
     831             : 
     832        4338 :   return res;
     833             : }
     834             : 
     835             : static int
     836       70046 : files_lines_compare (const void *p1, const void *p2)
     837             : {
     838       70046 :   const struct files_lines_s *t1 = p1;
     839       70046 :   const struct files_lines_s *t2 = p2;
     840             : 
     841       70046 :   if (t1->debug_line_offset < t2->debug_line_offset)
     842             :     return -1;
     843       70034 :   if (t1->debug_line_offset > t2->debug_line_offset)
     844             :     return 1;
     845             : 
     846           0 :   return 0;
     847             : }
     848             : 
     849             : int
     850             : internal_function
     851        4338 : __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
     852             :                      const char *comp_dir, unsigned address_size,
     853             :                      Dwarf_Lines **linesp, Dwarf_Files **filesp)
     854             : {
     855        4338 :   struct files_lines_s fake = { .debug_line_offset = debug_line_offset };
     856        4338 :   struct files_lines_s **found = tfind (&fake, &dbg->files_lines,
     857             :                                         files_lines_compare);
     858        4338 :   if (found == NULL)
     859             :     {
     860        4338 :       Elf_Data *data = __libdw_checked_get_data (dbg, IDX_debug_line);
     861        4338 :       if (data == NULL
     862        4338 :           || __libdw_offset_in_section (dbg, IDX_debug_line,
     863             :                                         debug_line_offset, 1) != 0)
     864             :         return -1;
     865             : 
     866        4338 :       const unsigned char *linep = data->d_buf + debug_line_offset;
     867        4338 :       const unsigned char *lineendp = data->d_buf + data->d_size;
     868             : 
     869        4338 :       struct files_lines_s *node = libdw_alloc (dbg, struct files_lines_s,
     870             :                                                 sizeof *node, 1);
     871             : 
     872        4338 :       if (read_srclines (dbg, linep, lineendp, comp_dir, address_size,
     873             :                          &node->lines, &node->files) != 0)
     874             :         return -1;
     875             : 
     876        4338 :       node->debug_line_offset = debug_line_offset;
     877             : 
     878        4338 :       found = tsearch (node, &dbg->files_lines, files_lines_compare);
     879        4338 :       if (found == NULL)
     880             :         {
     881           0 :           __libdw_seterrno (DWARF_E_NOMEM);
     882           0 :           return -1;
     883             :         }
     884             :     }
     885             : 
     886        4338 :   if (linesp != NULL)
     887        4334 :     *linesp = (*found)->lines;
     888             : 
     889        4338 :   if (filesp != NULL)
     890        4338 :     *filesp = (*found)->files;
     891             : 
     892             :   return 0;
     893             : }
     894             : 
     895             : /* Get the compilation directory, if any is set.  */
     896             : const char *
     897        4348 : __libdw_getcompdir (Dwarf_Die *cudie)
     898             : {
     899             :   Dwarf_Attribute compdir_attr_mem;
     900        4348 :   Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
     901             :                                                       DW_AT_comp_dir,
     902             :                                                       &compdir_attr_mem);
     903        4348 :   return INTUSE(dwarf_formstring) (compdir_attr);
     904             : }
     905             : 
     906             : int
     907        4366 : dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
     908             : {
     909        4366 :   if (cudie == NULL)
     910             :     return -1;
     911        8732 :   if (! is_cudie (cudie))
     912             :     {
     913           0 :       __libdw_seterrno (DWARF_E_NOT_CUDIE);
     914           0 :       return -1;
     915             :     }
     916             : 
     917             :   /* Get the information if it is not already known.  */
     918        4366 :   struct Dwarf_CU *const cu = cudie->cu;
     919        4366 :   if (cu->lines == NULL)
     920             :     {
     921             :       /* Failsafe mode: no data found.  */
     922        4334 :       cu->lines = (void *) -1l;
     923        4334 :       cu->files = (void *) -1l;
     924             : 
     925             :       /* The die must have a statement list associated.  */
     926             :       Dwarf_Attribute stmt_list_mem;
     927        4334 :       Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
     928             :                                                        &stmt_list_mem);
     929             : 
     930             :       /* Get the offset into the .debug_line section.  NB: this call
     931             :          also checks whether the previous dwarf_attr call failed.  */
     932             :       Dwarf_Off debug_line_offset;
     933        4334 :       if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
     934             :                            NULL, &debug_line_offset) == NULL)
     935           0 :         return -1;
     936             : 
     937        8668 :       if (__libdw_getsrclines (cu->dbg, debug_line_offset,
     938             :                                __libdw_getcompdir (cudie),
     939        4334 :                                cu->address_size, &cu->lines, &cu->files) < 0)
     940             :         return -1;
     941             :     }
     942          32 :   else if (cu->lines == (void *) -1l)
     943             :     return -1;
     944             : 
     945        4366 :   *lines = cu->lines;
     946        4366 :   *nlines = cu->lines->nlines;
     947             : 
     948             :   // XXX Eventually: unlocking here.
     949             : 
     950        4366 :   return 0;
     951             : }
     952             : INTDEF(dwarf_getsrclines)

Generated by: LCOV version 1.12