diff options
author | Doug Evans <dje@google.com> | 2014-08-28 16:15:23 -0700 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2014-08-28 16:15:23 -0700 |
commit | f1f58506e2b52740916fa233d3b223733e3847cf (patch) | |
tree | 13ac5e96d0aeeb554adfcccdf718d3482c7aa450 | |
parent | aab2f20890b9252f88a157611df14e79902e02b6 (diff) | |
download | gdb-f1f58506e2b52740916fa233d3b223733e3847cf.zip gdb-f1f58506e2b52740916fa233d3b223733e3847cf.tar.gz gdb-f1f58506e2b52740916fa233d3b223733e3847cf.tar.bz2 |
Move definition of some prologue-related functions to a better location.
gdb/ChangeLog:
* symtab.c (in_prologue): Move definition to better spot.
(skip_prologue_using_sal): Ditto.
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/symtab.c | 374 |
2 files changed, 192 insertions, 187 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bc3d401..1da3063 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,10 @@ 2014-08-28 Doug Evans <dje@google.com> + * symtab.c (in_prologue): Move definition to better spot. + (skip_prologue_using_sal): Ditto. + +2014-08-28 Doug Evans <dje@google.com> + * symtab.c (find_function_start_sal): Move definition to better spot. 2014-08-28 Yao Qi <yao@codesourcery.com> diff --git a/gdb/symtab.c b/gdb/symtab.c index c505f97..c530d50 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3034,6 +3034,193 @@ skip_prologue_sal (struct symtab_and_line *sal) } } +/* Determine if PC is in the prologue of a function. The prologue is the area + between the first instruction of a function, and the first executable line. + Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. + + If non-zero, func_start is where we think the prologue starts, possibly + by previous examination of symbol table information. */ + +int +in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) +{ + struct symtab_and_line sal; + CORE_ADDR func_addr, func_end; + + /* We have several sources of information we can consult to figure + this out. + - Compilers usually emit line number info that marks the prologue + as its own "source line". So the ending address of that "line" + is the end of the prologue. If available, this is the most + reliable method. + - The minimal symbols and partial symbols, which can usually tell + us the starting and ending addresses of a function. + - If we know the function's start address, we can call the + architecture-defined gdbarch_skip_prologue function to analyze the + instruction stream and guess where the prologue ends. + - Our `func_start' argument; if non-zero, this is the caller's + best guess as to the function's entry point. At the time of + this writing, handle_inferior_event doesn't get this right, so + it should be our last resort. */ + + /* Consult the partial symbol table, to find which function + the PC is in. */ + if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + CORE_ADDR prologue_end; + + /* We don't even have minsym information, so fall back to using + func_start, if given. */ + if (! func_start) + return 1; /* We *might* be in a prologue. */ + + prologue_end = gdbarch_skip_prologue (gdbarch, func_start); + + return func_start <= pc && pc < prologue_end; + } + + /* If we have line number information for the function, that's + usually pretty reliable. */ + sal = find_pc_line (func_addr, 0); + + /* Now sal describes the source line at the function's entry point, + which (by convention) is the prologue. The end of that "line", + sal.end, is the end of the prologue. + + Note that, for functions whose source code is all on a single + line, the line number information doesn't always end up this way. + So we must verify that our purported end-of-prologue address is + *within* the function, not at its start or end. */ + if (sal.line == 0 + || sal.end <= func_addr + || func_end <= sal.end) + { + /* We don't have any good line number info, so use the minsym + information, together with the architecture-specific prologue + scanning code. */ + CORE_ADDR prologue_end = gdbarch_skip_prologue (gdbarch, func_addr); + + return func_addr <= pc && pc < prologue_end; + } + + /* We have line number info, and it looks good. */ + return func_addr <= pc && pc < sal.end; +} + +/* Given PC at the function's start address, attempt to find the + prologue end using SAL information. Return zero if the skip fails. + + A non-optimized prologue traditionally has one SAL for the function + and a second for the function body. A single line function has + them both pointing at the same line. + + An optimized prologue is similar but the prologue may contain + instructions (SALs) from the instruction body. Need to skip those + while not getting into the function body. + + The functions end point and an increasing SAL line are used as + indicators of the prologue's endpoint. + + This code is based on the function refine_prologue_limit + (found in ia64). */ + +CORE_ADDR +skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) +{ + struct symtab_and_line prologue_sal; + CORE_ADDR start_pc; + CORE_ADDR end_pc; + const struct block *bl; + + /* Get an initial range for the function. */ + find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc); + start_pc += gdbarch_deprecated_function_start_offset (gdbarch); + + prologue_sal = find_pc_line (start_pc, 0); + if (prologue_sal.line != 0) + { + /* For languages other than assembly, treat two consecutive line + entries at the same address as a zero-instruction prologue. + The GNU assembler emits separate line notes for each instruction + in a multi-instruction macro, but compilers generally will not + do this. */ + if (prologue_sal.symtab->language != language_asm) + { + struct linetable *linetable = LINETABLE (prologue_sal.symtab); + int idx = 0; + + /* Skip any earlier lines, and any end-of-sequence marker + from a previous function. */ + while (linetable->item[idx].pc != prologue_sal.pc + || linetable->item[idx].line == 0) + idx++; + + if (idx+1 < linetable->nitems + && linetable->item[idx+1].line != 0 + && linetable->item[idx+1].pc == start_pc) + return start_pc; + } + + /* If there is only one sal that covers the entire function, + then it is probably a single line function, like + "foo(){}". */ + if (prologue_sal.end >= end_pc) + return 0; + + while (prologue_sal.end < end_pc) + { + struct symtab_and_line sal; + + sal = find_pc_line (prologue_sal.end, 0); + if (sal.line == 0) + break; + /* Assume that a consecutive SAL for the same (or larger) + line mark the prologue -> body transition. */ + if (sal.line >= prologue_sal.line) + break; + /* Likewise if we are in a different symtab altogether + (e.g. within a file included via #include). */ + if (sal.symtab != prologue_sal.symtab) + break; + + /* The line number is smaller. Check that it's from the + same function, not something inlined. If it's inlined, + then there is no point comparing the line numbers. */ + bl = block_for_pc (prologue_sal.end); + while (bl) + { + if (block_inlined_p (bl)) + break; + if (BLOCK_FUNCTION (bl)) + { + bl = NULL; + break; + } + bl = BLOCK_SUPERBLOCK (bl); + } + if (bl != NULL) + break; + + /* The case in which compiler's optimizer/scheduler has + moved instructions into the prologue. We look ahead in + the function looking for address ranges whose + corresponding line number is less the first one that we + found for the function. This is more conservative then + refine_prologue_limit which scans a large number of SALs + looking for any in the prologue. */ + prologue_sal = sal; + } + } + + if (prologue_sal.end < end_pc) + /* Return the end of this line, or zero if we could not find a + line. */ + return prologue_sal.end; + else + /* Don't return END_PC, which is past the end of the function. */ + return prologue_sal.pc; +} + /* If P is of the form "operator[ \t]+..." where `...' is some legitimate operator text, return a pointer to the beginning of the substring of the operator text. @@ -4827,193 +5014,6 @@ make_source_files_completion_list (const char *text, const char *word) return list; } - -/* Determine if PC is in the prologue of a function. The prologue is the area - between the first instruction of a function, and the first executable line. - Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue. - - If non-zero, func_start is where we think the prologue starts, possibly - by previous examination of symbol table information. */ - -int -in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) -{ - struct symtab_and_line sal; - CORE_ADDR func_addr, func_end; - - /* We have several sources of information we can consult to figure - this out. - - Compilers usually emit line number info that marks the prologue - as its own "source line". So the ending address of that "line" - is the end of the prologue. If available, this is the most - reliable method. - - The minimal symbols and partial symbols, which can usually tell - us the starting and ending addresses of a function. - - If we know the function's start address, we can call the - architecture-defined gdbarch_skip_prologue function to analyze the - instruction stream and guess where the prologue ends. - - Our `func_start' argument; if non-zero, this is the caller's - best guess as to the function's entry point. At the time of - this writing, handle_inferior_event doesn't get this right, so - it should be our last resort. */ - - /* Consult the partial symbol table, to find which function - the PC is in. */ - if (! find_pc_partial_function (pc, NULL, &func_addr, &func_end)) - { - CORE_ADDR prologue_end; - - /* We don't even have minsym information, so fall back to using - func_start, if given. */ - if (! func_start) - return 1; /* We *might* be in a prologue. */ - - prologue_end = gdbarch_skip_prologue (gdbarch, func_start); - - return func_start <= pc && pc < prologue_end; - } - - /* If we have line number information for the function, that's - usually pretty reliable. */ - sal = find_pc_line (func_addr, 0); - - /* Now sal describes the source line at the function's entry point, - which (by convention) is the prologue. The end of that "line", - sal.end, is the end of the prologue. - - Note that, for functions whose source code is all on a single - line, the line number information doesn't always end up this way. - So we must verify that our purported end-of-prologue address is - *within* the function, not at its start or end. */ - if (sal.line == 0 - || sal.end <= func_addr - || func_end <= sal.end) - { - /* We don't have any good line number info, so use the minsym - information, together with the architecture-specific prologue - scanning code. */ - CORE_ADDR prologue_end = gdbarch_skip_prologue (gdbarch, func_addr); - - return func_addr <= pc && pc < prologue_end; - } - - /* We have line number info, and it looks good. */ - return func_addr <= pc && pc < sal.end; -} - -/* Given PC at the function's start address, attempt to find the - prologue end using SAL information. Return zero if the skip fails. - - A non-optimized prologue traditionally has one SAL for the function - and a second for the function body. A single line function has - them both pointing at the same line. - - An optimized prologue is similar but the prologue may contain - instructions (SALs) from the instruction body. Need to skip those - while not getting into the function body. - - The functions end point and an increasing SAL line are used as - indicators of the prologue's endpoint. - - This code is based on the function refine_prologue_limit - (found in ia64). */ - -CORE_ADDR -skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) -{ - struct symtab_and_line prologue_sal; - CORE_ADDR start_pc; - CORE_ADDR end_pc; - const struct block *bl; - - /* Get an initial range for the function. */ - find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc); - start_pc += gdbarch_deprecated_function_start_offset (gdbarch); - - prologue_sal = find_pc_line (start_pc, 0); - if (prologue_sal.line != 0) - { - /* For languages other than assembly, treat two consecutive line - entries at the same address as a zero-instruction prologue. - The GNU assembler emits separate line notes for each instruction - in a multi-instruction macro, but compilers generally will not - do this. */ - if (prologue_sal.symtab->language != language_asm) - { - struct linetable *linetable = LINETABLE (prologue_sal.symtab); - int idx = 0; - - /* Skip any earlier lines, and any end-of-sequence marker - from a previous function. */ - while (linetable->item[idx].pc != prologue_sal.pc - || linetable->item[idx].line == 0) - idx++; - - if (idx+1 < linetable->nitems - && linetable->item[idx+1].line != 0 - && linetable->item[idx+1].pc == start_pc) - return start_pc; - } - - /* If there is only one sal that covers the entire function, - then it is probably a single line function, like - "foo(){}". */ - if (prologue_sal.end >= end_pc) - return 0; - - while (prologue_sal.end < end_pc) - { - struct symtab_and_line sal; - - sal = find_pc_line (prologue_sal.end, 0); - if (sal.line == 0) - break; - /* Assume that a consecutive SAL for the same (or larger) - line mark the prologue -> body transition. */ - if (sal.line >= prologue_sal.line) - break; - /* Likewise if we are in a different symtab altogether - (e.g. within a file included via #include). */ - if (sal.symtab != prologue_sal.symtab) - break; - - /* The line number is smaller. Check that it's from the - same function, not something inlined. If it's inlined, - then there is no point comparing the line numbers. */ - bl = block_for_pc (prologue_sal.end); - while (bl) - { - if (block_inlined_p (bl)) - break; - if (BLOCK_FUNCTION (bl)) - { - bl = NULL; - break; - } - bl = BLOCK_SUPERBLOCK (bl); - } - if (bl != NULL) - break; - - /* The case in which compiler's optimizer/scheduler has - moved instructions into the prologue. We look ahead in - the function looking for address ranges whose - corresponding line number is less the first one that we - found for the function. This is more conservative then - refine_prologue_limit which scans a large number of SALs - looking for any in the prologue. */ - prologue_sal = sal; - } - } - - if (prologue_sal.end < end_pc) - /* Return the end of this line, or zero if we could not find a - line. */ - return prologue_sal.end; - else - /* Don't return END_PC, which is past the end of the function. */ - return prologue_sal.pc; -} /* Track MAIN */ |