xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_line.c (revision d8109ce4330e1b8ad6c29f9fccacec969066bb9d)
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 #ifdef HAVE_ELF_H
43 #include <elf.h>
44 #endif
45 #include "pro_incl.h"
46 #include "pro_line.h"
47 
48 Dwarf_Unsigned _dwarf_pro_add_line_entry(Dwarf_P_Debug,
49                                          Dwarf_Unsigned file_index,
50                                          Dwarf_Addr code_address,
51                                          Dwarf_Unsigned symidx,
52                                          Dwarf_Unsigned line_no,
53                                          Dwarf_Signed col_no,
54                                          Dwarf_Bool is_stmt_begin,
55                                          Dwarf_Bool is_bb_begin,
56                                          Dwarf_Ubyte opc,
57                                          Dwarf_Error * error);
58 
59 /*-------------------------------------------------------------------------
60         Add a entry to the line information section
61         file_index: index of file in file entries, obtained from
62         add_file_entry() call.
63 
64         This function actually calls _dwarf_pro_add_line_entry(), with
65         an extra parameter, the opcode. Done so that interface calls
66         dwarf_lne_set_address() and dwarf_lne_end_sequence() can use
67         this internal routine.
68 ---------------------------------------------------------------------------*/
69 Dwarf_Unsigned
70 dwarf_add_line_entry(Dwarf_P_Debug dbg,
71                      Dwarf_Unsigned file_index,
72                      Dwarf_Addr code_address,
73                      Dwarf_Unsigned line_no,
74                      Dwarf_Signed col_no,
75                      Dwarf_Bool is_stmt_begin,
76                      Dwarf_Bool is_bb_begin, Dwarf_Error * error)
77 {
78     Dwarf_Unsigned retval;
79 
80     retval = _dwarf_pro_add_line_entry(dbg, file_index, code_address, 0,
81                                        line_no, col_no, is_stmt_begin,
82                                        is_bb_begin, 0, error);
83     return retval;
84 }
85 
86 /*------------------------------------------------------------------------
87         Ask to emit DW_LNE_set_address opcode explicitly. Used by be
88         to emit start of a new .text section, or to force a relocated
89         address into debug line information entry.
90 -------------------------------------------------------------------------*/
91 Dwarf_Unsigned
92 dwarf_lne_set_address(Dwarf_P_Debug dbg,
93                       Dwarf_Addr offs,
94                       Dwarf_Unsigned symidx, Dwarf_Error * error)
95 {
96     Dwarf_Ubyte opc;
97     Dwarf_Unsigned retval;
98 
99     opc = DW_LNE_set_address;
100     retval =
101         _dwarf_pro_add_line_entry(dbg, 0, offs, symidx, 0, 0, 0, 0, opc,
102                                   error);
103     return retval;
104 }
105 
106 /*------------------------------------------------------------------------
107         Ask to emit end_seqence opcode. Used normally at the end of a
108         compilation unit. Can also be used in the middle if there
109         are gaps in the region described by the code address.
110 -------------------------------------------------------------------------*/
111 Dwarf_Unsigned
112 dwarf_lne_end_sequence(Dwarf_P_Debug dbg,
113                        Dwarf_Addr end_address, Dwarf_Error * error)
114 {
115     Dwarf_Ubyte opc;
116     Dwarf_Unsigned retval;
117 
118     opc = DW_LNE_end_sequence;
119     retval =
120         _dwarf_pro_add_line_entry(dbg, 0, end_address, 0, 0, 0, 0, 0,
121                                   opc, error);
122     return retval;
123 }
124 
125 /*----------------------------------------------------------------------------
126         Add an entry in the internal list of lines mantained by producer.
127         Opc indicates if an opcode needs to be generated, rather than just
128         an entry in the matrix. During opcodes generation time, these
129         opcodes will be used.
130 -----------------------------------------------------------------------------*/
131 Dwarf_Unsigned
132 _dwarf_pro_add_line_entry(Dwarf_P_Debug dbg,
133                           Dwarf_Unsigned file_index,
134                           Dwarf_Addr code_address,
135                           Dwarf_Unsigned symidx,
136                           Dwarf_Unsigned line_no,
137                           Dwarf_Signed col_no,
138                           Dwarf_Bool is_stmt_begin,
139                           Dwarf_Bool is_bb_begin,
140                           Dwarf_Ubyte opc, Dwarf_Error * error)
141 {
142     if (dbg->de_lines == NULL) {
143         dbg->de_lines = (Dwarf_P_Line)
144             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
145         if (dbg->de_lines == NULL) {
146             DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
147         }
148         dbg->de_last_line = dbg->de_lines;
149         _dwarf_pro_reg_init(dbg->de_lines);
150 
151     } else {
152         dbg->de_last_line->dpl_next = (Dwarf_P_Line)
153             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Line_s));
154         if (dbg->de_last_line->dpl_next == NULL) {
155             DWARF_P_DBG_ERROR(dbg, DW_DLE_LINE_ALLOC, DW_DLV_NOCOUNT);
156         }
157         dbg->de_last_line = dbg->de_last_line->dpl_next;
158         _dwarf_pro_reg_init(dbg->de_last_line);
159     }
160     dbg->de_last_line->dpl_address = code_address;
161     dbg->de_last_line->dpl_file = (unsigned long) file_index;
162     dbg->de_last_line->dpl_line = (unsigned long) line_no;
163     dbg->de_last_line->dpl_column = (unsigned long) col_no;
164     dbg->de_last_line->dpl_is_stmt = is_stmt_begin;
165     dbg->de_last_line->dpl_basic_block = is_bb_begin;
166     dbg->de_last_line->dpl_opc = opc;
167     dbg->de_last_line->dpl_r_symidx = symidx;
168 
169     return (0);
170 }
171 
172 /*-----------------------------------------------------------------------
173         Add a directory declaration to the debug_line section. Stored
174         in linked list.
175 ------------------------------------------------------------------------*/
176 Dwarf_Unsigned
177 dwarf_add_directory_decl(Dwarf_P_Debug dbg,
178                          char *name, Dwarf_Error * error)
179 {
180     if (dbg->de_inc_dirs == NULL) {
181         dbg->de_inc_dirs = (Dwarf_P_Inc_Dir)
182             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s));
183         if (dbg->de_inc_dirs == NULL) {
184             DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
185         }
186         dbg->de_last_inc_dir = dbg->de_inc_dirs;
187         dbg->de_n_inc_dirs = 1;
188     } else {
189         dbg->de_last_inc_dir->did_next = (Dwarf_P_Inc_Dir)
190             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_Inc_Dir_s));
191         if (dbg->de_last_inc_dir->did_next == NULL) {
192             DWARF_P_DBG_ERROR(dbg, DW_DLE_INCDIR_ALLOC, DW_DLV_NOCOUNT);
193         }
194         dbg->de_last_inc_dir = dbg->de_last_inc_dir->did_next;
195         dbg->de_n_inc_dirs++;
196     }
197     dbg->de_last_inc_dir->did_name =
198         (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
199     if (dbg->de_last_inc_dir->did_name == NULL) {
200         DWARF_P_DBG_ERROR(dbg, DW_DLE_STRING_ALLOC, DW_DLV_NOCOUNT);
201     }
202     strcpy(dbg->de_last_inc_dir->did_name, name);
203     dbg->de_last_inc_dir->did_next = NULL;
204 
205     return dbg->de_n_inc_dirs;
206 }
207 
208 /*-----------------------------------------------------------------------
209         Add a file entry declaration to the debug_line section. Stored
210         in linked list. The data is immediately encodes as leb128
211         and stored in Dwarf_P_F_Entry_s struct.
212 ------------------------------------------------------------------------*/
213 Dwarf_Unsigned
214 dwarf_add_file_decl(Dwarf_P_Debug dbg,
215                     char *name,
216                     Dwarf_Unsigned dir_idx,
217                     Dwarf_Unsigned time_mod,
218                     Dwarf_Unsigned length, Dwarf_Error * error)
219 {
220     Dwarf_P_F_Entry cur;
221     char *ptr;
222     int nbytes_idx, nbytes_time, nbytes_len;
223     char buffidx[ENCODE_SPACE_NEEDED];
224     char bufftime[ENCODE_SPACE_NEEDED];
225     char bufflen[ENCODE_SPACE_NEEDED];
226     int res;
227 
228     if (dbg->de_file_entries == NULL) {
229         dbg->de_file_entries = (Dwarf_P_F_Entry)
230             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
231         if (dbg->de_file_entries == NULL) {
232             DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
233                               DW_DLV_NOCOUNT);
234         }
235         cur = dbg->de_file_entries;
236         dbg->de_last_file_entry = cur;
237         dbg->de_n_file_entries = 1;
238     } else {
239         cur = dbg->de_last_file_entry;
240         cur->dfe_next = (Dwarf_P_F_Entry)
241             _dwarf_p_get_alloc(dbg, sizeof(struct Dwarf_P_F_Entry_s));
242         if (cur->dfe_next == NULL) {
243             DWARF_P_DBG_ERROR(dbg, DW_DLE_FILE_ENTRY_ALLOC,
244                               DW_DLV_NOCOUNT);
245         }
246         cur = cur->dfe_next;
247         dbg->de_last_file_entry = cur;
248         dbg->de_n_file_entries++;
249     }
250     cur->dfe_name = (char *) _dwarf_p_get_alloc(dbg, strlen(name) + 1);
251     if (cur->dfe_name == NULL) {
252         DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
253     }
254     strcpy((char *) cur->dfe_name, name);
255     res = _dwarf_pro_encode_leb128_nm(dir_idx, &nbytes_idx,
256                                       buffidx, sizeof(buffidx));
257     if (res != DW_DLV_OK) {
258         DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
259     }
260     res = _dwarf_pro_encode_leb128_nm(time_mod, &nbytes_time,
261                                       bufftime, sizeof(bufftime));
262     if (res != DW_DLV_OK) {
263         DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
264     }
265     res = _dwarf_pro_encode_leb128_nm(length, &nbytes_len,
266                                       bufflen, sizeof(bufflen));
267     cur->dfe_args = (char *)
268         _dwarf_p_get_alloc(dbg, nbytes_idx + nbytes_time + nbytes_len);
269     if (cur->dfe_args == NULL) {
270         DWARF_P_DBG_ERROR(dbg, DW_DLE_ALLOC_FAIL, DW_DLV_NOCOUNT);
271     }
272     ptr = cur->dfe_args;
273     memcpy((void *) ptr, buffidx, nbytes_idx);
274     ptr += nbytes_idx;
275     memcpy((void *) ptr, bufftime, nbytes_time);
276     ptr += nbytes_time;
277     memcpy((void *) ptr, bufflen, nbytes_len);
278     ptr += nbytes_len;
279     cur->dfe_nbytes = nbytes_idx + nbytes_time + nbytes_len;
280     cur->dfe_next = NULL;
281 
282     return dbg->de_n_file_entries;
283 }
284 
285 
286 /*---------------------------------------------------------------------
287         Initialize a row of the matrix for line numbers, meaning
288         initialize the struct corresponding to it
289 ----------------------------------------------------------------------*/
290 void
291 _dwarf_pro_reg_init(Dwarf_P_Line cur_line)
292 {
293     cur_line->dpl_address = 0;
294     cur_line->dpl_file = 1;
295     cur_line->dpl_line = 1;
296     cur_line->dpl_column = 0;
297     cur_line->dpl_is_stmt = DEFAULT_IS_STMT;
298     cur_line->dpl_basic_block = false;
299     cur_line->dpl_next = NULL;
300 }
301