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