LCOV - code coverage report
Current view: top level - libdw - dwarf_cu_dwp_section_info.c (source / functions) Hit Total Coverage
Test: elfutils-0.191 Lines: 140 255 54.9 %
Date: 2024-08-30 13:26:44 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 101 218 46.3 %

           Branch data     Line data    Source code
       1                 :            : /* Read DWARF package file index sections.
       2                 :            :    Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       3                 :            :    This file is part of elfutils.
       4                 :            : 
       5                 :            :    This file is free software; you can redistribute it and/or modify
       6                 :            :    it under the terms of either
       7                 :            : 
       8                 :            :      * the GNU Lesser General Public License as published by the Free
       9                 :            :        Software Foundation; either version 3 of the License, or (at
      10                 :            :        your option) any later version
      11                 :            : 
      12                 :            :    or
      13                 :            : 
      14                 :            :      * the GNU General Public License as published by the Free
      15                 :            :        Software Foundation; either version 2 of the License, or (at
      16                 :            :        your option) any later version
      17                 :            : 
      18                 :            :    or both in parallel, as here.
      19                 :            : 
      20                 :            :    elfutils is distributed in the hope that it will be useful, but
      21                 :            :    WITHOUT ANY WARRANTY; without even the implied warranty of
      22                 :            :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      23                 :            :    General Public License for more details.
      24                 :            : 
      25                 :            :    You should have received copies of the GNU General Public License and
      26                 :            :    the GNU Lesser General Public License along with this program.  If
      27                 :            :    not, see <http://www.gnu.org/licenses/>.  */
      28                 :            : 
      29                 :            : #ifdef HAVE_CONFIG_H
      30                 :            : # include <config.h>
      31                 :            : #endif
      32                 :            : 
      33                 :            : #include <assert.h>
      34                 :            : 
      35                 :            : #include "libdwP.h"
      36                 :            : 
      37                 :            : static Dwarf_Package_Index *
      38                 :         52 : __libdw_read_package_index (Dwarf *dbg, bool tu)
      39                 :            : {
      40                 :         52 :   Elf_Data *data;
      41         [ +  + ]:         52 :   if (tu)
      42                 :         18 :     data = dbg->sectiondata[IDX_debug_tu_index];
      43                 :            :   else
      44                 :         34 :     data = dbg->sectiondata[IDX_debug_cu_index];
      45                 :            : 
      46                 :            :   /* We need at least 16 bytes for the header.  */
      47   [ -  +  -  + ]:         52 :   if (data == NULL || data->d_size < 16)
      48                 :            :     {
      49                 :          0 :     invalid:
      50                 :          0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
      51                 :          0 :       return NULL;
      52                 :            :     }
      53                 :            : 
      54                 :         52 :   const unsigned char *datap = data->d_buf;
      55                 :         52 :   const unsigned char *endp = datap + data->d_size;
      56                 :         52 :   uint16_t version;
      57                 :            :   /* In GNU DebugFission for DWARF 4, the version is 2 as a uword.  In the
      58                 :            :      standardized DWARF 5 format, it is a uhalf followed by a padding uhalf.
      59                 :            :      Check for both.  */
      60   [ -  +  +  + ]:         52 :   if (read_4ubyte_unaligned (dbg, datap) == 2)
      61                 :            :     version = 2;
      62                 :            :   else
      63                 :            :     {
      64         [ -  + ]:         28 :       version = read_2ubyte_unaligned (dbg, datap);
      65         [ -  + ]:         28 :       if (version != 5)
      66                 :            :         {
      67                 :          0 :           __libdw_seterrno (DWARF_E_VERSION);
      68                 :          0 :           return NULL;
      69                 :            :         }
      70                 :            :     }
      71                 :         52 :   datap += 4;
      72         [ -  + ]:         52 :   uint32_t section_count = read_4ubyte_unaligned_inc (dbg, datap);
      73         [ -  + ]:         52 :   uint32_t unit_count = read_4ubyte_unaligned_inc (dbg, datap);
      74         [ -  + ]:         52 :   uint32_t slot_count = read_4ubyte_unaligned_inc (dbg, datap);
      75                 :            : 
      76                 :            :   /* The specification has a stricter requirement that
      77                 :            :      slot_count > 3 * unit_count / 2, but this is enough for us.  */
      78         [ -  + ]:         52 :   if (slot_count < unit_count)
      79                 :          0 :     goto invalid;
      80                 :            : 
      81                 :            :   /* After the header, the section must contain:
      82                 :            : 
      83                 :            :        8 byte signature per hash table slot
      84                 :            :      + 4 byte index per hash table slot
      85                 :            :      + Section offset table with 1 header row, 1 row per unit, 1 column per
      86                 :            :        section, 4 bytes per field
      87                 :            :      + Section size table with 1 row per unit, 1 column per section, 4 bytes
      88                 :            :        per field
      89                 :            : 
      90                 :            :      We have to be careful about overflow when checking this.  */
      91                 :         52 :   const unsigned char *hash_table = datap;
      92         [ -  + ]:         52 :   if ((size_t) (endp - hash_table) < (uint64_t) slot_count * 12)
      93                 :          0 :     goto invalid;
      94                 :         52 :   const unsigned char *indices = hash_table + (size_t) slot_count * 8;
      95                 :         52 :   const unsigned char *sections = indices + (size_t) slot_count * 4;
      96         [ -  + ]:         52 :   if ((size_t) (endp - sections) < (uint64_t) section_count * 4)
      97                 :          0 :     goto invalid;
      98                 :         52 :   const unsigned char *section_offsets = sections + (size_t) section_count * 4;
      99         [ +  - ]:         52 :   if ((uint64_t) unit_count * section_count > UINT64_MAX / 8
     100                 :         52 :       || ((size_t) (endp - section_offsets)
     101         [ -  + ]:         52 :           < (uint64_t) unit_count * section_count * 8))
     102                 :          0 :     goto invalid;
     103                 :         52 :   const unsigned char *section_sizes
     104                 :         52 :     = section_offsets + (uint64_t) unit_count * section_count * 4;
     105                 :            : 
     106                 :         52 :   Dwarf_Package_Index *index = malloc (sizeof (*index));
     107         [ -  + ]:         52 :   if (index == NULL)
     108                 :            :     {
     109                 :          0 :       __libdw_seterrno (DWARF_E_NOMEM);
     110                 :          0 :       return NULL;
     111                 :            :     }
     112                 :            : 
     113                 :         52 :   index->dbg = dbg;
     114                 :            :   /* Set absent sections to UINT32_MAX.  */
     115                 :         52 :   for (size_t i = 0;
     116         [ +  + ]:        468 :        i < sizeof (index->sections) / sizeof (index->sections[0]); i++)
     117                 :        416 :     index->sections[i] = UINT32_MAX;
     118         [ +  + ]:        392 :   for (size_t i = 0; i < section_count; i++)
     119                 :            :     {
     120         [ -  + ]:        340 :       uint32_t section = read_4ubyte_unaligned (dbg, sections + i * 4);
     121                 :            :       /* 2 is DW_SECT_TYPES in version 2 and reserved in version 5.  We ignore
     122                 :            :          it for version 5.
     123                 :            :          5 is DW_SECT_LOC in version 2 and DW_SECT_LOCLISTS in version 5.  We
     124                 :            :          use the same index for both.
     125                 :            :          7 is DW_SECT_MACINFO in version 2 and DW_SECT_MACRO in version 5.  We
     126                 :            :          use the same index for both.
     127                 :            :          8 is DW_SECT_MACRO in version 2 and DW_SECT_RNGLISTS in version 5.  We
     128                 :            :          use the same index for version 2's DW_SECT_MACRO as version 2's
     129                 :            :          DW_SECT_MACINFO/version 5's DW_SECT_MACRO.
     130                 :            :          We ignore unknown sections.  */
     131         [ -  + ]:        340 :       if (section == 0)
     132                 :          0 :         continue;
     133         [ +  + ]:        340 :       if (version == 2)
     134                 :            :         {
     135         [ -  + ]:        144 :           if (section > 8)
     136                 :          0 :             continue;
     137         [ +  + ]:        144 :           else if (section == 8)
     138                 :        340 :             section = DW_SECT_MACRO;
     139                 :            :         }
     140                 :        196 :       else if (section == 2
     141                 :        196 :                || (section
     142         [ -  + ]:        196 :                    > sizeof (index->sections) / sizeof (index->sections[0])))
     143                 :          0 :         continue;
     144                 :        340 :       index->sections[section - 1] = i;
     145                 :            :     }
     146                 :            : 
     147                 :            :   /* DW_SECT_INFO (or DW_SECT_TYPES for DWARF 4 type units) and DW_SECT_ABBREV
     148                 :            :      are required.  */
     149   [ +  +  +  + ]:         52 :   if (((!tu || dbg->sectiondata[IDX_debug_types] == NULL)
     150         [ +  - ]:         48 :        && index->sections[DW_SECT_INFO - 1] == UINT32_MAX)
     151   [ +  +  +  + ]:         52 :       || (tu && dbg->sectiondata[IDX_debug_types] != NULL
     152         [ +  - ]:          4 :           && index->sections[DW_SECT_TYPES - 1] == UINT32_MAX)
     153         [ -  + ]:         52 :       || index->sections[DW_SECT_ABBREV - 1] == UINT32_MAX)
     154                 :            :     {
     155                 :          0 :       free (index);
     156                 :          0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     157                 :          0 :       return NULL;
     158                 :            :     }
     159                 :            : 
     160                 :         52 :   index->section_count = section_count;
     161                 :         52 :   index->unit_count = unit_count;
     162                 :         52 :   index->slot_count = slot_count;
     163                 :         52 :   index->last_unit_found = 0;
     164                 :         52 :   index->hash_table = hash_table;
     165                 :         52 :   index->indices = indices;
     166                 :         52 :   index->section_offsets = section_offsets;
     167                 :         52 :   index->section_sizes = section_sizes;
     168                 :         52 :   index->debug_info_offsets = NULL;
     169                 :            : 
     170                 :         52 :   return index;
     171                 :            : }
     172                 :            : 
     173                 :            : static Dwarf_Package_Index *
     174                 :        204 : __libdw_package_index (Dwarf *dbg, bool tu)
     175                 :            : {
     176   [ +  +  +  + ]:        204 :   if (tu && dbg->tu_index != NULL)
     177                 :            :     return dbg->tu_index;
     178         [ +  + ]:        168 :   else if (!tu && dbg->cu_index != NULL)
     179                 :            :     return dbg->cu_index;
     180                 :            : 
     181                 :         52 :   Dwarf_Package_Index *index = __libdw_read_package_index (dbg, tu);
     182         [ -  + ]:         52 :   if (index == NULL)
     183                 :            :     return NULL;
     184                 :            : 
     185                 :            :   /* Offsets in the section offset table are 32-bit unsigned integers.  In
     186                 :            :      practice, the .debug_info.dwo section for very large executables can be
     187                 :            :      larger than 4GB.  GNU dwp as of binutils 2.41 and llvm-dwp before LLVM 15
     188                 :            :      both accidentally truncate offsets larger than 4GB.
     189                 :            : 
     190                 :            :      LLVM 15 detects the overflow and errors out instead; see LLVM commit
     191                 :            :      f8df8114715b ("[DWP][DWARF] Detect and error on debug info offset
     192                 :            :      overflow").  However, lldb in LLVM 16 supports using dwp files with
     193                 :            :      truncated offsets by recovering them directly from the unit headers in the
     194                 :            :      .debug_info.dwo section; see LLVM commit c0db06227721 ("[DWARFLibrary] Add
     195                 :            :      support to re-construct cu-index").  Since LLVM 17, the overflow error can
     196                 :            :      be turned into a warning instead; see LLVM commit 53a483cee801 ("[DWP] add
     197                 :            :      overflow check for llvm-dwp tools if offset overflow").
     198                 :            : 
     199                 :            :      LLVM's support for > 4GB offsets is effectively an extension to the DWARF
     200                 :            :      package file format, which we implement here.  The strategy is to walk the
     201                 :            :      unit headers in .debug_info.dwo in lockstep with the DW_SECT_INFO columns
     202                 :            :      in the section offset tables.  As long as they are in the same order
     203                 :            :      (which they are in practice for both GNU dwp and llvm-dwp), we can
     204                 :            :      correlate the truncated offset and produce a corrected array of offsets.
     205                 :            : 
     206                 :            :      Note that this will be fixed properly in DWARF 6:
     207                 :            :      https://dwarfstd.org/issues/220708.2.html.  */
     208         [ +  + ]:         52 :   if (index->sections[DW_SECT_INFO - 1] != UINT32_MAX
     209         [ -  + ]:         48 :       && dbg->sectiondata[IDX_debug_info]->d_size > UINT32_MAX)
     210                 :            :     {
     211                 :          0 :       Dwarf_Package_Index *cu_index, *tu_index = NULL;
     212         [ #  # ]:          0 :       if (tu)
     213                 :            :         {
     214                 :          0 :           tu_index = index;
     215         [ #  # ]:          0 :           assert (dbg->cu_index == NULL);
     216                 :          0 :           cu_index = __libdw_read_package_index (dbg, false);
     217         [ #  # ]:          0 :           if (cu_index == NULL)
     218                 :            :             {
     219                 :          0 :               free(index);
     220                 :          0 :               return NULL;
     221                 :            :             }
     222                 :            :         }
     223                 :            :       else
     224                 :            :         {
     225                 :          0 :           cu_index = index;
     226         [ #  # ]:          0 :           if (dbg->sectiondata[IDX_debug_tu_index] != NULL
     227         [ #  # ]:          0 :               && dbg->sectiondata[IDX_debug_types] == NULL)
     228                 :            :             {
     229         [ #  # ]:          0 :               assert (dbg->tu_index == NULL);
     230                 :          0 :               tu_index = __libdw_read_package_index (dbg, true);
     231         [ #  # ]:          0 :               if (tu_index == NULL)
     232                 :            :                 {
     233                 :          0 :                   free(index);
     234                 :          0 :                   return NULL;
     235                 :            :                 }
     236                 :            :             }
     237                 :            :         }
     238                 :            : 
     239                 :          0 :       cu_index->debug_info_offsets = malloc (cu_index->unit_count
     240                 :            :                                              * sizeof (Dwarf_Off));
     241         [ #  # ]:          0 :       if (cu_index->debug_info_offsets == NULL)
     242                 :            :         {
     243                 :          0 :           free (tu_index);
     244                 :          0 :           free (cu_index);
     245                 :          0 :           __libdw_seterrno (DWARF_E_NOMEM);
     246                 :          0 :           return NULL;
     247                 :            :         }
     248         [ #  # ]:          0 :       if (tu_index != NULL)
     249                 :            :         {
     250                 :          0 :           tu_index->debug_info_offsets = malloc (tu_index->unit_count
     251                 :            :                                                  * sizeof (Dwarf_Off));
     252         [ #  # ]:          0 :           if (tu_index->debug_info_offsets == NULL)
     253                 :            :             {
     254                 :          0 :               free (tu_index);
     255                 :          0 :               free (cu_index->debug_info_offsets);
     256                 :          0 :               free (cu_index);
     257                 :          0 :               __libdw_seterrno (DWARF_E_NOMEM);
     258                 :          0 :               return NULL;
     259                 :            :             }
     260                 :            :         }
     261                 :            : 
     262                 :          0 :       Dwarf_Off off = 0;
     263                 :          0 :       uint32_t cui = 0, tui = 0;
     264                 :          0 :       uint32_t cu_count = cu_index->unit_count;
     265                 :          0 :       const unsigned char *cu_offset
     266                 :          0 :         = cu_index->section_offsets + cu_index->sections[DW_SECT_INFO - 1] * 4;
     267                 :          0 :       uint32_t tu_count = 0;
     268                 :          0 :       const unsigned char *tu_offset = NULL;
     269         [ #  # ]:          0 :       if (tu_index != NULL)
     270                 :            :         {
     271                 :          0 :           tu_count = tu_index->unit_count;
     272                 :          0 :           tu_offset = tu_index->section_offsets
     273                 :          0 :                       + tu_index->sections[DW_SECT_INFO - 1] * 4;
     274                 :            :         }
     275         [ #  # ]:          0 :       while (cui < cu_count || tui < tu_count)
     276                 :            :         {
     277                 :          0 :           Dwarf_Off next_off;
     278                 :          0 :           uint8_t unit_type;
     279         [ #  # ]:          0 :           if (__libdw_next_unit (dbg, false, off, &next_off, NULL, NULL,
     280                 :            :                                  &unit_type, NULL, NULL, NULL, NULL, NULL)
     281                 :            :               != 0)
     282                 :            :             {
     283                 :          0 :             not_sorted:
     284                 :          0 :               free (cu_index->debug_info_offsets);
     285                 :          0 :               cu_index->debug_info_offsets = NULL;
     286         [ #  # ]:          0 :               if (tu_index != NULL)
     287                 :            :                 {
     288                 :          0 :                   free (tu_index->debug_info_offsets);
     289                 :          0 :                   tu_index->debug_info_offsets = NULL;
     290                 :            :                 }
     291                 :          0 :               break;
     292                 :            :             }
     293   [ #  #  #  # ]:          0 :           if (unit_type != DW_UT_split_type && cui < cu_count)
     294                 :            :             {
     295   [ #  #  #  # ]:          0 :               if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, cu_offset))
     296                 :          0 :                 goto not_sorted;
     297                 :          0 :               cu_index->debug_info_offsets[cui++] = off;
     298                 :          0 :               cu_offset += cu_index->section_count * 4;
     299                 :            :             }
     300         [ #  # ]:          0 :           else if (unit_type == DW_UT_split_type && tu_index != NULL
     301         [ #  # ]:          0 :                    && tui < tu_count)
     302                 :            :             {
     303   [ #  #  #  # ]:          0 :               if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
     304                 :          0 :                 goto not_sorted;
     305                 :          0 :               tu_index->debug_info_offsets[tui++] = off;
     306                 :          0 :               tu_offset += tu_index->section_count * 4;
     307                 :            :             }
     308                 :          0 :           off = next_off;
     309                 :            :         }
     310                 :            : 
     311         [ #  # ]:          0 :       if (tu)
     312                 :          0 :         dbg->cu_index = cu_index;
     313         [ #  # ]:          0 :       else if (tu_index != NULL)
     314                 :          0 :         dbg->tu_index = tu_index;
     315                 :            :     }
     316                 :            : 
     317         [ +  + ]:         52 :   if (tu)
     318                 :         18 :     dbg->tu_index = index;
     319                 :            :   else
     320                 :         34 :     dbg->cu_index = index;
     321                 :            :   return index;
     322                 :            : }
     323                 :            : 
     324                 :            : static int
     325                 :         66 : __libdw_dwp_unit_row (Dwarf_Package_Index *index, uint64_t unit_id,
     326                 :            :                       uint32_t *unit_rowp)
     327                 :            : {
     328         [ +  - ]:         66 :   if (index == NULL)
     329                 :            :     return -1;
     330                 :            : 
     331                 :         66 :   uint32_t hash = unit_id;
     332                 :         66 :   uint32_t hash2 = (unit_id >> 32) | 1;
     333                 :            :   /* Only check each slot once.  */
     334         [ +  - ]:         66 :   for (uint32_t n = index->slot_count; n-- > 0; )
     335                 :            :     {
     336                 :         66 :       size_t slot = hash & (index->slot_count - 1);
     337         [ -  + ]:         66 :       uint64_t sig = read_8ubyte_unaligned (index->dbg,
     338                 :            :                                             index->hash_table + slot * 8);
     339         [ +  - ]:         66 :       if (sig == unit_id)
     340                 :            :         {
     341         [ -  + ]:         66 :           uint32_t row = read_4ubyte_unaligned (index->dbg,
     342                 :            :                                                 index->indices + slot * 4);
     343         [ -  + ]:         66 :           if (row > index->unit_count)
     344                 :            :             {
     345                 :          0 :               __libdw_seterrno (DWARF_E_INVALID_DWARF);
     346                 :          0 :               return -1;
     347                 :            :             }
     348                 :         66 :           *unit_rowp = row;
     349                 :         66 :           return 0;
     350                 :            :         }
     351         [ #  # ]:          0 :       else if (sig == 0
     352         [ #  # ]:          0 :                && read_4ubyte_unaligned (index->dbg,
     353         [ #  # ]:          0 :                                          index->indices + slot * 4) == 0)
     354                 :            :         break;
     355                 :          0 :       hash += hash2;
     356                 :            :     }
     357                 :          0 :   *unit_rowp = 0;
     358                 :          0 :   return 0;
     359                 :            : }
     360                 :            : 
     361                 :            : static int
     362                 :       6408 : __libdw_dwp_section_info (Dwarf_Package_Index *index, uint32_t unit_row,
     363                 :            :                           unsigned int section, Dwarf_Off *offsetp,
     364                 :            :                           Dwarf_Off *sizep)
     365                 :            : {
     366         [ +  - ]:       6408 :   if (index == NULL)
     367                 :            :     return -1;
     368         [ -  + ]:       6408 :   if (unit_row == 0)
     369                 :            :     {
     370                 :          0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     371                 :          0 :       return -1;
     372                 :            :     }
     373         [ +  + ]:       6408 :   if (index->sections[section - 1] == UINT32_MAX)
     374                 :            :     {
     375         [ +  - ]:         50 :       if (offsetp != NULL)
     376                 :         50 :         *offsetp = 0;
     377         [ +  - ]:         50 :       if (sizep != NULL)
     378                 :         50 :         *sizep = 0;
     379                 :         50 :       return 0;
     380                 :            :     }
     381                 :       6358 :   size_t i = (size_t)(unit_row - 1) * index->section_count
     382                 :       6358 :              + index->sections[section - 1];
     383         [ +  - ]:       6358 :   if (offsetp != NULL)
     384                 :            :     {
     385   [ +  +  -  + ]:       6358 :       if (section == DW_SECT_INFO && index->debug_info_offsets != NULL)
     386                 :          0 :         *offsetp = index->debug_info_offsets[unit_row - 1];
     387                 :            :       else
     388         [ -  + ]:       6358 :         *offsetp = read_4ubyte_unaligned (index->dbg,
     389                 :            :                                           index->section_offsets + i * 4);
     390                 :            :     }
     391         [ +  + ]:       6358 :   if (sizep != NULL)
     392         [ -  + ]:        328 :     *sizep = read_4ubyte_unaligned (index->dbg,
     393                 :            :                                     index->section_sizes + i * 4);
     394                 :            :   return 0;
     395                 :            : }
     396                 :            : 
     397                 :            : int
     398                 :            : internal_function
     399                 :      71570 : __libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off,
     400                 :            :                        uint16_t version, uint8_t unit_type, uint64_t unit_id8,
     401                 :            :                        uint32_t *unit_rowp, Dwarf_Off *abbrev_offsetp)
     402                 :            : {
     403                 :      71570 :   if (version >= 5
     404   [ +  +  +  + ]:      71570 :       && unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
     405                 :            :     {
     406                 :      70046 :     not_dwp:
     407                 :      71432 :       *unit_rowp = 0;
     408                 :      71432 :       *abbrev_offsetp = 0;
     409                 :      71432 :       return 0;
     410                 :            :     }
     411                 :       1524 :   bool tu = unit_type == DW_UT_split_type || debug_types;
     412   [ +  +  +  + ]:       2976 :   if (dbg->sectiondata[tu ? IDX_debug_tu_index : IDX_debug_cu_index] == NULL)
     413                 :       1386 :     goto not_dwp;
     414                 :        138 :   Dwarf_Package_Index *index = __libdw_package_index (dbg, tu);
     415         [ -  + ]:        138 :   if (index == NULL)
     416                 :            :     return -1;
     417                 :            : 
     418                 :            :   /* This is always called for ascending offsets.  The most obvious way for a
     419                 :            :      producer to generate the section offset table is sorted by offset; both
     420                 :            :      GNU dwp and llvm-dwp do this.  In this common case, we can avoid the full
     421                 :            :      lookup.  */
     422         [ +  - ]:        138 :   if (index->last_unit_found < index->unit_count)
     423                 :            :     {
     424                 :        138 :       Dwarf_Off offset, size;
     425   [ +  +  -  + ]:        268 :       if (__libdw_dwp_section_info (index, index->last_unit_found + 1,
     426                 :            :                                     debug_types ? DW_SECT_TYPES : DW_SECT_INFO,
     427                 :            :                                     &offset, &size) != 0)
     428                 :          0 :         return -1;
     429   [ +  -  +  - ]:        138 :       if (offset <= off && off - offset < size)
     430                 :            :         {
     431                 :        138 :           *unit_rowp = ++index->last_unit_found;
     432                 :        138 :           goto done;
     433                 :            :         }
     434                 :            :       else
     435                 :            :         /* The units are not sorted. Don't try again.  */
     436                 :          0 :         index->last_unit_found = index->unit_count;
     437                 :            :     }
     438                 :            : 
     439         [ #  # ]:          0 :   if (version >= 5 || debug_types)
     440                 :            :     {
     441                 :            :       /* In DWARF 5 and in type units, the unit signature is available in the
     442                 :            :          unit header.  */
     443         [ #  # ]:          0 :       if (__libdw_dwp_unit_row (index, unit_id8, unit_rowp) != 0)
     444                 :            :         return -1;
     445                 :            :     }
     446                 :            :   else
     447                 :            :     {
     448                 :            :       /* In DWARF 4 compilation units, the unit signature is an attribute.  We
     449                 :            :          can't parse attributes in the split unit until we get the abbreviation
     450                 :            :          table offset from the package index, which is a chicken-and-egg
     451                 :            :          problem.  We could get the signature from the skeleton unit, but that
     452                 :            :          may not be available.
     453                 :            : 
     454                 :            :          Instead, we resort to a linear scan through the section offset table.
     455                 :            :          Finding all units is therefore quadratic in the number of units.
     456                 :            :          However, this will likely never be needed in practice because of the
     457                 :            :          sorted fast path above.  If this ceases to be the case, we can try to
     458                 :            :          plumb through the skeleton unit's signature when it is available, or
     459                 :            :          build a sorted lookup table for binary search.  */
     460         [ #  # ]:          0 :       if (index->sections[DW_SECT_INFO - 1] == UINT32_MAX)
     461                 :            :         {
     462                 :          0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
     463                 :          0 :           return -1;
     464                 :            :         }
     465         [ #  # ]:          0 :       for (uint32_t i = 0; i < index->unit_count; i++)
     466                 :            :         {
     467                 :          0 :           Dwarf_Off offset, size;
     468                 :          0 :           __libdw_dwp_section_info (index, i + 1, DW_SECT_INFO, &offset,
     469                 :            :                                     &size);
     470   [ #  #  #  # ]:          0 :           if (offset <= off && off - offset < size)
     471                 :            :             {
     472                 :          0 :               *unit_rowp = i + 1;
     473                 :          0 :               goto done;
     474                 :            :             }
     475                 :            :         }
     476                 :          0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     477                 :          0 :       return -1;
     478                 :            :     }
     479                 :            : 
     480                 :        138 :  done:
     481                 :        138 :   return __libdw_dwp_section_info (index, *unit_rowp, DW_SECT_ABBREV,
     482                 :            :                                    abbrev_offsetp, NULL);
     483                 :            : }
     484                 :            : 
     485                 :            : Dwarf_CU *
     486                 :            : internal_function
     487                 :         66 : __libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8)
     488                 :            : {
     489                 :         66 :   Dwarf_Package_Index *index = __libdw_package_index (dbg, false);
     490                 :         66 :   uint32_t unit_row;
     491                 :         66 :   Dwarf_Off offset;
     492                 :         66 :   Dwarf_CU *cu;
     493         [ +  - ]:         66 :   if (__libdw_dwp_unit_row (index, unit_id8, &unit_row) == 0
     494         [ +  - ]:         66 :       && __libdw_dwp_section_info (index, unit_row, DW_SECT_INFO, &offset,
     495                 :            :                                    NULL) == 0
     496         [ +  - ]:         66 :       && (cu = __libdw_findcu (dbg, offset, false)) != NULL
     497         [ +  - ]:         66 :       && cu->unit_type == DW_UT_split_compile
     498         [ -  + ]:         66 :       && cu->unit_id8 == unit_id8)
     499                 :            :     return cu;
     500                 :            :   else
     501                 :          0 :     return NULL;
     502                 :            : }
     503                 :            : 
     504                 :            : int
     505                 :     598700 : dwarf_cu_dwp_section_info (Dwarf_CU *cu, unsigned int section,
     506                 :            :                            Dwarf_Off *offsetp, Dwarf_Off *sizep)
     507                 :            : {
     508         [ -  + ]:     598700 :   if (cu == NULL)
     509                 :            :     return -1;
     510         [ -  + ]:     598700 :   if (section < DW_SECT_INFO || section > DW_SECT_RNGLISTS)
     511                 :            :     {
     512                 :          0 :       __libdw_seterrno (DWARF_E_UNKNOWN_SECTION);
     513                 :          0 :       return -1;
     514                 :            :     }
     515         [ +  + ]:     598700 :   if (cu->dwp_row == 0)
     516                 :            :     {
     517         [ +  - ]:     592634 :       if (offsetp != NULL)
     518                 :     592634 :         *offsetp = 0;
     519         [ -  + ]:     592634 :       if (sizep != NULL)
     520                 :          0 :         *sizep = 0;
     521                 :     592634 :       return 0;
     522                 :            :     }
     523                 :            :   else
     524                 :            :     {
     525                 :      18198 :       Dwarf_Package_Index *index
     526         [ +  + ]:       6066 :         = cu->unit_type == DW_UT_split_compile
     527                 :       6066 :         ? cu->dbg->cu_index : cu->dbg->tu_index;
     528                 :       6066 :       return __libdw_dwp_section_info (index, cu->dwp_row, section, offsetp,
     529                 :            :                                        sizep);
     530                 :            :     }
     531                 :            : }
     532                 :            : INTDEF(dwarf_cu_dwp_section_info)

Generated by: LCOV version 1.16