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