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., 59 Temple Place - Suite 330, Boston MA 02111-1307,
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