xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_macinfo.c (revision bc1f688b4872ace323eaddbb1a6365d054e7bf56)
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 
65 static int
66 libdwarf_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 
136 static void
137 libdwarf_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 }
153 static int
154 libdwarf_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 */
186 static int
187 libdwarf_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 
202 int
203 dwarf_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 
262 int
263 dwarf_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 
307 int
308 dwarf_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 
342 int
343 dwarf_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 
368 int
369 dwarf_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 
414 int
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