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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
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 <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 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 --------------------------------------------------------------------------*/
58 Dwarf_Unsigned
dwarf_add_frame_cie(Dwarf_P_Debug dbg,char * augmenter,Dwarf_Small code_align,Dwarf_Small data_align,Dwarf_Small return_reg,Dwarf_Ptr init_bytes,Dwarf_Unsigned init_n_bytes,Dwarf_Error * error)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
dwarf_add_frame_fde(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Error * error)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
dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Unsigned symidx_of_end,Dwarf_Addr offset_from_end_sym,Dwarf_Error * error)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 fde->fde_dbg = dbg;
149
150 curfde = dbg->de_last_fde;
151 if (curfde == NULL) {
152 dbg->de_frame_fdes = fde;
153 dbg->de_last_fde = fde;
154 dbg->de_n_fde = 1;
155 } else {
156 curfde->fde_next = fde;
157 dbg->de_last_fde = fde;
158 dbg->de_n_fde++;
159 }
160 return dbg->de_n_fde;
161 }
162
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
166 structure.
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
182 be relocated.
183 --------------------------------------------------------------------------*/
184 Dwarf_Unsigned
dwarf_add_frame_info(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Signed offset_into_exception_tables,Dwarf_Unsigned exception_table_symbol,Dwarf_Error * error)185 dwarf_add_frame_info(Dwarf_P_Debug dbg,
186 Dwarf_P_Fde fde,
187 Dwarf_P_Die die,
188 Dwarf_Unsigned cie,
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,
194 Dwarf_Error * error)
195 {
196
197 return dwarf_add_frame_info_b(dbg, fde, die, cie, virt_addr,
198 code_len, symidx,
199 /* end_symbol */ 0,
200 /* offset_from_end */ 0,
201 offset_into_exception_tables,
202 exception_table_symbol, error);
203
204 }
205
206 /*ARGSUSED*/ /* pretend all args used */
207 Dwarf_Unsigned
dwarf_add_frame_info_b(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_P_Die die,Dwarf_Unsigned cie,Dwarf_Unsigned virt_addr,Dwarf_Unsigned code_len,Dwarf_Unsigned symidx,Dwarf_Unsigned end_symidx,Dwarf_Unsigned offset_from_end_symbol,Dwarf_Signed offset_into_exception_tables,Dwarf_Unsigned exception_table_symbol,Dwarf_Error * error)208 dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
209 Dwarf_P_Fde fde,
210 Dwarf_P_Die die,
211 Dwarf_Unsigned cie,
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,
219 Dwarf_Error * error)
220 {
221 Dwarf_P_Fde curfde;
222
223 fde->fde_die = die;
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;
233 fde->fde_dbg = dbg;
234
235 curfde = dbg->de_last_fde;
236 if (curfde == NULL) {
237 dbg->de_frame_fdes = fde;
238 dbg->de_last_fde = fde;
239 dbg->de_n_fde = 1;
240 } else {
241 curfde->fde_next = fde;
242 dbg->de_last_fde = fde;
243 dbg->de_n_fde++;
244 }
245 return dbg->de_n_fde;
246 }
247
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. */
251 int
dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_Unsigned len,Dwarf_Ptr ibytes,Dwarf_Error * error)252 dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
253 Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
254 Dwarf_Error *error)
255 {
256 if( len == 0) {
257 return DW_DLV_OK;
258 }
259 if(fde->fde_block || fde->fde_inst) {
260 DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
261 (int)DW_DLV_BADADDR);
262 }
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;
267 return DW_DLV_OK;
268 }
269
270
271
272 /*-------------------------------------------------------------------
273 Create a new fde.
274 ---------------------------------------------------------------------*/
275 Dwarf_P_Fde
dwarf_new_fde(Dwarf_P_Debug dbg,Dwarf_Error * error)276 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
277 {
278 Dwarf_P_Fde fde;
279
280 fde = (Dwarf_P_Fde)
281 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
282 if (fde == NULL) {
283 DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC,
284 (Dwarf_P_Fde) DW_DLV_BADADDR);
285 }
286
287 fde->fde_uwordb_size = dbg->de_offset_size;
288
289 return fde;
290 }
291
292
293 /*------------------------------------------------------------------------
294 Add a cfe_offset instruction to the fde passed in.
295 -------------------------------------------------------------------------*/
296 Dwarf_P_Fde
dwarf_fde_cfa_offset(Dwarf_P_Fde fde,Dwarf_Unsigned reg,Dwarf_Signed offset,Dwarf_Error * error)297 dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
298 Dwarf_Unsigned reg,
299 Dwarf_Signed offset, Dwarf_Error * error)
300 {
301 Dwarf_Ubyte opc, regno;
302 char *ptr;
303 Dwarf_P_Frame_Pgm curinst;
304 int nbytes;
305 int res;
306 char buff1[ENCODE_SPACE_NEEDED];
307 Dwarf_P_Debug dbg = fde->fde_dbg;
308
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);
314 }
315 opc = DW_CFA_offset;
316 regno = reg;
317 if (regno & 0xc0) {
318 DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,
319 (Dwarf_P_Fde) DW_DLV_BADADDR);
320 }
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);
328 }
329 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
330 if (ptr == NULL) {
331 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
332 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
333 }
334 memcpy(ptr, buff1, nbytes);
335
336 curinst->dfp_args = ptr;
337 curinst->dfp_nbytes = nbytes;
338 curinst->dfp_next = NULL;
339
340 _dwarf_pro_add_to_fde(fde, curinst);
341 return fde;
342 }
343
344 /*
345 Generic routine to add opcode to fde instructions. val1 and
346 val2 are parameters whose interpretation depends on the 'op'.
347
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.
354
355 This does not treat all DW_CFA instructions yet.
356
357 For certain operations a val? value must be
358 signed (though passed in as unsigned here).
359
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
363 dwarf3 or dwarf4.
364
365 */
366 Dwarf_P_Fde
dwarf_add_fde_inst(Dwarf_P_Fde fde,Dwarf_Small op,Dwarf_Unsigned val1,Dwarf_Unsigned val2,Dwarf_Error * error)367 dwarf_add_fde_inst(Dwarf_P_Fde fde,
368 Dwarf_Small op,
369 Dwarf_Unsigned val1,
370 Dwarf_Unsigned val2, Dwarf_Error * error)
371 {
372 Dwarf_P_Frame_Pgm curinst;
373 int nbytes, nbytes1, nbytes2;
374 Dwarf_Ubyte db;
375 Dwarf_Half dh;
376 Dwarf_Word dw;
377 Dwarf_Unsigned du;
378 char *ptr;
379 int res;
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;
387
388
389 nbytes = 0;
390 ptr = NULL;
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);
396 }
397
398 switch (op) {
399
400 case DW_CFA_advance_loc:
401 if (val1 <= 0x3f) {
402 db = val1;
403 op |= db;
404 }
405 /* test not portable FIX */
406 else if (val1 <= UCHAR_MAX) {
407 op = DW_CFA_advance_loc1;
408 db = val1;
409 ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
410 if (ptr == NULL) {
411 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
412 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
413 }
414 memcpy((void *) ptr, (const void *) &db, 1);
415 nbytes = 1;
416 }
417 /* test not portable FIX */
418 else if (val1 <= USHRT_MAX) {
419 op = DW_CFA_advance_loc2;
420 dh = val1;
421 ptr = (char *) _dwarf_p_get_alloc(dbg, 2);
422 if (ptr == NULL) {
423 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
424 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
425 }
426 memcpy((void *) ptr, (const void *) &dh, 2);
427 nbytes = 2;
428 }
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);
434 if (ptr == NULL) {
435 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
436 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
437 }
438 memcpy((void *) ptr, (const void *) &dw, 4);
439 nbytes = 4;
440 } else {
441 op = DW_CFA_MIPS_advance_loc8;
442 du = val1;
443 ptr =
444 (char *) _dwarf_p_get_alloc(dbg,
445 sizeof(Dwarf_Unsigned));
446 if (ptr == NULL) {
447 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
448 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
449 }
450 memcpy((void *) ptr, (const void *) &du, 8);
451 nbytes = 8;
452 }
453 break;
454
455 case DW_CFA_offset:
456 if (val1 <= MAX_6_BIT_VALUE) {
457 db = val1;
458 op |= db;
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);
464 }
465 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
466 if (ptr == NULL) {
467 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
468 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
469 }
470 memcpy(ptr, buff1, nbytes);
471
472 } else {
473 op = DW_CFA_offset_extended;
474 goto two_leb;
475 }
476 break;
477 case DW_CFA_offset_extended_sf: /* DWARF3 */
478 signed_second = 1;
479 goto two_leb;
480 case DW_CFA_offset_extended:
481 goto two_leb;
482
483 case DW_CFA_undefined:
484 case DW_CFA_same_value:
485 goto one_leb;
486
487 case DW_CFA_val_offset:
488 goto two_leb;
489 case DW_CFA_val_offset_sf:
490 signed_second = 1;
491 goto two_leb;
492 case DW_CFA_def_cfa_sf:
493 signed_second = 1;
494 goto two_leb;
495 case DW_CFA_register:
496 case DW_CFA_def_cfa:
497 two_leb:
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);
503 }
504 if (!signed_second) {
505 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
506 buff2, sizeof(buff2));
507 } else {
508 Dwarf_Signed val2s = val2;
509 res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
510 buff2, sizeof(buff2));
511 }
512
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);
518 }
519
520 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
521 if (ptr == NULL) {
522 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
523 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
524 }
525 memcpy(ptr, buff1, nbytes1);
526 memcpy(ptr + nbytes1, buff2, nbytes2);
527 nbytes = nbytes1 + nbytes2;
528 break;
529
530 case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
531 signed_first = 1;
532 goto one_leb;
533 case DW_CFA_def_cfa_register:
534 case DW_CFA_def_cfa_offset:
535 one_leb:
536 if(!signed_first) {
537 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
538 buff1, sizeof(buff1));
539 } else {
540 Dwarf_Signed val1s = val1;
541 res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
542 buff1, sizeof(buff1));
543 }
544 if (res != DW_DLV_OK) {
545 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
546 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
547 }
548 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
549 if (ptr == NULL) {
550 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
551 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
552 }
553 memcpy(ptr, buff1, nbytes);
554 break;
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. */
563 default:
564 _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
565 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
566 }
567
568 curinst->dfp_opcode = op;
569 curinst->dfp_args = ptr;
570 curinst->dfp_nbytes = nbytes;
571 curinst->dfp_next = NULL;
572
573 _dwarf_pro_add_to_fde(fde, curinst);
574 return fde;
575 }
576
577
578 /*------------------------------------------------------------------------
579 Instructions are added to an fde in the form of a linked
580 list. This function manages the linked list.
581 -------------------------------------------------------------------------*/
582 void
_dwarf_pro_add_to_fde(Dwarf_P_Fde fde,Dwarf_P_Frame_Pgm curinst)583 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
584 {
585 if (fde->fde_last_inst) {
586 fde->fde_last_inst->dfp_next = curinst;
587 fde->fde_last_inst = curinst;
588 fde->fde_n_inst++;
589 fde->fde_n_bytes +=
590 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
591 } else {
592 fde->fde_last_inst = curinst;
593 fde->fde_inst = curinst;
594 fde->fde_n_inst = 1;
595 fde->fde_n_bytes =
596 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
597 }
598 }
599