Imported Upstream version 0.155
[platform/upstream/elfutils.git] / libdw / dwarf_getmacros.c
1 /* Get macro information.
2    Copyright (C) 2002-2009 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of either
8
9      * the GNU Lesser General Public License as published by the Free
10        Software Foundation; either version 3 of the License, or (at
11        your option) any later version
12
13    or
14
15      * the GNU General Public License as published by the Free
16        Software Foundation; either version 2 of the License, or (at
17        your option) any later version
18
19    or both in parallel, as here.
20
21    elfutils is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24    General Public License for more details.
25
26    You should have received copies of the GNU General Public License and
27    the GNU Lesser General Public License along with this program.  If
28    not, see <http://www.gnu.org/licenses/>.  */
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <dwarf.h>
35 #include <string.h>
36
37 #include <libdwP.h>
38
39
40 ptrdiff_t
41 dwarf_getmacros (die, callback, arg, offset)
42      Dwarf_Die *die;
43      int (*callback) (Dwarf_Macro *, void *);
44      void *arg;
45      ptrdiff_t offset;
46 {
47   if (die == NULL)
48     return -1;
49
50   Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_macinfo];
51   if (unlikely (d == NULL) || unlikely (d->d_buf == NULL))
52     {
53       __libdw_seterrno (DWARF_E_NO_ENTRY);
54       return -1;
55     }
56
57   if (offset == 0)
58     {
59       /* Get the appropriate attribute.  */
60       Dwarf_Attribute attr;
61       if (INTUSE(dwarf_attr) (die, DW_AT_macro_info, &attr) == NULL)
62         return -1;
63
64       /* Offset into the .debug_macinfo section.  */
65       Dwarf_Word macoff;
66       if (INTUSE(dwarf_formudata) (&attr, &macoff) != 0)
67         return -1;
68
69       offset = macoff;
70     }
71   if (unlikely (offset > (ptrdiff_t) d->d_size))
72     goto invalid;
73
74   const unsigned char *readp = d->d_buf + offset;
75   const unsigned char *readendp = d->d_buf + d->d_size;
76
77   if (readp == readendp)
78     return 0;
79
80   while (readp < readendp)
81     {
82       unsigned int opcode = *readp++;
83       unsigned int u128;
84       unsigned int u128_2 = 0;
85       const char *str = NULL;
86       const unsigned char *endp;
87
88       switch (opcode)
89         {
90         case DW_MACINFO_define:
91         case DW_MACINFO_undef:
92         case DW_MACINFO_vendor_ext:
93           /*  For the first two opcodes the parameters are
94                 line, string
95               For the latter
96                 number, string.
97               We can treat these cases together.  */
98           get_uleb128 (u128, readp);
99
100           endp = memchr (readp, '\0', readendp - readp);
101           if (endp == NULL)
102             goto invalid;
103
104           str = (char *) readp;
105           readp = endp + 1;
106           break;
107
108         case DW_MACINFO_start_file:
109           /* The two parameters are line and file index.  */
110           get_uleb128 (u128, readp);
111           get_uleb128 (u128_2, readp);
112           break;
113
114         case DW_MACINFO_end_file:
115           /* No parameters for this one.  */
116           u128 = 0;
117           break;
118
119         case 0:
120           /* Nothing more to do.  */
121           return 0;
122
123         default:
124           goto invalid;
125         }
126
127       Dwarf_Macro mac;
128       mac.opcode = opcode;
129       mac.param1 = u128;
130       if (str == NULL)
131         mac.param2.u = u128_2;
132       else
133         mac.param2.s = str;
134
135       if (callback (&mac, arg) != DWARF_CB_OK)
136         return readp - (const unsigned char *) d->d_buf;
137     }
138
139   /* If we come here the termination of the data for the CU is not
140      present.  */
141  invalid:
142   __libdw_seterrno (DWARF_E_INVALID_DWARF);
143   return -1;
144 }