#include "config.h"
#include "dwarf_incl.h"
#include <stdio.h>
#include <limits.h>
#include "dwarf_macro.h"
#define LEFTPAREN '('
#define RIGHTPAREN ')'
#define SPACE ' '
char *
dwarf_find_macro_value_start(char *str)
{
char *lcp;
int funclike = 0;
for (lcp = str; *lcp; ++lcp) {
switch (*lcp) {
case LEFTPAREN:
funclike = 1;
break;
case RIGHTPAREN:
return lcp + 2;
case SPACE:
if (!funclike) {
return lcp + 1;
}
break;
}
}
return lcp;
}
static Dwarf_Signed *st_base;
static long max;
static long next_to_use;
static int was_fault = 0;
#define STARTERMAX 10
static void
_dwarf_reset_index_stack(void)
{
next_to_use = 0;
was_fault = 0;
}
static int
_dwarf_mac_push_index(Dwarf_Debug dbg, Dwarf_Signed indx)
{
Dwarf_Signed *newbase;
if (next_to_use >= max) {
long new_size;
if (max == 0) {
max = STARTERMAX;
}
new_size = max * 2;
newbase =
_dwarf_get_alloc(dbg, DW_DLA_STRING,
new_size * sizeof(Dwarf_Signed));
if (newbase == 0) {
was_fault = 1;
return DW_DLV_ERROR;
}
memcpy(newbase, st_base, next_to_use * sizeof(Dwarf_Signed));
dwarf_dealloc(dbg, st_base, DW_DLA_STRING);
st_base = newbase;
max = new_size;
}
st_base[next_to_use] = indx;
++next_to_use;
return DW_DLV_OK;
}
static Dwarf_Signed
_dwarf_mac_pop_index(void)
{
if (was_fault) {
return -1;
}
if (next_to_use > 0) {
next_to_use--;
return (*(st_base + next_to_use));
}
return -1;
}
int
dwarf_get_macro_details(Dwarf_Debug dbg,
Dwarf_Off macro_offset,
Dwarf_Unsigned maximum_count,
Dwarf_Signed * entry_count,
Dwarf_Macro_Details ** details,
Dwarf_Error * error)
{
Dwarf_Small *macro_base = 0;
Dwarf_Small *pnext = 0;
Dwarf_Unsigned endloc = 0;
unsigned char uc = 0;
unsigned long depth = 0;
int res = 0;
unsigned long str_space = 0;
int done = 0;
unsigned long space_needed = 0;
unsigned long string_offset = 0;
Dwarf_Small *return_data = 0;
Dwarf_Small *pdata = 0;
unsigned long final_count = 0;
Dwarf_Signed fileindex = -1;
Dwarf_Small *latest_str_loc = 0;
unsigned long count = 0;
unsigned long max_count = (unsigned long) maximum_count;
_dwarf_reset_index_stack();
if (dbg == NULL) {
_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
return (DW_DLV_ERROR);
}
res =
_dwarf_load_section(dbg,
dbg->de_debug_macinfo_index,
&dbg->de_debug_macinfo, error);
if (res != DW_DLV_OK) {
return res;
}
macro_base = dbg->de_debug_macinfo;
if (macro_base == NULL) {
return (DW_DLV_NO_ENTRY);
}
if (macro_offset >= dbg->de_debug_macinfo_size) {
return (DW_DLV_NO_ENTRY);
}
pnext = macro_base + macro_offset;
if (maximum_count == 0) {
max_count = ULONG_MAX;
}
endloc = (pnext - macro_base);
if (endloc >= dbg->de_debug_macinfo_size) {
if (endloc == dbg->de_debug_macinfo_size) {
return DW_DLV_NO_ENTRY;
}
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
return (DW_DLV_ERROR);
}
for (count = 0; !done && count < max_count; ++count) {
unsigned long slen;
Dwarf_Word len;
uc = *pnext;
++pnext;
switch (uc) {
case DW_MACINFO_define:
case DW_MACINFO_undef:
case DW_MACINFO_vendor_ext:
(void) _dwarf_decode_u_leb128(pnext, &len);
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
slen = strlen((char *) pnext) + 1;
pnext += slen;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
str_space += slen;
break;
case DW_MACINFO_start_file:
(void) _dwarf_decode_u_leb128(pnext, &len);
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
(void) _dwarf_decode_u_leb128(pnext, &len);
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
++depth;
break;
case DW_MACINFO_end_file:
if (--depth == 0) {
}
break;
case 0:
done = 1;
break;
default:
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
endloc = (pnext - macro_base);
if (endloc == dbg->de_debug_macinfo_size) {
done = 1;
} else if (endloc > dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
return (DW_DLV_ERROR);
}
}
if (count == 0) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INTERNAL_ERR);
return (DW_DLV_ERROR);
}
string_offset = count * sizeof(Dwarf_Macro_Details);
space_needed = string_offset + str_space + 2;
return_data = pdata =
_dwarf_get_alloc(dbg, DW_DLA_STRING, space_needed);
latest_str_loc = pdata + string_offset;
if (pdata == 0) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_MALLOC_SPACE);
return (DW_DLV_ERROR);
}
pnext = macro_base + macro_offset;
done = 0;
for (final_count = 0; !done && final_count < count; ++final_count) {
unsigned long slen;
Dwarf_Word len;
Dwarf_Unsigned v1;
Dwarf_Macro_Details *pdmd = (Dwarf_Macro_Details *) (pdata +
final_count
*
sizeof
(Dwarf_Macro_Details));
endloc = (pnext - macro_base);
if (endloc > dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_LENGTH_BAD);
return (DW_DLV_ERROR);
}
uc = *pnext;
pdmd->dmd_offset = (pnext - macro_base);
pdmd->dmd_type = uc;
pdmd->dmd_fileindex = fileindex;
pdmd->dmd_lineno = 0;
pdmd->dmd_macro = 0;
++pnext;
switch (uc) {
case DW_MACINFO_define:
case DW_MACINFO_undef:
case DW_MACINFO_vendor_ext:
v1 = _dwarf_decode_u_leb128(pnext, &len);
pdmd->dmd_lineno = v1;
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
slen = strlen((char *) pnext) + 1;
strcpy((char *) latest_str_loc, (char *) pnext);
pdmd->dmd_macro = (char *) latest_str_loc;
latest_str_loc += slen;
pnext += slen;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
str_space += slen;
break;
case DW_MACINFO_start_file:
v1 = _dwarf_decode_u_leb128(pnext, &len);
pdmd->dmd_lineno = v1;
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
v1 = _dwarf_decode_u_leb128(pnext, &len);
pdmd->dmd_fileindex = v1;
(void) _dwarf_mac_push_index(dbg, fileindex);
fileindex = v1;
pnext += len;
if (((pnext - macro_base)) >= dbg->de_debug_macinfo_size) {
_dwarf_error(dbg, error,
DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
break;
case DW_MACINFO_end_file:
fileindex = _dwarf_mac_pop_index();
break;
case 0:
done = 1;
break;
default:
_dwarf_error(dbg, error, DW_DLE_DEBUG_MACRO_INCONSISTENT);
return (DW_DLV_ERROR);
}
}
*entry_count = count;
*details = (Dwarf_Macro_Details *) return_data;
return DW_DLV_OK;
}