1 /* $NetBSD: libdwarf_info.c,v 1.2 2014/03/09 16:58:04 christos Exp $ */
4 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
5 * Copyright (c) 2010,2011 Kai Wang
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include "_libdwarf.h"
32 __RCSID("$NetBSD: libdwarf_info.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
33 ELFTC_VCSID("Id: libdwarf_info.c 2942 2013-05-04 23:03:54Z kaiwang27 ");
36 _dwarf_info_first_cu(Dwarf_Debug dbg
, Dwarf_Error
*error
)
41 assert(dbg
->dbg_cu_current
== NULL
);
42 cu
= STAILQ_FIRST(&dbg
->dbg_cu
);
44 dbg
->dbg_cu_current
= cu
;
48 if (dbg
->dbg_info_loaded
)
49 return (DW_DLE_NO_ENTRY
);
51 dbg
->dbg_info_off
= 0;
52 ret
= _dwarf_info_load(dbg
, 0, error
);
53 if (ret
!= DW_DLE_NONE
)
56 dbg
->dbg_cu_current
= STAILQ_FIRST(&dbg
->dbg_cu
);
62 _dwarf_info_next_cu(Dwarf_Debug dbg
, Dwarf_Error
*error
)
67 assert(dbg
->dbg_cu_current
!= NULL
);
68 cu
= STAILQ_NEXT(dbg
->dbg_cu_current
, cu_next
);
70 dbg
->dbg_cu_current
= cu
;
74 if (dbg
->dbg_info_loaded
) {
75 dbg
->dbg_cu_current
= NULL
;
76 return (DW_DLE_NO_ENTRY
);
79 ret
= _dwarf_info_load(dbg
, 0, error
);
80 if (ret
!= DW_DLE_NONE
)
83 dbg
->dbg_cu_current
= STAILQ_NEXT(dbg
->dbg_cu_current
, cu_next
);
89 _dwarf_info_load(Dwarf_Debug dbg
, int load_all
, Dwarf_Error
*error
)
99 if (dbg
->dbg_info_loaded
)
100 return (DW_DLE_NONE
);
102 offset
= dbg
->dbg_info_off
;
103 ds
= dbg
->dbg_info_sec
;
105 while (offset
< ds
->ds_size
) {
106 if ((cu
= calloc(1, sizeof(struct _Dwarf_CU
))) == NULL
) {
107 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
108 return (DW_DLE_MEMORY
);
112 cu
->cu_offset
= offset
;
114 length
= dbg
->read(ds
->ds_data
, &offset
, 4);
115 if (length
== 0xffffffff) {
116 length
= dbg
->read(ds
->ds_data
, &offset
, 8);
120 cu
->cu_dwarf_size
= dwarf_size
;
123 * Check if there is enough ELF data for this CU. This assumes
124 * that libelf gives us the entire section in one Elf_Data
127 if (length
> ds
->ds_size
- offset
) {
129 DWARF_SET_ERROR(dbg
, error
, DW_DLE_CU_LENGTH_ERROR
);
130 return (DW_DLE_CU_LENGTH_ERROR
);
133 /* Compute the offset to the next compilation unit: */
134 next_offset
= offset
+ length
;
135 dbg
->dbg_info_off
= next_offset
;
137 /* Initialise the compilation unit. */
138 cu
->cu_length
= length
;
139 cu
->cu_length_size
= (dwarf_size
== 4 ? 4 : 12);
140 cu
->cu_version
= dbg
->read(ds
->ds_data
, &offset
, 2);
141 cu
->cu_abbrev_offset
= dbg
->read(ds
->ds_data
, &offset
,
143 cu
->cu_abbrev_offset_cur
= cu
->cu_abbrev_offset
;
144 cu
->cu_pointer_size
= dbg
->read(ds
->ds_data
, &offset
, 1);
145 cu
->cu_next_offset
= next_offset
;
147 /* Add the compilation unit to the list. */
148 STAILQ_INSERT_TAIL(&dbg
->dbg_cu
, cu
, cu_next
);
150 if (cu
->cu_version
< 2 || cu
->cu_version
> 4) {
151 DWARF_SET_ERROR(dbg
, error
, DW_DLE_VERSION_STAMP_ERROR
);
152 ret
= DW_DLE_VERSION_STAMP_ERROR
;
156 cu
->cu_1st_offset
= offset
;
158 offset
= next_offset
;
164 if ((Dwarf_Unsigned
) dbg
->dbg_info_off
>= ds
->ds_size
)
165 dbg
->dbg_info_loaded
= 1;
171 _dwarf_info_cleanup(Dwarf_Debug dbg
)
175 assert(dbg
!= NULL
&& dbg
->dbg_mode
== DW_DLC_READ
);
177 STAILQ_FOREACH_SAFE(cu
, &dbg
->dbg_cu
, cu_next
, tcu
) {
178 STAILQ_REMOVE(&dbg
->dbg_cu
, cu
, _Dwarf_CU
, cu_next
);
179 _dwarf_abbrev_cleanup(cu
);
180 if (cu
->cu_lineinfo
!= NULL
) {
181 _dwarf_lineno_cleanup(cu
->cu_lineinfo
);
182 cu
->cu_lineinfo
= NULL
;
189 _dwarf_info_gen(Dwarf_P_Debug dbg
, Dwarf_Error
*error
)
192 Dwarf_Rel_Section drs
;
193 Dwarf_Unsigned offset
;
197 assert(dbg
!= NULL
&& dbg
->write_alloc
!= NULL
);
199 if (dbg
->dbgp_root_die
== NULL
)
200 return (DW_DLE_NONE
);
202 /* Create the single CU for this debugging object. */
203 if ((cu
= calloc(1, sizeof(struct _Dwarf_CU
))) == NULL
) {
204 DWARF_SET_ERROR(dbg
, error
, DW_DLE_MEMORY
);
205 return (DW_DLE_MEMORY
);
208 cu
->cu_version
= 2; /* DWARF2 */
209 cu
->cu_pointer_size
= dbg
->dbg_pointer_size
;
210 STAILQ_INSERT_TAIL(&dbg
->dbg_cu
, cu
, cu_next
);
212 /* Create .debug_info section. */
213 if ((ret
= _dwarf_section_init(dbg
, &dbg
->dbgp_info
, ".debug_info", 0,
214 error
)) != DW_DLE_NONE
)
218 /* Create relocation section for .debug_init */
219 if ((ret
= _dwarf_reloc_section_init(dbg
, &drs
, ds
, error
)) !=
223 /* Length placeholder. (We only use 32-bit DWARF format) */
224 RCHECK(WRITE_VALUE(cu
->cu_length
, 4));
226 /* Write CU version */
227 RCHECK(WRITE_VALUE(cu
->cu_version
, 2));
230 * Write abbrev offset. (always 0, we only support single CU)
231 * Also generate a relocation entry for this offset.
233 RCHECK(_dwarf_reloc_entry_add(dbg
, drs
, ds
, dwarf_drt_data_reloc
, 4,
234 ds
->ds_size
, 0, cu
->cu_abbrev_offset
, ".debug_abbrev", error
));
237 RCHECK(WRITE_VALUE(cu
->cu_pointer_size
, 1));
239 /* Transform the DIE(s) of this CU. */
240 RCHECK(_dwarf_die_gen(dbg
, cu
, drs
, error
));
242 /* Now we can fill in the length of this CU. */
243 cu
->cu_length
= ds
->ds_size
- 4;
245 dbg
->write(ds
->ds_data
, &offset
, cu
->cu_length
, 4);
247 /* Inform application the creation of .debug_info ELF section. */
248 RCHECK(_dwarf_section_callback(dbg
, ds
, SHT_PROGBITS
, 0, 0, 0, error
));
251 * Inform application the creation of relocation section for
254 RCHECK(_dwarf_reloc_section_finalize(dbg
, drs
, error
));
256 return (DW_DLE_NONE
);
259 _dwarf_reloc_section_free(dbg
, &drs
);
262 _dwarf_section_free(dbg
, &dbg
->dbgp_info
);
265 STAILQ_REMOVE(&dbg
->dbg_cu
, cu
, _Dwarf_CU
, cu_next
);
272 _dwarf_info_pro_cleanup(Dwarf_P_Debug dbg
)
276 assert(dbg
!= NULL
&& dbg
->dbg_mode
== DW_DLC_WRITE
);
278 cu
= STAILQ_FIRST(&dbg
->dbg_cu
);
280 STAILQ_REMOVE(&dbg
->dbg_cu
, cu
, _Dwarf_CU
, cu_next
);
281 _dwarf_abbrev_cleanup(cu
);