xref: /titanic_41/usr/src/tools/ctf/dwarf/common/pro_frame.c (revision 49d3bc91e27cd871b950d56c01398fa2f2e12ab4)
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 #include <limits.h>
43 #include "pro_incl.h"
44 #include "pro_frame.h"
45 
46 static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
47 				  Dwarf_P_Frame_Pgm inst);
48 
49 /*-------------------------------------------------------------------------
50 	This functions 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 --------------------------------------------------------------------------*/
58 Dwarf_Unsigned
59 dwarf_add_frame_cie(Dwarf_P_Debug dbg,
60 		    char *augmenter,
61 		    Dwarf_Small code_align,
62 		    Dwarf_Small data_align,
63 		    Dwarf_Small return_reg,
64 		    Dwarf_Ptr init_bytes,
65 		    Dwarf_Unsigned init_n_bytes, Dwarf_Error * error)
66 {
67     Dwarf_P_Cie curcie;
68 
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);
74 	}
75 	curcie = dbg->de_frame_cies;
76 	dbg->de_n_cie = 1;
77 	dbg->de_last_cie = curcie;
78     } else {
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);
84 	}
85 	curcie = curcie->cie_next;
86 	dbg->de_n_cie++;
87 	dbg->de_last_cie = curcie;
88     }
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;
97     return dbg->de_n_cie;
98 }
99 
100 
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 */
111     Dwarf_Unsigned
112 dwarf_add_frame_fde(Dwarf_P_Debug dbg,
113 		    Dwarf_P_Fde fde,
114 		    Dwarf_P_Die die,
115 		    Dwarf_Unsigned cie,
116 		    Dwarf_Unsigned virt_addr,
117 		    Dwarf_Unsigned code_len,
118 		    Dwarf_Unsigned symidx, Dwarf_Error * error)
119 {
120     return dwarf_add_frame_fde_b(dbg, fde, die, cie, virt_addr,
121 				 code_len, symidx, 0, 0, error);
122 }
123 
124 /*ARGSUSED10*/
125 Dwarf_Unsigned
126 dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
127 		      Dwarf_P_Fde fde,
128 		      Dwarf_P_Die die,
129 		      Dwarf_Unsigned cie,
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,
135 		      Dwarf_Error * error)
136 {
137     Dwarf_P_Fde curfde;
138 
139     fde->fde_die = die;
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;
148 
149     curfde = dbg->de_last_fde;
150     if (curfde == NULL) {
151 	dbg->de_frame_fdes = fde;
152 	dbg->de_last_fde = fde;
153 	dbg->de_n_fde = 1;
154     } else {
155 	curfde->fde_next = fde;
156 	dbg->de_last_fde = fde;
157 	dbg->de_n_fde++;
158     }
159     return dbg->de_n_fde;
160 }
161 
162 /*-------------------------------------------------------------------------
163 	This functions adds information to an fde. The fde is
164 	linked into the linked list of fde's maintained in the Dwarf_P_Debug
165 	structure.
166 	dbg: The debug descriptor.
167 	fde: The fde to be added.
168 	die: subprogram/function die corresponding to this fde
169 	cie: cie referred to by this fde, obtained from call to
170 	    add_frame_cie() routine.
171 	virt_addr: beginning address
172 	code_len: length of code reps by the fde
173 	symidx: The symbol id of the symbol wrt to which relocation needs
174 		to be performed for 'virt_addr'.
175 	offset_into_exception_tables: The start of exception tables for
176 		this function (indicated as an offset into the exception
177 		tables). A value of -1 indicates that there is no exception
178 		table entries associated with this function.
179 	exception_table_symbol: The symbol id of the section for exception
180 		tables wrt to which the offset_into_exception_tables will
181 		be relocated.
182 --------------------------------------------------------------------------*/
183 Dwarf_Unsigned
184 dwarf_add_frame_info(Dwarf_P_Debug dbg,
185 		     Dwarf_P_Fde fde,
186 		     Dwarf_P_Die die,
187 		     Dwarf_Unsigned cie,
188 		     Dwarf_Unsigned virt_addr,
189 		     Dwarf_Unsigned code_len,
190 		     Dwarf_Unsigned symidx,
191 		     Dwarf_Signed offset_into_exception_tables,
192 		     Dwarf_Unsigned exception_table_symbol,
193 		     Dwarf_Error * error)
194 {
195 
196     return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
197 				  code_len, symidx,
198 				  /* end_symbol */ 0,
199 				  /* offset_from_end */ 0,
200 				  offset_into_exception_tables,
201 				  exception_table_symbol, error);
202 
203 }
204 
205  /*ARGSUSED*/			/* pretend all args used */
206     Dwarf_Unsigned
207 dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
208 		       Dwarf_P_Fde fde,
209 		       Dwarf_P_Die die,
210 		       Dwarf_Unsigned cie,
211 		       Dwarf_Unsigned virt_addr,
212 		       Dwarf_Unsigned code_len,
213 		       Dwarf_Unsigned symidx,
214 		       Dwarf_Unsigned end_symidx,
215 		       Dwarf_Unsigned offset_from_end_symbol,
216 		       Dwarf_Signed offset_into_exception_tables,
217 		       Dwarf_Unsigned exception_table_symbol,
218 		       Dwarf_Error * error)
219 {
220     Dwarf_P_Fde curfde;
221 
222     fde->fde_die = die;
223     fde->fde_cie = (long) cie;
224     fde->fde_initloc = virt_addr;
225     fde->fde_r_symidx = symidx;
226     fde->fde_addr_range = code_len;
227     fde->fde_offset_into_exception_tables =
228 	offset_into_exception_tables;
229     fde->fde_exception_table_symbol = exception_table_symbol;
230     fde->fde_end_symbol_offset = offset_from_end_symbol;
231     fde->fde_end_symbol = end_symidx;
232 
233 
234     curfde = dbg->de_last_fde;
235     if (curfde == NULL) {
236 	dbg->de_frame_fdes = fde;
237 	dbg->de_last_fde = fde;
238 	dbg->de_n_fde = 1;
239     } else {
240 	curfde->fde_next = fde;
241 	dbg->de_last_fde = fde;
242 	dbg->de_n_fde++;
243     }
244     return dbg->de_n_fde;
245 }
246 
247 
248 /*-------------------------------------------------------------------
249 	Create a new fde
250 ---------------------------------------------------------------------*/
251 Dwarf_P_Fde
252 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
253 {
254     Dwarf_P_Fde fde;
255 
256     fde = (Dwarf_P_Fde)
257 	_dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
258     if (fde == NULL) {
259 	DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
260 			  (Dwarf_P_Fde) DW_DLV_BADADDR);
261     }
262     fde->fde_next = NULL;
263     fde->fde_inst = NULL;
264     fde->fde_n_inst = 0;
265     fde->fde_n_bytes = 0;
266     fde->fde_last_inst = NULL;
267     fde->fde_uwordb_size = dbg->de_offset_size;
268     return fde;
269 }
270 
271 /*------------------------------------------------------------------------
272 	Add cfe_offset instruction to fde
273 -------------------------------------------------------------------------*/
274 Dwarf_P_Fde
275 dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
276 		     Dwarf_Unsigned reg,
277 		     Dwarf_Signed offset, Dwarf_Error * error)
278 {
279     Dwarf_Ubyte opc, regno;
280     char *ptr;
281     Dwarf_P_Frame_Pgm curinst;
282     int nbytes;
283     int res;
284     char buff1[ENCODE_SPACE_NEEDED];
285 
286     curinst = (Dwarf_P_Frame_Pgm)
287 	_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s));
288     if (curinst == NULL) {
289 	DWARF_P_DBG_ERROR(NULL, DW_DLE_FPGM_ALLOC,
290 			  (Dwarf_P_Fde) DW_DLV_BADADDR);
291     }
292     opc = DW_CFA_offset;
293     regno = reg;
294     if (regno & 0xc0) {
295 	DWARF_P_DBG_ERROR(NULL, DW_DLE_REGNO_OVFL,
296 			  (Dwarf_P_Fde) DW_DLV_BADADDR);
297     }
298     opc = opc | regno;		/* lower 6 bits are register number */
299     curinst->dfp_opcode = opc;
300     res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
301 				      buff1, sizeof(buff1));
302     if (res != DW_DLV_OK) {
303 	_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
304 	return ((Dwarf_P_Fde) DW_DLV_BADADDR);
305     }
306     ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
307     if (ptr == NULL) {
308 	_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
309 	return ((Dwarf_P_Fde) DW_DLV_BADADDR);
310     }
311     memcpy(ptr, buff1, nbytes);
312 
313     curinst->dfp_args = ptr;
314     curinst->dfp_nbytes = nbytes;
315     curinst->dfp_next = NULL;
316 
317     _dwarf_pro_add_to_fde(fde, curinst);
318     return fde;
319 }
320 
321 /*
322     Generic routine to add opcode to fde instructions. val1 and
323     val2 are parameters whose interpretation depends on the 'op'.
324 
325     This does not work properly for  DW_DLC_SYMBOLIC_RELOCATIONS
326     for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
327     these ops normally are addresses or (DW_CFA_set_loc)
328     or code lengths (DW_DVA_advance_loc*) and such must be
329     represented with relocations and symbol indices for
330     DW_DLC_SYMBOLIC_RELOCATIONS.
331 
332 */
333 Dwarf_P_Fde
334 dwarf_add_fde_inst(Dwarf_P_Fde fde,
335 		   Dwarf_Small op,
336 		   Dwarf_Unsigned val1,
337 		   Dwarf_Unsigned val2, Dwarf_Error * error)
338 {
339     Dwarf_P_Frame_Pgm curinst;
340     int nbytes, nbytes1, nbytes2;
341     Dwarf_Ubyte db;
342     Dwarf_Half dh;
343     Dwarf_Word dw;
344     Dwarf_Unsigned du;
345     char *ptr;
346     int res;
347     char buff1[ENCODE_SPACE_NEEDED];
348     char buff2[ENCODE_SPACE_NEEDED];
349 
350 
351     nbytes = 0;
352     ptr = NULL;
353     curinst = (Dwarf_P_Frame_Pgm)
354 	_dwarf_p_get_alloc(NULL, sizeof(struct Dwarf_P_Frame_Pgm_s));
355     if (curinst == NULL) {
356 	_dwarf_p_error(NULL, error, DW_DLE_FPGM_ALLOC);
357 	return ((Dwarf_P_Fde) DW_DLV_BADADDR);
358     }
359 
360     switch (op) {
361 
362     case DW_CFA_advance_loc:
363 	if (val1 <= 0x3f) {
364 	    db = val1;
365 	    op |= db;
366 	}
367 	/* test not portable FIX */
368 	else if (val1 <= UCHAR_MAX) {
369 	    op = DW_CFA_advance_loc1;
370 	    db = val1;
371 	    ptr = (char *) _dwarf_p_get_alloc(NULL, 1);
372 	    if (ptr == NULL) {
373 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
374 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
375 	    }
376 	    memcpy((void *) ptr, (const void *) &db, 1);
377 	    nbytes = 1;
378 	}
379 	/* test not portable FIX */
380 	else if (val1 <= USHRT_MAX) {
381 	    op = DW_CFA_advance_loc2;
382 	    dh = val1;
383 	    ptr = (char *) _dwarf_p_get_alloc(NULL, 2);
384 	    if (ptr == NULL) {
385 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
386 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
387 	    }
388 	    memcpy((void *) ptr, (const void *) &dh, 2);
389 	    nbytes = 2;
390 	}
391 	/* test not portable FIX */
392 	else if (val1 <= ULONG_MAX) {
393 	    op = DW_CFA_advance_loc4;
394 	    dw = (Dwarf_Word) val1;
395 	    ptr = (char *) _dwarf_p_get_alloc(NULL, 4);
396 	    if (ptr == NULL) {
397 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
398 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
399 	    }
400 	    memcpy((void *) ptr, (const void *) &dw, 4);
401 	    nbytes = 4;
402 	} else {
403 	    op = DW_CFA_MIPS_advance_loc8;
404 	    du = val1;
405 	    ptr =
406 		(char *) _dwarf_p_get_alloc(NULL,
407 					    sizeof(Dwarf_Unsigned));
408 	    if (ptr == NULL) {
409 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
410 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
411 	    }
412 	    memcpy((void *) ptr, (const void *) &du, 8);
413 	    nbytes = 8;
414 	}
415 	break;
416 
417     case DW_CFA_offset:
418 	if (val1 <= MAX_6_BIT_VALUE) {
419 	    db = val1;
420 	    op |= db;
421 	    res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
422 					      buff1, sizeof(buff1));
423 	    if (res != DW_DLV_OK) {
424 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
425 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
426 	    }
427 	    ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
428 	    if (ptr == NULL) {
429 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
430 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
431 	    }
432 	    memcpy(ptr, buff1, nbytes);
433 
434 	} else {
435 	    op = DW_CFA_offset_extended;
436 
437 	    res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
438 					      buff1, sizeof(buff1));
439 	    if (res != DW_DLV_OK) {
440 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
441 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
442 	    }
443 	    res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
444 					      buff2, sizeof(buff2));
445 	    if (res != DW_DLV_OK) {
446 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
447 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
448 	    }
449 	    ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2);
450 	    if (ptr == NULL) {
451 		_dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
452 		return ((Dwarf_P_Fde) DW_DLV_BADADDR);
453 	    }
454 	    memcpy(ptr, buff1, nbytes1);
455 	    memcpy(ptr + nbytes1, buff2, nbytes2);
456 	    nbytes = nbytes1 + nbytes2;
457 	}
458 	break;
459 
460     case DW_CFA_undefined:
461     case DW_CFA_same_value:
462 	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
463 					  buff1, sizeof(buff1));
464 	if (res != DW_DLV_OK) {
465 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
466 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
467 	}
468 	ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
469 	if (ptr == NULL) {
470 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
471 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
472 	}
473 	memcpy(ptr, buff1, nbytes);
474 	break;
475 
476     case DW_CFA_register:
477     case DW_CFA_def_cfa:
478 	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
479 					  buff1, sizeof(buff1));
480 	if (res != DW_DLV_OK) {
481 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
482 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
483 	}
484 
485 	res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
486 					  buff2, sizeof(buff2));
487 	if (res != DW_DLV_OK) {
488 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
489 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
490 	}
491 
492 	ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes1 + nbytes2);
493 	if (ptr == NULL) {
494 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
495 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
496 	}
497 	memcpy(ptr, buff1, nbytes1);
498 	memcpy(ptr + nbytes1, buff2, nbytes2);
499 	nbytes = nbytes1 + nbytes2;
500 	break;
501 
502     case DW_CFA_def_cfa_register:
503     case DW_CFA_def_cfa_offset:
504 	res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
505 					  buff1, sizeof(buff1));
506 	if (res != DW_DLV_OK) {
507 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
508 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
509 	}
510 	ptr = (char *) _dwarf_p_get_alloc(NULL, nbytes);
511 	if (ptr == NULL) {
512 	    _dwarf_p_error(NULL, error, DW_DLE_STRING_ALLOC);
513 	    return ((Dwarf_P_Fde) DW_DLV_BADADDR);
514 	}
515 	memcpy(ptr, buff1, nbytes);
516 	break;
517 
518     default:
519 	break;
520     }
521 
522     curinst->dfp_opcode = op;
523     curinst->dfp_args = ptr;
524     curinst->dfp_nbytes = nbytes;
525     curinst->dfp_next = NULL;
526 
527     _dwarf_pro_add_to_fde(fde, curinst);
528     return fde;
529 }
530 
531 
532 /*------------------------------------------------------------------------
533 	instructions are added to fde in the form of a linked
534 	list. This function manages the linked list
535 -------------------------------------------------------------------------*/
536 void
537 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
538 {
539     if (fde->fde_last_inst) {
540 	fde->fde_last_inst->dfp_next = curinst;
541 	fde->fde_last_inst = curinst;
542 	fde->fde_n_inst++;
543 	fde->fde_n_bytes +=
544 	    (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
545     } else {
546 	fde->fde_last_inst = curinst;
547 	fde->fde_inst = curinst;
548 	fde->fde_n_inst = 1;
549 	fde->fde_n_bytes =
550 	    (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
551     }
552 }
553