xref: /aosp_15_r20/external/elfutils/libdw/dwarf_getmacros.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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 (&macro, 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