1/* Get public symbol information.
2   Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
3   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5   This program is Open Source software; you can redistribute it and/or
6   modify it under the terms of the Open Software License version 1.0 as
7   published by the Open Source Initiative.
8
9   You should have received a copy of the Open Software License along
10   with this program; if not, you may obtain a copy of the Open Software
11   License version 1.0 from http://www.opensource.org/licenses/osl.php or
12   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13   3001 King Ranch Road, Ukiah, CA 95482.   */
14
15#ifdef HAVE_CONFIG_H
16# include <config.h>
17#endif
18
19#include <dwarf.h>
20#include <string.h>
21
22#include <libdwP.h>
23
24
25ptrdiff_t
26dwarf_getmacros (die, callback, arg, offset)
27     Dwarf_Die *die;
28     int (*callback) (Dwarf_Macro *, void *);
29     void *arg;
30     ptrdiff_t offset;
31{
32  /* Get the appropriate attribute.  */
33  Dwarf_Attribute attr;
34  if (dwarf_attr (die, DW_AT_macro_info, &attr) == NULL)
35    return -1;
36
37  /* Offset into the .debug_macinfo section.  */
38  Dwarf_Word macoff;
39  if (dwarf_formudata (&attr, &macoff) != 0)
40    return -1;
41
42  const unsigned char *readp
43    = die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_buf + offset;
44  const unsigned char *readendp
45    = readp + die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_size;
46
47  if (readp == readendp)
48    return 0;
49
50  if (*readp != DW_MACINFO_start_file)
51    goto invalid;
52
53  while (readp < readendp)
54    {
55      unsigned int opcode = *readp++;
56      unsigned int u128;
57      unsigned int u128_2 = 0;
58      const char *str = NULL;
59      const unsigned char *endp;
60
61      switch (opcode)
62	{
63	case DW_MACINFO_define:
64	case DW_MACINFO_undef:
65	case DW_MACINFO_vendor_ext:
66	  /*  For the first two opcodes the parameters are
67	        line, string
68	      For the latter
69	        number, string.
70	      We can treat these cases together.  */
71	  get_uleb128 (u128, readp);
72
73	  endp = memchr (readp, '\0', readendp - readp);
74	  if (endp == NULL)
75	    goto invalid;
76
77	  str = (char *) readp;
78	  readp = endp + 1;
79	  break;
80
81	case DW_MACINFO_start_file:
82	  /* The two parameters are line and file index.  */
83	  get_uleb128 (u128, readp);
84	  get_uleb128 (u128_2, readp);
85	  break;
86
87	case DW_MACINFO_end_file:
88	  /* Nothing more to do.  */
89	  return 0;
90
91	default:
92	  goto invalid;
93	}
94
95      Dwarf_Macro mac;
96      mac.opcode = opcode;
97      mac.param1 = u128;
98      if (str == NULL)
99	mac.param2.u = u128_2;
100      else
101	mac.param2.s = str;
102
103      if (callback (&mac, arg) != DWARF_CB_OK)
104	return (readp
105		- ((unsigned char *) die->cu->dbg->sectiondata[IDX_debug_macinfo]->d_buf
106		   + offset));
107    }
108
109  /* If we come here the termination of the data for the CU is not
110     present.  */
111 invalid:
112  __libdw_seterrno (DWARF_E_INVALID_DWARF);
113  return -1;
114}
115