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*/
55Dwarf_Unsigned
56dwarf_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}
71int
72dwarf_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*/
91int
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.  */
159int
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