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