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