3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
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.
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.
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.
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,
25 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
26 Mountain View, CA 94043, or:
30 For further information regarding this notice, see:
32 http://oss.sgi.com/projects/GenInfo/NoticeExplan
39 #include "libdwarfdefs.h"
44 #include "pro_frame.h"
46 static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde
,
47 Dwarf_P_Frame_Pgm inst
);
49 /*-------------------------------------------------------------------------
50 This function adds a cie struct to the debug pointer. Its in the
51 form of a linked list.
52 augmenter: string reps augmentation (implementation defined)
53 code_align: alignment of code
54 data_align: alignment of data
55 init_bytes: byts having initial instructions
56 init_n_bytes: number of bytes of initial instructions
57 --------------------------------------------------------------------------*/
59 dwarf_add_frame_cie(Dwarf_P_Debug dbg
,
61 Dwarf_Small code_align
,
62 Dwarf_Small data_align
,
63 Dwarf_Small return_reg
,
65 Dwarf_Unsigned init_n_bytes
, Dwarf_Error
* error
)
69 if (dbg
->de_frame_cies
== NULL
) {
70 dbg
->de_frame_cies
= (Dwarf_P_Cie
)
71 _dwarf_p_get_alloc(dbg
, sizeof(struct Dwarf_P_Cie_s
));
72 if (dbg
->de_frame_cies
== NULL
) {
73 DWARF_P_DBG_ERROR(dbg
, DW_DLE_CIE_ALLOC
, DW_DLV_NOCOUNT
);
75 curcie
= dbg
->de_frame_cies
;
77 dbg
->de_last_cie
= curcie
;
79 curcie
= dbg
->de_last_cie
;
80 curcie
->cie_next
= (Dwarf_P_Cie
)
81 _dwarf_p_get_alloc(dbg
, sizeof(struct Dwarf_P_Cie_s
));
82 if (curcie
->cie_next
== NULL
) {
83 DWARF_P_DBG_ERROR(dbg
, DW_DLE_CIE_ALLOC
, DW_DLV_NOCOUNT
);
85 curcie
= curcie
->cie_next
;
87 dbg
->de_last_cie
= curcie
;
89 curcie
->cie_version
= DW_CIE_VERSION
;
90 curcie
->cie_aug
= augmenter
;
91 curcie
->cie_code_align
= code_align
;
92 curcie
->cie_data_align
= data_align
;
93 curcie
->cie_ret_reg
= return_reg
;
94 curcie
->cie_inst
= (char *) init_bytes
;
95 curcie
->cie_inst_bytes
= (long) init_n_bytes
;
96 curcie
->cie_next
= NULL
;
101 /*-------------------------------------------------------------------------
102 This functions adds a fde struct to the debug pointer. Its in the
103 form of a linked list.
104 die: subprogram/function die corresponding to this fde
105 cie: cie referred to by this fde, obtained from call to
106 add_frame_cie() routine.
107 virt_addr: beginning address
108 code_len: length of code reps by the fde
109 --------------------------------------------------------------------------*/
110 /*ARGSUSED*/ /* pretend all args used */
112 dwarf_add_frame_fde(Dwarf_P_Debug dbg
,
116 Dwarf_Unsigned virt_addr
,
117 Dwarf_Unsigned code_len
,
118 Dwarf_Unsigned symidx
, Dwarf_Error
* error
)
120 return dwarf_add_frame_fde_b(dbg
, fde
, die
, cie
, virt_addr
,
121 code_len
, symidx
, 0, 0, error
);
126 dwarf_add_frame_fde_b(Dwarf_P_Debug dbg
,
130 Dwarf_Unsigned virt_addr
,
131 Dwarf_Unsigned code_len
,
132 Dwarf_Unsigned symidx
,
133 Dwarf_Unsigned symidx_of_end
,
134 Dwarf_Addr offset_from_end_sym
,
140 fde
->fde_cie
= (long) cie
;
141 fde
->fde_initloc
= virt_addr
;
142 fde
->fde_r_symidx
= symidx
;
143 fde
->fde_addr_range
= code_len
;
144 fde
->fde_offset_into_exception_tables
= DW_DLX_NO_EH_OFFSET
;
145 fde
->fde_exception_table_symbol
= 0;
146 fde
->fde_end_symbol_offset
= offset_from_end_sym
;
147 fde
->fde_end_symbol
= symidx_of_end
;
150 curfde
= dbg
->de_last_fde
;
151 if (curfde
== NULL
) {
152 dbg
->de_frame_fdes
= fde
;
153 dbg
->de_last_fde
= fde
;
156 curfde
->fde_next
= fde
;
157 dbg
->de_last_fde
= fde
;
160 return dbg
->de_n_fde
;
163 /*-------------------------------------------------------------------------
164 This functions adds information to an fde. The fde is
165 linked into the linked list of fde's maintained in the Dwarf_P_Debug
167 dbg: The debug descriptor.
168 fde: The fde to be added.
169 die: subprogram/function die corresponding to this fde
170 cie: cie referred to by this fde, obtained from call to
171 add_frame_cie() routine.
172 virt_addr: beginning address
173 code_len: length of code reps by the fde
174 symidx: The symbol id of the symbol wrt to which relocation needs
175 to be performed for 'virt_addr'.
176 offset_into_exception_tables: The start of exception tables for
177 this function (indicated as an offset into the exception
178 tables). A value of -1 indicates that there is no exception
179 table entries associated with this function.
180 exception_table_symbol: The symbol id of the section for exception
181 tables wrt to which the offset_into_exception_tables will
183 --------------------------------------------------------------------------*/
185 dwarf_add_frame_info(Dwarf_P_Debug dbg
,
189 Dwarf_Unsigned virt_addr
,
190 Dwarf_Unsigned code_len
,
191 Dwarf_Unsigned symidx
,
192 Dwarf_Signed offset_into_exception_tables
,
193 Dwarf_Unsigned exception_table_symbol
,
197 return dwarf_add_frame_info_b(dbg
, fde
, die
, cie
, virt_addr
,
200 /* offset_from_end */ 0,
201 offset_into_exception_tables
,
202 exception_table_symbol
, error
);
206 /*ARGSUSED*/ /* pretend all args used */
208 dwarf_add_frame_info_b(Dwarf_P_Debug dbg
,
212 Dwarf_Unsigned virt_addr
,
213 Dwarf_Unsigned code_len
,
214 Dwarf_Unsigned symidx
,
215 Dwarf_Unsigned end_symidx
,
216 Dwarf_Unsigned offset_from_end_symbol
,
217 Dwarf_Signed offset_into_exception_tables
,
218 Dwarf_Unsigned exception_table_symbol
,
224 fde
->fde_cie
= (long) cie
;
225 fde
->fde_initloc
= virt_addr
;
226 fde
->fde_r_symidx
= symidx
;
227 fde
->fde_addr_range
= code_len
;
228 fde
->fde_offset_into_exception_tables
=
229 offset_into_exception_tables
;
230 fde
->fde_exception_table_symbol
= exception_table_symbol
;
231 fde
->fde_end_symbol_offset
= offset_from_end_symbol
;
232 fde
->fde_end_symbol
= end_symidx
;
235 curfde
= dbg
->de_last_fde
;
236 if (curfde
== NULL
) {
237 dbg
->de_frame_fdes
= fde
;
238 dbg
->de_last_fde
= fde
;
241 curfde
->fde_next
= fde
;
242 dbg
->de_last_fde
= fde
;
245 return dbg
->de_n_fde
;
248 /* This is an alternate to inserting frame instructions
249 one instruction at a time. But use either this
250 or instruction level, not both in one fde. */
252 dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg
,
253 Dwarf_P_Fde fde
,Dwarf_Unsigned len
, Dwarf_Ptr ibytes
,
259 if(fde
->fde_block
|| fde
->fde_inst
) {
260 DWARF_P_DBG_ERROR(dbg
, DW_DLE_DUPLICATE_INST_BLOCK
,
261 (int)DW_DLV_BADADDR
);
263 fde
->fde_block
= (Dwarf_Ptr
)_dwarf_p_get_alloc(dbg
, len
);
264 memcpy(fde
->fde_block
,ibytes
,len
);
265 fde
->fde_inst_block_size
= len
;
266 fde
->fde_n_bytes
+= len
;
272 /*-------------------------------------------------------------------
274 ---------------------------------------------------------------------*/
276 dwarf_new_fde(Dwarf_P_Debug dbg
, Dwarf_Error
* error
)
281 _dwarf_p_get_alloc(dbg
, sizeof(struct Dwarf_P_Fde_s
));
283 DWARF_P_DBG_ERROR(dbg
, DW_DLE_FDE_ALLOC
,
284 (Dwarf_P_Fde
) DW_DLV_BADADDR
);
287 fde
->fde_uwordb_size
= dbg
->de_offset_size
;
293 /*------------------------------------------------------------------------
294 Add a cfe_offset instruction to the fde passed in.
295 -------------------------------------------------------------------------*/
297 dwarf_fde_cfa_offset(Dwarf_P_Fde fde
,
299 Dwarf_Signed offset
, Dwarf_Error
* error
)
301 Dwarf_Ubyte opc
, regno
;
303 Dwarf_P_Frame_Pgm curinst
;
306 char buff1
[ENCODE_SPACE_NEEDED
];
307 Dwarf_P_Debug dbg
= fde
->fde_dbg
;
309 curinst
= (Dwarf_P_Frame_Pgm
)
310 _dwarf_p_get_alloc(dbg
, sizeof(struct Dwarf_P_Frame_Pgm_s
));
311 if (curinst
== NULL
) {
312 DWARF_P_DBG_ERROR(dbg
, DW_DLE_FPGM_ALLOC
,
313 (Dwarf_P_Fde
) DW_DLV_BADADDR
);
318 DWARF_P_DBG_ERROR(dbg
, DW_DLE_REGNO_OVFL
,
319 (Dwarf_P_Fde
) DW_DLV_BADADDR
);
321 opc
= opc
| regno
; /* lower 6 bits are register number */
322 curinst
->dfp_opcode
= opc
;
323 res
= _dwarf_pro_encode_leb128_nm(offset
, &nbytes
,
324 buff1
, sizeof(buff1
));
325 if (res
!= DW_DLV_OK
) {
326 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
327 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
329 ptr
= (char *) _dwarf_p_get_alloc(dbg
, nbytes
);
331 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
332 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
334 memcpy(ptr
, buff1
, nbytes
);
336 curinst
->dfp_args
= ptr
;
337 curinst
->dfp_nbytes
= nbytes
;
338 curinst
->dfp_next
= NULL
;
340 _dwarf_pro_add_to_fde(fde
, curinst
);
345 Generic routine to add opcode to fde instructions. val1 and
346 val2 are parameters whose interpretation depends on the 'op'.
348 This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS
349 for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
350 these ops normally are addresses or (DW_CFA_set_loc)
351 or code lengths (DW_DVA_advance_loc*) and such must be
352 represented with relocations and symbol indices for
353 DW_DLC_SYMBOLIC_RELOCATIONS.
355 This does not treat all DW_CFA instructions yet.
357 For certain operations a val? value must be
358 signed (though passed in as unsigned here).
360 Currently this does not check that the frame
361 version is 3(for dwarf3) or 4 (for dwarf4)
362 when applying operations that are only valid for
367 dwarf_add_fde_inst(Dwarf_P_Fde fde
,
370 Dwarf_Unsigned val2
, Dwarf_Error
* error
)
372 Dwarf_P_Frame_Pgm curinst
;
373 int nbytes
, nbytes1
, nbytes2
;
380 char buff1
[ENCODE_SPACE_NEEDED
];
381 char buff2
[ENCODE_SPACE_NEEDED
];
382 Dwarf_P_Debug dbg
= fde
->fde_dbg
;
383 /* This is a hack telling the code when to transform
384 a value to a signed leb number. */
385 int signed_second
= 0;
386 int signed_first
= 0;
391 curinst
= (Dwarf_P_Frame_Pgm
)
392 _dwarf_p_get_alloc(dbg
, sizeof(struct Dwarf_P_Frame_Pgm_s
));
393 if (curinst
== NULL
) {
394 _dwarf_p_error(dbg
, error
, DW_DLE_FPGM_ALLOC
);
395 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
400 case DW_CFA_advance_loc
:
405 /* test not portable FIX */
406 else if (val1
<= UCHAR_MAX
) {
407 op
= DW_CFA_advance_loc1
;
409 ptr
= (char *) _dwarf_p_get_alloc(dbg
, 1);
411 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
412 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
414 memcpy((void *) ptr
, (const void *) &db
, 1);
417 /* test not portable FIX */
418 else if (val1
<= USHRT_MAX
) {
419 op
= DW_CFA_advance_loc2
;
421 ptr
= (char *) _dwarf_p_get_alloc(dbg
, 2);
423 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
424 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
426 memcpy((void *) ptr
, (const void *) &dh
, 2);
429 /* test not portable FIX */
430 else if (val1
<= ULONG_MAX
) {
431 op
= DW_CFA_advance_loc4
;
432 dw
= (Dwarf_Word
) val1
;
433 ptr
= (char *) _dwarf_p_get_alloc(dbg
, 4);
435 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
436 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
438 memcpy((void *) ptr
, (const void *) &dw
, 4);
441 op
= DW_CFA_MIPS_advance_loc8
;
444 (char *) _dwarf_p_get_alloc(dbg
,
445 sizeof(Dwarf_Unsigned
));
447 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
448 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
450 memcpy((void *) ptr
, (const void *) &du
, 8);
456 if (val1
<= MAX_6_BIT_VALUE
) {
459 res
= _dwarf_pro_encode_leb128_nm(val2
, &nbytes
,
460 buff1
, sizeof(buff1
));
461 if (res
!= DW_DLV_OK
) {
462 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
463 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
465 ptr
= (char *) _dwarf_p_get_alloc(dbg
, nbytes
);
467 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
468 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
470 memcpy(ptr
, buff1
, nbytes
);
473 op
= DW_CFA_offset_extended
;
477 case DW_CFA_offset_extended_sf
: /* DWARF3 */
480 case DW_CFA_offset_extended
:
483 case DW_CFA_undefined
:
484 case DW_CFA_same_value
:
487 case DW_CFA_val_offset
:
489 case DW_CFA_val_offset_sf
:
492 case DW_CFA_def_cfa_sf
:
495 case DW_CFA_register
:
498 res
= _dwarf_pro_encode_leb128_nm(val1
, &nbytes1
,
499 buff1
, sizeof(buff1
));
500 if (res
!= DW_DLV_OK
) {
501 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
502 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
504 if (!signed_second
) {
505 res
= _dwarf_pro_encode_leb128_nm(val2
, &nbytes2
,
506 buff2
, sizeof(buff2
));
508 Dwarf_Signed val2s
= val2
;
509 res
= _dwarf_pro_encode_signed_leb128_nm(val2s
, &nbytes2
,
510 buff2
, sizeof(buff2
));
513 res
= _dwarf_pro_encode_leb128_nm(val2
, &nbytes2
,
514 buff2
, sizeof(buff2
));
515 if (res
!= DW_DLV_OK
) {
516 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
517 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
520 ptr
= (char *) _dwarf_p_get_alloc(dbg
, nbytes1
+ nbytes2
);
522 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
523 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
525 memcpy(ptr
, buff1
, nbytes1
);
526 memcpy(ptr
+ nbytes1
, buff2
, nbytes2
);
527 nbytes
= nbytes1
+ nbytes2
;
530 case DW_CFA_def_cfa_offset_sf
: /* DWARF3 */
533 case DW_CFA_def_cfa_register
:
534 case DW_CFA_def_cfa_offset
:
537 res
= _dwarf_pro_encode_leb128_nm(val1
, &nbytes
,
538 buff1
, sizeof(buff1
));
540 Dwarf_Signed val1s
= val1
;
541 res
= _dwarf_pro_encode_signed_leb128_nm(val1s
, &nbytes
,
542 buff1
, sizeof(buff1
));
544 if (res
!= DW_DLV_OK
) {
545 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
546 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
548 ptr
= (char *) _dwarf_p_get_alloc(dbg
, nbytes
);
550 _dwarf_p_error(dbg
, error
, DW_DLE_STRING_ALLOC
);
551 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
553 memcpy(ptr
, buff1
, nbytes
);
555 case DW_CFA_def_cfa_expression
: /* DWARF3 */
556 /* FIXME: argument is dwarf expr, not handled yet. */
557 case DW_CFA_expression
: /* DWARF3 */
558 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
559 FIXME: not handled yet. */
560 case DW_CFA_val_expression
: /* DWARF3f */
561 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
562 FIXME: not handled yet. */
564 _dwarf_p_error(dbg
, error
, DW_DLE_DEBUGFRAME_ERROR
);
565 return ((Dwarf_P_Fde
) DW_DLV_BADADDR
);
568 curinst
->dfp_opcode
= op
;
569 curinst
->dfp_args
= ptr
;
570 curinst
->dfp_nbytes
= nbytes
;
571 curinst
->dfp_next
= NULL
;
573 _dwarf_pro_add_to_fde(fde
, curinst
);
578 /*------------------------------------------------------------------------
579 Instructions are added to an fde in the form of a linked
580 list. This function manages the linked list.
581 -------------------------------------------------------------------------*/
583 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde
, Dwarf_P_Frame_Pgm curinst
)
585 if (fde
->fde_last_inst
) {
586 fde
->fde_last_inst
->dfp_next
= curinst
;
587 fde
->fde_last_inst
= curinst
;
590 (long) (curinst
->dfp_nbytes
+ sizeof(Dwarf_Ubyte
));
592 fde
->fde_last_inst
= curinst
;
593 fde
->fde_inst
= curinst
;
596 (long) (curinst
->dfp_nbytes
+ sizeof(Dwarf_Ubyte
));