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