#include "defs.h"
#include "symtab.h"
#include "bfd.h"
#include "objfiles.h"
#include "frame.h"
#include "gdbcore.h"
#include "value.h"
#include "target.h"
#include "inferior.h"
#include "annotate.h"
#include "regcache.h"
#include "gdb_assert.h"
#include "dummy-frame.h"
#include "command.h"
#include "gdbcmd.h"
#include "block.h"
void _initialize_blockframe (void);
int
addr_inside_main_func (CORE_ADDR pc)
{
struct minimal_symbol *msymbol;
if (symfile_objfile == 0)
return 0;
if (symfile_objfile->ei.main_func_lowpc != INVALID_ENTRY_LOWPC
&& symfile_objfile->ei.main_func_highpc != INVALID_ENTRY_LOWPC)
return (symfile_objfile->ei.main_func_lowpc <= pc
&& symfile_objfile->ei.main_func_highpc > pc);
msymbol = lookup_minimal_symbol (main_name (), NULL, NULL);
if (msymbol != NULL
&& symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC
&& symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
{
struct symbol *mainsym =
find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK)
{
struct block *bl = SYMBOL_BLOCK_VALUE (mainsym);
if (BLOCK_RANGES (bl))
{
int last = BLOCK_RANGES (bl)->nelts - 1;
symfile_objfile->ei.main_func_lowpc = BLOCK_LOWEST_PC (bl);
symfile_objfile->ei.main_func_highpc = BLOCK_HIGHEST_PC (bl);
}
else
{
symfile_objfile->ei.main_func_lowpc =
BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
symfile_objfile->ei.main_func_highpc =
BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
}
}
}
if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text)
{
CORE_ADDR maddr = SYMBOL_VALUE_ADDRESS (msymbol);
asection *msect = SYMBOL_BFD_SECTION (msymbol);
struct obj_section *osect = find_pc_sect_section (maddr, msect);
if (osect != NULL)
{
int i;
for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
{
if (SYMBOL_VALUE_ADDRESS (msymbol + i) != maddr
&& SYMBOL_BFD_SECTION (msymbol + i) == msect)
break;
}
symfile_objfile->ei.main_func_lowpc = maddr;
if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
&& SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
symfile_objfile->ei.main_func_highpc =
SYMBOL_VALUE_ADDRESS (msymbol + i);
else
symfile_objfile->ei.main_func_highpc = osect->endaddr;
}
}
return (symfile_objfile->ei.main_func_lowpc <= pc
&& symfile_objfile->ei.main_func_highpc > pc);
}
struct block *
get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
{
const CORE_ADDR pc = get_frame_address_in_block (frame);
if (addr_in_block)
*addr_in_block = pc;
return block_for_pc (pc);
}
CORE_ADDR
get_pc_function_start (CORE_ADDR pc)
{
struct block *bl;
struct minimal_symbol *msymbol;
bl = block_for_pc (pc);
if (bl)
{
struct symbol *symbol = block_function (bl);
if (symbol)
{
bl = SYMBOL_BLOCK_VALUE (symbol);
return BLOCK_LOWEST_PC (bl);
}
}
msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol)
{
CORE_ADDR fstart = SYMBOL_VALUE_ADDRESS (msymbol);
if (find_pc_section (fstart))
return fstart;
}
return 0;
}
struct symbol *
get_frame_function (struct frame_info *frame)
{
struct block *bl = get_frame_block (frame, 0);
if (bl == 0)
return 0;
return block_function (bl);
}
struct symbol *
find_pc_sect_function (CORE_ADDR pc, struct bfd_section *section)
{
struct block *b;
if (pc == last_function_lookup_pc
&& pc == last_mapped_section_lookup_pc
&& section == cached_mapped_section
&& cached_pc_function)
return cached_pc_function;
last_function_lookup_pc = pc;
b = block_for_pc_sect (pc, section);
if (b == 0)
{
cached_pc_function = NULL;
return 0;
}
cached_pc_function = block_function (b);
return block_function (b);
}
struct symbol *
find_pc_function (CORE_ADDR pc)
{
return find_pc_sect_function (pc, find_pc_mapped_section (pc));
}
static CORE_ADDR cache_pc_function_low = 0;
static CORE_ADDR cache_pc_function_high = 0;
static char *cache_pc_function_name = 0;
static struct bfd_section *cache_pc_function_section = NULL;
void
clear_pc_function_cache (void)
{
cache_pc_function_low = 0;
cache_pc_function_high = 0;
cache_pc_function_name = (char *) 0;
cache_pc_function_section = NULL;
}
int
find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
CORE_ADDR *endaddr)
{
struct bfd_section *section;
struct partial_symtab *pst;
struct symbol *f;
struct minimal_symbol *msymbol;
struct partial_symbol *psb;
struct obj_section *osect;
int i;
CORE_ADDR mapped_pc;
section = find_pc_overlay (pc);
if (section == NULL)
{
struct obj_section *obj_section = find_pc_section (pc);
if (obj_section == NULL)
section = NULL;
else
section = obj_section->the_bfd_section;
}
mapped_pc = overlay_mapped_address (pc, section);
if (mapped_pc >= cache_pc_function_low
&& mapped_pc < cache_pc_function_high
&& section == cache_pc_function_section)
goto return_cached_value;
msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
pst = find_pc_sect_psymtab (mapped_pc, section);
if (pst)
{
if (endaddr != NULL && !pst->readin)
{
target_terminal_ours_for_output ();
PSYMTAB_TO_SYMTAB (pst);
}
if (pst->readin)
{
f = find_pc_sect_function (mapped_pc, section);
if (f != NULL
&& (msymbol == NULL
|| (BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (f))
>= SYMBOL_VALUE_ADDRESS (msymbol))))
{
cache_pc_function_low = BLOCK_LOWEST_PC (SYMBOL_BLOCK_VALUE (f));
if (BLOCK_RANGES (SYMBOL_BLOCK_VALUE (f)))
cache_pc_function_high =
BLOCK_HIGHEST_PC (SYMBOL_BLOCK_VALUE (f));
else
cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
cache_pc_function_name = DEPRECATED_SYMBOL_NAME (f);
cache_pc_function_section = section;
goto return_cached_value;
}
}
else
{
psb = find_pc_sect_psymbol (pst, mapped_pc, section);
if (psb
&& (msymbol == NULL ||
(SYMBOL_VALUE_ADDRESS (psb)
>= SYMBOL_VALUE_ADDRESS (msymbol))))
{
if (address)
*address = SYMBOL_VALUE_ADDRESS (psb);
if (name)
*name = DEPRECATED_SYMBOL_NAME (psb);
return 1;
}
}
}
osect = find_pc_sect_section (mapped_pc, section);
if (!osect)
msymbol = NULL;
if (msymbol == NULL)
{
if (name != NULL)
*name = 0;
if (address != NULL)
*address = 0;
if (endaddr != NULL)
*endaddr = 0;
return 0;
}
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
cache_pc_function_name = DEPRECATED_SYMBOL_NAME (msymbol);
cache_pc_function_section = section;
for (i = 1; DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL; i++)
{
if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol)
&& SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol))
break;
}
if (DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL
&& SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
else
cache_pc_function_high = osect->endaddr;
return_cached_value:
if (address)
{
if (pc_in_unmapped_range (pc, section))
*address = overlay_unmapped_address (cache_pc_function_low, section);
else
*address = cache_pc_function_low;
}
if (name)
*name = cache_pc_function_name;
if (endaddr)
{
if (pc_in_unmapped_range (pc, section))
{
*endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1,
section);
}
else
*endaddr = cache_pc_function_high;
}
return 1;
}
struct frame_info *
block_innermost_frame (struct block *block)
{
struct frame_info *frame;
CORE_ADDR start;
CORE_ADDR end;
CORE_ADDR calling_pc;
if (block == NULL)
return NULL;
start = BLOCK_START (block);
end = BLOCK_END (block);
frame = NULL;
while (1)
{
frame = get_prev_frame (frame);
if (frame == NULL)
return NULL;
calling_pc = get_frame_address_in_block (frame);
if (block_contains_pc (block, calling_pc))
return frame;
}
}