xref: /freebsd/contrib/elftoolchain/libdwarf/libdwarf_loclist.c (revision 98e0ffaefb0f241cda3a72395d3be04192ae0d47)
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