Home | History | Annotate | Download | only in libdw
      1 /* Advance to next CU header.
      2    Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <libdwP.h>
     20 
     21 
     22 int
     23 dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp,
     24 	      address_sizep, offset_sizep)
     25      Dwarf *dwarf;
     26      Dwarf_Off off;
     27      Dwarf_Off *next_off;
     28      size_t *header_sizep;
     29      Dwarf_Off *abbrev_offsetp;
     30      uint8_t *address_sizep;
     31      uint8_t *offset_sizep;
     32 {
     33   /* Maybe there has been an error before.  */
     34   if (dwarf == NULL)
     35     return -1;
     36 
     37   /* If we reached the end before don't do anything.  */
     38   if (off == (Dwarf_Off) -1l
     39       /* Make sure there is enough space in the .debug_info section
     40 	 for at least the initial word.  We cannot test the rest since
     41 	 we don't know yet whether this is a 64-bit object or not.  */
     42       || unlikely (off + 4 >= dwarf->sectiondata[IDX_debug_info]->d_size))
     43     {
     44       *next_off = (Dwarf_Off) -1l;
     45       return 1;
     46     }
     47 
     48   /* This points into the .debug_info section to the beginning of the
     49      CU entry.  */
     50   char *bytes = (char *) dwarf->sectiondata[IDX_debug_info]->d_buf + off;
     51 
     52   /* The format of the CU header is described in dwarf2p1 7.5.1:
     53 
     54      1.  A 4-byte or 12-byte unsigned integer representing the length
     55 	 of the .debug_info contribution for that compilation unit, not
     56 	 including the length field itself. In the 32-bit DWARF format,
     57 	 this is a 4-byte unsigned integer (which must be less than
     58 	 0xffffff00); in the 64-bit DWARF format, this consists of the
     59 	 4-byte value 0xffffffff followed by an 8-byte unsigned integer
     60 	 that gives the actual length (see Section 7.4).
     61 
     62       2. A 2-byte unsigned integer representing the version of the
     63 	 DWARF information for that compilation unit. For DWARF Version
     64 	 2.1, the value in this field is 2.
     65 
     66       3. A 4-byte or 8-byte unsigned offset into the .debug_abbrev
     67 	 section. This offset associates the compilation unit with a
     68 	 particular set of debugging information entry abbreviations. In
     69 	 the 32-bit DWARF format, this is a 4-byte unsigned length; in
     70 	 the 64-bit DWARF format, this is an 8-byte unsigned length (see
     71 	 Section 7.4).
     72 
     73       4. A 1-byte unsigned integer representing the size in bytes of
     74 	 an address on the target architecture. If the system uses
     75 	 segmented addressing, this value represents the size of the
     76 	 offset portion of an address.  */
     77   uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
     78   size_t offset_size = 4;
     79   if (length == 0xffffffffu)
     80     offset_size = 8;
     81 
     82   /* Now we know how large the header is.  Note the trick in the
     83      computation.  If the offset_size is 4 the '- 4' term undoes the
     84      '2 *'.  If offset_size is 8 this term computes the size of the
     85      escape value plus the 8 byte offset.  */
     86   if (unlikely (off + 2 * offset_size - 4 + sizeof (uint16_t)
     87 		+ offset_size + sizeof (uint8_t)
     88 		>= dwarf->sectiondata[IDX_debug_info]->d_size))
     89     {
     90       *next_off = -1;
     91       return 1;
     92     }
     93 
     94   if (length == 0xffffffffu)
     95     /* This is a 64-bit DWARF format.  */
     96     length = read_8ubyte_unaligned_inc (dwarf, bytes);
     97 
     98   /* Read the version stamp.  Always a 16-bit value.
     99      XXX Do we need the value?  */
    100   read_2ubyte_unaligned_inc (dwarf, bytes);
    101 
    102   /* Get offset in .debug_abbrev.  Note that the size of the entry
    103      depends on whether this is a 32-bit or 64-bit DWARF definition.  */
    104   uint64_t abbrev_offset;
    105   if (offset_size == 4)
    106     abbrev_offset = read_4ubyte_unaligned_inc (dwarf, bytes);
    107   else
    108     abbrev_offset = read_8ubyte_unaligned_inc (dwarf, bytes);
    109   if (abbrev_offsetp != NULL)
    110     *abbrev_offsetp = abbrev_offset;
    111 
    112   /* The address size.  Always an 8-bit value.  */
    113   uint8_t address_size = *bytes++;
    114   if (address_sizep != NULL)
    115     *address_sizep = address_size;
    116 
    117   /* Store the offset size.  */
    118   if (offset_sizep != NULL)
    119     *offset_sizep = offset_size;
    120 
    121   /* Store the header length.  */
    122   if (header_sizep != NULL)
    123     *header_sizep = (bytes
    124 		     - ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf
    125 			+ off));
    126 
    127   /* See above for an explanation of the trick in this formula.  */
    128   *next_off = off + 2 * offset_size - 4 + length;
    129 
    130   return 0;
    131 }
    132