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