1/*
2
3  Copyright (C) 2000,2004 Silicon Graphics, Inc.  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  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26  Mountain View, CA 94043, or:
27
28  http://www.sgi.com
29
30  For further information regarding this notice, see:
31
32  http://oss.sgi.com/projects/GenInfo/NoticeExplan
33
34*/
35
36
37
38#include "config.h"
39#include "libdwarfdefs.h"
40#include <stdio.h>
41#include <string.h>
42#include "pro_incl.h"
43#include "pro_section.h"
44#include "pro_macinfo.h"
45
46/*
47        I don't much like the error strings this generates, since
48        like the rest of libdwarf they are simple strings with
49        no useful numbers in them. But that's not something I can
50        fix without more work than I have time for
51        right now.  davea Nov 94.
52*/
53
54/* these are gross overestimates of the number of
55** bytes needed to store a number in LEB form.
56** Just estimates, and since blocks are reasonable size,
57** the end-block waste is small.
58** Of course the waste is NOT present on disk.
59*/
60
61#define COMMAND_LEN ENCODE_SPACE_NEEDED
62#define LINE_LEN    ENCODE_SPACE_NEEDED
63#define BASE_MACINFO_MALLOC_LEN 2048
64
65static int
66libdwarf_compose_begin(Dwarf_P_Debug dbg, int code,
67                       size_t maxlen, int *compose_error_type)
68{
69    unsigned char *nextchar;
70    struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
71
72    if (curblk == 0) {
73        struct dw_macinfo_block_s *newb;
74        size_t len;
75
76        /* initial allocation */
77        size_t blen = BASE_MACINFO_MALLOC_LEN;
78
79        if (blen < maxlen) {
80            blen = 2 * maxlen;
81        }
82        len = sizeof(struct dw_macinfo_block_s) + blen;
83        newb =
84            (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len);
85        if (!newb) {
86            *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
87            return DW_DLV_ERROR;
88        }
89        newb->mb_data =
90            (char *) newb + sizeof(struct dw_macinfo_block_s);
91        newb->mb_avail_len = blen;
92        newb->mb_used_len = 0;
93        newb->mb_macinfo_data_space_len = blen;
94        dbg->de_first_macinfo = newb;
95        dbg->de_current_macinfo = newb;
96        curblk = newb;
97    } else if (curblk->mb_avail_len < maxlen) {
98        struct dw_macinfo_block_s *newb;
99        size_t len;
100
101        /* no space left in block: allocate a new block */
102        size_t blen =
103            dbg->de_current_macinfo->mb_macinfo_data_space_len * 2;
104        if (blen < maxlen) {
105            blen = 2 * maxlen;
106        }
107        len = sizeof(struct dw_macinfo_block_s) + blen;
108        newb =
109            (struct dw_macinfo_block_s *) _dwarf_p_get_alloc(dbg, len);
110        if (!newb) {
111            *compose_error_type = DW_DLE_MACINFO_MALLOC_FAIL;
112            return DW_DLV_ERROR;
113        }
114        newb->mb_data =
115            (char *) newb + sizeof(struct dw_macinfo_block_s);
116        newb->mb_avail_len = blen;
117        newb->mb_used_len = 0;
118        newb->mb_macinfo_data_space_len = blen;
119        dbg->de_first_macinfo->mb_next = newb;
120        dbg->de_current_macinfo = newb;
121        curblk = newb;
122    }
123    /* now curblk has enough room */
124    dbg->de_compose_avail = curblk->mb_avail_len;
125    dbg->de_compose_used_len = curblk->mb_used_len;
126    nextchar =
127        (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
128    *nextchar = code;
129    dbg->de_compose_avail--;
130    ++dbg->de_compose_used_len;
131    return DW_DLV_OK;
132}
133
134
135
136static void
137libdwarf_compose_add_string(Dwarf_P_Debug dbg, char *string, size_t len)
138{
139    struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
140    unsigned char *nextchar;
141
142    nextchar =
143        (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
144
145    len += 1;                   /* count the null terminator */
146
147    memcpy(nextchar, string, len);
148    dbg->de_compose_avail -= len;
149    dbg->de_compose_used_len += len;
150    return;
151
152}
153static int
154libdwarf_compose_add_line(Dwarf_P_Debug dbg,
155                          Dwarf_Unsigned line, int *compose_error_type)
156{
157    struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
158    unsigned char *nextchar;
159    int res;
160    int nbytes;
161
162    nextchar =
163        (unsigned char *) (curblk->mb_data + dbg->de_compose_used_len);
164
165    /* Put the created leb number directly into the macro buffer If
166       dbg->de_compose_avail is > INT_MAX this will not work as the
167       'int' will look negative to _dwarf_pro_encode_leb128_nm! */
168
169    res = _dwarf_pro_encode_leb128_nm(line, &nbytes,
170                                      (char *) nextchar,
171                                      (int) dbg->de_compose_avail);
172    if (res != DW_DLV_OK) {
173        *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
174        return DW_DLV_ERROR;
175    }
176
177    dbg->de_compose_avail -= nbytes;
178    dbg->de_compose_used_len += nbytes;
179    return DW_DLV_OK;
180}
181
182/*
183   This function actually 'commits' the space used by the
184   preceeding calls.
185*/
186static int
187libdwarf_compose_complete(Dwarf_P_Debug dbg, int *compose_error_type)
188{
189    struct dw_macinfo_block_s *curblk = dbg->de_current_macinfo;
190
191    if (dbg->de_compose_used_len > curblk->mb_macinfo_data_space_len) {
192        *compose_error_type = DW_DLE_MACINFO_INTERNAL_ERROR_SPACE;
193        return DW_DLV_ERROR;
194    }
195    curblk->mb_avail_len = dbg->de_compose_avail;
196    curblk->mb_used_len = dbg->de_compose_used_len;
197    return DW_DLV_OK;
198}
199
200
201
202int
203dwarf_def_macro(Dwarf_P_Debug dbg,
204                Dwarf_Unsigned line,
205                char *macname, char *macvalue, Dwarf_Error * error)
206{
207    size_t len;
208    size_t len2;
209    size_t length_est;
210    int res;
211    int compose_error_type;
212
213    if (dbg == NULL) {
214        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
215        return (DW_DLV_ERROR);
216    }
217    if (macname == 0) {
218        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
219        return (DW_DLV_ERROR);
220    }
221    len = strlen(macname) + 1;
222    if (len == 0) {
223        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
224        return (DW_DLV_ERROR);
225    }
226    if (macvalue) {
227        len2 = strlen(macvalue) + 1;
228    } else {
229        len2 = 0;
230    }
231    length_est = COMMAND_LEN + LINE_LEN + len + len2 + 1;       /* 1
232                                                                   for
233                                                                   space
234                                                                   character
235                                                                   we
236                                                                   add */
237    res = libdwarf_compose_begin(dbg, DW_MACINFO_define, length_est,
238                                 &compose_error_type);
239    if (res != DW_DLV_OK) {
240        _dwarf_p_error(NULL, error, compose_error_type);
241        return (DW_DLV_ERROR);
242    }
243    res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
244    if (res != DW_DLV_OK) {
245        _dwarf_p_error(NULL, error, compose_error_type);
246        return (DW_DLV_ERROR);
247    }
248    libdwarf_compose_add_string(dbg, macname, len);
249    libdwarf_compose_add_string(dbg, " ", 1);
250    if (macvalue) {
251        libdwarf_compose_add_string(dbg, " ", 1);
252        libdwarf_compose_add_string(dbg, macvalue, len2);
253    }
254    res = libdwarf_compose_complete(dbg, &compose_error_type);
255    if (res != DW_DLV_OK) {
256        _dwarf_p_error(NULL, error, compose_error_type);
257        return (DW_DLV_ERROR);
258    }
259    return DW_DLV_OK;
260}
261
262int
263dwarf_undef_macro(Dwarf_P_Debug dbg,
264                  Dwarf_Unsigned line,
265                  char *macname, Dwarf_Error * error)
266{
267
268    size_t len;
269    size_t length_est;
270    int res;
271    int compose_error_type;
272
273    if (dbg == NULL) {
274        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
275        return (DW_DLV_ERROR);
276    }
277    if (macname == 0) {
278        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
279        return (DW_DLV_ERROR);
280    }
281    len = strlen(macname) + 1;
282    if (len == 0) {
283        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
284        return (DW_DLV_ERROR);
285    }
286    length_est = COMMAND_LEN + LINE_LEN + len;
287    res = libdwarf_compose_begin(dbg, DW_MACINFO_undef, length_est,
288                                 &compose_error_type);
289    if (res != DW_DLV_OK) {
290        _dwarf_p_error(NULL, error, compose_error_type);
291        return (DW_DLV_ERROR);
292    }
293    res = libdwarf_compose_add_line(dbg, line, &compose_error_type);
294    if (res != DW_DLV_OK) {
295        _dwarf_p_error(NULL, error, compose_error_type);
296        return (DW_DLV_ERROR);
297    }
298    libdwarf_compose_add_string(dbg, macname, len);
299    res = libdwarf_compose_complete(dbg, &compose_error_type);
300    if (res != DW_DLV_OK) {
301        _dwarf_p_error(NULL, error, compose_error_type);
302        return (DW_DLV_ERROR);
303    }
304    return DW_DLV_OK;
305}
306
307int
308dwarf_start_macro_file(Dwarf_P_Debug dbg,
309                       Dwarf_Unsigned fileindex,
310                       Dwarf_Unsigned linenumber, Dwarf_Error * error)
311{
312    size_t length_est;
313    int res;
314    int compose_error_type;
315
316    if (dbg == NULL) {
317        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
318        return (DW_DLV_ERROR);
319    }
320    length_est = COMMAND_LEN + LINE_LEN + LINE_LEN;
321    res = libdwarf_compose_begin(dbg, DW_MACINFO_start_file, length_est,
322                                 &compose_error_type);
323    if (res != DW_DLV_OK) {
324        _dwarf_p_error(NULL, error, compose_error_type);
325        return (DW_DLV_ERROR);
326    }
327    res = libdwarf_compose_add_line(dbg, fileindex,
328                                    &compose_error_type);
329    if (res != DW_DLV_OK) {
330        _dwarf_p_error(NULL, error, compose_error_type);
331        return (DW_DLV_ERROR);
332    }
333    res = libdwarf_compose_add_line(dbg, linenumber,
334                                    &compose_error_type);
335    if (res != DW_DLV_OK) {
336        _dwarf_p_error(NULL, error, compose_error_type);
337        return (DW_DLV_ERROR);
338    }
339    return DW_DLV_OK;
340}
341
342int
343dwarf_end_macro_file(Dwarf_P_Debug dbg, Dwarf_Error * error)
344{
345    size_t length_est;
346    int res;
347    int compose_error_type;
348
349    if (dbg == NULL) {
350        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
351        return (DW_DLV_ERROR);
352    }
353    length_est = COMMAND_LEN;
354    res = libdwarf_compose_begin(dbg, DW_MACINFO_end_file, length_est,
355                                 &compose_error_type);
356    if (res != DW_DLV_OK) {
357        _dwarf_p_error(NULL, error, compose_error_type);
358        return (DW_DLV_ERROR);
359    }
360    res = libdwarf_compose_complete(dbg, &compose_error_type);
361    if (res != DW_DLV_OK) {
362        _dwarf_p_error(NULL, error, compose_error_type);
363        return (DW_DLV_ERROR);
364    }
365    return DW_DLV_OK;
366}
367
368int
369dwarf_vendor_ext(Dwarf_P_Debug dbg,
370                 Dwarf_Unsigned constant,
371                 char *string, Dwarf_Error * error)
372{
373    size_t len;
374    size_t length_est;
375    int res;
376    int compose_error_type;
377
378    if (dbg == NULL) {
379        _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
380        return (DW_DLV_ERROR);
381    }
382    if (string == 0) {
383        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_NULL);
384        return (DW_DLV_ERROR);
385    }
386    len = strlen(string) + 1;
387    if (len == 0) {
388        _dwarf_p_error(NULL, error, DW_DLE_MACINFO_STRING_EMPTY);
389        return (DW_DLV_ERROR);
390    }
391    length_est = COMMAND_LEN + LINE_LEN + len;
392    res = libdwarf_compose_begin(dbg, DW_MACINFO_vendor_ext, length_est,
393                                 &compose_error_type);
394    if (res != DW_DLV_OK) {
395        _dwarf_p_error(NULL, error, compose_error_type);
396        return (DW_DLV_ERROR);
397    }
398    res = libdwarf_compose_add_line(dbg, constant, &compose_error_type);
399    if (res != DW_DLV_OK) {
400        _dwarf_p_error(NULL, error, compose_error_type);
401        return (DW_DLV_ERROR);
402    }
403    libdwarf_compose_add_string(dbg, string, len);
404    libdwarf_compose_complete(dbg, &compose_error_type);
405    if (res != DW_DLV_OK) {
406        _dwarf_p_error(NULL, error, compose_error_type);
407        return (DW_DLV_ERROR);
408    }
409    return DW_DLV_OK;
410}
411
412
413
414int
415_dwarf_pro_transform_macro_info_to_disk(Dwarf_P_Debug dbg,
416                                        Dwarf_Error * error)
417{
418    /* Total num of bytes in .debug_macinfo section. */
419    Dwarf_Unsigned mac_num_bytes;
420
421    /* Points to first byte of .debug_macinfo buffer. */
422    Dwarf_Small *macinfo;
423
424    /* Fills in the .debug_macinfo buffer. */
425    Dwarf_Small *macinfo_ptr;
426
427
428    /* Used to scan the section data buffers. */
429    struct dw_macinfo_block_s *m_prev;
430    struct dw_macinfo_block_s *m_sect;
431
432
433    /* Get the size of the debug_macinfo data */
434    mac_num_bytes = 0;
435    for (m_sect = dbg->de_first_macinfo; m_sect != NULL;
436         m_sect = m_sect->mb_next) {
437        mac_num_bytes += m_sect->mb_used_len;
438    }
439    /* Tthe final entry has a type code of 0 to indicate It is final
440       for this CU Takes just 1 byte. */
441    mac_num_bytes += 1;
442
443    GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_MACINFO],
444              macinfo, (unsigned long) mac_num_bytes, error);
445    if (macinfo == NULL) {
446        _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
447        return (0);
448    }
449
450    macinfo_ptr = macinfo;
451    m_prev = 0;
452    for (m_sect = dbg->de_first_macinfo; m_sect != NULL;
453         m_sect = m_sect->mb_next) {
454        memcpy(macinfo_ptr, m_sect->mb_data, m_sect->mb_used_len);
455        macinfo_ptr += m_sect->mb_used_len;
456        if (m_prev) {
457            _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev);
458            m_prev = 0;
459        }
460        m_prev = m_sect;
461    }
462    *macinfo_ptr = 0;           /* the type code of 0 as last entry */
463    if (m_prev) {
464        _dwarf_p_dealloc(dbg, (Dwarf_Small *) m_prev);
465        m_prev = 0;
466    }
467
468    dbg->de_first_macinfo = NULL;
469    dbg->de_current_macinfo = NULL;
470
471    return (int) dbg->de_n_debug_sect;
472}
473