Coverage Report

Created: 2025-07-11 06:46

/src/elfutils/libdw/dwarf_formaddr.c
Line
Count
Source (jump to first uncovered line)
1
/* Return address represented by attribute.
2
   Copyright (C) 2003-2010, 2018 Red Hat, Inc.
3
   This file is part of elfutils.
4
5
   This file is free software; you can redistribute it and/or modify
6
   it under the terms of either
7
8
     * the GNU Lesser General Public License as published by the Free
9
       Software Foundation; either version 3 of the License, or (at
10
       your option) any later version
11
12
   or
13
14
     * the GNU General Public License as published by the Free
15
       Software Foundation; either version 2 of the License, or (at
16
       your option) any later version
17
18
   or both in parallel, as here.
19
20
   elfutils is distributed in the hope that it will be useful, but
21
   WITHOUT ANY WARRANTY; without even the implied warranty of
22
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23
   General Public License for more details.
24
25
   You should have received copies of the GNU General Public License and
26
   the GNU Lesser General Public License along with this program.  If
27
   not, see <http://www.gnu.org/licenses/>.  */
28
29
#ifdef HAVE_CONFIG_H
30
# include <config.h>
31
#endif
32
33
#include <dwarf.h>
34
#include "libdwP.h"
35
36
37
int
38
__libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
39
0
{
40
0
  Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
41
0
  if (addr_off == (Dwarf_Off) -1)
42
0
    return -1;
43
44
0
  Dwarf *dbg = cu->dbg;
45
0
  if (dbg->sectiondata[IDX_debug_addr] == NULL)
46
0
    {
47
0
      __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
48
0
      return -1;
49
0
    }
50
51
  /* The section should at least contain room for one address.  */
52
0
  int address_size = cu->address_size;
53
0
  if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size)
54
0
    {
55
0
    invalid_offset:
56
0
      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
57
0
      return -1;
58
0
    }
59
60
0
  if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
61
0
      - address_size))
62
0
    goto invalid_offset;
63
64
0
  idx *= address_size;
65
0
  if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
66
0
       - address_size - addr_off))
67
0
    goto invalid_offset;
68
69
0
  const unsigned char *datap;
70
0
  datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
71
0
  if (address_size == 4)
72
0
    *addr = read_4ubyte_unaligned (dbg, datap);
73
0
  else
74
0
    *addr = read_8ubyte_unaligned (dbg, datap);
75
76
0
  return 0;
77
0
}
78
79
int
80
dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
81
0
{
82
0
  if (attr == NULL)
83
0
    return -1;
84
85
0
  Dwarf_Word idx;
86
0
  Dwarf_CU *cu = attr->cu;
87
0
  Dwarf *dbg = cu->dbg;
88
0
  const unsigned char *datap = attr->valp;
89
0
  const unsigned char *endp = attr->cu->endp;
90
0
  switch (attr->form)
91
0
    {
92
      /* There is one form that just encodes the whole address.  */
93
0
      case DW_FORM_addr:
94
0
  if (__libdw_read_address (dbg, cu_sec_idx (cu), datap,
95
0
          cu->address_size, return_addr))
96
0
    return -1;
97
0
  return 0;
98
99
      /* All others encode an index into the .debug_addr section where
100
   the address can be found.  */
101
0
      case DW_FORM_GNU_addr_index:
102
0
      case DW_FORM_addrx:
103
0
  if (datap >= endp)
104
0
    {
105
0
    invalid:
106
0
      __libdw_seterrno (DWARF_E_INVALID_DWARF);
107
0
      return -1;
108
0
    }
109
0
  get_uleb128 (idx, datap, endp);
110
0
  break;
111
112
0
      case DW_FORM_addrx1:
113
0
  if (datap >= endp - 1)
114
0
    goto invalid;
115
0
  idx = *datap;
116
0
  break;
117
118
0
      case DW_FORM_addrx2:
119
0
  if (datap >= endp - 2)
120
0
    goto invalid;
121
0
  idx = read_2ubyte_unaligned (dbg, datap);
122
0
  break;
123
124
0
      case DW_FORM_addrx3:
125
0
  if (datap >= endp - 3)
126
0
    goto invalid;
127
0
  idx = read_3ubyte_unaligned (dbg, datap);
128
0
  break;
129
130
0
      case DW_FORM_addrx4:
131
0
  if (datap >= endp - 4)
132
0
    goto invalid;
133
0
  idx = read_4ubyte_unaligned (dbg, datap);
134
0
  break;
135
136
0
      default:
137
0
  __libdw_seterrno (DWARF_E_NO_ADDR);
138
0
  return -1;
139
0
    }
140
141
  /* So we got an index.  Lets see if it is valid and we can get the actual
142
     address.  */
143
0
  if (__libdw_addrx (cu, idx, return_addr) != 0)
144
0
    return -1;
145
146
0
  return 0;
147
0
}
148
INTDEF(dwarf_formaddr)