#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <dwarf.h>
#include "libdwP.h"
const char *
dwarf_formstring (Dwarf_Attribute *attrp)
{
if (attrp == NULL)
return NULL;
if (attrp->form == DW_FORM_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]);
size_t data_size = ((attrp->form == DW_FORM_line_strp)
? dbg_ret->string_section_size[STR_SCN_IDX_debug_line_str]
: dbg_ret->string_section_size[STR_SCN_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;
}
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;
}
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;
}
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 >= data_size)
goto invalid_offset;
return (const char *) data->d_buf + off;
}
INTDEF(dwarf_formstring)