1 /*
2
3 Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright 2011-2017 David Anderson. All Rights Reserved.
5 Portions Copyright 2012 SN Systems Ltd. All rights reserved.
6
7 This program is free software; you can redistribute it
8 and/or modify it under the terms of version 2.1 of the
9 GNU Lesser General Public License as published by the Free
10 Software Foundation.
11
12 This program is distributed in the hope that it would be
13 useful, but WITHOUT ANY WARRANTY; without even the implied
14 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE.
16
17 Further, this software is distributed without any warranty
18 that it is free of the rightful claim of any third person
19 regarding infringement or the like. Any license provided
20 herein, whether implied or otherwise, applies only to this
21 software file. Patent licenses, if any, provided herein
22 do not apply to combinations of this program with other
23 software, or any other product whatsoever.
24
25 You should have received a copy of the GNU Lesser General
26 Public License along with this program; if not, write the
27 Free Software Foundation, Inc., 51 Franklin Street - Fifth
28 Floor, Boston MA 02110-1301, USA.
29
30 */
31
32 #include "config.h"
33 #include "libdwarfdefs.h"
34 #include <stdio.h>
35 #include <string.h>
36 #include <limits.h>
37 #include "pro_incl.h"
38 #include <stddef.h>
39 #include "dwarf.h"
40 #include "libdwarf.h"
41 #include "pro_opaque.h"
42 #include "pro_error.h"
43 #include "pro_alloc.h"
44 #include "pro_encode_nm.h"
45 #include "pro_frame.h"
46
47 #define SIZEOFT16 2
48 #define SIZEOFT32 4
49 #define SIZEOFT64 8
50
51 #ifdef WORDS_BIGENDIAN
52 #define ASNOUT(t,s,l) \
53 do { \
54 unsigned sbyte = 0; \
55 const char *p = 0; \
56 if (l > sizeof(s)) { \
57 _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
58 return DW_DLV_ERROR; \
59 } \
60 sbyte = sizeof(s) - l; \
61 p = (const char *)(&s); \
62 dbg->de_copy_word(t,(const void *)(p+sbyte),l);\
63 } while (0)
64 #else /* LITTLEENDIAN */
65 #define ASNOUT(t,s,l) \
66 do { \
67 const char *p = 0; \
68 if (l > sizeof(s)) { \
69 _dwarf_p_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);\
70 return DW_DLV_ERROR; \
71 } \
72 p = (const char *)(&s); \
73 dbg->de_copy_word(t,(const void *)p,l); \
74 } while (0)
75 #endif /* ENDIANNESS */
76
77
78 static void _dwarf_pro_add_to_fde(Dwarf_P_Fde fde,
79 Dwarf_P_Frame_Pgm inst);
80
81 /* This function adds a cie struct to the debug pointer. Its in the
82 form of a linked list.
83 augmenter: string reps augmentation (implementation defined)
84 code_align: alignment of code
85 data_align: alignment of data
86 init_bytes: byts having initial instructions
87 init_n_bytes: number of bytes of initial instructions */
88
89
90 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)91 dwarf_add_frame_cie(Dwarf_P_Debug dbg,
92 char *augmenter,
93 Dwarf_Small code_align,
94 Dwarf_Small data_align,
95 Dwarf_Small return_reg,
96 Dwarf_Ptr init_bytes,
97 Dwarf_Unsigned init_n_bytes,
98 Dwarf_Error * error)
99 {
100 Dwarf_Unsigned index = 0;
101 int res = 0;
102
103 res = dwarf_add_frame_cie_a(dbg,augmenter, code_align,
104 data_align,return_reg,init_bytes,
105 init_n_bytes,
106 &index,error);
107 if (res != DW_DLV_OK) {
108 return DW_DLV_NOCOUNT;
109 }
110 return index;
111 }
112
113
114 int
dwarf_add_frame_cie_a(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_Unsigned * cie_index_out,Dwarf_Error * error)115 dwarf_add_frame_cie_a(Dwarf_P_Debug dbg,
116 char *augmenter,
117 Dwarf_Small code_align,
118 Dwarf_Small data_align,
119 Dwarf_Small return_reg,
120 Dwarf_Ptr init_bytes,
121 Dwarf_Unsigned init_n_bytes,
122 Dwarf_Unsigned * cie_index_out,
123 Dwarf_Error * error)
124 {
125 Dwarf_P_Cie curcie;
126 char *tmpaug = 0;
127
128 if (dbg->de_frame_cies == NULL) {
129 dbg->de_frame_cies = (Dwarf_P_Cie)
130 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
131 if (dbg->de_frame_cies == NULL) {
132 DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
133 }
134 curcie = dbg->de_frame_cies;
135 dbg->de_n_cie = 1;
136 dbg->de_last_cie = curcie;
137 } else {
138 curcie = dbg->de_last_cie;
139 curcie->cie_next = (Dwarf_P_Cie)
140 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Cie_s));
141 if (curcie->cie_next == NULL) {
142 DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
143 }
144 curcie = curcie->cie_next;
145 dbg->de_n_cie++;
146 dbg->de_last_cie = curcie;
147 }
148 curcie->cie_version = 1;
149 if (dbg->de_output_version > 2) {
150 curcie->cie_version = dbg->de_output_version;
151 } else {
152 /* V2 dwarf has debug_frame as version 1, there
153 is no 2 used in this section. */
154 curcie->cie_version = 1;
155 }
156 tmpaug = (char *)_dwarf_p_get_alloc(dbg,strlen(augmenter)+1);
157 if (!tmpaug) {
158 DWARF_P_DBG_ERROR(dbg, DW_DLE_CIE_ALLOC, DW_DLV_ERROR);
159 }
160 strcpy(tmpaug,augmenter);
161 curcie->cie_aug = tmpaug;
162 curcie->cie_code_align = code_align;
163 curcie->cie_data_align = data_align;
164 curcie->cie_ret_reg = return_reg;
165 curcie->cie_inst = (char *) init_bytes;
166 curcie->cie_inst_bytes = (long) init_n_bytes;
167 curcie->cie_next = NULL;
168 *cie_index_out = dbg->de_n_cie;
169 return DW_DLV_OK;
170 }
171
172
173 /* This functions adds a fde struct to the debug pointer. Its in the
174 form of a linked list.
175 die: subprogram/function die corresponding to this fde
176 cie: cie referred to by this fde, obtained from call to
177 add_frame_cie() routine.
178 virt_addr: beginning address
179 code_len: length of code reps by the fde */
180 /*ARGSUSED*/ /* pretend all args used */
181 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)182 dwarf_add_frame_fde(Dwarf_P_Debug dbg,
183 Dwarf_P_Fde fde,
184 Dwarf_P_Die die,
185 Dwarf_Unsigned cie,
186 Dwarf_Unsigned virt_addr,
187 Dwarf_Unsigned code_len,
188 Dwarf_Unsigned symidx, Dwarf_Error * error)
189 {
190 Dwarf_Unsigned index = 0;
191 int res = 0;
192
193 res = dwarf_add_frame_fde_c(dbg, fde, die, cie, virt_addr,
194 code_len, symidx, 0, 0,&index, error);
195 if (res != DW_DLV_OK) {
196 return DW_DLV_NOCOUNT;
197 }
198 return index;
199 }
200
201 /* There is no dwarf_add_frame_fde_a */
202 /*ARGSUSED10*/
203 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)204 dwarf_add_frame_fde_b(Dwarf_P_Debug dbg,
205 Dwarf_P_Fde fde,
206 Dwarf_P_Die die,
207 Dwarf_Unsigned cie,
208 Dwarf_Unsigned virt_addr,
209 Dwarf_Unsigned code_len,
210 Dwarf_Unsigned symidx,
211 Dwarf_Unsigned symidx_of_end,
212 Dwarf_Addr offset_from_end_sym,
213 Dwarf_Error * error)
214 {
215 Dwarf_Unsigned index = 0;
216 int res = 0;
217
218 res = dwarf_add_frame_fde_c(dbg,fde,die,cie,
219 virt_addr,code_len,symidx,symidx_of_end,
220 offset_from_end_sym,&index,error);
221 if (res != DW_DLV_OK) {
222 return DW_DLV_NOCOUNT;
223 }
224 return index;
225 }
226
227 /* New December 2018 */
228 int
dwarf_add_frame_fde_c(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_Unsigned * index_to_fde,UNUSEDARG Dwarf_Error * error)229 dwarf_add_frame_fde_c(Dwarf_P_Debug dbg,
230 Dwarf_P_Fde fde,
231 Dwarf_P_Die die,
232 Dwarf_Unsigned cie,
233 Dwarf_Unsigned virt_addr,
234 Dwarf_Unsigned code_len,
235 Dwarf_Unsigned symidx,
236 Dwarf_Unsigned symidx_of_end,
237 Dwarf_Addr offset_from_end_sym,
238 Dwarf_Unsigned *index_to_fde,
239 UNUSEDARG Dwarf_Error * error)
240 {
241 Dwarf_P_Fde curfde;
242
243 fde->fde_die = die;
244 fde->fde_cie = (long) cie;
245 fde->fde_initloc = virt_addr;
246 fde->fde_r_symidx = symidx;
247 fde->fde_addr_range = code_len;
248 fde->fde_offset_into_exception_tables = DW_DLX_NO_EH_OFFSET;
249 fde->fde_exception_table_symbol = 0;
250 fde->fde_end_symbol_offset = offset_from_end_sym;
251 fde->fde_end_symbol = symidx_of_end;
252 fde->fde_dbg = dbg;
253
254 curfde = dbg->de_last_fde;
255 if (curfde == NULL) {
256 dbg->de_frame_fdes = fde;
257 dbg->de_last_fde = fde;
258 dbg->de_n_fde = 1;
259 } else {
260 curfde->fde_next = fde;
261 dbg->de_last_fde = fde;
262 dbg->de_n_fde++;
263 }
264 *index_to_fde = dbg->de_n_fde;
265 return DW_DLV_OK;
266 }
267
268 /* This function adds information to an fde. The fde is
269 linked into the linked list of fde's maintained in the Dwarf_P_Debug
270 structure.
271 dbg: The debug descriptor.
272 fde: The fde to be added.
273 die: subprogram/function die corresponding to this fde
274 cie: cie referred to by this fde, obtained from call to
275 add_frame_cie() routine.
276 virt_addr: beginning address
277 code_len: length of code reps by the fde
278 symidx: The symbol id of the symbol wrt to which relocation needs
279 to be performed for 'virt_addr'.
280 offset_into_exception_tables: The start of exception tables for
281 this function (indicated as an offset into the exception
282 tables). A value of -1 indicates that there is no exception
283 table entries associated with this function.
284 exception_table_symbol: The symbol id of the section for exception
285 tables wrt to which the offset_into_exception_tables will
286 be relocated. */
287 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)288 dwarf_add_frame_info(Dwarf_P_Debug dbg,
289 Dwarf_P_Fde fde,
290 Dwarf_P_Die die,
291 Dwarf_Unsigned cie,
292 Dwarf_Unsigned virt_addr,
293 Dwarf_Unsigned code_len,
294 Dwarf_Unsigned symidx,
295 Dwarf_Signed offset_into_exception_tables,
296 Dwarf_Unsigned exception_table_symbol,
297 Dwarf_Error * error)
298 {
299 Dwarf_Unsigned fde_index = 0;
300 int res = 0;
301
302 res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr,
303 code_len, symidx,
304 /* end_symbol */ 0,
305 /* offset_from_end */ 0,
306 offset_into_exception_tables,
307 exception_table_symbol,
308 &fde_index, error);
309 if (res != DW_DLV_OK) {
310 return DW_DLV_NOCOUNT;
311 }
312 return fde_index;
313 }
314
315 /*ARGSUSED*/ /* pretend all args used */
316 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,UNUSEDARG Dwarf_Error * error)317 dwarf_add_frame_info_b(Dwarf_P_Debug dbg,
318 Dwarf_P_Fde fde,
319 Dwarf_P_Die die,
320 Dwarf_Unsigned cie,
321 Dwarf_Unsigned virt_addr,
322 Dwarf_Unsigned code_len,
323 Dwarf_Unsigned symidx,
324 Dwarf_Unsigned end_symidx,
325 Dwarf_Unsigned offset_from_end_symbol,
326 Dwarf_Signed offset_into_exception_tables,
327 Dwarf_Unsigned exception_table_symbol,
328 UNUSEDARG Dwarf_Error * error)
329 {
330 Dwarf_Unsigned fde_index = 0;
331 int res = 0;
332
333 res = dwarf_add_frame_info_c(dbg, fde, die, cie, virt_addr,
334 code_len, symidx, end_symidx,
335 offset_from_end_symbol,
336 offset_into_exception_tables,
337 exception_table_symbol,
338 &fde_index, error);
339 if (res != DW_DLV_OK) {
340 return DW_DLV_NOCOUNT;
341 }
342 return fde_index;
343 }
344
345 int
dwarf_add_frame_info_c(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_Unsigned * fde_index_out,UNUSEDARG Dwarf_Error * error)346 dwarf_add_frame_info_c(Dwarf_P_Debug dbg,
347 Dwarf_P_Fde fde,
348 Dwarf_P_Die die,
349 Dwarf_Unsigned cie,
350 Dwarf_Unsigned virt_addr,
351 Dwarf_Unsigned code_len,
352 Dwarf_Unsigned symidx,
353 Dwarf_Unsigned end_symidx,
354 Dwarf_Unsigned offset_from_end_symbol,
355 Dwarf_Signed offset_into_exception_tables,
356 Dwarf_Unsigned exception_table_symbol,
357 Dwarf_Unsigned *fde_index_out,
358 UNUSEDARG Dwarf_Error * error)
359 {
360 Dwarf_P_Fde curfde;
361
362 fde->fde_die = die;
363 fde->fde_cie = (long) cie;
364 fde->fde_initloc = virt_addr;
365 fde->fde_r_symidx = symidx;
366 fde->fde_addr_range = code_len;
367 fde->fde_offset_into_exception_tables =
368 offset_into_exception_tables;
369 fde->fde_exception_table_symbol = exception_table_symbol;
370 fde->fde_end_symbol_offset = offset_from_end_symbol;
371 fde->fde_end_symbol = end_symidx;
372 fde->fde_dbg = dbg;
373
374 curfde = dbg->de_last_fde;
375 if (curfde == NULL) {
376 dbg->de_frame_fdes = fde;
377 dbg->de_last_fde = fde;
378 dbg->de_n_fde = 1;
379 } else {
380 curfde->fde_next = fde;
381 dbg->de_last_fde = fde;
382 dbg->de_n_fde++;
383 }
384 *fde_index_out = dbg->de_n_fde;
385 return DW_DLV_OK;
386 }
387
388 /* This is an alternate to inserting frame instructions
389 one instruction at a time. But use either this
390 or instruction level, not both in one fde. */
391 int
dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,Dwarf_P_Fde fde,Dwarf_Unsigned len,Dwarf_Ptr ibytes,Dwarf_Error * error)392 dwarf_insert_fde_inst_bytes(Dwarf_P_Debug dbg,
393 Dwarf_P_Fde fde,Dwarf_Unsigned len, Dwarf_Ptr ibytes,
394 Dwarf_Error *error)
395 {
396 if (len == 0) {
397 return DW_DLV_OK;
398 }
399 if (fde->fde_block || fde->fde_inst) {
400 DWARF_P_DBG_ERROR(dbg, DW_DLE_DUPLICATE_INST_BLOCK,
401 DW_DLV_ERROR);
402 }
403 fde->fde_block = (Dwarf_Ptr)_dwarf_p_get_alloc(dbg, len);
404 memcpy(fde->fde_block,ibytes,len);
405 fde->fde_inst_block_size = len;
406 fde->fde_n_bytes += len;
407 return DW_DLV_OK;
408 }
409
410
411
412 /* Create a new fde. */
413 Dwarf_P_Fde
dwarf_new_fde(Dwarf_P_Debug dbg,Dwarf_Error * error)414 dwarf_new_fde(Dwarf_P_Debug dbg, Dwarf_Error * error)
415 {
416 Dwarf_P_Fde fde = 0;
417 int res = 0;
418
419 res = dwarf_new_fde_a(dbg,&fde,error);
420 if (res != DW_DLV_OK) {
421 return (Dwarf_P_Fde) DW_DLV_BADADDR;
422 }
423 return fde;
424 }
425 int
dwarf_new_fde_a(Dwarf_P_Debug dbg,Dwarf_P_Fde * fde_out,Dwarf_Error * error)426 dwarf_new_fde_a(Dwarf_P_Debug dbg,
427 Dwarf_P_Fde *fde_out,
428 Dwarf_Error * error)
429 {
430 Dwarf_P_Fde fde;
431
432 fde = (Dwarf_P_Fde)
433 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Fde_s));
434 if (fde == NULL) {
435 DWARF_P_DBG_ERROR(dbg, DW_DLE_FDE_ALLOC, DW_DLV_ERROR);
436 }
437 fde->fde_dbg = dbg;
438 fde->fde_uwordb_size = dbg->de_dwarf_offset_size;
439 *fde_out = fde;
440 return DW_DLV_OK;
441 }
442
443
444 /* Add a cfe_offset instruction to the fde passed in. */
445 Dwarf_P_Fde
dwarf_fde_cfa_offset(Dwarf_P_Fde fde,Dwarf_Unsigned reg,Dwarf_Signed offset,Dwarf_Error * error)446 dwarf_fde_cfa_offset(Dwarf_P_Fde fde,
447 Dwarf_Unsigned reg,
448 Dwarf_Signed offset,
449 Dwarf_Error * error)
450 {
451 int res = 0;
452
453 res = dwarf_fde_cfa_offset_a(fde,reg,offset,error);
454 if (res != DW_DLV_OK) {
455 return (Dwarf_P_Fde) DW_DLV_BADADDR;
456 }
457 return fde;
458 }
459
460
461 int
dwarf_fde_cfa_offset_a(Dwarf_P_Fde fde,Dwarf_Unsigned reg,Dwarf_Signed offset,Dwarf_Error * error)462 dwarf_fde_cfa_offset_a(Dwarf_P_Fde fde,
463 Dwarf_Unsigned reg,
464 Dwarf_Signed offset,
465 Dwarf_Error * error)
466 {
467 Dwarf_Ubyte opc, regno;
468 char *ptr = 0;
469 Dwarf_P_Frame_Pgm curinst;
470 int nbytes = 0;
471 int res = 0;
472 char buff1[ENCODE_SPACE_NEEDED];
473 Dwarf_P_Debug dbg = fde->fde_dbg;
474
475 curinst = (Dwarf_P_Frame_Pgm)
476 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
477 if (curinst == NULL) {
478 DWARF_P_DBG_ERROR(dbg, DW_DLE_FPGM_ALLOC, DW_DLV_ERROR);
479 }
480 opc = DW_CFA_offset;
481 regno = reg;
482 if (regno & 0xc0) {
483 DWARF_P_DBG_ERROR(dbg, DW_DLE_REGNO_OVFL,DW_DLV_ERROR);
484 }
485 opc = opc | regno; /* lower 6 bits are register number */
486 curinst->dfp_opcode = opc;
487 res = _dwarf_pro_encode_leb128_nm(offset, &nbytes,
488 buff1, sizeof(buff1));
489 if (res != DW_DLV_OK) {
490 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
491 return DW_DLV_ERROR;
492 }
493 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
494 if (ptr == NULL) {
495 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
496 return DW_DLV_ERROR;
497 }
498 memcpy(ptr, buff1, nbytes);
499
500 curinst->dfp_args = ptr;
501 curinst->dfp_nbytes = nbytes;
502 curinst->dfp_next = NULL;
503
504 _dwarf_pro_add_to_fde(fde, curinst);
505 return DW_DLV_OK;
506 }
507
508 /* Generic routine to add opcode to fde instructions. val1 and
509 val2 are parameters whose interpretation depends on the 'op'.
510
511 This does not work properly for DW_DLC_SYMBOLIC_RELOCATIONS
512 for DW_CFA_set_loc or DW_DVA_advance_loc* 'op', as
513 these ops normally are addresses or (DW_CFA_set_loc)
514 or code lengths (DW_DVA_advance_loc*) and such must be
515 represented with relocations and symbol indices for
516 DW_DLC_SYMBOLIC_RELOCATIONS.
517
518 This does not treat all DW_CFA instructions yet.
519
520 For certain operations a val? value must be
521 signed (though passed in as unsigned here).
522
523 Does not check that the frame
524 version is 3(for dwarf3) or 4 (for dwarf4) or 5
525 when applying operations that are only valid for
526 particular versions. */
527 Dwarf_P_Fde
dwarf_add_fde_inst(Dwarf_P_Fde fde,Dwarf_Small op,Dwarf_Unsigned val1,Dwarf_Unsigned val2,Dwarf_Error * error)528 dwarf_add_fde_inst(Dwarf_P_Fde fde,
529 Dwarf_Small op,
530 Dwarf_Unsigned val1,
531 Dwarf_Unsigned val2, Dwarf_Error * error)
532 {
533 int res = 0;
534
535 res = dwarf_add_fde_inst_a(fde,op,val1,val2,error);
536 if (res != DW_DLV_OK) {
537 return ((Dwarf_P_Fde) DW_DLV_BADADDR);
538 }
539 return fde;
540 }
541
542 /* December 2018. A more sensible return value. */
543 int
dwarf_add_fde_inst_a(Dwarf_P_Fde fde,Dwarf_Small op,Dwarf_Unsigned val1,Dwarf_Unsigned val2,Dwarf_Error * error)544 dwarf_add_fde_inst_a(Dwarf_P_Fde fde,
545 Dwarf_Small op,
546 Dwarf_Unsigned val1,
547 Dwarf_Unsigned val2,
548 Dwarf_Error * error)
549 {
550 Dwarf_P_Frame_Pgm curinst;
551 int nbytes = 0;
552 int nbytes1 = 0;
553 int nbytes2 = 0;
554 Dwarf_Ubyte db = 0;
555 Dwarf_Half dh = 0;
556 Dwarf_Unsigned du = 0;
557 char *ptr = 0;
558 int res = 0;
559 char buff1[ENCODE_SPACE_NEEDED];
560 char buff2[ENCODE_SPACE_NEEDED];
561 Dwarf_P_Debug dbg = fde->fde_dbg;
562 /* This is a hack telling the code when to transform
563 a value to a signed leb number. */
564 int signed_second = 0;
565 int signed_first = 0;
566
567
568 buff1[0] = 0;
569 buff2[0] = 0;
570 curinst = (Dwarf_P_Frame_Pgm)
571 _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Frame_Pgm_s));
572 if (curinst == NULL) {
573 _dwarf_p_error(dbg, error, DW_DLE_FPGM_ALLOC);
574 return DW_DLV_ERROR;
575 }
576 switch (op) {
577
578 case DW_CFA_advance_loc: {
579 if (val1 <= 0x3f) {
580 db = val1;
581 op |= db;
582 } else if (!(val1& ~0xff)) {
583 op = DW_CFA_advance_loc1;
584 db = val1;
585 ptr = (char *) _dwarf_p_get_alloc(dbg, 1);
586 if (ptr == NULL) {
587 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
588 return DW_DLV_ERROR;
589 }
590 memcpy((void *) ptr, (const void *) &db, 1);
591 nbytes = 1;
592 } else if (!(val1& (~(Dwarf_Unsigned)0xffff))) {
593 if (sizeof(dh) < SIZEOFT16) {
594 _dwarf_p_error(dbg, error,
595 DW_DLE_DEBUG_FRAME_LENGTH_BAD);
596 return DW_DLV_ERROR;
597 }
598 op = DW_CFA_advance_loc2;
599 dh = val1;
600 ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT16);
601 if (ptr == NULL) {
602 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
603 return DW_DLV_ERROR;
604 }
605 /* No byte swapping, assuming running at
606 target endianness. */
607 ASNOUT((void *) ptr, dh, SIZEOFT16);
608 nbytes = SIZEOFT16;
609 } else if (!(val1& ~(Dwarf_Unsigned)0xffffffff)) {
610 if (sizeof(du) < SIZEOFT32) {
611 _dwarf_p_error(dbg, error,
612 DW_DLE_DEBUG_FRAME_LENGTH_BAD);
613 return DW_DLV_ERROR;
614 }
615 op = DW_CFA_advance_loc4;
616 du = val1;
617 ptr = (char *) _dwarf_p_get_alloc(dbg, SIZEOFT32);
618 if (ptr == NULL) {
619 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
620 return DW_DLV_ERROR;
621 }
622 ASNOUT((void *) ptr, du, SIZEOFT32);
623 nbytes = SIZEOFT32;
624 } else {
625 if (sizeof(du) < SIZEOFT64) {
626 _dwarf_p_error(dbg, error,
627 DW_DLE_DEBUG_FRAME_LENGTH_BAD);
628 return DW_DLV_ERROR;
629 }
630 op = DW_CFA_MIPS_advance_loc8;
631 du = val1;
632 ptr = (char *) _dwarf_p_get_alloc(dbg,
633 SIZEOFT64);
634 if (ptr == NULL) {
635 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
636 return DW_DLV_ERROR;
637 }
638 /* No byte swapping, assuming running at
639 target endianness. */
640 ASNOUT((void *) ptr, du, SIZEOFT64);
641 nbytes = SIZEOFT64;
642 }
643 break;
644 }
645 case DW_CFA_offset:
646 if (val1 <= MAX_6_BIT_VALUE) {
647 db = val1;
648 op |= db;
649 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes,
650 buff1, sizeof(buff1));
651 if (res != DW_DLV_OK) {
652 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
653 return DW_DLV_ERROR;
654 }
655 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
656 if (ptr == NULL) {
657 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
658 return DW_DLV_ERROR;
659 }
660 memcpy(ptr, buff1, nbytes);
661
662 } else {
663 op = DW_CFA_offset_extended;
664 goto two_leb;
665 }
666 break;
667 case DW_CFA_offset_extended_sf: /* DWARF3 */
668 signed_second = 1;
669 goto two_leb;
670 case DW_CFA_offset_extended:
671 goto two_leb;
672
673 case DW_CFA_undefined:
674 case DW_CFA_same_value:
675 goto one_leb;
676
677 case DW_CFA_val_offset:
678 goto two_leb;
679 case DW_CFA_val_offset_sf:
680 signed_second = 1;
681 goto two_leb;
682 case DW_CFA_def_cfa_sf:
683 signed_second = 1;
684 goto two_leb;
685 case DW_CFA_register:
686 case DW_CFA_def_cfa:
687 two_leb:
688 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes1,
689 buff1, sizeof(buff1));
690 if (res != DW_DLV_OK) {
691 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
692 return DW_DLV_ERROR;
693 }
694 if (!signed_second) {
695 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
696 buff2, sizeof(buff2));
697 } else {
698 Dwarf_Signed val2s = val2;
699 res = _dwarf_pro_encode_signed_leb128_nm(val2s, &nbytes2,
700 buff2, sizeof(buff2));
701 }
702 if (res != DW_DLV_OK) {
703 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
704 return DW_DLV_ERROR;
705 }
706
707 res = _dwarf_pro_encode_leb128_nm(val2, &nbytes2,
708 buff2, sizeof(buff2));
709 if (res != DW_DLV_OK) {
710 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
711 return DW_DLV_ERROR;
712 }
713
714 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes1 + nbytes2);
715 if (ptr == NULL) {
716 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
717 return DW_DLV_ERROR;
718 }
719 memcpy(ptr, buff1, nbytes1);
720 memcpy(ptr + nbytes1, buff2, nbytes2);
721 nbytes = nbytes1 + nbytes2;
722 break;
723
724 case DW_CFA_def_cfa_offset_sf: /* DWARF3 */
725 signed_first = 1;
726 goto one_leb;
727 case DW_CFA_def_cfa_register:
728 case DW_CFA_def_cfa_offset:
729 one_leb:
730 if (!signed_first) {
731 res = _dwarf_pro_encode_leb128_nm(val1, &nbytes,
732 buff1, sizeof(buff1));
733 } else {
734 Dwarf_Signed val1s = val1;
735 res = _dwarf_pro_encode_signed_leb128_nm(val1s, &nbytes,
736 buff1, sizeof(buff1));
737 }
738 if (res != DW_DLV_OK) {
739 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
740 return DW_DLV_ERROR;
741 }
742 ptr = (char *) _dwarf_p_get_alloc(dbg, nbytes);
743 if (ptr == NULL) {
744 _dwarf_p_error(dbg, error, DW_DLE_STRING_ALLOC);
745 return DW_DLV_ERROR;
746 }
747 memcpy(ptr, buff1, nbytes);
748 break;
749 case DW_CFA_def_cfa_expression: /* DWARF3 */
750 /* FIXME: argument is dwarf expr, not handled yet. */
751 case DW_CFA_expression: /* DWARF3 */
752 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
753 FIXME: not handled yet. */
754 case DW_CFA_val_expression: /* DWARF3f */
755 /* First arg: ULEB reg num. 2nd arg dwarf expr in form block.
756 FIXME: not handled yet. */
757 default:
758 _dwarf_p_error(dbg, error, DW_DLE_DEBUGFRAME_ERROR);
759 return DW_DLV_ERROR;
760 }
761
762 curinst->dfp_opcode = op;
763 curinst->dfp_args = ptr;
764 curinst->dfp_nbytes = nbytes;
765 curinst->dfp_next = NULL;
766 _dwarf_pro_add_to_fde(fde, curinst);
767 return DW_DLV_OK;
768 }
769
770
771 /* Instructions are added to an fde in the form of a linked
772 list. This function manages the linked list. */
773 void
_dwarf_pro_add_to_fde(Dwarf_P_Fde fde,Dwarf_P_Frame_Pgm curinst)774 _dwarf_pro_add_to_fde(Dwarf_P_Fde fde, Dwarf_P_Frame_Pgm curinst)
775 {
776 if (fde->fde_last_inst) {
777 fde->fde_last_inst->dfp_next = curinst;
778 fde->fde_last_inst = curinst;
779 fde->fde_n_inst++;
780 fde->fde_n_bytes +=
781 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
782 } else {
783 fde->fde_last_inst = curinst;
784 fde->fde_inst = curinst;
785 fde->fde_n_inst = 1;
786 fde->fde_n_bytes =
787 (long) (curinst->dfp_nbytes + sizeof(Dwarf_Ubyte));
788 }
789 }
790