xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_frame.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
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