1 /*
2 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
3 Portions Copyright 2011-2019 David Anderson. All Rights Reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2.1 of the GNU Lesser General Public License
7 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it would be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 Further, this software is distributed without any warranty that it is
14 free of the rightful claim of any third person regarding infringement
15 or the like. Any license provided herein, whether implied or
16 otherwise, applies only to this software file. Patent licenses, if
17 any, provided herein do not apply to combinations of this program with
18 other software, or any other product whatsoever.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this program; if not, write the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23 USA.
24
25 */
26
27 #include "config.h"
28 #include "libdwarfdefs.h"
29 #include <stdio.h>
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif /* HAVE_STRING_H */
33 #ifdef HAVE_ELFACCESS_H
34 #include <elfaccess.h>
35 #endif
36 #include "pro_incl.h"
37 #ifdef HAVE_STDDEF_H
38 #include <stddef.h>
39 #endif /* HAVE_STDDEF_H */
40 #include "dwarf.h"
41 #include "libdwarf.h"
42 #include "pro_opaque.h"
43 #include "pro_error.h"
44 #include "pro_alloc.h"
45 #include "pro_section.h"
46 #include "pro_types.h"
47
48 #define SIZEOFT32 4
49
50 /*
51 This function adds another type name to the
52 list of type names for the given Dwarf_P_Debug.
53 It returns 0 on error, and 1 otherwise.
54 */
55 Dwarf_Unsigned
dwarf_add_typename(Dwarf_P_Debug dbg,Dwarf_P_Die die,char * type_name,Dwarf_Error * error)56 dwarf_add_typename(Dwarf_P_Debug dbg,
57 Dwarf_P_Die die,
58 char *type_name,
59 Dwarf_Error * error)
60 {
61 int res = 0;
62
63 res = _dwarf_add_simple_name_entry(dbg, die, type_name,
64 dwarf_snk_typename, error);
65 if (res != DW_DLV_OK) {
66 return 0;
67 }
68 return 1;
69
70 }
71 int
dwarf_add_typename_a(Dwarf_P_Debug dbg,Dwarf_P_Die die,char * type_name,Dwarf_Error * error)72 dwarf_add_typename_a(Dwarf_P_Debug dbg,
73 Dwarf_P_Die die,
74 char *type_name,
75 Dwarf_Error * error)
76 {
77 int res = 0;
78
79 res = _dwarf_add_simple_name_entry(dbg, die, type_name,
80 dwarf_snk_typename, error);
81 return res;
82 }
83
84 /*
85 The following is the generic 'add a simple name entry'
86 for any of the simple name sections.
87
88 See enum dwarf_sn_kind in pro_opaque.h
89
90 */
91 int
_dwarf_add_simple_name_entry(Dwarf_P_Debug dbg,Dwarf_P_Die die,char * entry_name,enum dwarf_sn_kind entrykind,Dwarf_Error * error)92 _dwarf_add_simple_name_entry(Dwarf_P_Debug dbg,
93 Dwarf_P_Die die,
94 char *entry_name,
95 enum dwarf_sn_kind entrykind,
96 Dwarf_Error * error)
97 {
98 Dwarf_P_Simple_nameentry nameentry;
99 Dwarf_P_Simple_name_header hdr;
100 char *name;
101 int uword_size;
102
103 if (dbg == NULL) {
104 _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
105 return DW_DLV_ERROR;
106 }
107
108 if (die == NULL) {
109 _dwarf_p_error(NULL, error, DW_DLE_DIE_NULL);
110 return DW_DLV_ERROR;
111 }
112
113
114 nameentry = (Dwarf_P_Simple_nameentry)
115 _dwarf_p_get_alloc(dbg,
116 sizeof(struct Dwarf_P_Simple_nameentry_s));
117 if (nameentry == NULL) {
118 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
119 return DW_DLV_ERROR;
120 }
121
122 name = _dwarf_p_get_alloc(dbg, strlen(entry_name) + 1);
123 if (name == NULL) {
124 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
125 return DW_DLV_ERROR;
126 }
127 strcpy(name, entry_name);
128
129 nameentry->sne_die = die;
130 nameentry->sne_name = name;
131 nameentry->sne_name_len = strlen(name);
132 uword_size = dbg->de_dwarf_offset_size;
133
134 hdr = &dbg->de_simple_name_headers[entrykind];
135 if (hdr->sn_head == NULL)
136 hdr->sn_head = hdr->sn_tail = nameentry;
137 else {
138 hdr->sn_tail->sne_next = nameentry;
139 hdr->sn_tail = nameentry;
140 }
141 hdr->sn_count++;
142 hdr->sn_net_len += uword_size + nameentry->sne_name_len + 1;
143
144 return DW_DLV_OK;
145 }
146
147
148
149 /*
150 _dwarf_transform_simplename_to_disk writes
151 ".rel.debug_pubnames",
152 ".rel.debug_funcnames", sgi extension
153 ".rel.debug_typenames", sgi extension
154 ".rel.debug_varnames", sgi extension
155 ".rel.debug_weaknames", sgi extension
156 to disk.
157 section_index indexes one of those sections.
158 entrykind is one of those 'kind's. */
159 int
_dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg,enum dwarf_sn_kind entrykind,int section_index,Dwarf_Signed * nbufs,Dwarf_Error * error)160 _dwarf_transform_simplename_to_disk(Dwarf_P_Debug dbg,
161 enum dwarf_sn_kind entrykind,
162 int section_index, /* in de_elf_sects etc */
163 Dwarf_Signed *nbufs,
164 Dwarf_Error * error)
165 {
166
167
168 /* Used to fill in 0. */
169 const Dwarf_Signed big_zero = 0;
170
171 /* Used to scan the section data buffers. */
172 Dwarf_P_Section_Data debug_sect;
173
174 Dwarf_Signed debug_info_size;
175
176 Dwarf_P_Simple_nameentry nameentry_original;
177 Dwarf_P_Simple_nameentry nameentry;
178 Dwarf_Small *stream_bytes;
179 Dwarf_Small *cur_stream_bytes_ptr;
180 Dwarf_Unsigned stream_bytes_count;
181 Dwarf_Unsigned adjusted_length; /* count excluding length field */
182
183
184 int uword_size = dbg->de_dwarf_offset_size;
185 int extension_size = dbg->de_64bit_extension ? 4 : 0;
186
187 Dwarf_P_Simple_name_header hdr;
188
189
190 /* ***** BEGIN CODE ***** */
191
192 debug_info_size = 0;
193 for (debug_sect = dbg->de_debug_sects; debug_sect != NULL;
194 debug_sect = debug_sect->ds_next) {
195 /* We want the size of the .debug_info section for this CU
196 because the dwarf spec requires us to output it below so we
197 look for it specifically. */
198 if (debug_sect->ds_elf_sect_no == dbg->de_elf_sects[DEBUG_INFO]) {
199 debug_info_size += debug_sect->ds_nbytes;
200 }
201 }
202
203 hdr = &dbg->de_simple_name_headers[entrykind];
204 /* Size of the .debug_typenames (or similar) section header. */
205 stream_bytes_count = extension_size + uword_size + /* Size of
206 length field. */
207 DWARF_HALF_SIZE + /* Size of version field. */
208 uword_size + /* Size of .debug_info offset. */
209 uword_size; /* Size of .debug_names. */
210
211
212
213 nameentry_original = hdr->sn_head;
214 /* add in the content size */
215 stream_bytes_count += hdr->sn_net_len;
216
217 /* Size of the last 0 offset. */
218 stream_bytes_count += uword_size;
219
220 /* Now we know how long the entire section is */
221 GET_CHUNK(dbg, dbg->de_elf_sects[section_index],
222 stream_bytes, (unsigned long) stream_bytes_count, error);
223 cur_stream_bytes_ptr = stream_bytes;
224
225 if (extension_size) {
226 DISTINGUISHED_VALUE_ARRAY(v4);
227
228 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
229 (const void *)&v4[0],SIZEOFT32 , extension_size);
230 cur_stream_bytes_ptr += extension_size;
231
232 }
233 /* Write the adjusted length of .debug_*names section. */
234 adjusted_length = stream_bytes_count - uword_size - extension_size;
235 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
236 (const void *) &adjusted_length,
237 sizeof(adjusted_length), uword_size);
238 cur_stream_bytes_ptr += uword_size;
239
240 /* Write the version as 2 bytes. */
241 {
242 Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
243
244 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
245 (const void *) &verstamp,
246 sizeof(verstamp), DWARF_HALF_SIZE);
247 cur_stream_bytes_ptr += DWARF_HALF_SIZE;
248 }
249
250 /* Write the offset of the compile-unit. */
251 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
252 (const void *) &big_zero,
253 sizeof(big_zero), uword_size);
254 cur_stream_bytes_ptr += uword_size;
255
256 /* now create the relocation for the compile_unit offset */
257 {
258 int res = dbg->de_relocate_by_name_symbol(dbg,
259 section_index,
260 extension_size + uword_size +
261 DWARF_HALF_SIZE /* r_offset */ ,
262 /* debug_info section name symbol */
263 dbg->de_sect_name_idx[DEBUG_INFO],
264 dwarf_drt_data_reloc,
265 uword_size);
266
267 if (res != DW_DLV_OK) {
268 _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
269 return DW_DLV_ERROR;
270 }
271 }
272
273 /* Write the size of .debug_info section. */
274 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
275 (const void *) &debug_info_size,
276 sizeof(debug_info_size), uword_size);
277 cur_stream_bytes_ptr += uword_size;
278
279
280 for (nameentry = nameentry_original;
281 nameentry != NULL; nameentry = nameentry->sne_next) {
282
283 /* Copy offset of die from start of compile-unit. */
284 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
285 (const void *) &nameentry->sne_die->di_offset,
286 sizeof(nameentry->sne_die->di_offset),
287 uword_size);
288 cur_stream_bytes_ptr += uword_size;
289
290 /* Copy the type name. */
291 strcpy((char *) cur_stream_bytes_ptr, nameentry->sne_name);
292 cur_stream_bytes_ptr += nameentry->sne_name_len + 1;
293 }
294
295 WRITE_UNALIGNED(dbg, cur_stream_bytes_ptr,
296 (const void *) &big_zero,
297 sizeof(big_zero), uword_size);
298 *nbufs = dbg->de_n_debug_sect;
299 return DW_DLV_OK;
300 }
301