You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
4.8 KiB
181 lines
4.8 KiB
/* Return string associated with given attribute.
|
|
Copyright (C) 2003-2010, 2013, 2017, 2018 Red Hat, Inc.
|
|
This file is part of elfutils.
|
|
|
|
This file is free software; you can redistribute it and/or modify
|
|
it under the terms of either
|
|
|
|
* the GNU Lesser General Public License as published by the Free
|
|
Software Foundation; either version 3 of the License, or (at
|
|
your option) any later version
|
|
|
|
or
|
|
|
|
* the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2 of the License, or (at
|
|
your option) any later version
|
|
|
|
or both in parallel, as here.
|
|
|
|
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 copies of the GNU General Public License and
|
|
the GNU Lesser General Public License along with this program. If
|
|
not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <dwarf.h>
|
|
#include "libdwP.h"
|
|
|
|
|
|
const char *
|
|
dwarf_formstring (Dwarf_Attribute *attrp)
|
|
{
|
|
/* Ignore earlier errors. */
|
|
if (attrp == NULL)
|
|
return NULL;
|
|
|
|
/* We found it. Now determine where the string is stored. */
|
|
if (attrp->form == DW_FORM_string)
|
|
/* A simple inlined string. */
|
|
return (const char *) attrp->valp;
|
|
|
|
Dwarf_CU *cu = attrp->cu;
|
|
Dwarf *dbg = cu->dbg;
|
|
Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
|
|
|| attrp->form == DW_FORM_strp_sup)
|
|
? INTUSE(dwarf_getalt) (dbg) : dbg);
|
|
|
|
if (unlikely (dbg_ret == NULL))
|
|
{
|
|
__libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
|
|
return NULL;
|
|
}
|
|
|
|
Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
|
|
? dbg_ret->sectiondata[IDX_debug_line_str]
|
|
: dbg_ret->sectiondata[IDX_debug_str]);
|
|
if (data == NULL)
|
|
{
|
|
__libdw_seterrno ((attrp->form == DW_FORM_line_strp)
|
|
? DWARF_E_NO_DEBUG_LINE_STR
|
|
: DWARF_E_NO_DEBUG_STR);
|
|
return NULL;
|
|
}
|
|
|
|
uint64_t off;
|
|
if (attrp->form == DW_FORM_strp
|
|
|| attrp->form == DW_FORM_GNU_strp_alt
|
|
|| attrp->form == DW_FORM_strp_sup)
|
|
{
|
|
if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
|
|
attrp->valp, cu->offset_size, &off,
|
|
IDX_debug_str, 1))
|
|
return NULL;
|
|
}
|
|
else if (attrp->form == DW_FORM_line_strp)
|
|
{
|
|
if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
|
|
attrp->valp, cu->offset_size, &off,
|
|
IDX_debug_line_str, 1))
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
Dwarf_Word idx;
|
|
const unsigned char *datap = attrp->valp;
|
|
const unsigned char *endp = cu->endp;
|
|
switch (attrp->form)
|
|
{
|
|
case DW_FORM_strx:
|
|
case DW_FORM_GNU_str_index:
|
|
if (datap >= endp)
|
|
{
|
|
invalid:
|
|
__libdw_seterrno (DWARF_E_INVALID_DWARF);
|
|
return NULL;
|
|
}
|
|
get_uleb128 (idx, datap, endp);
|
|
break;
|
|
|
|
case DW_FORM_strx1:
|
|
if (datap >= endp - 1)
|
|
goto invalid;
|
|
idx = *datap;
|
|
break;
|
|
|
|
case DW_FORM_strx2:
|
|
if (datap >= endp - 2)
|
|
goto invalid;
|
|
idx = read_2ubyte_unaligned (dbg, datap);
|
|
break;
|
|
|
|
case DW_FORM_strx3:
|
|
if (datap >= endp - 3)
|
|
goto invalid;
|
|
idx = read_3ubyte_unaligned (dbg, datap);
|
|
break;
|
|
|
|
case DW_FORM_strx4:
|
|
if (datap >= endp - 4)
|
|
goto invalid;
|
|
idx = read_4ubyte_unaligned (dbg, datap);
|
|
break;
|
|
|
|
default:
|
|
__libdw_seterrno (DWARF_E_NO_STRING);
|
|
return NULL;
|
|
}
|
|
|
|
/* So we got an index in the .debug_str_offsets. Lets see if it
|
|
is valid and we can get the actual .debug_str offset. */
|
|
Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
|
|
if (str_off == (Dwarf_Off) -1)
|
|
return NULL;
|
|
|
|
if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
|
|
{
|
|
__libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
|
|
return NULL;
|
|
}
|
|
|
|
/* The section should at least contain room for one offset. */
|
|
int offset_size = cu->offset_size;
|
|
if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
|
|
{
|
|
invalid_offset:
|
|
__libdw_seterrno (DWARF_E_INVALID_OFFSET);
|
|
return NULL;
|
|
}
|
|
|
|
/* And the base offset should be at least inside the section. */
|
|
if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
|
|
- offset_size))
|
|
goto invalid_offset;
|
|
|
|
size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
|
|
- offset_size - str_off) / offset_size;
|
|
if (idx > max_idx)
|
|
goto invalid_offset;
|
|
|
|
datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
|
|
+ str_off + (idx * offset_size));
|
|
if (offset_size == 4)
|
|
off = read_4ubyte_unaligned (dbg, datap);
|
|
else
|
|
off = read_8ubyte_unaligned (dbg, datap);
|
|
|
|
if (off > dbg->sectiondata[IDX_debug_str]->d_size)
|
|
goto invalid_offset;
|
|
}
|
|
|
|
return (const char *) data->d_buf + off;
|
|
}
|
|
INTDEF(dwarf_formstring)
|