1 /* DWARF aranges handling 2 3 Copyright (C) 1994-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "dwarf2/aranges.h" 21 #include "dwarf2/read.h" 22 23 /* See aranges.h. */ 24 25 bool 26 read_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, 27 dwarf2_section_info *section, 28 addrmap_mutable *mutable_map, 29 deferred_warnings *warn) 30 { 31 /* Caller must ensure that the section has already been read. */ 32 gdb_assert (section->readin); 33 if (section->empty ()) 34 return false; 35 36 struct objfile *objfile = per_objfile->objfile; 37 bfd *abfd = objfile->obfd.get (); 38 struct gdbarch *gdbarch = objfile->arch (); 39 dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; 40 41 std::unordered_map<sect_offset, 42 dwarf2_per_cu_data *, 43 gdb::hash_enum<sect_offset>> 44 debug_info_offset_to_per_cu; 45 for (const auto &per_cu : per_bfd->all_units) 46 { 47 /* A TU will not need aranges, and skipping them here is an easy 48 way of ignoring .debug_types -- and possibly seeing a 49 duplicate section offset -- entirely. The same applies to 50 units coming from a dwz file. */ 51 if (per_cu->is_debug_types || per_cu->is_dwz) 52 continue; 53 54 const auto insertpair 55 = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, 56 per_cu.get ()); 57 58 /* Assume no duplicate offsets in all_units. */ 59 gdb_assert (insertpair.second); 60 } 61 62 std::set<sect_offset> debug_info_offset_seen; 63 const bfd_endian dwarf5_byte_order = gdbarch_byte_order (gdbarch); 64 const gdb_byte *addr = section->buffer; 65 while (addr < section->buffer + section->size) 66 { 67 const gdb_byte *const entry_addr = addr; 68 unsigned int bytes_read; 69 70 const LONGEST entry_length = read_initial_length (abfd, addr, 71 &bytes_read); 72 addr += bytes_read; 73 74 const gdb_byte *const entry_end = addr + entry_length; 75 const bool dwarf5_is_dwarf64 = bytes_read != 4; 76 const uint8_t offset_size = dwarf5_is_dwarf64 ? 8 : 4; 77 if (addr + entry_length > section->buffer + section->size) 78 { 79 warn->warn (_("Section .debug_aranges in %s entry at offset %s " 80 "length %s exceeds section length %s, " 81 "ignoring .debug_aranges."), 82 objfile_name (objfile), 83 plongest (entry_addr - section->buffer), 84 plongest (bytes_read + entry_length), 85 pulongest (section->size)); 86 return false; 87 } 88 89 /* The version number. */ 90 const uint16_t version = read_2_bytes (abfd, addr); 91 addr += 2; 92 if (version != 2) 93 { 94 warn->warn 95 (_("Section .debug_aranges in %s entry at offset %s " 96 "has unsupported version %d, ignoring .debug_aranges."), 97 objfile_name (objfile), 98 plongest (entry_addr - section->buffer), version); 99 return false; 100 } 101 102 const uint64_t debug_info_offset 103 = extract_unsigned_integer (addr, offset_size, dwarf5_byte_order); 104 addr += offset_size; 105 const auto per_cu_it 106 = debug_info_offset_to_per_cu.find (sect_offset (debug_info_offset)); 107 if (per_cu_it == debug_info_offset_to_per_cu.cend ()) 108 { 109 warn->warn (_("Section .debug_aranges in %s entry at offset %s " 110 "debug_info_offset %s does not exists, " 111 "ignoring .debug_aranges."), 112 objfile_name (objfile), 113 plongest (entry_addr - section->buffer), 114 pulongest (debug_info_offset)); 115 return false; 116 } 117 const auto insertpair 118 = debug_info_offset_seen.insert (sect_offset (debug_info_offset)); 119 if (!insertpair.second) 120 { 121 warn->warn (_("Section .debug_aranges in %s has duplicate " 122 "debug_info_offset %s, ignoring .debug_aranges."), 123 objfile_name (objfile), 124 sect_offset_str (sect_offset (debug_info_offset))); 125 return false; 126 } 127 dwarf2_per_cu_data *const per_cu = per_cu_it->second; 128 129 const uint8_t address_size = *addr++; 130 if (address_size < 1 || address_size > 8) 131 { 132 warn->warn 133 (_("Section .debug_aranges in %s entry at offset %s " 134 "address_size %u is invalid, ignoring .debug_aranges."), 135 objfile_name (objfile), 136 plongest (entry_addr - section->buffer), address_size); 137 return false; 138 } 139 140 const uint8_t segment_selector_size = *addr++; 141 if (segment_selector_size != 0) 142 { 143 warn->warn (_("Section .debug_aranges in %s entry at offset %s " 144 "segment_selector_size %u is not supported, " 145 "ignoring .debug_aranges."), 146 objfile_name (objfile), 147 plongest (entry_addr - section->buffer), 148 segment_selector_size); 149 return false; 150 } 151 152 /* Must pad to an alignment boundary that is twice the address 153 size. It is undocumented by the DWARF standard but GCC does 154 use it. However, not every compiler does this. We can see 155 whether it has happened by looking at the total length of the 156 contents of the aranges for this CU -- it if isn't a multiple 157 of twice the address size, then we skip any leftover 158 bytes. */ 159 addr += (entry_end - addr) % (2 * address_size); 160 161 while (addr < entry_end) 162 { 163 if (addr + 2 * address_size > entry_end) 164 { 165 warn->warn (_("Section .debug_aranges in %s entry at offset %s " 166 "address list is not properly terminated, " 167 "ignoring .debug_aranges."), 168 objfile_name (objfile), 169 plongest (entry_addr - section->buffer)); 170 return false; 171 } 172 ULONGEST start = extract_unsigned_integer (addr, address_size, 173 dwarf5_byte_order); 174 addr += address_size; 175 ULONGEST length = extract_unsigned_integer (addr, address_size, 176 dwarf5_byte_order); 177 addr += address_size; 178 if (start == 0 && length == 0) 179 { 180 /* This can happen on some targets with --gc-sections. 181 This pair of values is also used to mark the end of 182 the entries for a given CU, but we ignore it and 183 instead handle termination using the check at the top 184 of the loop. */ 185 continue; 186 } 187 if (start == 0 && !per_bfd->has_section_at_zero) 188 { 189 /* Symbol was eliminated due to a COMDAT group. */ 190 continue; 191 } 192 ULONGEST end = start + length; 193 mutable_map->set_empty (start, end - 1, per_cu); 194 } 195 196 per_cu->addresses_seen = true; 197 } 198 199 return true; 200 } 201