LCOV - code coverage report
Current view: top level - libdw - dwarf_nextcu.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 83.7 % 86 72
Test Date: 2025-08-30 14:31:09 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 79.8 % 84 67

             Branch data     Line data    Source code
       1                 :             : /* Advance to next CU header.
       2                 :             :    Copyright (C) 2002-2010, 2016, 2017 Red Hat, Inc.
       3                 :             :    This file is part of elfutils.
       4                 :             :    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
       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 <libdwP.h>
      35                 :             : #include <dwarf.h>
      36                 :             : 
      37                 :             : 
      38                 :             : int
      39                 :       70848 : dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
      40                 :             :                  size_t *header_sizep, Dwarf_Half *versionp,
      41                 :             :                  Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
      42                 :             :                  uint8_t *offset_sizep, uint64_t *v4_type_signaturep,
      43                 :             :                  Dwarf_Off *v4_type_offsetp)
      44                 :             : {
      45                 :       70848 :   const bool v4_debug_types = v4_type_signaturep != NULL;
      46                 :       70848 :   return __libdw_next_unit (dwarf, v4_debug_types, off, next_off,
      47                 :             :                              header_sizep, versionp, NULL,
      48                 :             :                              abbrev_offsetp, address_sizep, offset_sizep,
      49                 :             :                              v4_type_signaturep, v4_type_offsetp);
      50                 :             : }
      51                 :             : INTDEF(dwarf_next_unit)
      52                 :             : 
      53                 :             : int
      54                 :             : internal_function
      55                 :      155056 : __libdw_next_unit (Dwarf *dwarf, bool v4_debug_types, Dwarf_Off off,
      56                 :             :                    Dwarf_Off *next_off, size_t *header_sizep,
      57                 :             :                    Dwarf_Half *versionp, uint8_t *unit_typep,
      58                 :             :                    Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
      59                 :             :                    uint8_t *offset_sizep, uint64_t *unit_id8p,
      60                 :             :                    Dwarf_Off *subdie_offsetp)
      61                 :             : {
      62                 :             :   /* Note that debug_type units come from .debug_types in DWARF < 5 and
      63                 :             :      from .debug_info in DWARF >= 5.  If the user requested the
      64                 :             :      v4_type_signature we return from .debug_types always.  If no signature
      65                 :             :      is requested we return units (any type) from .debug_info.  */
      66                 :      155056 :   const size_t sec_idx = v4_debug_types ? IDX_debug_types : IDX_debug_info;
      67                 :             : 
      68                 :             :   /* Maybe there has been an error before.  */
      69         [ +  + ]:      155056 :   if (dwarf == NULL)
      70                 :             :     return -1;
      71                 :             : 
      72                 :             :   /* If we reached the end before don't do anything.  */
      73         [ +  - ]:      155032 :   if (off == (Dwarf_Off) -1l
      74         [ +  + ]:      155032 :       || unlikely (dwarf->sectiondata[sec_idx] == NULL)
      75                 :             :       /* Make sure there is enough space in the .debug_info section
      76                 :             :          for at least the initial word.  We cannot test the rest since
      77                 :             :          we don't know yet whether this is a 64-bit object or not.  */
      78         [ +  + ]:      154986 :       || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size))
      79                 :             :     {
      80                 :         902 :       *next_off = (Dwarf_Off) -1l;
      81                 :         902 :       return 1;
      82                 :             :     }
      83                 :             : 
      84                 :             :   /* This points into the .debug_info or .debug_types section to the
      85                 :             :      beginning of the CU entry.  */
      86                 :      154130 :   const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf;
      87                 :      154130 :   const unsigned char *bytes = data + off;
      88                 :      154130 :   const unsigned char *bytes_end = data + dwarf->sectiondata[sec_idx]->d_size;
      89                 :             : 
      90                 :             :   /* The format of the CU header is described in dwarf2p1 7.5.1 and
      91                 :             :      changed in DWARFv5 (to include unit type, switch location of some
      92                 :             :      fields and add some optional fields).
      93                 :             : 
      94                 :             :      1.  A 4-byte or 12-byte unsigned integer representing the length
      95                 :             :          of the .debug_info contribution for that compilation unit, not
      96                 :             :          including the length field itself. In the 32-bit DWARF format,
      97                 :             :          this is a 4-byte unsigned integer (which must be less than
      98                 :             :          0xfffffff0); in the 64-bit DWARF format, this consists of the
      99                 :             :          4-byte value 0xffffffff followed by an 8-byte unsigned integer
     100                 :             :          that gives the actual length (see Section 7.2.2). This field
     101                 :             :          indicates whether this unit is 32-bit of 64-bit DWARF, which
     102                 :             :          affects all other offset fields in this header.
     103                 :             : 
     104                 :             :       2. A 2-byte unsigned integer representing the version of the
     105                 :             :          DWARF information for that compilation unit. For DWARF Version
     106                 :             :          2.1, the value in this field is 2 (3 for v3, 4 for v4, 5 for v5).
     107                 :             :          This fields determines the order of the next fields and whether
     108                 :             :          there are any optional fields in this header.
     109                 :             : 
     110                 :             :       3. For DWARF 2, 3 and 4 (including v4 type units):
     111                 :             :          A 4-byte or 8-byte unsigned offset into the .debug_abbrev
     112                 :             :          section. This offset associates the compilation unit with a
     113                 :             :          particular set of debugging information entry abbreviations. In
     114                 :             :          the 32-bit DWARF format, this is a 4-byte unsigned length; in
     115                 :             :          the 64-bit DWARF format, this is an 8-byte unsigned length (see
     116                 :             :          Section 7.4).
     117                 :             : 
     118                 :             :          For DWARF 5:
     119                 :             :          A 1-byte unsigned integer representing the unit (header) type.
     120                 :             :          This field determines what the optional fields in the header
     121                 :             :          represent.  If this is an unknown unit type then we cannot
     122                 :             :          assume anything about the rest of the unit (header).
     123                 :             : 
     124                 :             :       4. For all DWARF versions (including v4 type units):
     125                 :             :          A 1-byte unsigned integer representing the size in bytes of
     126                 :             :          an address on the target architecture. If the system uses
     127                 :             :          segmented addressing, this value represents the size of the
     128                 :             :          offset portion of an address. This is the last field in the header
     129                 :             :          for DWARF versions 2, 3 and 4 (except for v4 type units).
     130                 :             : 
     131                 :             :       5. For DWARF 5 only (this is field 3 for DWARF 2, 3, 4 and v4 types):
     132                 :             :          A 4-byte or 8-byte unsigned offset into the .debug_abbrev
     133                 :             :          section. This offset associates the compilation unit with a
     134                 :             :          particular set of debugging information entry abbreviations. In
     135                 :             :          the 32-bit DWARF format, this is a 4-byte unsigned length; in
     136                 :             :          the 64-bit DWARF format, this is an 8-byte unsigned length.
     137                 :             : 
     138                 :             :       6. For v4 type units (this is really field 5 for v4 types) and
     139                 :             :          DWARF 5 optional (skeleton, split_compile, type and
     140                 :             :          split_type): An 8 byte (opaque) integer constant value. For
     141                 :             :          v4 and v5 type units this is the type signature. For skeleton
     142                 :             :          and split compile units this is the compilation ID.
     143                 :             : 
     144                 :             :       7. For v4 type units (this is really field 6 for v4 types) and
     145                 :             :          DWARF 5 optional (type and split_type) and v4 type units:
     146                 :             :          A 4-byte or 8-byte unsigned offset. In the 32-bit DWARF format,
     147                 :             :          this is a 4-byte unsigned length; in the 64-bit DWARF format,
     148                 :             :          this is an 8-byte unsigned length. This is the type DIE offset
     149                 :             :          (which is not necessarily the first DIE in the unit).
     150                 :             :   */
     151                 :             : 
     152         [ +  + ]:      154130 :   uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
     153                 :      154130 :   size_t offset_size = 4;
     154                 :             :   /* Lengths of 0xfffffff0 - 0xffffffff are escape codes.  Oxffffffff is
     155                 :             :      used to indicate that 64-bit dwarf information is being used, the
     156                 :             :      other values are currently reserved.  */
     157         [ +  - ]:      154130 :   if (length == DWARF3_LENGTH_64_BIT)
     158                 :             :     offset_size = 8;
     159         [ -  + ]:      154130 :   else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
     160                 :             :                      && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
     161                 :             :     {
     162                 :           0 :     invalid:
     163                 :           0 :       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     164                 :           0 :       return -1;
     165                 :             :     }
     166                 :             : 
     167                 :           0 :   if (length == DWARF3_LENGTH_64_BIT)
     168                 :             :     {
     169                 :             :       /* This is a 64-bit DWARF format.  */
     170         [ #  # ]:           0 :       if (bytes_end - bytes < 8)
     171                 :           0 :         goto invalid;
     172         [ #  # ]:           0 :       length = read_8ubyte_unaligned_inc (dwarf, bytes);
     173                 :             :     }
     174                 :             : 
     175                 :             :   /* Read the version stamp.  Always a 16-bit value.  */
     176         [ -  + ]:      154130 :   if (bytes_end - bytes < 2)
     177                 :           0 :     goto invalid;
     178         [ +  + ]:      154130 :   uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes);
     179                 :             : 
     180                 :             :   /* We keep unit_type at zero for older DWARF since we cannot
     181                 :             :      easily guess whether it is a compile or partial unit.  */
     182                 :      154130 :   uint8_t unit_type = 0;
     183         [ +  + ]:      154130 :   if (version >= 5)
     184                 :             :     {
     185         [ -  + ]:      152276 :       if (bytes_end - bytes < 1)
     186                 :           0 :         goto invalid;
     187                 :      152276 :       unit_type = *bytes++;
     188                 :             :     }
     189                 :             : 
     190                 :             :   /* All these are optional.  */
     191                 :      154130 :   Dwarf_Off subdie_off = 0;
     192                 :      154130 :   uint64_t sig_id = 0;
     193                 :      154130 :   Dwarf_Off abbrev_offset = 0;
     194                 :      154130 :   uint8_t address_size = 0;
     195                 :             : 
     196         [ +  - ]:      154130 :   if (version < 2 || version > 5
     197         [ +  + ]:      154130 :       || (version == 5 && ! (unit_type == DW_UT_compile
     198         [ +  + ]:      152276 :                              || unit_type == DW_UT_partial
     199                 :             :                              || unit_type == DW_UT_skeleton
     200         [ +  + ]:         304 :                              || unit_type == DW_UT_split_compile
     201                 :          34 :                              || unit_type == DW_UT_type
     202         [ -  + ]:          34 :                              || unit_type == DW_UT_split_type)))
     203                 :             :     {
     204                 :             :       /* We cannot really know more about the header.  Just report
     205                 :             :          the length of the unit, version and unit type.  */
     206                 :           0 :       goto done;
     207                 :             :     }
     208                 :             : 
     209                 :             :   /* We have to guess the unit_type. But we don't have a real CUDIE.  */
     210         [ +  + ]:      154130 :   if (version < 5)
     211         [ +  + ]:        1854 :     unit_type = v4_debug_types ? DW_UT_type : DW_UT_compile;
     212                 :             : 
     213                 :             :   /* Now we know how large the header is (should be).  */
     214         [ -  + ]:      154130 :   if (unlikely (__libdw_first_die_from_cu_start (off, offset_size, version,
     215                 :             :                                                  unit_type)
     216                 :             :                 >= dwarf->sectiondata[sec_idx]->d_size))
     217                 :             :     {
     218                 :           0 :       *next_off = -1;
     219                 :           0 :       return 1;
     220                 :             :     }
     221                 :             : 
     222                 :             :   /* The address size.  Always an 8-bit value.
     223                 :             :      Comes after abbrev_offset for version < 5, otherwise unit type
     224                 :             :      and address size (if a known unit type) comes before abbrev_offset.  */
     225         [ +  + ]:      154130 :   if (version >= 5)
     226                 :      152276 :     address_size = *bytes++;
     227                 :             : 
     228                 :             :   /* Get offset in .debug_abbrev.  Note that the size of the entry
     229                 :             :      depends on whether this is a 32-bit or 64-bit DWARF definition.  */
     230         [ -  + ]:      154130 :   if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
     231                 :             :                                &abbrev_offset, IDX_debug_abbrev, 0))
     232                 :             :     return -1;
     233                 :             : 
     234         [ +  + ]:      154130 :   if (version < 5)
     235                 :        1854 :     address_size = *bytes++;
     236                 :             : 
     237                 :             :   /* Extra fields, signature/id and type offset/padding.  */
     238         [ +  + ]:      154130 :   if (v4_debug_types
     239         [ +  + ]:      154070 :       || (version >= 5
     240                 :      152276 :           && (unit_type == DW_UT_skeleton || unit_type == DW_UT_split_compile
     241   [ +  +  +  + ]:      152276 :               || unit_type == DW_UT_type || unit_type == DW_UT_split_type)))
     242                 :             :     {
     243         [ -  + ]:         364 :       sig_id = read_8ubyte_unaligned_inc (dwarf, bytes);
     244                 :             : 
     245                 :         364 :       if ((v4_debug_types
     246   [ +  +  +  + ]:         364 :            || unit_type == DW_UT_type || unit_type == DW_UT_split_type))
     247                 :             :         {
     248         [ -  + ]:          94 :           if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
     249                 :             :                                        &subdie_off, sec_idx, 0))
     250                 :             :             return -1;
     251                 :             : 
     252                 :             :           /* Validate that the TYPE_OFFSET points past the header.  */
     253         [ +  - ]:          94 :           if (unlikely (subdie_off < (size_t) (bytes - (data + off))))
     254                 :           0 :             goto invalid;
     255                 :             :         }
     256                 :             :     }
     257                 :             : 
     258                 :      154130 :  done:
     259         [ +  + ]:      154130 :   if (unit_id8p != NULL)
     260                 :       84214 :     *unit_id8p = sig_id;
     261                 :             : 
     262         [ +  + ]:      154130 :   if (subdie_offsetp != NULL)
     263                 :       84202 :     *subdie_offsetp = subdie_off;
     264                 :             : 
     265                 :             :   /* Store the header length.  This is really how much we have read
     266                 :             :      from the header.  If we didn't recognize the unit type the
     267                 :             :      header might actually be bigger.  */
     268         [ +  + ]:      154130 :   if (header_sizep != NULL)
     269                 :       69932 :     *header_sizep = bytes - (data + off);
     270                 :             : 
     271         [ +  + ]:      154130 :   if (versionp != NULL)
     272                 :       84202 :     *versionp = version;
     273                 :             : 
     274         [ +  + ]:      154130 :   if (unit_typep != NULL)
     275                 :       84198 :     *unit_typep = unit_type;
     276                 :             : 
     277         [ +  + ]:      154130 :   if (abbrev_offsetp != NULL)
     278                 :       86738 :     *abbrev_offsetp = abbrev_offset;
     279                 :             : 
     280         [ +  + ]:      154130 :   if (address_sizep != NULL)
     281                 :       86738 :     *address_sizep = address_size;
     282                 :             : 
     283                 :             :   /* Store the offset size.  */
     284         [ +  + ]:      154130 :   if (offset_sizep != NULL)
     285                 :       86738 :     *offset_sizep = offset_size;
     286                 :             : 
     287                 :             :   /* The length of the unit doesn't include the length field itself.
     288                 :             :      The length field is either, with offset == 4: 2 * 4 - 4 == 4,
     289                 :             :      or with offset == 8: 2 * 8 - 4 == 12.  */
     290                 :      154130 :   *next_off = off + 2 * offset_size - 4 + length;
     291                 :             : 
     292                 :             :   /* This means that the length field is bogus, but return the CU anyway.
     293                 :             :      We just won't return anything after this.  */
     294         [ -  + ]:      154130 :   if (*next_off <= off)
     295                 :           0 :     *next_off = (Dwarf_Off) -1;
     296                 :             : 
     297                 :             :   return 0;
     298                 :             : }
     299                 :             : 
     300                 :             : int
     301                 :       70784 : dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
     302                 :             :               size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
     303                 :             :               uint8_t *address_sizep, uint8_t *offset_sizep)
     304                 :             : {
     305                 :       70784 :   return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL,
     306                 :             :                                   abbrev_offsetp, address_sizep, offset_sizep,
     307                 :             :                                   NULL, NULL);
     308                 :             : }
     309                 :             : INTDEF(dwarf_nextcu)
        

Generated by: LCOV version 2.0-1