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