1*7304104dSAndroid Build Coastguard Worker /* Get macro information.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2002-2009, 2014, 2017, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include <assert.h>
34*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
35*7304104dSAndroid Build Coastguard Worker #include <search.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
37*7304104dSAndroid Build Coastguard Worker #include <string.h>
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker #include <libdwP.h>
40*7304104dSAndroid Build Coastguard Worker
41*7304104dSAndroid Build Coastguard Worker static int
get_offset_from(Dwarf_Die * die,int name,Dwarf_Word * retp)42*7304104dSAndroid Build Coastguard Worker get_offset_from (Dwarf_Die *die, int name, Dwarf_Word *retp)
43*7304104dSAndroid Build Coastguard Worker {
44*7304104dSAndroid Build Coastguard Worker /* Get the appropriate attribute. */
45*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
46*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_attr) (die, name, &attr) == NULL)
47*7304104dSAndroid Build Coastguard Worker return -1;
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker /* Offset into the corresponding section. */
50*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_formudata) (&attr, retp) != 0)
51*7304104dSAndroid Build Coastguard Worker return -1;
52*7304104dSAndroid Build Coastguard Worker
53*7304104dSAndroid Build Coastguard Worker Dwarf_Off offset;
54*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_cu_dwp_section_info) (die->cu, DW_SECT_MACRO, &offset, NULL)
55*7304104dSAndroid Build Coastguard Worker != 0)
56*7304104dSAndroid Build Coastguard Worker return -1;
57*7304104dSAndroid Build Coastguard Worker *retp += offset;
58*7304104dSAndroid Build Coastguard Worker return 0;
59*7304104dSAndroid Build Coastguard Worker }
60*7304104dSAndroid Build Coastguard Worker
61*7304104dSAndroid Build Coastguard Worker static int
macro_op_compare(const void * p1,const void * p2)62*7304104dSAndroid Build Coastguard Worker macro_op_compare (const void *p1, const void *p2)
63*7304104dSAndroid Build Coastguard Worker {
64*7304104dSAndroid Build Coastguard Worker const Dwarf_Macro_Op_Table *t1 = (const Dwarf_Macro_Op_Table *) p1;
65*7304104dSAndroid Build Coastguard Worker const Dwarf_Macro_Op_Table *t2 = (const Dwarf_Macro_Op_Table *) p2;
66*7304104dSAndroid Build Coastguard Worker
67*7304104dSAndroid Build Coastguard Worker if (t1->offset < t2->offset)
68*7304104dSAndroid Build Coastguard Worker return -1;
69*7304104dSAndroid Build Coastguard Worker if (t1->offset > t2->offset)
70*7304104dSAndroid Build Coastguard Worker return 1;
71*7304104dSAndroid Build Coastguard Worker
72*7304104dSAndroid Build Coastguard Worker if (t1->sec_index < t2->sec_index)
73*7304104dSAndroid Build Coastguard Worker return -1;
74*7304104dSAndroid Build Coastguard Worker if (t1->sec_index > t2->sec_index)
75*7304104dSAndroid Build Coastguard Worker return 1;
76*7304104dSAndroid Build Coastguard Worker
77*7304104dSAndroid Build Coastguard Worker return 0;
78*7304104dSAndroid Build Coastguard Worker }
79*7304104dSAndroid Build Coastguard Worker
80*7304104dSAndroid Build Coastguard Worker static void
build_table(Dwarf_Macro_Op_Table * table,Dwarf_Macro_Op_Proto op_protos[static255])81*7304104dSAndroid Build Coastguard Worker build_table (Dwarf_Macro_Op_Table *table,
82*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto op_protos[static 255])
83*7304104dSAndroid Build Coastguard Worker {
84*7304104dSAndroid Build Coastguard Worker unsigned ct = 0;
85*7304104dSAndroid Build Coastguard Worker for (unsigned i = 1; i < 256; ++i)
86*7304104dSAndroid Build Coastguard Worker if (op_protos[i - 1].forms != NULL)
87*7304104dSAndroid Build Coastguard Worker table->table[table->opcodes[i - 1] = ct++] = op_protos[i - 1];
88*7304104dSAndroid Build Coastguard Worker else
89*7304104dSAndroid Build Coastguard Worker table->opcodes[i - 1] = 0xff;
90*7304104dSAndroid Build Coastguard Worker }
91*7304104dSAndroid Build Coastguard Worker
92*7304104dSAndroid Build Coastguard Worker #define MACRO_PROTO(NAME, ...) \
93*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto NAME = ({ \
94*7304104dSAndroid Build Coastguard Worker static const uint8_t proto[] = {__VA_ARGS__}; \
95*7304104dSAndroid Build Coastguard Worker (Dwarf_Macro_Op_Proto) {sizeof proto, proto}; \
96*7304104dSAndroid Build Coastguard Worker })
97*7304104dSAndroid Build Coastguard Worker
98*7304104dSAndroid Build Coastguard Worker enum { macinfo_data_size = offsetof (Dwarf_Macro_Op_Table, table[5]) };
99*7304104dSAndroid Build Coastguard Worker static unsigned char macinfo_data[macinfo_data_size]
100*7304104dSAndroid Build Coastguard Worker __attribute__ ((aligned (__alignof (Dwarf_Macro_Op_Table))));
101*7304104dSAndroid Build Coastguard Worker
102*7304104dSAndroid Build Coastguard Worker static __attribute__ ((constructor)) void
init_macinfo_table(void)103*7304104dSAndroid Build Coastguard Worker init_macinfo_table (void)
104*7304104dSAndroid Build Coastguard Worker {
105*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
106*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
107*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_none);
108*7304104dSAndroid Build Coastguard Worker
109*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto op_protos[255] =
110*7304104dSAndroid Build Coastguard Worker {
111*7304104dSAndroid Build Coastguard Worker [DW_MACINFO_define - 1] = p_udata_str,
112*7304104dSAndroid Build Coastguard Worker [DW_MACINFO_undef - 1] = p_udata_str,
113*7304104dSAndroid Build Coastguard Worker [DW_MACINFO_vendor_ext - 1] = p_udata_str,
114*7304104dSAndroid Build Coastguard Worker [DW_MACINFO_start_file - 1] = p_udata_udata,
115*7304104dSAndroid Build Coastguard Worker [DW_MACINFO_end_file - 1] = p_none,
116*7304104dSAndroid Build Coastguard Worker /* If you are adding more elements to this array, increase
117*7304104dSAndroid Build Coastguard Worker MACINFO_DATA_SIZE above. */
118*7304104dSAndroid Build Coastguard Worker };
119*7304104dSAndroid Build Coastguard Worker
120*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table *macinfo_table = (void *) macinfo_data;
121*7304104dSAndroid Build Coastguard Worker memset (macinfo_table, 0, sizeof macinfo_data);
122*7304104dSAndroid Build Coastguard Worker build_table (macinfo_table, op_protos);
123*7304104dSAndroid Build Coastguard Worker macinfo_table->sec_index = IDX_debug_macinfo;
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker
126*7304104dSAndroid Build Coastguard Worker static Dwarf_Macro_Op_Table *
get_macinfo_table(Dwarf * dbg,Dwarf_Word macoff,Dwarf_Die * cudie)127*7304104dSAndroid Build Coastguard Worker get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die *cudie)
128*7304104dSAndroid Build Coastguard Worker {
129*7304104dSAndroid Build Coastguard Worker assert (cudie != NULL);
130*7304104dSAndroid Build Coastguard Worker
131*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem, *attr
132*7304104dSAndroid Build Coastguard Worker = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
133*7304104dSAndroid Build Coastguard Worker Dwarf_Off line_offset = (Dwarf_Off) -1;
134*7304104dSAndroid Build Coastguard Worker if (attr != NULL)
135*7304104dSAndroid Build Coastguard Worker {
136*7304104dSAndroid Build Coastguard Worker if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
137*7304104dSAndroid Build Coastguard Worker return NULL;
138*7304104dSAndroid Build Coastguard Worker }
139*7304104dSAndroid Build Coastguard Worker else if (cudie->cu->unit_type == DW_UT_split_compile
140*7304104dSAndroid Build Coastguard Worker && dbg->sectiondata[IDX_debug_line] != NULL)
141*7304104dSAndroid Build Coastguard Worker line_offset = 0;
142*7304104dSAndroid Build Coastguard Worker if (line_offset != (Dwarf_Off) -1)
143*7304104dSAndroid Build Coastguard Worker {
144*7304104dSAndroid Build Coastguard Worker Dwarf_Off dwp_offset;
145*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
146*7304104dSAndroid Build Coastguard Worker &dwp_offset, NULL) != 0)
147*7304104dSAndroid Build Coastguard Worker return NULL;
148*7304104dSAndroid Build Coastguard Worker line_offset += dwp_offset;
149*7304104dSAndroid Build Coastguard Worker }
150*7304104dSAndroid Build Coastguard Worker
151*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
152*7304104dSAndroid Build Coastguard Worker macinfo_data_size, 1);
153*7304104dSAndroid Build Coastguard Worker memcpy (table, macinfo_data, macinfo_data_size);
154*7304104dSAndroid Build Coastguard Worker
155*7304104dSAndroid Build Coastguard Worker table->dbg = dbg;
156*7304104dSAndroid Build Coastguard Worker table->offset = macoff;
157*7304104dSAndroid Build Coastguard Worker table->sec_index = IDX_debug_macinfo;
158*7304104dSAndroid Build Coastguard Worker table->line_offset = line_offset;
159*7304104dSAndroid Build Coastguard Worker table->address_size = cudie->cu->address_size;
160*7304104dSAndroid Build Coastguard Worker table->offset_size = cudie->cu->offset_size;
161*7304104dSAndroid Build Coastguard Worker table->comp_dir = __libdw_getcompdir (cudie);
162*7304104dSAndroid Build Coastguard Worker
163*7304104dSAndroid Build Coastguard Worker return table;
164*7304104dSAndroid Build Coastguard Worker }
165*7304104dSAndroid Build Coastguard Worker
166*7304104dSAndroid Build Coastguard Worker static Dwarf_Macro_Op_Table *
get_table_for_offset(Dwarf * dbg,Dwarf_Word macoff,const unsigned char * readp,const unsigned char * const endp,Dwarf_Die * cudie)167*7304104dSAndroid Build Coastguard Worker get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
168*7304104dSAndroid Build Coastguard Worker const unsigned char *readp,
169*7304104dSAndroid Build Coastguard Worker const unsigned char *const endp,
170*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie)
171*7304104dSAndroid Build Coastguard Worker {
172*7304104dSAndroid Build Coastguard Worker const unsigned char *startp = readp;
173*7304104dSAndroid Build Coastguard Worker
174*7304104dSAndroid Build Coastguard Worker /* Request at least 3 bytes for header. */
175*7304104dSAndroid Build Coastguard Worker if (readp + 3 > endp)
176*7304104dSAndroid Build Coastguard Worker {
177*7304104dSAndroid Build Coastguard Worker invalid_dwarf:
178*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
179*7304104dSAndroid Build Coastguard Worker return NULL;
180*7304104dSAndroid Build Coastguard Worker }
181*7304104dSAndroid Build Coastguard Worker
182*7304104dSAndroid Build Coastguard Worker uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
183*7304104dSAndroid Build Coastguard Worker if (version != 4 && version != 5)
184*7304104dSAndroid Build Coastguard Worker {
185*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_VERSION);
186*7304104dSAndroid Build Coastguard Worker return NULL;
187*7304104dSAndroid Build Coastguard Worker }
188*7304104dSAndroid Build Coastguard Worker
189*7304104dSAndroid Build Coastguard Worker uint8_t flags = *readp++;
190*7304104dSAndroid Build Coastguard Worker bool is_64bit = (flags & 0x1) != 0;
191*7304104dSAndroid Build Coastguard Worker
192*7304104dSAndroid Build Coastguard Worker Dwarf_Off line_offset = (Dwarf_Off) -1;
193*7304104dSAndroid Build Coastguard Worker if ((flags & 0x2) != 0)
194*7304104dSAndroid Build Coastguard Worker {
195*7304104dSAndroid Build Coastguard Worker line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
196*7304104dSAndroid Build Coastguard Worker if (readp > endp)
197*7304104dSAndroid Build Coastguard Worker goto invalid_dwarf;
198*7304104dSAndroid Build Coastguard Worker }
199*7304104dSAndroid Build Coastguard Worker else if (cudie != NULL)
200*7304104dSAndroid Build Coastguard Worker {
201*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr_mem, *attr
202*7304104dSAndroid Build Coastguard Worker = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
203*7304104dSAndroid Build Coastguard Worker if (attr != NULL)
204*7304104dSAndroid Build Coastguard Worker if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
205*7304104dSAndroid Build Coastguard Worker return NULL;
206*7304104dSAndroid Build Coastguard Worker }
207*7304104dSAndroid Build Coastguard Worker if (line_offset != (Dwarf_Off) -1 && cudie != NULL)
208*7304104dSAndroid Build Coastguard Worker {
209*7304104dSAndroid Build Coastguard Worker Dwarf_Off dwp_offset;
210*7304104dSAndroid Build Coastguard Worker if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
211*7304104dSAndroid Build Coastguard Worker &dwp_offset, NULL) != 0)
212*7304104dSAndroid Build Coastguard Worker return NULL;
213*7304104dSAndroid Build Coastguard Worker line_offset += dwp_offset;
214*7304104dSAndroid Build Coastguard Worker }
215*7304104dSAndroid Build Coastguard Worker
216*7304104dSAndroid Build Coastguard Worker uint8_t address_size;
217*7304104dSAndroid Build Coastguard Worker if (cudie != NULL)
218*7304104dSAndroid Build Coastguard Worker address_size = cudie->cu->address_size;
219*7304104dSAndroid Build Coastguard Worker else
220*7304104dSAndroid Build Coastguard Worker {
221*7304104dSAndroid Build Coastguard Worker char *ident = elf_getident (dbg->elf, NULL);
222*7304104dSAndroid Build Coastguard Worker address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
223*7304104dSAndroid Build Coastguard Worker }
224*7304104dSAndroid Build Coastguard Worker
225*7304104dSAndroid Build Coastguard Worker /* """The macinfo entry types defined in this standard may, but
226*7304104dSAndroid Build Coastguard Worker might not, be described in the table""".
227*7304104dSAndroid Build Coastguard Worker
228*7304104dSAndroid Build Coastguard Worker I.e. these may be present. It's tempting to simply skip them,
229*7304104dSAndroid Build Coastguard Worker but it's probably more correct to tolerate that a producer tweaks
230*7304104dSAndroid Build Coastguard Worker the way certain opcodes are encoded, for whatever reasons. */
231*7304104dSAndroid Build Coastguard Worker
232*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
233*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
234*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup);
235*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx);
236*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
237*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
238*7304104dSAndroid Build Coastguard Worker MACRO_PROTO (p_none);
239*7304104dSAndroid Build Coastguard Worker
240*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto op_protos[255] =
241*7304104dSAndroid Build Coastguard Worker {
242*7304104dSAndroid Build Coastguard Worker [DW_MACRO_define - 1] = p_udata_str,
243*7304104dSAndroid Build Coastguard Worker [DW_MACRO_undef - 1] = p_udata_str,
244*7304104dSAndroid Build Coastguard Worker [DW_MACRO_define_strp - 1] = p_udata_strp,
245*7304104dSAndroid Build Coastguard Worker [DW_MACRO_undef_strp - 1] = p_udata_strp,
246*7304104dSAndroid Build Coastguard Worker [DW_MACRO_start_file - 1] = p_udata_udata,
247*7304104dSAndroid Build Coastguard Worker [DW_MACRO_end_file - 1] = p_none,
248*7304104dSAndroid Build Coastguard Worker [DW_MACRO_import - 1] = p_secoffset,
249*7304104dSAndroid Build Coastguard Worker [DW_MACRO_define_sup - 1] = p_udata_strsup,
250*7304104dSAndroid Build Coastguard Worker [DW_MACRO_undef_sup - 1] = p_udata_strsup,
251*7304104dSAndroid Build Coastguard Worker [DW_MACRO_import_sup - 1] = p_secoffset, /* XXX - but in sup!. */
252*7304104dSAndroid Build Coastguard Worker [DW_MACRO_define_strx - 1] = p_udata_strx,
253*7304104dSAndroid Build Coastguard Worker [DW_MACRO_undef_strx - 1] = p_udata_strx,
254*7304104dSAndroid Build Coastguard Worker };
255*7304104dSAndroid Build Coastguard Worker
256*7304104dSAndroid Build Coastguard Worker if ((flags & 0x4) != 0)
257*7304104dSAndroid Build Coastguard Worker {
258*7304104dSAndroid Build Coastguard Worker unsigned count = *readp++;
259*7304104dSAndroid Build Coastguard Worker for (unsigned i = 0; i < count; ++i)
260*7304104dSAndroid Build Coastguard Worker {
261*7304104dSAndroid Build Coastguard Worker unsigned opcode = *readp++;
262*7304104dSAndroid Build Coastguard Worker
263*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto e;
264*7304104dSAndroid Build Coastguard Worker if (readp >= endp)
265*7304104dSAndroid Build Coastguard Worker goto invalid;
266*7304104dSAndroid Build Coastguard Worker get_uleb128 (e.nforms, readp, endp);
267*7304104dSAndroid Build Coastguard Worker e.forms = readp;
268*7304104dSAndroid Build Coastguard Worker op_protos[opcode - 1] = e;
269*7304104dSAndroid Build Coastguard Worker
270*7304104dSAndroid Build Coastguard Worker readp += e.nforms;
271*7304104dSAndroid Build Coastguard Worker if (readp > endp)
272*7304104dSAndroid Build Coastguard Worker {
273*7304104dSAndroid Build Coastguard Worker invalid:
274*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
275*7304104dSAndroid Build Coastguard Worker return NULL;
276*7304104dSAndroid Build Coastguard Worker }
277*7304104dSAndroid Build Coastguard Worker }
278*7304104dSAndroid Build Coastguard Worker }
279*7304104dSAndroid Build Coastguard Worker
280*7304104dSAndroid Build Coastguard Worker size_t ct = 0;
281*7304104dSAndroid Build Coastguard Worker for (unsigned i = 1; i < 256; ++i)
282*7304104dSAndroid Build Coastguard Worker if (op_protos[i - 1].forms != NULL)
283*7304104dSAndroid Build Coastguard Worker ++ct;
284*7304104dSAndroid Build Coastguard Worker
285*7304104dSAndroid Build Coastguard Worker /* We support at most 0xfe opcodes defined in the table, as 0xff is
286*7304104dSAndroid Build Coastguard Worker a value that means that given opcode is not stored at all. But
287*7304104dSAndroid Build Coastguard Worker that should be fine, as opcode 0 is not allocated. */
288*7304104dSAndroid Build Coastguard Worker assert (ct < 0xff);
289*7304104dSAndroid Build Coastguard Worker
290*7304104dSAndroid Build Coastguard Worker size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
291*7304104dSAndroid Build Coastguard Worker
292*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
293*7304104dSAndroid Build Coastguard Worker macop_table_size, 1);
294*7304104dSAndroid Build Coastguard Worker
295*7304104dSAndroid Build Coastguard Worker *table = (Dwarf_Macro_Op_Table) {
296*7304104dSAndroid Build Coastguard Worker .dbg = dbg,
297*7304104dSAndroid Build Coastguard Worker .offset = macoff,
298*7304104dSAndroid Build Coastguard Worker .sec_index = IDX_debug_macro,
299*7304104dSAndroid Build Coastguard Worker .line_offset = line_offset,
300*7304104dSAndroid Build Coastguard Worker .header_len = readp - startp,
301*7304104dSAndroid Build Coastguard Worker .version = version,
302*7304104dSAndroid Build Coastguard Worker .address_size = address_size,
303*7304104dSAndroid Build Coastguard Worker .offset_size = is_64bit ? 8 : 4,
304*7304104dSAndroid Build Coastguard Worker
305*7304104dSAndroid Build Coastguard Worker /* NULL if CUDIE is NULL or DW_AT_comp_dir is absent. */
306*7304104dSAndroid Build Coastguard Worker .comp_dir = __libdw_getcompdir (cudie),
307*7304104dSAndroid Build Coastguard Worker };
308*7304104dSAndroid Build Coastguard Worker build_table (table, op_protos);
309*7304104dSAndroid Build Coastguard Worker
310*7304104dSAndroid Build Coastguard Worker return table;
311*7304104dSAndroid Build Coastguard Worker }
312*7304104dSAndroid Build Coastguard Worker
313*7304104dSAndroid Build Coastguard Worker static Dwarf_Macro_Op_Table *
cache_op_table(Dwarf * dbg,int sec_index,Dwarf_Off macoff,const unsigned char * startp,const unsigned char * const endp,Dwarf_Die * cudie)314*7304104dSAndroid Build Coastguard Worker cache_op_table (Dwarf *dbg, int sec_index, Dwarf_Off macoff,
315*7304104dSAndroid Build Coastguard Worker const unsigned char *startp,
316*7304104dSAndroid Build Coastguard Worker const unsigned char *const endp,
317*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie)
318*7304104dSAndroid Build Coastguard Worker {
319*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
320*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
321*7304104dSAndroid Build Coastguard Worker macro_op_compare);
322*7304104dSAndroid Build Coastguard Worker if (found != NULL)
323*7304104dSAndroid Build Coastguard Worker return *found;
324*7304104dSAndroid Build Coastguard Worker
325*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
326*7304104dSAndroid Build Coastguard Worker ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
327*7304104dSAndroid Build Coastguard Worker : get_macinfo_table (dbg, macoff, cudie);
328*7304104dSAndroid Build Coastguard Worker
329*7304104dSAndroid Build Coastguard Worker if (table == NULL)
330*7304104dSAndroid Build Coastguard Worker return NULL;
331*7304104dSAndroid Build Coastguard Worker
332*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
333*7304104dSAndroid Build Coastguard Worker macro_op_compare);
334*7304104dSAndroid Build Coastguard Worker if (unlikely (ret == NULL))
335*7304104dSAndroid Build Coastguard Worker {
336*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
337*7304104dSAndroid Build Coastguard Worker return NULL;
338*7304104dSAndroid Build Coastguard Worker }
339*7304104dSAndroid Build Coastguard Worker
340*7304104dSAndroid Build Coastguard Worker return *ret;
341*7304104dSAndroid Build Coastguard Worker }
342*7304104dSAndroid Build Coastguard Worker
343*7304104dSAndroid Build Coastguard Worker static ptrdiff_t
read_macros(Dwarf * dbg,int sec_index,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,bool accept_0xff,Dwarf_Die * cudie)344*7304104dSAndroid Build Coastguard Worker read_macros (Dwarf *dbg, int sec_index,
345*7304104dSAndroid Build Coastguard Worker Dwarf_Off macoff, int (*callback) (Dwarf_Macro *, void *),
346*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t offset, bool accept_0xff,
347*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie)
348*7304104dSAndroid Build Coastguard Worker {
349*7304104dSAndroid Build Coastguard Worker Elf_Data *d = dbg->sectiondata[sec_index];
350*7304104dSAndroid Build Coastguard Worker if (unlikely (d == NULL || d->d_buf == NULL))
351*7304104dSAndroid Build Coastguard Worker {
352*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NO_ENTRY);
353*7304104dSAndroid Build Coastguard Worker return -1;
354*7304104dSAndroid Build Coastguard Worker }
355*7304104dSAndroid Build Coastguard Worker
356*7304104dSAndroid Build Coastguard Worker if (unlikely (macoff >= d->d_size))
357*7304104dSAndroid Build Coastguard Worker {
358*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
359*7304104dSAndroid Build Coastguard Worker return -1;
360*7304104dSAndroid Build Coastguard Worker }
361*7304104dSAndroid Build Coastguard Worker
362*7304104dSAndroid Build Coastguard Worker const unsigned char *const startp = d->d_buf + macoff;
363*7304104dSAndroid Build Coastguard Worker const unsigned char *const endp = d->d_buf + d->d_size;
364*7304104dSAndroid Build Coastguard Worker
365*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
366*7304104dSAndroid Build Coastguard Worker startp, endp, cudie);
367*7304104dSAndroid Build Coastguard Worker if (table == NULL)
368*7304104dSAndroid Build Coastguard Worker return -1;
369*7304104dSAndroid Build Coastguard Worker
370*7304104dSAndroid Build Coastguard Worker if (offset == 0)
371*7304104dSAndroid Build Coastguard Worker offset = table->header_len;
372*7304104dSAndroid Build Coastguard Worker
373*7304104dSAndroid Build Coastguard Worker assert (offset >= 0);
374*7304104dSAndroid Build Coastguard Worker assert (offset < endp - startp);
375*7304104dSAndroid Build Coastguard Worker const unsigned char *readp = startp + offset;
376*7304104dSAndroid Build Coastguard Worker
377*7304104dSAndroid Build Coastguard Worker while (readp < endp)
378*7304104dSAndroid Build Coastguard Worker {
379*7304104dSAndroid Build Coastguard Worker unsigned int opcode = *readp++;
380*7304104dSAndroid Build Coastguard Worker if (opcode == 0)
381*7304104dSAndroid Build Coastguard Worker /* Nothing more to do. */
382*7304104dSAndroid Build Coastguard Worker return 0;
383*7304104dSAndroid Build Coastguard Worker
384*7304104dSAndroid Build Coastguard Worker if (unlikely (opcode == 0xff && ! accept_0xff))
385*7304104dSAndroid Build Coastguard Worker {
386*7304104dSAndroid Build Coastguard Worker /* See comment below at dwarf_getmacros for explanation of
387*7304104dSAndroid Build Coastguard Worker why we are doing this. */
388*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_OPCODE);
389*7304104dSAndroid Build Coastguard Worker return -1;
390*7304104dSAndroid Build Coastguard Worker }
391*7304104dSAndroid Build Coastguard Worker
392*7304104dSAndroid Build Coastguard Worker unsigned int idx = table->opcodes[opcode - 1];
393*7304104dSAndroid Build Coastguard Worker if (idx == 0xff)
394*7304104dSAndroid Build Coastguard Worker {
395*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_OPCODE);
396*7304104dSAndroid Build Coastguard Worker return -1;
397*7304104dSAndroid Build Coastguard Worker }
398*7304104dSAndroid Build Coastguard Worker
399*7304104dSAndroid Build Coastguard Worker Dwarf_Macro_Op_Proto *proto = &table->table[idx];
400*7304104dSAndroid Build Coastguard Worker
401*7304104dSAndroid Build Coastguard Worker /* A fake CU with bare minimum data to fool dwarf_formX into
402*7304104dSAndroid Build Coastguard Worker doing the right thing with the attributes that we put out.
403*7304104dSAndroid Build Coastguard Worker We pretend it is the same version as the actual table.
404*7304104dSAndroid Build Coastguard Worker Version 4 for the old GNU extension, version 5 for DWARF5.
405*7304104dSAndroid Build Coastguard Worker To handle DW_FORM_strx[1234] we set the .str_offsets_base
406*7304104dSAndroid Build Coastguard Worker from the given CU.
407*7304104dSAndroid Build Coastguard Worker XXX We will need to deal with DW_MACRO_import_sup and change
408*7304104dSAndroid Build Coastguard Worker out the dbg somehow for the DW_FORM_sec_offset to make sense. */
409*7304104dSAndroid Build Coastguard Worker Dwarf_CU fake_cu = {
410*7304104dSAndroid Build Coastguard Worker .dbg = dbg,
411*7304104dSAndroid Build Coastguard Worker .sec_idx = sec_index,
412*7304104dSAndroid Build Coastguard Worker .version = table->version,
413*7304104dSAndroid Build Coastguard Worker .offset_size = table->offset_size,
414*7304104dSAndroid Build Coastguard Worker .str_off_base = str_offsets_base_off (dbg, (cudie != NULL
415*7304104dSAndroid Build Coastguard Worker ? cudie->cu: NULL)),
416*7304104dSAndroid Build Coastguard Worker .startp = (void *) startp + offset,
417*7304104dSAndroid Build Coastguard Worker .endp = (void *) endp,
418*7304104dSAndroid Build Coastguard Worker };
419*7304104dSAndroid Build Coastguard Worker
420*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute *attributes;
421*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute *attributesp = NULL;
422*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute nattributes[8];
423*7304104dSAndroid Build Coastguard Worker if (unlikely (proto->nforms > 8))
424*7304104dSAndroid Build Coastguard Worker {
425*7304104dSAndroid Build Coastguard Worker attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms);
426*7304104dSAndroid Build Coastguard Worker if (attributesp == NULL)
427*7304104dSAndroid Build Coastguard Worker {
428*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
429*7304104dSAndroid Build Coastguard Worker return -1;
430*7304104dSAndroid Build Coastguard Worker }
431*7304104dSAndroid Build Coastguard Worker attributes = attributesp;
432*7304104dSAndroid Build Coastguard Worker }
433*7304104dSAndroid Build Coastguard Worker else
434*7304104dSAndroid Build Coastguard Worker attributes = &nattributes[0];
435*7304104dSAndroid Build Coastguard Worker
436*7304104dSAndroid Build Coastguard Worker for (Dwarf_Word i = 0; i < proto->nforms; ++i)
437*7304104dSAndroid Build Coastguard Worker {
438*7304104dSAndroid Build Coastguard Worker /* We pretend this is a DW_AT[_GNU]_macros attribute so that
439*7304104dSAndroid Build Coastguard Worker DW_FORM_sec_offset forms get correctly interpreted as
440*7304104dSAndroid Build Coastguard Worker offset into .debug_macro. XXX Deal with DW_MACRO_import_sup
441*7304104dSAndroid Build Coastguard Worker (swap .dbg) for DW_FORM_sec_offset? */
442*7304104dSAndroid Build Coastguard Worker attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros
443*7304104dSAndroid Build Coastguard Worker : DW_AT_macros);
444*7304104dSAndroid Build Coastguard Worker attributes[i].form = proto->forms[i];
445*7304104dSAndroid Build Coastguard Worker attributes[i].valp = (void *) readp;
446*7304104dSAndroid Build Coastguard Worker attributes[i].cu = &fake_cu;
447*7304104dSAndroid Build Coastguard Worker
448*7304104dSAndroid Build Coastguard Worker /* We don't want forms that aren't allowed because they could
449*7304104dSAndroid Build Coastguard Worker read from the "abbrev" like DW_FORM_implicit_const. */
450*7304104dSAndroid Build Coastguard Worker if (! libdw_valid_user_form (attributes[i].form))
451*7304104dSAndroid Build Coastguard Worker {
452*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
453*7304104dSAndroid Build Coastguard Worker free (attributesp);
454*7304104dSAndroid Build Coastguard Worker return -1;
455*7304104dSAndroid Build Coastguard Worker }
456*7304104dSAndroid Build Coastguard Worker
457*7304104dSAndroid Build Coastguard Worker size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
458*7304104dSAndroid Build Coastguard Worker if (unlikely (len == (size_t) -1))
459*7304104dSAndroid Build Coastguard Worker {
460*7304104dSAndroid Build Coastguard Worker free (attributesp);
461*7304104dSAndroid Build Coastguard Worker return -1;
462*7304104dSAndroid Build Coastguard Worker }
463*7304104dSAndroid Build Coastguard Worker
464*7304104dSAndroid Build Coastguard Worker readp += len;
465*7304104dSAndroid Build Coastguard Worker }
466*7304104dSAndroid Build Coastguard Worker
467*7304104dSAndroid Build Coastguard Worker Dwarf_Macro macro = {
468*7304104dSAndroid Build Coastguard Worker .table = table,
469*7304104dSAndroid Build Coastguard Worker .opcode = opcode,
470*7304104dSAndroid Build Coastguard Worker .attributes = attributes,
471*7304104dSAndroid Build Coastguard Worker };
472*7304104dSAndroid Build Coastguard Worker
473*7304104dSAndroid Build Coastguard Worker int res = callback (¯o, arg);
474*7304104dSAndroid Build Coastguard Worker if (unlikely (attributesp != NULL))
475*7304104dSAndroid Build Coastguard Worker free (attributesp);
476*7304104dSAndroid Build Coastguard Worker
477*7304104dSAndroid Build Coastguard Worker if (res != DWARF_CB_OK)
478*7304104dSAndroid Build Coastguard Worker return readp - startp;
479*7304104dSAndroid Build Coastguard Worker }
480*7304104dSAndroid Build Coastguard Worker
481*7304104dSAndroid Build Coastguard Worker return 0;
482*7304104dSAndroid Build Coastguard Worker }
483*7304104dSAndroid Build Coastguard Worker
484*7304104dSAndroid Build Coastguard Worker /* Token layout:
485*7304104dSAndroid Build Coastguard Worker
486*7304104dSAndroid Build Coastguard Worker - The highest bit is used for distinguishing between callers that
487*7304104dSAndroid Build Coastguard Worker know that opcode 0xff may have one of two incompatible meanings.
488*7304104dSAndroid Build Coastguard Worker The mask that we use for selecting this bit is
489*7304104dSAndroid Build Coastguard Worker DWARF_GETMACROS_START.
490*7304104dSAndroid Build Coastguard Worker
491*7304104dSAndroid Build Coastguard Worker - The rest of the token (31 or 63 bits) encodes address inside the
492*7304104dSAndroid Build Coastguard Worker macro unit.
493*7304104dSAndroid Build Coastguard Worker
494*7304104dSAndroid Build Coastguard Worker Besides, token value of 0 signals end of iteration and -1 is
495*7304104dSAndroid Build Coastguard Worker reserved for signaling errors. That means it's impossible to
496*7304104dSAndroid Build Coastguard Worker represent maximum offset of a .debug_macro unit to new-style
497*7304104dSAndroid Build Coastguard Worker callers (which in practice decreases the permissible macro unit
498*7304104dSAndroid Build Coastguard Worker size by another 1 byte). */
499*7304104dSAndroid Build Coastguard Worker
500*7304104dSAndroid Build Coastguard Worker static ptrdiff_t
token_from_offset(ptrdiff_t offset,bool accept_0xff)501*7304104dSAndroid Build Coastguard Worker token_from_offset (ptrdiff_t offset, bool accept_0xff)
502*7304104dSAndroid Build Coastguard Worker {
503*7304104dSAndroid Build Coastguard Worker if (offset == -1 || offset == 0)
504*7304104dSAndroid Build Coastguard Worker return offset;
505*7304104dSAndroid Build Coastguard Worker
506*7304104dSAndroid Build Coastguard Worker /* Make sure the offset didn't overflow into the flag bit. */
507*7304104dSAndroid Build Coastguard Worker if ((offset & DWARF_GETMACROS_START) != 0)
508*7304104dSAndroid Build Coastguard Worker {
509*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_TOO_BIG);
510*7304104dSAndroid Build Coastguard Worker return -1;
511*7304104dSAndroid Build Coastguard Worker }
512*7304104dSAndroid Build Coastguard Worker
513*7304104dSAndroid Build Coastguard Worker if (accept_0xff)
514*7304104dSAndroid Build Coastguard Worker offset |= DWARF_GETMACROS_START;
515*7304104dSAndroid Build Coastguard Worker
516*7304104dSAndroid Build Coastguard Worker return offset;
517*7304104dSAndroid Build Coastguard Worker }
518*7304104dSAndroid Build Coastguard Worker
519*7304104dSAndroid Build Coastguard Worker static ptrdiff_t
offset_from_token(ptrdiff_t token,bool * accept_0xffp)520*7304104dSAndroid Build Coastguard Worker offset_from_token (ptrdiff_t token, bool *accept_0xffp)
521*7304104dSAndroid Build Coastguard Worker {
522*7304104dSAndroid Build Coastguard Worker *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
523*7304104dSAndroid Build Coastguard Worker token &= ~DWARF_GETMACROS_START;
524*7304104dSAndroid Build Coastguard Worker
525*7304104dSAndroid Build Coastguard Worker return token;
526*7304104dSAndroid Build Coastguard Worker }
527*7304104dSAndroid Build Coastguard Worker
528*7304104dSAndroid Build Coastguard Worker static ptrdiff_t
gnu_macros_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,bool accept_0xff,Dwarf_Die * cudie)529*7304104dSAndroid Build Coastguard Worker gnu_macros_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
530*7304104dSAndroid Build Coastguard Worker int (*callback) (Dwarf_Macro *, void *),
531*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t offset, bool accept_0xff,
532*7304104dSAndroid Build Coastguard Worker Dwarf_Die *cudie)
533*7304104dSAndroid Build Coastguard Worker {
534*7304104dSAndroid Build Coastguard Worker assert (offset >= 0);
535*7304104dSAndroid Build Coastguard Worker
536*7304104dSAndroid Build Coastguard Worker if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
537*7304104dSAndroid Build Coastguard Worker {
538*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_OFFSET);
539*7304104dSAndroid Build Coastguard Worker return -1;
540*7304104dSAndroid Build Coastguard Worker }
541*7304104dSAndroid Build Coastguard Worker
542*7304104dSAndroid Build Coastguard Worker return read_macros (dbg, IDX_debug_macro, macoff,
543*7304104dSAndroid Build Coastguard Worker callback, arg, offset, accept_0xff, cudie);
544*7304104dSAndroid Build Coastguard Worker }
545*7304104dSAndroid Build Coastguard Worker
546*7304104dSAndroid Build Coastguard Worker static ptrdiff_t
macro_info_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t offset,Dwarf_Die * cudie)547*7304104dSAndroid Build Coastguard Worker macro_info_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
548*7304104dSAndroid Build Coastguard Worker int (*callback) (Dwarf_Macro *, void *),
549*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t offset, Dwarf_Die *cudie)
550*7304104dSAndroid Build Coastguard Worker {
551*7304104dSAndroid Build Coastguard Worker assert (offset >= 0);
552*7304104dSAndroid Build Coastguard Worker
553*7304104dSAndroid Build Coastguard Worker return read_macros (dbg, IDX_debug_macinfo, macoff,
554*7304104dSAndroid Build Coastguard Worker callback, arg, offset, true, cudie);
555*7304104dSAndroid Build Coastguard Worker }
556*7304104dSAndroid Build Coastguard Worker
557*7304104dSAndroid Build Coastguard Worker ptrdiff_t
dwarf_getmacros_off(Dwarf * dbg,Dwarf_Off macoff,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t token)558*7304104dSAndroid Build Coastguard Worker dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
559*7304104dSAndroid Build Coastguard Worker int (*callback) (Dwarf_Macro *, void *),
560*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t token)
561*7304104dSAndroid Build Coastguard Worker {
562*7304104dSAndroid Build Coastguard Worker if (dbg == NULL)
563*7304104dSAndroid Build Coastguard Worker {
564*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NO_DWARF);
565*7304104dSAndroid Build Coastguard Worker return -1;
566*7304104dSAndroid Build Coastguard Worker }
567*7304104dSAndroid Build Coastguard Worker
568*7304104dSAndroid Build Coastguard Worker bool accept_0xff;
569*7304104dSAndroid Build Coastguard Worker ptrdiff_t offset = offset_from_token (token, &accept_0xff);
570*7304104dSAndroid Build Coastguard Worker assert (accept_0xff);
571*7304104dSAndroid Build Coastguard Worker
572*7304104dSAndroid Build Coastguard Worker offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
573*7304104dSAndroid Build Coastguard Worker accept_0xff, NULL);
574*7304104dSAndroid Build Coastguard Worker
575*7304104dSAndroid Build Coastguard Worker return token_from_offset (offset, accept_0xff);
576*7304104dSAndroid Build Coastguard Worker }
577*7304104dSAndroid Build Coastguard Worker
578*7304104dSAndroid Build Coastguard Worker ptrdiff_t
dwarf_getmacros(Dwarf_Die * cudie,int (* callback)(Dwarf_Macro *,void *),void * arg,ptrdiff_t token)579*7304104dSAndroid Build Coastguard Worker dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *),
580*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t token)
581*7304104dSAndroid Build Coastguard Worker {
582*7304104dSAndroid Build Coastguard Worker if (cudie == NULL)
583*7304104dSAndroid Build Coastguard Worker {
584*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NO_DWARF);
585*7304104dSAndroid Build Coastguard Worker return -1;
586*7304104dSAndroid Build Coastguard Worker }
587*7304104dSAndroid Build Coastguard Worker
588*7304104dSAndroid Build Coastguard Worker /* This function might be called from a code that expects to see
589*7304104dSAndroid Build Coastguard Worker DW_MACINFO_* opcodes, not DW_MACRO_{GNU_,}* ones. It is fine to
590*7304104dSAndroid Build Coastguard Worker serve most DW_MACRO_{GNU_,}* opcodes to such code, because those
591*7304104dSAndroid Build Coastguard Worker whose values are the same as DW_MACINFO_* ones also have the same
592*7304104dSAndroid Build Coastguard Worker behavior. It is not very likely that a .debug_macro section
593*7304104dSAndroid Build Coastguard Worker would only use the part of opcode space that it shares with
594*7304104dSAndroid Build Coastguard Worker .debug_macinfo, but it is possible. Serving the opcodes that are
595*7304104dSAndroid Build Coastguard Worker only valid in DW_MACRO_{GNU_,}* domain is OK as well, because
596*7304104dSAndroid Build Coastguard Worker clients in general need to be ready that newer standards define
597*7304104dSAndroid Build Coastguard Worker more opcodes, and have coping mechanisms for unfamiliar opcodes.
598*7304104dSAndroid Build Coastguard Worker
599*7304104dSAndroid Build Coastguard Worker The one exception to the above rule is opcode 0xff, which has
600*7304104dSAndroid Build Coastguard Worker concrete semantics in .debug_macinfo, but falls into vendor block
601*7304104dSAndroid Build Coastguard Worker in .debug_macro, and can be assigned to do whatever. There is
602*7304104dSAndroid Build Coastguard Worker some small probability that the two opcodes would look
603*7304104dSAndroid Build Coastguard Worker superficially similar enough that a client would be confused and
604*7304104dSAndroid Build Coastguard Worker misbehave as a result. For this reason, we refuse to serve
605*7304104dSAndroid Build Coastguard Worker through this interface 0xff's originating from .debug_macro
606*7304104dSAndroid Build Coastguard Worker unless the TOKEN that we obtained indicates the call originates
607*7304104dSAndroid Build Coastguard Worker from a new-style caller. See above for details on what
608*7304104dSAndroid Build Coastguard Worker information is encoded into tokens. */
609*7304104dSAndroid Build Coastguard Worker
610*7304104dSAndroid Build Coastguard Worker bool accept_0xff;
611*7304104dSAndroid Build Coastguard Worker ptrdiff_t offset = offset_from_token (token, &accept_0xff);
612*7304104dSAndroid Build Coastguard Worker
613*7304104dSAndroid Build Coastguard Worker /* DW_AT_macro_info */
614*7304104dSAndroid Build Coastguard Worker if (dwarf_hasattr (cudie, DW_AT_macro_info))
615*7304104dSAndroid Build Coastguard Worker {
616*7304104dSAndroid Build Coastguard Worker Dwarf_Word macoff;
617*7304104dSAndroid Build Coastguard Worker if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
618*7304104dSAndroid Build Coastguard Worker return -1;
619*7304104dSAndroid Build Coastguard Worker offset = macro_info_getmacros_off (cudie->cu->dbg, macoff,
620*7304104dSAndroid Build Coastguard Worker callback, arg, offset, cudie);
621*7304104dSAndroid Build Coastguard Worker }
622*7304104dSAndroid Build Coastguard Worker else
623*7304104dSAndroid Build Coastguard Worker {
624*7304104dSAndroid Build Coastguard Worker /* DW_AT_GNU_macros, DW_AT_macros */
625*7304104dSAndroid Build Coastguard Worker Dwarf_Word macoff;
626*7304104dSAndroid Build Coastguard Worker if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0
627*7304104dSAndroid Build Coastguard Worker && get_offset_from (cudie, DW_AT_macros, &macoff) != 0)
628*7304104dSAndroid Build Coastguard Worker return -1;
629*7304104dSAndroid Build Coastguard Worker offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
630*7304104dSAndroid Build Coastguard Worker callback, arg, offset, accept_0xff,
631*7304104dSAndroid Build Coastguard Worker cudie);
632*7304104dSAndroid Build Coastguard Worker }
633*7304104dSAndroid Build Coastguard Worker
634*7304104dSAndroid Build Coastguard Worker return token_from_offset (offset, accept_0xff);
635*7304104dSAndroid Build Coastguard Worker }
636