1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi
3*7fd79137SRobert Mustacchi Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
4*7fd79137SRobert Mustacchi
5*7fd79137SRobert Mustacchi This program is free software; you can redistribute it and/or modify it
6*7fd79137SRobert Mustacchi under the terms of version 2.1 of the GNU Lesser General Public License
7*7fd79137SRobert Mustacchi as published by the Free Software Foundation.
8*7fd79137SRobert Mustacchi
9*7fd79137SRobert Mustacchi This program is distributed in the hope that it would be useful, but
10*7fd79137SRobert Mustacchi WITHOUT ANY WARRANTY; without even the implied warranty of
11*7fd79137SRobert Mustacchi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*7fd79137SRobert Mustacchi
13*7fd79137SRobert Mustacchi Further, this software is distributed without any warranty that it is
14*7fd79137SRobert Mustacchi free of the rightful claim of any third person regarding infringement
15*7fd79137SRobert Mustacchi or the like. Any license provided herein, whether implied or
16*7fd79137SRobert Mustacchi otherwise, applies only to this software file. Patent licenses, if
17*7fd79137SRobert Mustacchi any, provided herein do not apply to combinations of this program with
18*7fd79137SRobert Mustacchi other software, or any other product whatsoever.
19*7fd79137SRobert Mustacchi
20*7fd79137SRobert Mustacchi You should have received a copy of the GNU Lesser General Public
21*7fd79137SRobert Mustacchi License along with this program; if not, write the Free Software
22*7fd79137SRobert Mustacchi Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23*7fd79137SRobert Mustacchi USA.
24*7fd79137SRobert Mustacchi
25*7fd79137SRobert Mustacchi Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
26*7fd79137SRobert Mustacchi Mountain View, CA 94043, or:
27*7fd79137SRobert Mustacchi
28*7fd79137SRobert Mustacchi http://www.sgi.com
29*7fd79137SRobert Mustacchi
30*7fd79137SRobert Mustacchi For further information regarding this notice, see:
31*7fd79137SRobert Mustacchi
32*7fd79137SRobert Mustacchi http://oss.sgi.com/projects/GenInfo/NoticeExplan
33*7fd79137SRobert Mustacchi
34*7fd79137SRobert Mustacchi */
35*7fd79137SRobert Mustacchi
36*7fd79137SRobert Mustacchi
37*7fd79137SRobert Mustacchi
38*7fd79137SRobert Mustacchi #include "config.h"
39*7fd79137SRobert Mustacchi #include "libdwarfdefs.h"
40*7fd79137SRobert Mustacchi #include <stdio.h>
41*7fd79137SRobert Mustacchi #include <string.h>
42*7fd79137SRobert Mustacchi #ifdef HAVE_ELFACCESS_H
43*7fd79137SRobert Mustacchi #include <elfaccess.h>
44*7fd79137SRobert Mustacchi #endif
45*7fd79137SRobert Mustacchi #include "pro_incl.h"
46*7fd79137SRobert Mustacchi #include "pro_arange.h"
47*7fd79137SRobert Mustacchi #include "pro_section.h"
48*7fd79137SRobert Mustacchi #include "pro_reloc.h"
49*7fd79137SRobert Mustacchi
50*7fd79137SRobert Mustacchi
51*7fd79137SRobert Mustacchi
52*7fd79137SRobert Mustacchi /*
53*7fd79137SRobert Mustacchi This function adds another address range
54*7fd79137SRobert Mustacchi to the list of address ranges for the
55*7fd79137SRobert Mustacchi given Dwarf_P_Debug. It returns 0 on error,
56*7fd79137SRobert Mustacchi and 1 otherwise.
57*7fd79137SRobert Mustacchi */
58*7fd79137SRobert Mustacchi Dwarf_Unsigned
dwarf_add_arange(Dwarf_P_Debug dbg,Dwarf_Addr begin_address,Dwarf_Unsigned length,Dwarf_Signed symbol_index,Dwarf_Error * error)59*7fd79137SRobert Mustacchi dwarf_add_arange(Dwarf_P_Debug dbg,
60*7fd79137SRobert Mustacchi Dwarf_Addr begin_address,
61*7fd79137SRobert Mustacchi Dwarf_Unsigned length,
62*7fd79137SRobert Mustacchi Dwarf_Signed symbol_index, Dwarf_Error * error)
63*7fd79137SRobert Mustacchi {
64*7fd79137SRobert Mustacchi return dwarf_add_arange_b(dbg, begin_address, length, symbol_index,
65*7fd79137SRobert Mustacchi /* end_symbol_index */ 0,
66*7fd79137SRobert Mustacchi /* offset_from_end_sym */ 0,
67*7fd79137SRobert Mustacchi error);
68*7fd79137SRobert Mustacchi }
69*7fd79137SRobert Mustacchi
70*7fd79137SRobert Mustacchi /*
71*7fd79137SRobert Mustacchi This function adds another address range
72*7fd79137SRobert Mustacchi to the list of address ranges for the
73*7fd79137SRobert Mustacchi given Dwarf_P_Debug. It returns 0 on error,
74*7fd79137SRobert Mustacchi and 1 otherwise.
75*7fd79137SRobert Mustacchi */
76*7fd79137SRobert Mustacchi Dwarf_Unsigned
dwarf_add_arange_b(Dwarf_P_Debug dbg,Dwarf_Addr begin_address,Dwarf_Unsigned length,Dwarf_Unsigned symbol_index,Dwarf_Unsigned end_symbol_index,Dwarf_Addr offset_from_end_sym,Dwarf_Error * error)77*7fd79137SRobert Mustacchi dwarf_add_arange_b(Dwarf_P_Debug dbg,
78*7fd79137SRobert Mustacchi Dwarf_Addr begin_address,
79*7fd79137SRobert Mustacchi Dwarf_Unsigned length,
80*7fd79137SRobert Mustacchi Dwarf_Unsigned symbol_index,
81*7fd79137SRobert Mustacchi Dwarf_Unsigned end_symbol_index,
82*7fd79137SRobert Mustacchi Dwarf_Addr offset_from_end_sym, Dwarf_Error * error)
83*7fd79137SRobert Mustacchi {
84*7fd79137SRobert Mustacchi Dwarf_P_Arange arange;
85*7fd79137SRobert Mustacchi
86*7fd79137SRobert Mustacchi if (dbg == NULL) {
87*7fd79137SRobert Mustacchi _dwarf_p_error(NULL, error, DW_DLE_DBG_NULL);
88*7fd79137SRobert Mustacchi return (0);
89*7fd79137SRobert Mustacchi }
90*7fd79137SRobert Mustacchi
91*7fd79137SRobert Mustacchi arange = (Dwarf_P_Arange)
92*7fd79137SRobert Mustacchi _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Arange_s));
93*7fd79137SRobert Mustacchi if (arange == NULL) {
94*7fd79137SRobert Mustacchi _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
95*7fd79137SRobert Mustacchi return (0);
96*7fd79137SRobert Mustacchi }
97*7fd79137SRobert Mustacchi
98*7fd79137SRobert Mustacchi arange->ag_begin_address = begin_address;
99*7fd79137SRobert Mustacchi arange->ag_length = length;
100*7fd79137SRobert Mustacchi arange->ag_symbol_index = symbol_index;
101*7fd79137SRobert Mustacchi arange->ag_end_symbol_index = end_symbol_index;
102*7fd79137SRobert Mustacchi arange->ag_end_symbol_offset = offset_from_end_sym;
103*7fd79137SRobert Mustacchi
104*7fd79137SRobert Mustacchi if (dbg->de_arange == NULL)
105*7fd79137SRobert Mustacchi dbg->de_arange = dbg->de_last_arange = arange;
106*7fd79137SRobert Mustacchi else {
107*7fd79137SRobert Mustacchi dbg->de_last_arange->ag_next = arange;
108*7fd79137SRobert Mustacchi dbg->de_last_arange = arange;
109*7fd79137SRobert Mustacchi }
110*7fd79137SRobert Mustacchi dbg->de_arange_count++;
111*7fd79137SRobert Mustacchi
112*7fd79137SRobert Mustacchi return (1);
113*7fd79137SRobert Mustacchi }
114*7fd79137SRobert Mustacchi
115*7fd79137SRobert Mustacchi
116*7fd79137SRobert Mustacchi int
_dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg,Dwarf_Error * error)117*7fd79137SRobert Mustacchi _dwarf_transform_arange_to_disk(Dwarf_P_Debug dbg, Dwarf_Error * error)
118*7fd79137SRobert Mustacchi {
119*7fd79137SRobert Mustacchi /* Total num of bytes in .debug_aranges section. */
120*7fd79137SRobert Mustacchi Dwarf_Unsigned arange_num_bytes;
121*7fd79137SRobert Mustacchi
122*7fd79137SRobert Mustacchi /*
123*7fd79137SRobert Mustacchi Adjustment to align the start of the actual address ranges on a
124*7fd79137SRobert Mustacchi boundary aligned with twice the address size. */
125*7fd79137SRobert Mustacchi Dwarf_Small remainder;
126*7fd79137SRobert Mustacchi
127*7fd79137SRobert Mustacchi /* Total number of bytes excluding the length field. */
128*7fd79137SRobert Mustacchi Dwarf_Unsigned adjusted_length;
129*7fd79137SRobert Mustacchi
130*7fd79137SRobert Mustacchi /* Points to first byte of .debug_aranges buffer. */
131*7fd79137SRobert Mustacchi Dwarf_Small *arange;
132*7fd79137SRobert Mustacchi
133*7fd79137SRobert Mustacchi /* Fills in the .debug_aranges buffer. */
134*7fd79137SRobert Mustacchi Dwarf_Small *arange_ptr;
135*7fd79137SRobert Mustacchi
136*7fd79137SRobert Mustacchi /* Scans the list of address ranges provided by user. */
137*7fd79137SRobert Mustacchi Dwarf_P_Arange given_arange;
138*7fd79137SRobert Mustacchi
139*7fd79137SRobert Mustacchi /* Used to fill in 0. */
140*7fd79137SRobert Mustacchi const Dwarf_Signed big_zero = 0;
141*7fd79137SRobert Mustacchi
142*7fd79137SRobert Mustacchi int extension_word_size = dbg->de_64bit_extension ? 4 : 0;
143*7fd79137SRobert Mustacchi int uword_size = dbg->de_offset_size;
144*7fd79137SRobert Mustacchi int upointer_size = dbg->de_pointer_size;
145*7fd79137SRobert Mustacchi int res;
146*7fd79137SRobert Mustacchi
147*7fd79137SRobert Mustacchi
148*7fd79137SRobert Mustacchi /* ***** BEGIN CODE ***** */
149*7fd79137SRobert Mustacchi
150*7fd79137SRobert Mustacchi /* Size of the .debug_aranges section header. */
151*7fd79137SRobert Mustacchi arange_num_bytes = extension_word_size + uword_size + /* Size
152*7fd79137SRobert Mustacchi of
153*7fd79137SRobert Mustacchi length
154*7fd79137SRobert Mustacchi field.
155*7fd79137SRobert Mustacchi */
156*7fd79137SRobert Mustacchi sizeof(Dwarf_Half) + /* Size of version field. */
157*7fd79137SRobert Mustacchi uword_size + /* Size of .debug_info offset. */
158*7fd79137SRobert Mustacchi sizeof(Dwarf_Small) + /* Size of address size field. */
159*7fd79137SRobert Mustacchi sizeof(Dwarf_Small); /* Size of segment size field. */
160*7fd79137SRobert Mustacchi
161*7fd79137SRobert Mustacchi /*
162*7fd79137SRobert Mustacchi Adjust the size so that the set of aranges begins on a boundary
163*7fd79137SRobert Mustacchi that aligned with twice the address size. This is a Libdwarf
164*7fd79137SRobert Mustacchi requirement. */
165*7fd79137SRobert Mustacchi remainder = arange_num_bytes % (2 * upointer_size);
166*7fd79137SRobert Mustacchi if (remainder != 0)
167*7fd79137SRobert Mustacchi arange_num_bytes += (2 * upointer_size) - remainder;
168*7fd79137SRobert Mustacchi
169*7fd79137SRobert Mustacchi
170*7fd79137SRobert Mustacchi /* Add the bytes for the actual address ranges. */
171*7fd79137SRobert Mustacchi arange_num_bytes += upointer_size * 2 * (dbg->de_arange_count + 1);
172*7fd79137SRobert Mustacchi
173*7fd79137SRobert Mustacchi GET_CHUNK(dbg, dbg->de_elf_sects[DEBUG_ARANGES],
174*7fd79137SRobert Mustacchi arange, (unsigned long) arange_num_bytes, error);
175*7fd79137SRobert Mustacchi arange_ptr = arange;
176*7fd79137SRobert Mustacchi if (arange == NULL) {
177*7fd79137SRobert Mustacchi _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
178*7fd79137SRobert Mustacchi return (0);
179*7fd79137SRobert Mustacchi }
180*7fd79137SRobert Mustacchi if (extension_word_size) {
181*7fd79137SRobert Mustacchi Dwarf_Word x = DISTINGUISHED_VALUE;
182*7fd79137SRobert Mustacchi
183*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
184*7fd79137SRobert Mustacchi (const void *) &x,
185*7fd79137SRobert Mustacchi sizeof(x), extension_word_size);
186*7fd79137SRobert Mustacchi arange_ptr += extension_word_size;
187*7fd79137SRobert Mustacchi }
188*7fd79137SRobert Mustacchi
189*7fd79137SRobert Mustacchi /* Write the total length of .debug_aranges section. */
190*7fd79137SRobert Mustacchi adjusted_length = arange_num_bytes - uword_size
191*7fd79137SRobert Mustacchi - extension_word_size;
192*7fd79137SRobert Mustacchi {
193*7fd79137SRobert Mustacchi Dwarf_Unsigned du = adjusted_length;
194*7fd79137SRobert Mustacchi
195*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
196*7fd79137SRobert Mustacchi (const void *) &du, sizeof(du), uword_size);
197*7fd79137SRobert Mustacchi arange_ptr += uword_size;
198*7fd79137SRobert Mustacchi }
199*7fd79137SRobert Mustacchi
200*7fd79137SRobert Mustacchi /* Write the version as 2 bytes. */
201*7fd79137SRobert Mustacchi {
202*7fd79137SRobert Mustacchi Dwarf_Half verstamp = CURRENT_VERSION_STAMP;
203*7fd79137SRobert Mustacchi
204*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
205*7fd79137SRobert Mustacchi (const void *) &verstamp,
206*7fd79137SRobert Mustacchi sizeof(verstamp), sizeof(Dwarf_Half));
207*7fd79137SRobert Mustacchi arange_ptr += sizeof(Dwarf_Half);
208*7fd79137SRobert Mustacchi }
209*7fd79137SRobert Mustacchi
210*7fd79137SRobert Mustacchi
211*7fd79137SRobert Mustacchi /* Write the .debug_info offset. This is always 0. */
212*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
213*7fd79137SRobert Mustacchi (const void *) &big_zero,
214*7fd79137SRobert Mustacchi sizeof(big_zero), uword_size);
215*7fd79137SRobert Mustacchi arange_ptr += uword_size;
216*7fd79137SRobert Mustacchi
217*7fd79137SRobert Mustacchi {
218*7fd79137SRobert Mustacchi unsigned long count = dbg->de_arange_count + 1;
219*7fd79137SRobert Mustacchi int res;
220*7fd79137SRobert Mustacchi
221*7fd79137SRobert Mustacchi if (dbg->de_reloc_pair) {
222*7fd79137SRobert Mustacchi count = (3 * dbg->de_arange_count) + 1;
223*7fd79137SRobert Mustacchi }
224*7fd79137SRobert Mustacchi /* the following is a small optimization: not needed for
225*7fd79137SRobert Mustacchi correctness */
226*7fd79137SRobert Mustacchi res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg,
227*7fd79137SRobert Mustacchi DEBUG_ARANGES, count);
228*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
229*7fd79137SRobert Mustacchi {
230*7fd79137SRobert Mustacchi _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
231*7fd79137SRobert Mustacchi return (0);
232*7fd79137SRobert Mustacchi }
233*7fd79137SRobert Mustacchi }
234*7fd79137SRobert Mustacchi }
235*7fd79137SRobert Mustacchi
236*7fd79137SRobert Mustacchi /* reloc for .debug_info */
237*7fd79137SRobert Mustacchi res = dbg->de_reloc_name(dbg,
238*7fd79137SRobert Mustacchi DEBUG_ARANGES,
239*7fd79137SRobert Mustacchi extension_word_size +
240*7fd79137SRobert Mustacchi uword_size + sizeof(Dwarf_Half),
241*7fd79137SRobert Mustacchi dbg->de_sect_name_idx[DEBUG_INFO],
242*7fd79137SRobert Mustacchi dwarf_drt_data_reloc, uword_size);
243*7fd79137SRobert Mustacchi
244*7fd79137SRobert Mustacchi /* Write the size of addresses. */
245*7fd79137SRobert Mustacchi *arange_ptr = dbg->de_pointer_size;
246*7fd79137SRobert Mustacchi arange_ptr++;
247*7fd79137SRobert Mustacchi
248*7fd79137SRobert Mustacchi /*
249*7fd79137SRobert Mustacchi Write the size of segment addresses. This is zero for MIPS
250*7fd79137SRobert Mustacchi architectures. */
251*7fd79137SRobert Mustacchi *arange_ptr = 0;
252*7fd79137SRobert Mustacchi arange_ptr++;
253*7fd79137SRobert Mustacchi
254*7fd79137SRobert Mustacchi /*
255*7fd79137SRobert Mustacchi Skip over the padding to align the start of the actual address
256*7fd79137SRobert Mustacchi ranges to twice the address size. */
257*7fd79137SRobert Mustacchi if (remainder != 0)
258*7fd79137SRobert Mustacchi arange_ptr += (2 * upointer_size) - remainder;
259*7fd79137SRobert Mustacchi
260*7fd79137SRobert Mustacchi
261*7fd79137SRobert Mustacchi
262*7fd79137SRobert Mustacchi
263*7fd79137SRobert Mustacchi
264*7fd79137SRobert Mustacchi /* The arange address, length are pointer-size fields of the target
265*7fd79137SRobert Mustacchi machine. */
266*7fd79137SRobert Mustacchi for (given_arange = dbg->de_arange; given_arange != NULL;
267*7fd79137SRobert Mustacchi given_arange = given_arange->ag_next) {
268*7fd79137SRobert Mustacchi
269*7fd79137SRobert Mustacchi /* Write relocation record for beginning of address range. */
270*7fd79137SRobert Mustacchi res = dbg->de_reloc_name(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset
271*7fd79137SRobert Mustacchi */
272*7fd79137SRobert Mustacchi (long) given_arange->ag_symbol_index,
273*7fd79137SRobert Mustacchi dwarf_drt_data_reloc, upointer_size);
274*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
275*7fd79137SRobert Mustacchi {
276*7fd79137SRobert Mustacchi _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
277*7fd79137SRobert Mustacchi return (0);
278*7fd79137SRobert Mustacchi }
279*7fd79137SRobert Mustacchi }
280*7fd79137SRobert Mustacchi
281*7fd79137SRobert Mustacchi /* Copy beginning address of range. */
282*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
283*7fd79137SRobert Mustacchi (const void *) &given_arange->ag_begin_address,
284*7fd79137SRobert Mustacchi sizeof(given_arange->ag_begin_address),
285*7fd79137SRobert Mustacchi upointer_size);
286*7fd79137SRobert Mustacchi arange_ptr += upointer_size;
287*7fd79137SRobert Mustacchi
288*7fd79137SRobert Mustacchi if (dbg->de_reloc_pair &&
289*7fd79137SRobert Mustacchi given_arange->ag_end_symbol_index != 0 &&
290*7fd79137SRobert Mustacchi given_arange->ag_length == 0) {
291*7fd79137SRobert Mustacchi /* symbolic reloc, need reloc for length What if we really
292*7fd79137SRobert Mustacchi know the length? If so, should use the other part of
293*7fd79137SRobert Mustacchi 'if'. */
294*7fd79137SRobert Mustacchi Dwarf_Unsigned val;
295*7fd79137SRobert Mustacchi
296*7fd79137SRobert Mustacchi res = dbg->de_reloc_pair(dbg, DEBUG_ARANGES, arange_ptr - arange, /* r_offset
297*7fd79137SRobert Mustacchi */
298*7fd79137SRobert Mustacchi given_arange->ag_symbol_index,
299*7fd79137SRobert Mustacchi given_arange->ag_end_symbol_index,
300*7fd79137SRobert Mustacchi dwarf_drt_first_of_length_pair,
301*7fd79137SRobert Mustacchi upointer_size);
302*7fd79137SRobert Mustacchi if (res != DW_DLV_OK) {
303*7fd79137SRobert Mustacchi {
304*7fd79137SRobert Mustacchi _dwarf_p_error(dbg, error, DW_DLE_ALLOC_FAIL);
305*7fd79137SRobert Mustacchi return (0);
306*7fd79137SRobert Mustacchi }
307*7fd79137SRobert Mustacchi }
308*7fd79137SRobert Mustacchi
309*7fd79137SRobert Mustacchi /* arrange pre-calc so assem text can do .word end - begin
310*7fd79137SRobert Mustacchi + val (gets val from stream) */
311*7fd79137SRobert Mustacchi val = given_arange->ag_end_symbol_offset -
312*7fd79137SRobert Mustacchi given_arange->ag_begin_address;
313*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
314*7fd79137SRobert Mustacchi (const void *) &val,
315*7fd79137SRobert Mustacchi sizeof(val), upointer_size);
316*7fd79137SRobert Mustacchi arange_ptr += upointer_size;
317*7fd79137SRobert Mustacchi
318*7fd79137SRobert Mustacchi } else {
319*7fd79137SRobert Mustacchi /* plain old length to copy, no relocation at all */
320*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
321*7fd79137SRobert Mustacchi (const void *) &given_arange->ag_length,
322*7fd79137SRobert Mustacchi sizeof(given_arange->ag_length),
323*7fd79137SRobert Mustacchi upointer_size);
324*7fd79137SRobert Mustacchi arange_ptr += upointer_size;
325*7fd79137SRobert Mustacchi }
326*7fd79137SRobert Mustacchi }
327*7fd79137SRobert Mustacchi
328*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
329*7fd79137SRobert Mustacchi (const void *) &big_zero,
330*7fd79137SRobert Mustacchi sizeof(big_zero), upointer_size);
331*7fd79137SRobert Mustacchi
332*7fd79137SRobert Mustacchi arange_ptr += upointer_size;
333*7fd79137SRobert Mustacchi WRITE_UNALIGNED(dbg, (void *) arange_ptr,
334*7fd79137SRobert Mustacchi (const void *) &big_zero,
335*7fd79137SRobert Mustacchi sizeof(big_zero), upointer_size);
336*7fd79137SRobert Mustacchi return (int) dbg->de_n_debug_sect;
337*7fd79137SRobert Mustacchi }
338