2 * Copyright (c) 2009,2011 Kai Wang
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include "_libdwarf.h"
29 ELFTC_VCSID("$Id: dwarf_frame.c 2073 2011-10-27 03:30:47Z jkoshy $");
32 dwarf_get_fde_list(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
33 Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
37 if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
38 fde_list == NULL || fde_count == NULL) {
39 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
40 return (DW_DLV_ERROR);
43 if (dbg->dbg_internal_reg_table == NULL) {
44 if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
45 return (DW_DLV_ERROR);
48 if (dbg->dbg_frame == NULL) {
49 if (_dwarf_frame_section_load(dbg, error) != DW_DLE_NONE)
50 return (DW_DLV_ERROR);
51 if (dbg->dbg_frame == NULL) {
52 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
53 return (DW_DLV_NO_ENTRY);
57 if (dbg->dbg_frame->fs_ciearray == NULL ||
58 dbg->dbg_frame->fs_fdearray == NULL) {
59 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
60 return (DW_DLV_NO_ENTRY);
63 *cie_list = dbg->dbg_frame->fs_ciearray;
64 *cie_count = dbg->dbg_frame->fs_cielen;
65 *fde_list = dbg->dbg_frame->fs_fdearray;
66 *fde_count = dbg->dbg_frame->fs_fdelen;
72 dwarf_get_fde_list_eh(Dwarf_Debug dbg, Dwarf_Cie **cie_list,
73 Dwarf_Signed *cie_count, Dwarf_Fde **fde_list, Dwarf_Signed *fde_count,
77 if (dbg == NULL || cie_list == NULL || cie_count == NULL ||
78 fde_list == NULL || fde_count == NULL) {
79 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
80 return (DW_DLV_ERROR);
83 if (dbg->dbg_internal_reg_table == NULL) {
84 if (_dwarf_frame_interal_table_init(dbg, error) != DW_DLE_NONE)
85 return (DW_DLV_ERROR);
88 if (dbg->dbg_eh_frame == NULL) {
89 if (_dwarf_frame_section_load_eh(dbg, error) != DW_DLE_NONE)
90 return (DW_DLV_ERROR);
91 if (dbg->dbg_eh_frame == NULL) {
92 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
93 return (DW_DLV_NO_ENTRY);
97 if (dbg->dbg_eh_frame->fs_ciearray == NULL ||
98 dbg->dbg_eh_frame->fs_fdearray == NULL) {
99 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
100 return (DW_DLV_NO_ENTRY);
103 *cie_list = dbg->dbg_eh_frame->fs_ciearray;
104 *cie_count = dbg->dbg_eh_frame->fs_cielen;
105 *fde_list = dbg->dbg_eh_frame->fs_fdearray;
106 *fde_count = dbg->dbg_eh_frame->fs_fdelen;
112 dwarf_get_fde_n(Dwarf_Fde *fdelist, Dwarf_Unsigned fde_index,
113 Dwarf_Fde *ret_fde, Dwarf_Error *error)
118 dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
120 if (fdelist == NULL || ret_fde == NULL) {
121 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
122 return (DW_DLV_ERROR);
125 fs = fdelist[0]->fde_fs;
128 if (fde_index >= fs->fs_fdelen) {
129 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
130 return (DW_DLV_NO_ENTRY);
133 *ret_fde = fdelist[fde_index];
139 dwarf_get_fde_at_pc(Dwarf_Fde *fdelist, Dwarf_Addr pc, Dwarf_Fde *ret_fde,
140 Dwarf_Addr *lopc, Dwarf_Addr *hipc, Dwarf_Error *error)
147 dbg = fdelist != NULL ? (*fdelist)->fde_dbg : NULL;
149 if (fdelist == NULL || ret_fde == NULL || lopc == NULL ||
151 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
152 return (DW_DLV_ERROR);
155 fs = fdelist[0]->fde_fs;
158 for (i = 0; (Dwarf_Unsigned)i < fs->fs_fdelen; i++) {
160 if (pc >= fde->fde_initloc && pc < fde->fde_initloc +
163 *lopc = fde->fde_initloc;
164 *hipc = fde->fde_initloc + fde->fde_adrange - 1;
169 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
170 return (DW_DLV_NO_ENTRY);
174 dwarf_get_cie_of_fde(Dwarf_Fde fde, Dwarf_Cie *ret_cie, Dwarf_Error *error)
178 dbg = fde != NULL ? fde->fde_dbg : NULL;
180 if (fde == NULL || ret_cie == NULL) {
181 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
182 return (DW_DLV_ERROR);
185 *ret_cie = fde->fde_cie;
191 dwarf_get_fde_range(Dwarf_Fde fde, Dwarf_Addr *low_pc, Dwarf_Unsigned *func_len,
192 Dwarf_Ptr *fde_bytes, Dwarf_Unsigned *fde_byte_len, Dwarf_Off *cie_offset,
193 Dwarf_Signed *cie_index, Dwarf_Off *fde_offset, Dwarf_Error *error)
197 dbg = fde != NULL ? fde->fde_dbg : NULL;
199 if (fde == NULL || low_pc == NULL || func_len == NULL ||
200 fde_bytes == NULL || fde_byte_len == NULL || cie_offset == NULL ||
201 cie_index == NULL || fde_offset == NULL) {
202 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
203 return (DW_DLV_ERROR);
206 *low_pc = fde->fde_initloc;
207 *func_len = fde->fde_adrange;
208 *fde_bytes = fde->fde_addr;
209 *fde_byte_len = fde->fde_length;
210 *cie_offset = fde->fde_cieoff;
211 *cie_index = fde->fde_cie->cie_index;
212 *fde_offset = fde->fde_offset;
218 dwarf_get_cie_info(Dwarf_Cie cie, Dwarf_Unsigned *bytes_in_cie,
219 Dwarf_Small *version, char **augmenter, Dwarf_Unsigned *caf,
220 Dwarf_Unsigned *daf, Dwarf_Half *ra, Dwarf_Ptr *initinst,
221 Dwarf_Unsigned *inst_len, Dwarf_Error *error)
224 if (cie == NULL || bytes_in_cie == NULL || version == NULL ||
225 augmenter == NULL || caf == NULL || daf == NULL || ra == NULL ||
226 initinst == NULL || inst_len == NULL) {
227 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
228 return (DW_DLV_ERROR);
231 *bytes_in_cie = cie->cie_length;
232 *version = cie->cie_version;
233 *augmenter = (char *) cie->cie_augment;
237 *initinst = cie->cie_initinst;
238 *inst_len = cie->cie_instlen;
244 dwarf_get_cie_index(Dwarf_Cie cie, Dwarf_Signed *cie_index, Dwarf_Error *error)
247 if (cie == NULL || cie_index == NULL) {
248 DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
249 return (DW_DLV_ERROR);
252 *cie_index = cie->cie_index;
258 dwarf_get_fde_instr_bytes(Dwarf_Fde fde, Dwarf_Ptr *ret_inst,
259 Dwarf_Unsigned *ret_len, Dwarf_Error *error)
263 dbg = fde != NULL ? fde->fde_dbg : NULL;
265 if (fde == NULL || ret_inst == NULL || ret_len == NULL) {
266 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
267 return (DW_DLV_ERROR);
270 *ret_inst = fde->fde_inst;
271 *ret_len = fde->fde_instlen;
276 #define RL rt->rt3_rules[table_column]
277 #define CFA rt->rt3_cfa_rule
280 dwarf_get_fde_info_for_reg(Dwarf_Fde fde, Dwarf_Half table_column,
281 Dwarf_Addr pc_requested, Dwarf_Signed *offset_relevant,
282 Dwarf_Signed *register_num, Dwarf_Signed *offset, Dwarf_Addr *row_pc,
290 dbg = fde != NULL ? fde->fde_dbg : NULL;
292 if (fde == NULL || offset_relevant == NULL || register_num == NULL ||
293 offset == NULL || row_pc == NULL) {
294 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
295 return (DW_DLV_ERROR);
298 if (pc_requested < fde->fde_initloc ||
299 pc_requested >= fde->fde_initloc + fde->fde_adrange) {
300 DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
301 return (DW_DLV_ERROR);
304 ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
306 if (ret != DW_DLE_NONE)
307 return (DW_DLV_ERROR);
309 if (table_column == dbg->dbg_frame_cfa_value) {
310 /* Application ask for CFA. */
311 *offset_relevant = CFA.dw_offset_relevant;
312 *register_num = CFA.dw_regnum;
313 *offset = CFA.dw_offset_or_block_len;
315 /* Application ask for normal registers. */
316 if (table_column >= dbg->dbg_frame_rule_table_size ||
317 table_column >= DW_REG_TABLE_SIZE) {
318 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
319 return (DW_DLV_ERROR);
322 *offset_relevant = RL.dw_offset_relevant;
323 *register_num = RL.dw_regnum;
324 *offset = RL.dw_offset_or_block_len;
333 dwarf_get_fde_info_for_all_regs(Dwarf_Fde fde, Dwarf_Addr pc_requested,
334 Dwarf_Regtable *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
342 dbg = fde != NULL ? fde->fde_dbg : NULL;
344 if (fde == NULL || reg_table == NULL || row_pc == NULL) {
345 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
346 return (DW_DLV_ERROR);
351 if (pc_requested < fde->fde_initloc ||
352 pc_requested >= fde->fde_initloc + fde->fde_adrange) {
353 DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
354 return (DW_DLV_ERROR);
357 ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
359 if (ret != DW_DLE_NONE)
360 return (DW_DLV_ERROR);
363 * Copy the CFA rule to the column intended for holding the CFA,
364 * if it's within the range of regtable.
366 cfa = dbg->dbg_frame_cfa_value;
367 if (cfa < DW_REG_TABLE_SIZE) {
368 reg_table->rules[cfa].dw_offset_relevant =
369 CFA.dw_offset_relevant;
370 reg_table->rules[cfa].dw_regnum = CFA.dw_regnum;
371 reg_table->rules[cfa].dw_offset = CFA.dw_offset_or_block_len;
375 * Copy other columns.
377 for (i = 0; i < DW_REG_TABLE_SIZE && i < dbg->dbg_frame_rule_table_size;
380 /* Do not overwrite CFA column */
384 reg_table->rules[i].dw_offset_relevant =
385 rt->rt3_rules[i].dw_offset_relevant;
386 reg_table->rules[i].dw_regnum = rt->rt3_rules[i].dw_regnum;
387 reg_table->rules[i].dw_offset =
388 rt->rt3_rules[i].dw_offset_or_block_len;
397 dwarf_get_fde_info_for_reg3(Dwarf_Fde fde, Dwarf_Half table_column,
398 Dwarf_Addr pc_requested, Dwarf_Small *value_type,
399 Dwarf_Signed *offset_relevant, Dwarf_Signed *register_num,
400 Dwarf_Signed *offset_or_block_len, Dwarf_Ptr *block_ptr,
401 Dwarf_Addr *row_pc, Dwarf_Error *error)
408 dbg = fde != NULL ? fde->fde_dbg : NULL;
410 if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
411 register_num == NULL || offset_or_block_len == NULL ||
412 block_ptr == NULL || row_pc == NULL) {
413 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
414 return (DW_DLV_ERROR);
417 if (pc_requested < fde->fde_initloc ||
418 pc_requested >= fde->fde_initloc + fde->fde_adrange) {
419 DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
420 return (DW_DLV_ERROR);
423 ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
425 if (ret != DW_DLE_NONE)
426 return (DW_DLV_ERROR);
428 if (table_column >= dbg->dbg_frame_rule_table_size) {
429 DWARF_SET_ERROR(dbg, error, DW_DLE_FRAME_TABLE_COL_BAD);
430 return (DW_DLV_ERROR);
433 *value_type = RL.dw_value_type;
434 *offset_relevant = RL.dw_offset_relevant;
435 *register_num = RL.dw_regnum;
436 *offset_or_block_len = RL.dw_offset_or_block_len;
437 *block_ptr = RL.dw_block_ptr;
444 dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
445 Dwarf_Small *value_type, Dwarf_Signed *offset_relevant,
446 Dwarf_Signed *register_num, Dwarf_Signed *offset_or_block_len,
447 Dwarf_Ptr *block_ptr, Dwarf_Addr *row_pc, Dwarf_Error *error)
454 dbg = fde != NULL ? fde->fde_dbg : NULL;
456 if (fde == NULL || value_type == NULL || offset_relevant == NULL ||
457 register_num == NULL || offset_or_block_len == NULL ||
458 block_ptr == NULL || row_pc == NULL) {
459 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
460 return (DW_DLV_ERROR);
463 if (pc_requested < fde->fde_initloc ||
464 pc_requested >= fde->fde_initloc + fde->fde_adrange) {
465 DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
466 return (DW_DLV_ERROR);
469 ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
471 if (ret != DW_DLE_NONE)
472 return (DW_DLV_ERROR);
474 *value_type = CFA.dw_value_type;
475 *offset_relevant = CFA.dw_offset_relevant;
476 *register_num = CFA.dw_regnum;
477 *offset_or_block_len = CFA.dw_offset_or_block_len;
478 *block_ptr = CFA.dw_block_ptr;
488 dwarf_get_fde_info_for_all_regs3(Dwarf_Fde fde, Dwarf_Addr pc_requested,
489 Dwarf_Regtable3 *reg_table, Dwarf_Addr *row_pc, Dwarf_Error *error)
496 dbg = fde != NULL ? fde->fde_dbg : NULL;
498 if (fde == NULL || reg_table == NULL || reg_table->rt3_rules == NULL ||
500 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
501 return (DW_DLV_ERROR);
506 if (pc_requested < fde->fde_initloc ||
507 pc_requested >= fde->fde_initloc + fde->fde_adrange) {
508 DWARF_SET_ERROR(dbg, error, DW_DLE_PC_NOT_IN_FDE_RANGE);
509 return (DW_DLV_ERROR);
512 ret = _dwarf_frame_get_internal_table(fde, pc_requested, &rt, &pc,
514 if (ret != DW_DLE_NONE)
515 return (DW_DLV_ERROR);
517 ret = _dwarf_frame_regtable_copy(dbg, ®_table, rt, error);
518 if (ret != DW_DLE_NONE)
519 return (DW_DLV_ERROR);
527 dwarf_expand_frame_instructions(Dwarf_Cie cie, Dwarf_Ptr instruction,
528 Dwarf_Unsigned len, Dwarf_Frame_Op **ret_oplist, Dwarf_Signed *ret_opcnt,
534 dbg = cie != NULL ? cie->cie_dbg : NULL;
536 if (cie == NULL || instruction == NULL || len == 0 ||
537 ret_oplist == NULL || ret_opcnt == NULL) {
538 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
539 return (DW_DLV_ERROR);
542 ret = _dwarf_frame_get_fop(dbg, instruction, len, ret_oplist, ret_opcnt,
544 if (ret != DW_DLE_NONE)
545 return (DW_DLV_ERROR);
551 dwarf_set_frame_rule_table_size(Dwarf_Debug dbg, Dwarf_Half value)
553 Dwarf_Half old_value;
555 old_value = dbg->dbg_frame_rule_table_size;
556 dbg->dbg_frame_rule_table_size = value;
562 dwarf_set_frame_rule_initial_value(Dwarf_Debug dbg, Dwarf_Half value)
564 Dwarf_Half old_value;
566 old_value = dbg->dbg_frame_rule_initial_value;
567 dbg->dbg_frame_rule_initial_value = value;
573 dwarf_set_frame_cfa_value(Dwarf_Debug dbg, Dwarf_Half value)
575 Dwarf_Half old_value;
577 old_value = dbg->dbg_frame_cfa_value;
578 dbg->dbg_frame_cfa_value = value;
584 dwarf_set_frame_same_value(Dwarf_Debug dbg, Dwarf_Half value)
586 Dwarf_Half old_value;
588 old_value = dbg->dbg_frame_same_value;
589 dbg->dbg_frame_same_value = value;
595 dwarf_set_frame_undefined_value(Dwarf_Debug dbg, Dwarf_Half value)
597 Dwarf_Half old_value;
599 old_value = dbg->dbg_frame_undefined_value;
600 dbg->dbg_frame_undefined_value = value;