+++ /dev/null
-/* Associate Ebl handle with Dwarf_CFI handle.
- Copyright (C) 2006 Red Hat, Inc.
- This file is part of Red Hat elfutils.
-
- Red Hat elfutils is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by the
- Free Software Foundation; version 2 of the License.
-
- Red Hat elfutils is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with Red Hat elfutils; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
-
- In addition, as a special exception, Red Hat, Inc. gives You the
- additional right to link the code of Red Hat elfutils with code licensed
- under any Open Source Initiative certified open source license
- (http://www.opensource.org/licenses/index.php) which requires the
- distribution of source code with any binary distribution and to
- distribute linked combinations of the two. Non-GPL Code permitted under
- this exception must only link to the code of Red Hat elfutils through
- those well defined interfaces identified in the file named EXCEPTION
- found in the source code files (the "Approved Interfaces"). The files
- of Non-GPL Code may instantiate templates or use macros or inline
- functions from the Approved Interfaces without causing the resulting
- work to be covered by the GNU General Public License. Only Red Hat,
- Inc. may make changes or additions to the list of Approved Interfaces.
- Red Hat's grant of this exception is conditioned upon your not adding
- any new exceptions. If you wish to add a new Approved Interface or
- exception, please contact Red Hat. You must obey the GNU General Public
- License in all respects for all of the Red Hat elfutils code and other
- code used in conjunction with Red Hat elfutils except the Non-GPL Code
- covered by this exception. If you modify this file, you may extend this
- exception to your version of the file, but you are not obligated to do
- so. If you do not wish to provide this exception without modification,
- you must delete this exception statement from your version and license
- this file solely under the GPL without exception.
-
- Red Hat elfutils is an included package of the Open Invention Network.
- An included package of the Open Invention Network is a package for which
- Open Invention Network licensees cross-license their patents. No patent
- license is granted, either expressly or impliedly, by designation as an
- included package. Should you wish to participate in the Open Invention
- Network licensing program, please visit www.openinventionnetwork.com
- <http://www.openinventionnetwork.com>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "libdwP.h"
-#include "unwindP.h"
-#include "../libebl/libebl.h"
-
-int
-dwarf_cfi_setebl (cfi, ebl)
- Dwarf_CFI *cfi;
- Ebl *ebl;
-{
- if (cfi == NULL)
- return -1;
-
- cfi->ebl = ebl;
-
- return 0;
-}
-INTDEF (dwarf_cfi_setebl)
return result;
}
-int
-internal_function
-__libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
- Dwarf_Addr address, Dwarf_Frame **frame)
+static int
+cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
{
- if (fde->cie->initial_state == NULL)
- {
- /* This CIE has not been used before. Play out its initial
- instructions and cache the initial state that results. */
+ int result = DWARF_E_NOERROR;
- Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
- if (unlikely (cie_fs == NULL))
- return DWARF_E_NOMEM;
+ if (likely (cie->initial_state != NULL))
+ return result;
+
+ /* This CIE has not been used before. Play out its initial
+ instructions and cache the initial state that results.
+ First we'll let the backend fill in the default initial
+ state for this machine's ABI. */
- int result = DWARF_E_NOERROR;
+ Dwarf_CIE abi_info = { CIE_ID, 1, 1, -1, "", NULL, 0, 0, NULL, NULL };
- /* First we'll let the backend fill in the default initial
- state for this machine's ABI. */
+ /* Make sure we have a backend handle cached. */
+ if (unlikely (cache->ebl == NULL))
+ {
+ cache->ebl = ebl_openbackend (cache->elf);
+ if (unlikely (cache->ebl == NULL))
+ cache->ebl = (void *) -1l;
+ }
- Dwarf_CIE abi_info = { CIE_ID, 1, 1, -1, "", NULL, 0, 0, NULL, NULL };
- if (cache->ebl != NULL && ebl_abi_cfi (cache->ebl, &abi_info) < 0)
- return DWARF_E_UNKNOWN_ERROR;
+ /* Fetch the ABI's default CFI program. */
+ if (likely (cache->ebl != (void *) -1l)
+ && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0))
+ return DWARF_E_UNKNOWN_ERROR;
- /* If the default state of any register is not "undefined"
- (i.e. call-clobbered), then the backend supplies instructions
- for the standard initial state. */
- if (abi_info.initial_instructions_end > abi_info.initial_instructions)
+ Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
+ if (unlikely (cie_fs == NULL))
+ return DWARF_E_NOMEM;
+
+ /* If the default state of any register is not "undefined"
+ (i.e. call-clobbered), then the backend supplies instructions
+ for the standard initial state. */
+ if (abi_info.initial_instructions_end > abi_info.initial_instructions)
+ {
+ /* Dummy CIE for backend's instructions. */
+ struct dwarf_cie abi_cie =
{
- /* Dummy CIE for backend's instructions. */
- struct dwarf_cie abi_cie =
- {
- .code_alignment_factor = abi_info.code_alignment_factor,
- .data_alignment_factor = abi_info.data_alignment_factor,
- };
- result = execute_cfi (cache, &abi_cie, &cie_fs,
- abi_info.initial_instructions,
- abi_info.initial_instructions_end, true,
- 0, (Dwarf_Addr) -1l);
- }
+ .code_alignment_factor = abi_info.code_alignment_factor,
+ .data_alignment_factor = abi_info.data_alignment_factor,
+ };
+ result = execute_cfi (cache, &abi_cie, &cie_fs,
+ abi_info.initial_instructions,
+ abi_info.initial_instructions_end, true,
+ 0, (Dwarf_Addr) -1l);
+ }
+
+ /* Now run the CIE's initial instructions. */
+ if (cie->initial_instructions_end > cie->initial_instructions
+ && likely (result == DWARF_E_NOERROR))
+ result = execute_cfi (cache, cie, &cie_fs,
+ cie->initial_instructions,
+ cie->initial_instructions_end, false,
+ 0, (Dwarf_Addr) -1l);
- /* Now run the CIE's initial instructions. */
- if (fde->cie->initial_instructions_end > fde->cie->initial_instructions
- && result == DWARF_E_NOERROR)
- result = execute_cfi (cache, fde->cie, &cie_fs,
- fde->cie->initial_instructions,
- fde->cie->initial_instructions_end, false,
- 0, (Dwarf_Addr) -1l);
-
- if (result != DWARF_E_NOERROR)
- return result;
-
- /* Now we have the initial state of things that all
- FDEs using this CIE will start from. */
- cie_fs->cache = cache;
- fde->cie->initial_state = cie_fs;
+ if (unlikely (result != DWARF_E_NOERROR))
+ {
+ free (cie_fs);
+ return result;
}
- Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
- if (unlikely (fs == NULL))
- return DWARF_E_NOMEM;
+ /* Now we have the initial state of things that all
+ FDEs using this CIE will start from. */
+ cie_fs->cache = cache;
+ cie->initial_state = cie_fs;
+
+ return result;
+}
+
+int
+internal_function
+__libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
+ Dwarf_Addr address, Dwarf_Frame **frame)
+{
+ int result = cie_cache_initial_state (cache, fde->cie);
+ if (likely (result == DWARF_E_NOERROR))
+ {
+ Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
+ if (unlikely (fs == NULL))
+ return DWARF_E_NOMEM;
- fs->fde = fde;
- fs->start = fde->start;
- fs->end = fde->end;
+ fs->fde = fde;
+ fs->start = fde->start;
+ fs->end = fde->end;
- int result = execute_cfi (cache, fde->cie, &fs,
+ result = execute_cfi (cache, fde->cie, &fs,
fde->instructions, fde->instructions_end, false,
fde->start, address);
- if (unlikely (result != DWARF_E_NOERROR))
- free (fs);
- else
- *frame = fs;
-
+ if (unlikely (result != DWARF_E_NOERROR))
+ free (fs);
+ else
+ *frame = fs;
+ }
return result;
}