summaryrefslogtreecommitdiffstats
path: root/src/libdw/dwarf_getmacros.c
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-02-24 19:24:25 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-02-24 19:24:25 +0000
commit36e62782f45c6b004d370a79fbc895e0f321181d (patch)
treea63e40b5dd9927bd04ec7427c8797975c2a71f85 /src/libdw/dwarf_getmacros.c
parentb48bfdc826ebdd316d5d8a4ff8f213391f1c710b (diff)
parent03333823c75a1c1887e923828113a1b0fd12020c (diff)
downloadandroid_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.tar.gz
android_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.tar.bz2
android_external_elfutils-36e62782f45c6b004d370a79fbc895e0f321181d.zip
Merge "Upgrade to elfutils 0.161."
Diffstat (limited to 'src/libdw/dwarf_getmacros.c')
-rw-r--r--src/libdw/dwarf_getmacros.c617
1 files changed, 500 insertions, 117 deletions
diff --git a/src/libdw/dwarf_getmacros.c b/src/libdw/dwarf_getmacros.c
index b9ec34b9..f9f29961 100644
--- a/src/libdw/dwarf_getmacros.c
+++ b/src/libdw/dwarf_getmacros.c
@@ -1,165 +1,548 @@
/* Get macro information.
- Copyright (C) 2002-2009 Red Hat, Inc.
- This file is part of Red Hat elfutils.
+ Copyright (C) 2002-2009, 2014 Red Hat, Inc.
+ This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
- Red Hat elfutils is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by the
- Free Software Foundation; version 2 of the License.
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
- Red Hat elfutils is distributed in the hope that it will be useful, but
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with Red Hat elfutils; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
- In addition, as a special exception, Red Hat, Inc. gives You the
- additional right to link the code of Red Hat elfutils with code licensed
- under any Open Source Initiative certified open source license
- (http://www.opensource.org/licenses/index.php) which requires the
- distribution of source code with any binary distribution and to
- distribute linked combinations of the two. Non-GPL Code permitted under
- this exception must only link to the code of Red Hat elfutils through
- those well defined interfaces identified in the file named EXCEPTION
- found in the source code files (the "Approved Interfaces"). The files
- of Non-GPL Code may instantiate templates or use macros or inline
- functions from the Approved Interfaces without causing the resulting
- work to be covered by the GNU General Public License. Only Red Hat,
- Inc. may make changes or additions to the list of Approved Interfaces.
- Red Hat's grant of this exception is conditioned upon your not adding
- any new exceptions. If you wish to add a new Approved Interface or
- exception, please contact Red Hat. You must obey the GNU General Public
- License in all respects for all of the Red Hat elfutils code and other
- code used in conjunction with Red Hat elfutils except the Non-GPL Code
- covered by this exception. If you modify this file, you may extend this
- exception to your version of the file, but you are not obligated to do
- so. If you do not wish to provide this exception without modification,
- you must delete this exception statement from your version and license
- this file solely under the GPL without exception.
-
- Red Hat elfutils is an included package of the Open Invention Network.
- An included package of the Open Invention Network is a package for which
- Open Invention Network licensees cross-license their patents. No patent
- license is granted, either expressly or impliedly, by designation as an
- included package. Should you wish to participate in the Open Invention
- Network licensing program, please visit www.openinventionnetwork.com
- <http://www.openinventionnetwork.com>. */
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include <assert.h>
#include <dwarf.h>
+#include <search.h>
+#include <stdlib.h>
#include <string.h>
#include <libdwP.h>
+static int
+get_offset_from (Dwarf_Die *die, int name, Dwarf_Word *retp)
+{
+ /* Get the appropriate attribute. */
+ Dwarf_Attribute attr;
+ if (INTUSE(dwarf_attr) (die, name, &attr) == NULL)
+ return -1;
-ptrdiff_t
-dwarf_getmacros (die, callback, arg, offset)
- Dwarf_Die *die;
- int (*callback) (Dwarf_Macro *, void *);
- void *arg;
- ptrdiff_t offset;
+ /* Offset into the corresponding section. */
+ return INTUSE(dwarf_formudata) (&attr, retp);
+}
+
+static int
+macro_op_compare (const void *p1, const void *p2)
{
- if (die == NULL)
+ const Dwarf_Macro_Op_Table *t1 = (const Dwarf_Macro_Op_Table *) p1;
+ const Dwarf_Macro_Op_Table *t2 = (const Dwarf_Macro_Op_Table *) p2;
+
+ if (t1->offset < t2->offset)
return -1;
+ if (t1->offset > t2->offset)
+ return 1;
+
+ if (t1->sec_index < t2->sec_index)
+ return -1;
+ if (t1->sec_index > t2->sec_index)
+ return 1;
+
+ return 0;
+}
+
+static void
+build_table (Dwarf_Macro_Op_Table *table,
+ Dwarf_Macro_Op_Proto op_protos[static 255])
+{
+ unsigned ct = 0;
+ for (unsigned i = 1; i < 256; ++i)
+ if (op_protos[i - 1].forms != NULL)
+ table->table[table->opcodes[i - 1] = ct++] = op_protos[i - 1];
+ else
+ table->opcodes[i - 1] = 0xff;
+}
+
+#define MACRO_PROTO(NAME, ...) \
+ Dwarf_Macro_Op_Proto NAME = ({ \
+ static const uint8_t proto[] = {__VA_ARGS__}; \
+ (Dwarf_Macro_Op_Proto) {sizeof proto, proto}; \
+ })
+
+enum { macinfo_data_size = offsetof (Dwarf_Macro_Op_Table, table[5]) };
+static unsigned char macinfo_data[macinfo_data_size]
+ __attribute__ ((aligned (__alignof (Dwarf_Macro_Op_Table))));
+
+static __attribute__ ((constructor)) void
+init_macinfo_table (void)
+{
+ MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
+ MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
+ MACRO_PROTO (p_none);
+
+ Dwarf_Macro_Op_Proto op_protos[255] =
+ {
+ [DW_MACINFO_define - 1] = p_udata_str,
+ [DW_MACINFO_undef - 1] = p_udata_str,
+ [DW_MACINFO_vendor_ext - 1] = p_udata_str,
+ [DW_MACINFO_start_file - 1] = p_udata_udata,
+ [DW_MACINFO_end_file - 1] = p_none,
+ /* If you are adding more elements to this array, increase
+ MACINFO_DATA_SIZE above. */
+ };
+
+ Dwarf_Macro_Op_Table *macinfo_table = (void *) macinfo_data;
+ memset (macinfo_table, 0, sizeof macinfo_data);
+ build_table (macinfo_table, op_protos);
+ macinfo_table->sec_index = IDX_debug_macinfo;
+}
+
+static Dwarf_Macro_Op_Table *
+get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die *cudie)
+{
+ assert (cudie != NULL);
+
+ Dwarf_Attribute attr_mem, *attr
+ = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
+ Dwarf_Off line_offset = (Dwarf_Off) -1;
+ if (attr != NULL)
+ INTUSE(dwarf_formudata) (attr, &line_offset);
+
+ Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
+ macinfo_data_size, 1);
+ memcpy (table, macinfo_data, macinfo_data_size);
+
+ table->offset = macoff;
+ table->sec_index = IDX_debug_macinfo;
+ table->line_offset = line_offset;
+ table->is_64bit = cudie->cu->address_size == 8;
+ table->comp_dir = __libdw_getcompdir (cudie);
+
+ return table;
+}
+
+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)
+{
+ const unsigned char *startp = readp;
+
+ /* Request at least 3 bytes for header. */
+ if (readp + 3 > endp)
+ {
+ invalid_dwarf:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
- Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_macinfo];
- if (unlikely (d == NULL) || unlikely (d->d_buf == NULL))
+ uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+ if (version != 4)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_VERSION);
+ return NULL;
+ }
+
+ uint8_t flags = *readp++;
+ bool is_64bit = (flags & 0x1) != 0;
+
+ Dwarf_Off line_offset = (Dwarf_Off) -1;
+ if ((flags & 0x2) != 0)
+ {
+ line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
+ if (readp > endp)
+ goto invalid_dwarf;
+ }
+ else if (cudie != NULL)
+ {
+ Dwarf_Attribute attr_mem, *attr
+ = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
+ if (attr != NULL)
+ INTUSE(dwarf_formudata) (attr, &line_offset);
+ }
+
+ /* """The macinfo entry types defined in this standard may, but
+ might not, be described in the table""".
+
+ I.e. these may be present. It's tempting to simply skip them,
+ but it's probably more correct to tolerate that a producer tweaks
+ the way certain opcodes are encoded, for whatever reasons. */
+
+ MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
+ MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
+ MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
+ MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
+ MACRO_PROTO (p_none);
+
+ Dwarf_Macro_Op_Proto op_protos[255] =
+ {
+ [DW_MACRO_GNU_define - 1] = p_udata_str,
+ [DW_MACRO_GNU_undef - 1] = p_udata_str,
+ [DW_MACRO_GNU_define_indirect - 1] = p_udata_strp,
+ [DW_MACRO_GNU_undef_indirect - 1] = p_udata_strp,
+ [DW_MACRO_GNU_start_file - 1] = p_udata_udata,
+ [DW_MACRO_GNU_end_file - 1] = p_none,
+ [DW_MACRO_GNU_transparent_include - 1] = p_secoffset,
+ /* N.B. DW_MACRO_undef_indirectx, DW_MACRO_define_indirectx
+ should be added when 130313.1 is supported. */
+ };
+
+ if ((flags & 0x4) != 0)
+ {
+ unsigned count = *readp++;
+ for (unsigned i = 0; i < count; ++i)
+ {
+ unsigned opcode = *readp++;
+
+ Dwarf_Macro_Op_Proto e;
+ if (readp >= endp)
+ goto invalid;
+ get_uleb128 (e.nforms, readp, endp);
+ e.forms = readp;
+ op_protos[opcode - 1] = e;
+
+ readp += e.nforms;
+ if (readp > endp)
+ {
+ invalid:
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return NULL;
+ }
+ }
+ }
+
+ size_t ct = 0;
+ for (unsigned i = 1; i < 256; ++i)
+ if (op_protos[i - 1].forms != NULL)
+ ++ct;
+
+ /* We support at most 0xfe opcodes defined in the table, as 0xff is
+ a value that means that given opcode is not stored at all. But
+ that should be fine, as opcode 0 is not allocated. */
+ assert (ct < 0xff);
+
+ size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
+
+ Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
+ macop_table_size, 1);
+
+ *table = (Dwarf_Macro_Op_Table) {
+ .offset = macoff,
+ .sec_index = IDX_debug_macro,
+ .line_offset = line_offset,
+ .header_len = readp - startp,
+ .version = version,
+ .is_64bit = is_64bit,
+
+ /* NULL if CUDIE is NULL or DW_AT_comp_dir is absent. */
+ .comp_dir = __libdw_getcompdir (cudie),
+ };
+ build_table (table, op_protos);
+
+ return table;
+}
+
+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)
+{
+ Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
+ Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
+ macro_op_compare);
+ if (found != NULL)
+ return *found;
+
+ Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
+ ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
+ : get_macinfo_table (dbg, macoff, cudie);
+
+ if (table == NULL)
+ return NULL;
+
+ Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
+ macro_op_compare);
+ if (unlikely (ret == NULL))
+ {
+ __libdw_seterrno (DWARF_E_NOMEM);
+ return NULL;
+ }
+
+ return *ret;
+}
+
+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)
+{
+ Elf_Data *d = dbg->sectiondata[sec_index];
+ if (unlikely (d == NULL || d->d_buf == NULL))
{
__libdw_seterrno (DWARF_E_NO_ENTRY);
return -1;
}
- if (offset == 0)
+ if (unlikely (macoff >= d->d_size))
{
- /* Get the appropriate attribute. */
- Dwarf_Attribute attr;
- if (INTUSE(dwarf_attr) (die, DW_AT_macro_info, &attr) == NULL)
- return -1;
+ __libdw_seterrno (DWARF_E_INVALID_DWARF);
+ return -1;
+ }
- /* Offset into the .debug_macinfo section. */
- Dwarf_Word macoff;
- if (INTUSE(dwarf_formudata) (&attr, &macoff) != 0)
- return -1;
+ const unsigned char *const startp = d->d_buf + macoff;
+ const unsigned char *const endp = d->d_buf + d->d_size;
- offset = macoff;
- }
- if (unlikely (offset > (ptrdiff_t) d->d_size))
- goto invalid;
+ Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
+ startp, endp, cudie);
+ if (table == NULL)
+ return -1;
- const unsigned char *readp = d->d_buf + offset;
- const unsigned char *readendp = d->d_buf + d->d_size;
+ if (offset == 0)
+ offset = table->header_len;
- if (readp == readendp)
- return 0;
+ assert (offset >= 0);
+ assert (offset < endp - startp);
+ const unsigned char *readp = startp + offset;
- while (readp < readendp)
+ while (readp < endp)
{
unsigned int opcode = *readp++;
- unsigned int u128;
- unsigned int u128_2 = 0;
- const char *str = NULL;
- const unsigned char *endp;
+ if (opcode == 0)
+ /* Nothing more to do. */
+ return 0;
- switch (opcode)
+ if (unlikely (opcode == 0xff && ! accept_0xff))
{
- case DW_MACINFO_define:
- case DW_MACINFO_undef:
- case DW_MACINFO_vendor_ext:
- /* For the first two opcodes the parameters are
- line, string
- For the latter
- number, string.
- We can treat these cases together. */
- get_uleb128 (u128, readp);
-
- endp = memchr (readp, '\0', readendp - readp);
- if (endp == NULL)
- goto invalid;
+ /* See comment below at dwarf_getmacros for explanation of
+ why we are doing this. */
+ __libdw_seterrno (DWARF_E_INVALID_OPCODE);
+ return -1;
+ }
+
+ unsigned int idx = table->opcodes[opcode - 1];
+ if (idx == 0xff)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OPCODE);
+ return -1;
+ }
- str = (char *) readp;
- readp = endp + 1;
- break;
+ Dwarf_Macro_Op_Proto *proto = &table->table[idx];
- case DW_MACINFO_start_file:
- /* The two parameters are line and file index. */
- get_uleb128 (u128, readp);
- get_uleb128 (u128_2, readp);
- break;
+ /* A fake CU with bare minimum data to fool dwarf_formX into
+ doing the right thing with the attributes that we put out.
+ We arbitrarily pretend it's version 4. */
+ Dwarf_CU fake_cu = {
+ .dbg = dbg,
+ .version = 4,
+ .offset_size = table->is_64bit ? 8 : 4,
+ .startp = (void *) startp + offset,
+ .endp = (void *) endp,
+ };
- case DW_MACINFO_end_file:
- /* No parameters for this one. */
- u128 = 0;
- break;
+ Dwarf_Attribute attributes[proto->nforms];
+ for (Dwarf_Word i = 0; i < proto->nforms; ++i)
+ {
+ /* We pretend this is a DW_AT_GNU_macros attribute so that
+ DW_FORM_sec_offset forms get correctly interpreted as
+ offset into .debug_macro. */
+ attributes[i].code = DW_AT_GNU_macros;
+ attributes[i].form = proto->forms[i];
+ attributes[i].valp = (void *) readp;
+ attributes[i].cu = &fake_cu;
- case 0:
- /* Nothing more to do. */
- return 0;
+ size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
+ if (len == (size_t) -1)
+ return -1;
- default:
- goto invalid;
+ readp += len;
}
- Dwarf_Macro mac;
- mac.opcode = opcode;
- mac.param1 = u128;
- if (str == NULL)
- mac.param2.u = u128_2;
- else
- mac.param2.s = str;
+ Dwarf_Macro macro = {
+ .table = table,
+ .opcode = opcode,
+ .attributes = attributes,
+ };
+
+ if (callback (&macro, arg) != DWARF_CB_OK)
+ return readp - startp;
+ }
+
+ return 0;
+}
+
+/* Token layout:
+
+ - The highest bit is used for distinguishing between callers that
+ know that opcode 0xff may have one of two incompatible meanings.
+ The mask that we use for selecting this bit is
+ DWARF_GETMACROS_START.
+
+ - The rest of the token (31 or 63 bits) encodes address inside the
+ macro unit.
+
+ Besides, token value of 0 signals end of iteration and -1 is
+ reserved for signaling errors. That means it's impossible to
+ represent maximum offset of a .debug_macro unit to new-style
+ callers (which in practice decreases the permissible macro unit
+ size by another 1 byte). */
+
+static ptrdiff_t
+token_from_offset (ptrdiff_t offset, bool accept_0xff)
+{
+ if (offset == -1 || offset == 0)
+ return offset;
+
+ /* Make sure the offset didn't overflow into the flag bit. */
+ if ((offset & DWARF_GETMACROS_START) != 0)
+ {
+ __libdw_seterrno (DWARF_E_TOO_BIG);
+ return -1;
+ }
+
+ if (accept_0xff)
+ offset |= DWARF_GETMACROS_START;
+
+ return offset;
+}
+
+static ptrdiff_t
+offset_from_token (ptrdiff_t token, bool *accept_0xffp)
+{
+ *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
+ token &= ~DWARF_GETMACROS_START;
+
+ return token;
+}
+
+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)
+{
+ assert (offset >= 0);
- if (callback (&mac, arg) != DWARF_CB_OK)
- return readp - (const unsigned char *) d->d_buf;
+ if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
+ {
+ __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+ return -1;
+ }
+
+ return read_macros (dbg, IDX_debug_macro, macoff,
+ callback, arg, offset, accept_0xff, cudie);
+}
+
+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)
+{
+ assert (offset >= 0);
+
+ return read_macros (dbg, IDX_debug_macinfo, macoff,
+ callback, arg, offset, true, cudie);
+}
+
+ptrdiff_t
+dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
+ int (*callback) (Dwarf_Macro *, void *),
+ void *arg, ptrdiff_t token)
+{
+ if (dbg == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_DWARF);
+ return -1;
+ }
+
+ bool accept_0xff;
+ ptrdiff_t offset = offset_from_token (token, &accept_0xff);
+ assert (accept_0xff);
+
+ offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
+ accept_0xff, NULL);
+
+ return token_from_offset (offset, accept_0xff);
+}
+
+ptrdiff_t
+dwarf_getmacros (cudie, callback, arg, token)
+ Dwarf_Die *cudie;
+ int (*callback) (Dwarf_Macro *, void *);
+ void *arg;
+ ptrdiff_t token;
+{
+ if (cudie == NULL)
+ {
+ __libdw_seterrno (DWARF_E_NO_DWARF);
+ return -1;
+ }
+
+ /* This function might be called from a code that expects to see
+ DW_MACINFO_* opcodes, not DW_MACRO_{GNU_,}* ones. It is fine to
+ serve most DW_MACRO_{GNU_,}* opcodes to such code, because those
+ whose values are the same as DW_MACINFO_* ones also have the same
+ behavior. It is not very likely that a .debug_macro section
+ would only use the part of opcode space that it shares with
+ .debug_macinfo, but it is possible. Serving the opcodes that are
+ only valid in DW_MACRO_{GNU_,}* domain is OK as well, because
+ clients in general need to be ready that newer standards define
+ more opcodes, and have coping mechanisms for unfamiliar opcodes.
+
+ The one exception to the above rule is opcode 0xff, which has
+ concrete semantics in .debug_macinfo, but falls into vendor block
+ in .debug_macro, and can be assigned to do whatever. There is
+ some small probability that the two opcodes would look
+ superficially similar enough that a client would be confused and
+ misbehave as a result. For this reason, we refuse to serve
+ through this interface 0xff's originating from .debug_macro
+ unless the TOKEN that we obtained indicates the call originates
+ from a new-style caller. See above for details on what
+ information is encoded into tokens. */
+
+ bool accept_0xff;
+ ptrdiff_t offset = offset_from_token (token, &accept_0xff);
+
+ /* DW_AT_macro_info */
+ if (dwarf_hasattr (cudie, DW_AT_macro_info))
+ {
+ Dwarf_Word macoff;
+ if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
+ return -1;
+ offset = macro_info_getmacros_off (cudie->cu->dbg, macoff,
+ callback, arg, offset, cudie);
+ }
+ else
+ {
+ /* DW_AT_GNU_macros, DW_AT_macros */
+ Dwarf_Word macoff;
+ if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0)
+ return -1;
+ offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
+ callback, arg, offset, accept_0xff,
+ cudie);
}
- /* If we come here the termination of the data for the CU is not
- present. */
- invalid:
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ return token_from_offset (offset, accept_0xff);
}