pro_line.c revision 07dc1947c362e187fb955d283b692f8769dd5def
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
48Dwarf_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---------------------------------------------------------------------------*/
69Dwarf_Unsigned
70dwarf_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-------------------------------------------------------------------------*/
91Dwarf_Unsigned
92dwarf_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-------------------------------------------------------------------------*/
111Dwarf_Unsigned
112dwarf_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-----------------------------------------------------------------------------*/
131Dwarf_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------------------------------------------------------------------------*/
176Dwarf_Unsigned
177dwarf_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------------------------------------------------------------------------*/
213Dwarf_Unsigned
214dwarf_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----------------------------------------------------------------------*/
290void
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