xref: /titanic_41/usr/src/tools/ctf/dwarf/common/pro_arange.c (revision 26f3cdf03f1adcc98f6d3d99843ee71e9229a8c0)
1 /*
2 
3   Copyright (C) 2000 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., 1600 Amphitheatre Pky,
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 #ifdef HAVE_ELFACCESS_H
43 #include <elfaccess.h>
44 #endif
45 #include "pro_incl.h"
46 #include "pro_arange.h"
47 #include "pro_section.h"
48 #include "pro_reloc.h"
49 
50 
51 
52 /*
53     This function adds another address range
54     to the list of address ranges for the
55     given Dwarf_P_Debug.  It returns 0 on error,
56     and 1 otherwise.
57 */
58 Dwarf_Unsigned
59 dwarf_add_arange(Dwarf_P_Debug dbg,
60 		 Dwarf_Addr begin_address,
61 		 Dwarf_Unsigned length,
62 		 Dwarf_Signed symbol_index, Dwarf_Error * error)
63 {
64     return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
65 			      /* end_symbol_index */ 0,
66 			      /* offset_from_end_sym */ 0,
67 			      error);
68 }
69 
70 /*
71     This function adds another address range
72     to the list of address ranges for the
73     given Dwarf_P_Debug.  It returns 0 on error,
74     and 1 otherwise.
75 */
76 Dwarf_Unsigned
77 dwarf_add_arange_b(Dwarf_P_Debug dbg,
78 		   Dwarf_Addr begin_address,
79 		   Dwarf_Unsigned length,
80 		   Dwarf_Unsigned symbol_index,
81 		   Dwarf_Unsigned end_symbol_index,
82 		   Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
83 {
84     Dwarf_P_Arange arange;
85 
86     if (dbg == NULL) {
87 	_dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
88 	return (0);
89     }
90 
91     arange = (Dwarf_P_Arange)
92 	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
93     if (arange == NULL) {
94 	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
95 	return (0);
96     }
97 
98     arange->ag_begin_address = begin_address;
99     arange->ag_length = length;
100     arange->ag_symbol_index = symbol_index;
101     arange->ag_end_symbol_index = end_symbol_index;
102     arange->ag_end_symbol_offset = offset_from_end_sym;
103 
104     if (dbg->de_arange == NULL)
105 	dbg->de_arange = dbg->de_last_arange = arange;
106     else {
107 	dbg->de_last_arange->ag_next = arange;
108 	dbg->de_last_arange = arange;
109     }
110     dbg->de_arange_count++;
111 
112     return (1);
113 }
114 
115 
116 int
117 _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
118 {
119     /* Total num of bytes in .debug_aranges section. */
120     Dwarf_Unsigned arange_num_bytes;
121 
122     /*
123        Adjustment to align the start of the actual address ranges on a
124        boundary aligned with twice the address size. */
125     Dwarf_Small remainder;
126 
127     /* Total number of bytes excluding the length field. */
128     Dwarf_Unsigned adjusted_length;
129 
130     /* Points to first byte of .debug_aranges buffer. */
131     Dwarf_Small *arange;
132 
133     /* Fills in the .debug_aranges buffer. */
134     Dwarf_Small *arange_ptr;
135 
136     /* Scans the list of address ranges provided by user. */
137     Dwarf_P_Arange given_arange;
138 
139     /* Used to fill in 0. */
140     const Dwarf_Signed big_zero = 0;
141 
142     int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
143     int uword_size = dbg->de_offset_size;
144     int upointer_size = dbg->de_pointer_size;
145     int res;
146 
147 
148     /* ***** BEGIN CODE ***** */
149 
150     /* Size of the .debug_aranges section header. */
151     arange_num_bytes = extension_word_size + uword_size +	/* Size
152 								   of
153 								   length
154 								   field.
155 								 */
156 	sizeof(Dwarf_Half) +	/* Size of version field. */
157 	uword_size +		/* Size of .debug_info offset. */
158 	sizeof(Dwarf_Small) +	/* Size of address size field. */
159 	sizeof(Dwarf_Small);	/* Size of segment size field. */
160 
161     /*
162        Adjust the size so that the set of aranges begins on a boundary
163        that aligned with twice the address size.  This is a Libdwarf
164        requirement. */
165     remainder = arange_num_bytes % (2 * upointer_size);
166     if (remainder != 0)
167 	arange_num_bytes += (2 * upointer_size) - remainder;
168 
169 
170     /* Add the bytes for the actual address ranges. */
171     arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
172 
173     GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
174 	      arange, (unsigned long) arange_num_bytes, error);
175     arange_ptr = arange;
176     if (arange == NULL) {
177 	_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
178 	return (0);
179     }
180     if (extension_word_size) {
181 	Dwarf_Word x = DISTINGUISHED_VALUE;
182 
183 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
184 			(const void *) &x,
185 			sizeof(x), extension_word_size);
186 	arange_ptr += extension_word_size;
187     }
188 
189     /* Write the total length of .debug_aranges section. */
190     adjusted_length = arange_num_bytes - uword_size
191 	- extension_word_size;
192     {
193 	Dwarf_Unsigned du = adjusted_length;
194 
195 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
196 			(const void *) &du, sizeof(du), uword_size);
197 	arange_ptr += uword_size;
198     }
199 
200     /* Write the version as 2 bytes. */
201     {
202 	Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
203 
204 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
205 			(const void *) &verstamp,
206 			sizeof(verstamp), sizeof(Dwarf_Half));
207 	arange_ptr += sizeof(Dwarf_Half);
208     }
209 
210 
211     /* Write the .debug_info offset.  This is always 0. */
212     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
213 		    (const void *) &big_zero,
214 		    sizeof(big_zero), uword_size);
215     arange_ptr += uword_size;
216 
217     {
218 	unsigned long count = dbg->de_arange_count + 1;
219 	int res;
220 
221 	if (dbg->de_reloc_pair) {
222 	    count = (3 * dbg->de_arange_count) + 1;
223 	}
224 	/* the following is a small optimization: not needed for
225 	   correctness */
226 	res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
227 						 DEBUG_ARANGES, count);
228 	if (res != DW_DLV_OK) {
229 	    {
230 		_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
231 		return (0);
232 	    }
233 	}
234     }
235 
236     /* reloc for .debug_info */
237     res = dbg->de_reloc_name(dbg,
238 			     DEBUG_ARANGES,
239 			     extension_word_size +
240 			     uword_size + sizeof(Dwarf_Half),
241 			     dbg->de_sect_name_idx[DEBUG_INFO],
242 			     dwarf_drt_data_reloc, uword_size);
243 
244     /* Write the size of addresses. */
245     *arange_ptr = dbg->de_pointer_size;
246     arange_ptr++;
247 
248     /*
249        Write the size of segment addresses. This is zero for MIPS
250        architectures. */
251     *arange_ptr = 0;
252     arange_ptr++;
253 
254     /*
255        Skip over the padding to align the start of the actual address
256        ranges to twice the address size. */
257     if (remainder != 0)
258 	arange_ptr += (2 * upointer_size) - remainder;
259 
260 
261 
262 
263 
264     /* The arange address, length are pointer-size fields of the target
265        machine. */
266     for (given_arange = dbg->de_arange; given_arange != NULL;
267 	 given_arange = given_arange->ag_next) {
268 
269 	/* Write relocation record for beginning of address range. */
270 	res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange,	/* r_offset */
271 				 (long) given_arange->ag_symbol_index,
272 				 dwarf_drt_data_reloc, upointer_size);
273 	if (res != DW_DLV_OK) {
274 	    {
275 		_dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
276 		return (0);
277 	    }
278 	}
279 
280 	/* Copy beginning address of range. */
281 	WRITE_UNALIGNED(dbg, (void *) arange_ptr,
282 			(const void *) &given_arange->ag_begin_address,
283 			sizeof(given_arange->ag_begin_address),
284 			upointer_size);
285 	arange_ptr += upointer_size;
286 
287 	if (dbg->de_reloc_pair &&
288 	    given_arange->ag_end_symbol_index != 0 &&
289 	    given_arange->ag_length == 0) {
290 	    /* symbolic reloc, need reloc for length What if we really
291 	       know the length? If so, should use the other part of
292 	       'if'. */
293 	    Dwarf_Unsigned val;
294 
295 	    res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange,	/* r_offset
296 										 */
297 				     given_arange->ag_symbol_index,
298 				     given_arange->ag_end_symbol_index,
299 				     dwarf_drt_first_of_length_pair,
300 				     upointer_size);
301 	    if (res != DW_DLV_OK) {
302 		{
303 		    _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
304 		    return (0);
305 		}
306 	    }
307 
308 	    /* arrange pre-calc so assem text can do .word end - begin
309 	       + val (gets val from stream) */
310 	    val = given_arange->ag_end_symbol_offset -
311 		given_arange->ag_begin_address;
312 	    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
313 			    (const void *) &val,
314 			    sizeof(val), upointer_size);
315 	    arange_ptr += upointer_size;
316 
317 	} else {
318 	    /* plain old length to copy, no relocation at all */
319 	    WRITE_UNALIGNED(dbg, (void *) arange_ptr,
320 			    (const void *) &given_arange->ag_length,
321 			    sizeof(given_arange->ag_length),
322 			    upointer_size);
323 	    arange_ptr += upointer_size;
324 	}
325     }
326 
327     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
328 		    (const void *) &big_zero,
329 		    sizeof(big_zero), upointer_size);
330 
331     arange_ptr += upointer_size;
332     WRITE_UNALIGNED(dbg, (void *) arange_ptr,
333 		    (const void *) &big_zero,
334 		    sizeof(big_zero), upointer_size);
335     return (int) dbg->de_n_debug_sect;
336 }
337