12de3b87aSKai Wang /*-
22de3b87aSKai Wang * Copyright (c) 2009,2011 Kai Wang
32de3b87aSKai Wang * All rights reserved.
42de3b87aSKai Wang *
52de3b87aSKai Wang * Redistribution and use in source and binary forms, with or without
62de3b87aSKai Wang * modification, are permitted provided that the following conditions
72de3b87aSKai Wang * are met:
82de3b87aSKai Wang * 1. Redistributions of source code must retain the above copyright
92de3b87aSKai Wang * notice, this list of conditions and the following disclaimer.
102de3b87aSKai Wang * 2. Redistributions in binary form must reproduce the above copyright
112de3b87aSKai Wang * notice, this list of conditions and the following disclaimer in the
122de3b87aSKai Wang * documentation and/or other materials provided with the distribution.
132de3b87aSKai Wang *
142de3b87aSKai Wang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152de3b87aSKai Wang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162de3b87aSKai Wang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172de3b87aSKai Wang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182de3b87aSKai Wang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192de3b87aSKai Wang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202de3b87aSKai Wang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212de3b87aSKai Wang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222de3b87aSKai Wang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232de3b87aSKai Wang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242de3b87aSKai Wang * SUCH DAMAGE.
252de3b87aSKai Wang */
262de3b87aSKai Wang
272de3b87aSKai Wang #include "_libdwarf.h"
282de3b87aSKai Wang
29*cf781b2eSEd Maste ELFTC_VCSID("$Id: libdwarf_loclist.c 3061 2014-06-02 00:42:41Z kaiwang27 $");
302de3b87aSKai Wang
312de3b87aSKai Wang static int
_dwarf_loclist_add_locdesc(Dwarf_Debug dbg,Dwarf_CU cu,Dwarf_Section * ds,Dwarf_Unsigned * off,Dwarf_Locdesc ** ld,Dwarf_Signed * ldlen,Dwarf_Unsigned * total_len,Dwarf_Error * error)322de3b87aSKai Wang _dwarf_loclist_add_locdesc(Dwarf_Debug dbg, Dwarf_CU cu, Dwarf_Section *ds,
33*cf781b2eSEd Maste Dwarf_Unsigned *off, Dwarf_Locdesc **ld, Dwarf_Signed *ldlen,
342de3b87aSKai Wang Dwarf_Unsigned *total_len, Dwarf_Error *error)
352de3b87aSKai Wang {
362de3b87aSKai Wang uint64_t start, end;
372de3b87aSKai Wang int i, len, ret;
382de3b87aSKai Wang
392de3b87aSKai Wang if (total_len != NULL)
402de3b87aSKai Wang *total_len = 0;
412de3b87aSKai Wang
422de3b87aSKai Wang for (i = 0; *off < ds->ds_size; i++) {
432de3b87aSKai Wang start = dbg->read(ds->ds_data, off, cu->cu_pointer_size);
442de3b87aSKai Wang end = dbg->read(ds->ds_data, off, cu->cu_pointer_size);
452de3b87aSKai Wang if (ld != NULL) {
462de3b87aSKai Wang ld[i]->ld_lopc = start;
472de3b87aSKai Wang ld[i]->ld_hipc = end;
482de3b87aSKai Wang }
492de3b87aSKai Wang
502de3b87aSKai Wang if (total_len != NULL)
512de3b87aSKai Wang *total_len += 2 * cu->cu_pointer_size;
522de3b87aSKai Wang
532de3b87aSKai Wang /* Check if it is the end entry. */
542de3b87aSKai Wang if (start == 0 && end ==0) {
552de3b87aSKai Wang i++;
562de3b87aSKai Wang break;
572de3b87aSKai Wang }
582de3b87aSKai Wang
592de3b87aSKai Wang /* Check if it is base-select entry. */
602de3b87aSKai Wang if ((cu->cu_pointer_size == 4 && start == ~0U) ||
612de3b87aSKai Wang (cu->cu_pointer_size == 8 && start == ~0ULL))
622de3b87aSKai Wang continue;
632de3b87aSKai Wang
642de3b87aSKai Wang /* Otherwise it's normal entry. */
652de3b87aSKai Wang len = dbg->read(ds->ds_data, off, 2);
662de3b87aSKai Wang if (*off + len > ds->ds_size) {
672de3b87aSKai Wang DWARF_SET_ERROR(dbg, error,
682de3b87aSKai Wang DW_DLE_DEBUG_LOC_SECTION_SHORT);
692de3b87aSKai Wang return (DW_DLE_DEBUG_LOC_SECTION_SHORT);
702de3b87aSKai Wang }
712de3b87aSKai Wang
722de3b87aSKai Wang if (total_len != NULL)
732de3b87aSKai Wang *total_len += len;
742de3b87aSKai Wang
752de3b87aSKai Wang if (ld != NULL) {
762de3b87aSKai Wang ret = _dwarf_loc_fill_locdesc(dbg, ld[i],
772de3b87aSKai Wang ds->ds_data + *off, len, cu->cu_pointer_size,
78*cf781b2eSEd Maste cu->cu_length_size == 4 ? 4 : 8, cu->cu_version,
792de3b87aSKai Wang error);
802de3b87aSKai Wang if (ret != DW_DLE_NONE)
812de3b87aSKai Wang return (ret);
822de3b87aSKai Wang }
832de3b87aSKai Wang
842de3b87aSKai Wang *off += len;
852de3b87aSKai Wang }
862de3b87aSKai Wang
872de3b87aSKai Wang if (ldlen != NULL)
882de3b87aSKai Wang *ldlen = i;
892de3b87aSKai Wang
902de3b87aSKai Wang return (DW_DLE_NONE);
912de3b87aSKai Wang }
922de3b87aSKai Wang
932de3b87aSKai Wang int
_dwarf_loclist_find(Dwarf_Debug dbg,Dwarf_CU cu,uint64_t lloff,Dwarf_Locdesc *** ret_llbuf,Dwarf_Signed * listlen,Dwarf_Unsigned * entry_len,Dwarf_Error * error)942de3b87aSKai Wang _dwarf_loclist_find(Dwarf_Debug dbg, Dwarf_CU cu, uint64_t lloff,
95*cf781b2eSEd Maste Dwarf_Locdesc ***ret_llbuf, Dwarf_Signed *listlen,
96*cf781b2eSEd Maste Dwarf_Unsigned *entry_len, Dwarf_Error *error)
972de3b87aSKai Wang {
98*cf781b2eSEd Maste Dwarf_Locdesc **llbuf;
992de3b87aSKai Wang Dwarf_Section *ds;
100*cf781b2eSEd Maste Dwarf_Signed ldlen;
101*cf781b2eSEd Maste Dwarf_Unsigned off;
1022de3b87aSKai Wang int i, ret;
1032de3b87aSKai Wang
1042de3b87aSKai Wang if ((ds = _dwarf_find_section(dbg, ".debug_loc")) == NULL) {
1052de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
1062de3b87aSKai Wang return (DW_DLE_NO_ENTRY);
1072de3b87aSKai Wang }
1082de3b87aSKai Wang
109255d921aSKai Wang if (lloff >= ds->ds_size) {
110255d921aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
111255d921aSKai Wang return (DW_DLE_NO_ENTRY);
112255d921aSKai Wang }
113255d921aSKai Wang
1142de3b87aSKai Wang /* Get the number of locdesc the first round. */
115*cf781b2eSEd Maste off = lloff;
116*cf781b2eSEd Maste ret = _dwarf_loclist_add_locdesc(dbg, cu, ds, &off, NULL, &ldlen,
1172de3b87aSKai Wang NULL, error);
1182de3b87aSKai Wang if (ret != DW_DLE_NONE)
119*cf781b2eSEd Maste return (ret);
120*cf781b2eSEd Maste
121*cf781b2eSEd Maste if (ldlen == 0)
122*cf781b2eSEd Maste return (DW_DLE_NO_ENTRY);
1232de3b87aSKai Wang
1242de3b87aSKai Wang /*
1252de3b87aSKai Wang * Dwarf_Locdesc list memory is allocated in this way (one more level
1262de3b87aSKai Wang * of indirect) to make the loclist API be compatible with SGI libdwarf.
1272de3b87aSKai Wang */
128*cf781b2eSEd Maste if ((llbuf = calloc(ldlen, sizeof(Dwarf_Locdesc *))) == NULL) {
1292de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
130*cf781b2eSEd Maste return (DW_DLE_MEMORY);
1312de3b87aSKai Wang }
132*cf781b2eSEd Maste for (i = 0; i < ldlen; i++) {
133*cf781b2eSEd Maste if ((llbuf[i] = calloc(1, sizeof(Dwarf_Locdesc))) == NULL) {
1342de3b87aSKai Wang DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
1352de3b87aSKai Wang ret = DW_DLE_MEMORY;
1362de3b87aSKai Wang goto fail_cleanup;
1372de3b87aSKai Wang }
1382de3b87aSKai Wang }
1392de3b87aSKai Wang
140*cf781b2eSEd Maste off = lloff;
1412de3b87aSKai Wang
1422de3b87aSKai Wang /* Fill in locdesc. */
143*cf781b2eSEd Maste ret = _dwarf_loclist_add_locdesc(dbg, cu, ds, &off, llbuf, NULL,
144*cf781b2eSEd Maste entry_len, error);
1452de3b87aSKai Wang if (ret != DW_DLE_NONE)
1462de3b87aSKai Wang goto fail_cleanup;
1472de3b87aSKai Wang
148*cf781b2eSEd Maste *ret_llbuf = llbuf;
149*cf781b2eSEd Maste *listlen = ldlen;
1502de3b87aSKai Wang
1512de3b87aSKai Wang return (DW_DLE_NONE);
1522de3b87aSKai Wang
1532de3b87aSKai Wang fail_cleanup:
1542de3b87aSKai Wang
155*cf781b2eSEd Maste if (llbuf != NULL) {
156*cf781b2eSEd Maste for (i = 0; i < ldlen; i++) {
157*cf781b2eSEd Maste if (llbuf[i]->ld_s)
158*cf781b2eSEd Maste free(llbuf[i]->ld_s);
159*cf781b2eSEd Maste free(llbuf[i]);
160*cf781b2eSEd Maste }
161*cf781b2eSEd Maste free(llbuf);
162*cf781b2eSEd Maste }
1632de3b87aSKai Wang
1642de3b87aSKai Wang return (ret);
1652de3b87aSKai Wang }
166