[PATCH] Remove some obfuscation from ${arch}_skip_prologue functions

Doug Evans
2014-09-02T23:53:11Z

Hi.

This patch is a follow up to an observation made here:
https://sourceware.org/ml/gdb-patches/2014-08/msg00539.html

Basically, I think there's either or both of some
bitrot/misunderstanding in the prologue parsers.

1) There's no need to call find_pc_partial_function before
calling skip_prologue_using_sal: The first thing skip_prologue_using_sal
does is call find_pc_partial_function!
[There is another reason for ${arch}_skip_prologue routines to call
find_pc_partial_function: to find the end address of the function
to set an upper bound on how many insns to parse. Some routines
do this, e.g., rs6000_skip_prologue, and I think some other routines
*could* do this (grep for FIXME) in the patch. However, I have not done
this here because I wanted to restrict the patch to unobfuscation.
This patch is intended to be a functional no-op - ASSUMING my observation is
correct.]

2) Several ${arch}_skip_prologue routines call skip_prologue_using_sal
a second time if the first one fails in order to find an upper bound on
insns to scan. I don't see how this can work:
If either find_pc_partial_function or the first call to
skip_prologue_using_sal fails, then the second call to
skip_prologue_using_sal is going to fail too.

I should also make clear that I'm totally willing to believe the
misunderstanding is mine! I've gone through this code several times
trying to find a situation I'm missing and I can't. Plus I've regression
tested this patch on amd64, i386, ppc64, aarch64 (and build with
--enable-targets=all). So I think the observation is valid,
but of course the testsuite may not cover the case that
is the reason why the code is the way it is currently.
At the very least, I'd like to document Why Things Are The Way They Are
if there is indeed a reason for it.

There may still be bugs in the prologue parsers, but I would like to
unobfuscate them first. Again, this patch is believed to be a
functional no-op, it just simplifies/unobfuscates the code.

Can I enlist any of the other arch maintainers to regression test this
there: lm32, mips, arm, nios2, tic6x, tilegx, avr, moxie, sh?
Some have simulators, so I may try to get a full toolchain going
for a few of them, though having tested this on four arches and having
all of the changes being mechanical, I'm ok with not checking all of them.

Arch maintainers I could find from the MAINTAINERS file:
mips: macro@codesourcery.com
moxie: green@moxielogic.com
nios2: yao@codesourcery.com
tic6x:yao@codesourcery.com

2014-09-02 Doug Evans <dje@google.com>

* symtab.c (skip_prologue_using_sal): Return zero if
find_pc_partial_function fails.
* aarch64-tdep.c (aarch64_skip_prologue): Remove redundant call
to find_pc_partial_function. Remove useless second call to
skip_prologue_using_sal.
* lm32-tdep.c (lm32_analyze_prologue): Ditto.
* mips-tdep.c (mips_skip_prologue): Ditto.
* amd64-tdep.c (amd64_skip_prologue): Remove redundant call to
find_pc_partial_function.
* amd64-windows-tdep.c (amd64_windows_skip_prologue): Ditto.
* arm-tdep.c (arm_skip_prologue): Ditto.
* i386-tdep.c (i386_skip_prologue): Ditto.
* nios2-tdep.c (nios2_skip_prologue): Ditto.
* tic6x-tdep.c (tic6x_analyze_prologue): Ditto.
* tilegx-tdep.c (tilegx_analyze_prologue): Ditto.
* avr-tdep.c (avr_skip_prologue): Clean up, call
skip_prologue_using_sal before find_pc_partial_function.
* moxie-tdep.c (moxie_analyze_prologue): Ditto.
* rs6000-tdep.c (rs6000_skip_prologue): Ditto.
* sh-tdep.c (sh_skip_prologue): Ditto. Remove useless second call to
skip_prologue_using_sal.

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 1898f6b..3f902b8 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -841,33 +841,22 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
static CORE_ADDR
aarch64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- unsigned long inst;
- CORE_ADDR skip_pc;
- CORE_ADDR func_addr, limit_pc;
- struct symtab_and_line sal;
+ CORE_ADDR limit_pc;
+ CORE_ADDR post_prologue_pc;

/* See if we can determine the end of the prologue via the symbol
table. If so, then return either PC, or the PC after the
prologue, whichever is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
-
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */

- /* Find an upper limit on the function prologue using the debug
- information. If the debug information could not be used to
- provide that bound, then use an arbitrary large number as the
- upper bound. */
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
- limit_pc = pc + 128; /* Magic. */
+ /* Use an arbitrary large number as the upper bound. */
+ limit_pc = pc + 128; /* Magic. */
+ /* FIXME: could do what rs6000-tdep.c does here */

/* Try disassembling prologue. */
return aarch64_analyze_prologue (gdbarch, pc, limit_pc, NULL);
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index abd9c48..84e2c0e 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2359,21 +2359,19 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
struct amd64_frame_cache cache;
CORE_ADDR pc;
- CORE_ADDR func_addr;
+ CORE_ADDR post_prologue_pc;

- if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+ if (post_prologue_pc != 0)
{
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- struct symtab *s = find_pc_symtab (func_addr);
+ struct symtab *s = find_pc_symtab (start_pc);

/* Clang always emits a line note before the prologue and another
one after. We trust clang to emit usable line notes. */
- if (post_prologue_pc
- && (s != NULL
- && s->producer != NULL
- && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
- return max (start_pc, post_prologue_pc);
+ if (s != NULL
+ && s->producer != NULL
+ && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0)
+ return max (start_pc, post_prologue_pc);
}

amd64_init_frame_cache (&cache);
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index f90bd5b..b800666 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1095,9 +1095,9 @@ static const struct frame_unwind amd64_windows_frame_unwind =
static CORE_ADDR
amd64_windows_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- CORE_ADDR func_addr;
CORE_ADDR unwind_info = 0;
CORE_ADDR image_base, start_rva, end_rva;
+ CORE_ADDR post_prologue_pc;
struct external_pex64_unwind_info ex_ui;

/* Use prologue size from unwind info. */
@@ -1118,14 +1118,9 @@ amd64_windows_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* See if we can determine the end of the prologue via the symbol
table. If so, then return either the PC, or the PC after
the prologue, whichever is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
-
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

return pc;
}
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index f9feb52..a14ed41 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -1384,22 +1384,16 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
unsigned long inst;
- CORE_ADDR skip_pc;
- CORE_ADDR func_addr, limit_pc;
+ CORE_ADDR skip_pc, limit_pc, post_prologue_pc;

- /* See if we can determine the end of the prologue via the symbol table.
- If so, then return either PC, or the PC after the prologue, whichever
- is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+ /* See if we can determine the end of the prologue via the symbol table. */
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
{
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- struct symtab *s = find_pc_symtab (func_addr);
-
- if (post_prologue_pc)
- post_prologue_pc
- = arm_skip_stack_protector (post_prologue_pc, gdbarch);
+ struct symtab *s = find_pc_symtab (pc);
+ CORE_ADDR analyzed_limit;

+ post_prologue_pc = arm_skip_stack_protector (post_prologue_pc, gdbarch);

/* GCC always emits a line note before the prologue and another
one after, even if the two are at the same address or on the
@@ -1407,38 +1401,32 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
know every instruction that might appear in the prologue. We
will have producer information for most binaries; if it is
missing (e.g. for -gstabs), assuming the GNU tools. */
- if (post_prologue_pc
- && (s == NULL
- || s->producer == NULL
- || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0
- || strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
+ if (s == NULL
+ || s->producer == NULL
+ || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0
+ || strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0)
return post_prologue_pc;

- if (post_prologue_pc != 0)
- {
- CORE_ADDR analyzed_limit;
-
- /* For non-GCC compilers, make sure the entire line is an
- acceptable prologue; GDB will round this function's
- return value up to the end of the following line so we
- can not skip just part of a line (and we do not want to).
+ /* For non-GCC compilers, make sure the entire line is an
+ acceptable prologue; GDB will round this function's
+ return value up to the end of the following line so we
+ can not skip just part of a line (and we do not want to).

- RealView does not treat the prologue specially, but does
- associate prologue code with the opening brace; so this
- lets us skip the first line if we think it is the opening
- brace. */
- if (arm_pc_is_thumb (gdbarch, func_addr))
- analyzed_limit = thumb_analyze_prologue (gdbarch, func_addr,
- post_prologue_pc, NULL);
- else
- analyzed_limit = arm_analyze_prologue (gdbarch, func_addr,
- post_prologue_pc, NULL);
+ RealView does not treat the prologue specially, but does
+ associate prologue code with the opening brace; so this
+ lets us skip the first line if we think it is the opening
+ brace. */
+ if (arm_pc_is_thumb (gdbarch, pc))
+ analyzed_limit = thumb_analyze_prologue (gdbarch, pc,
+ post_prologue_pc, NULL);
+ else
+ analyzed_limit = arm_analyze_prologue (gdbarch, pc,
+ post_prologue_pc, NULL);

- if (analyzed_limit != post_prologue_pc)
- return func_addr;
+ if (analyzed_limit != post_prologue_pc)
+ return pc;

- return post_prologue_pc;
- }
+ return post_prologue_pc;
}

/* Can't determine prologue from the symbol table, need to examine
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index d2b5f5f..c460959 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -874,15 +874,14 @@ avr_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
CORE_ADDR func_addr, func_end;
CORE_ADDR post_prologue_pc;

- /* See what the symbol table says */
+ /* See what the symbol table says. */
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
return pc;

- post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
-
{
CORE_ADDR prologue_end = pc;
struct avr_unwind_cache info = {0};
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 1e68505..02e3eaa 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -1812,20 +1812,18 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
CORE_ADDR pc;
gdb_byte op;
int i;
- CORE_ADDR func_addr;
+ CORE_ADDR post_prologue_pc;

- if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+ if (post_prologue_pc != 0)
{
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- struct symtab *s = find_pc_symtab (func_addr);
+ struct symtab *s = find_pc_symtab (start_pc);

/* Clang always emits a line note before the prologue and another
one after. We trust clang to emit usable line notes. */
- if (post_prologue_pc
- && (s != NULL
- && s->producer != NULL
- && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
+ if (s != NULL
+ && s->producer != NULL
+ && strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0)
return max (start_pc, post_prologue_pc);
}

diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c
index 908abce..7045d2f 100644
--- a/gdb/lm32-tdep.c
+++ b/gdb/lm32-tdep.c
@@ -185,20 +185,16 @@ lm32_analyze_prologue (struct gdbarch *gdbarch,
static CORE_ADDR
lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- CORE_ADDR func_addr, limit_pc;
+ CORE_ADDR post_prologue_pc, limit_pc;
struct lm32_frame_cache frame_info;
struct trad_frame_saved_reg saved_regs[SIM_LM32_NUM_REGS];

/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */
@@ -206,9 +202,8 @@ lm32_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
- limit_pc = pc + 100; /* Magic. */
+ limit_pc = pc + 100; /* Magic. */
+ /* FIXME: could do what rs6000-tdep.c does here */

frame_info.saved_regs = saved_regs;
return lm32_analyze_prologue (gdbarch, pc, limit_pc, &frame_info);
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 188580f..278ccfe 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -6398,18 +6398,14 @@ static CORE_ADDR
mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR limit_pc;
- CORE_ADDR func_addr;
+ CORE_ADDR post_prologue_pc;

/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */
@@ -6417,9 +6413,8 @@ mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
- limit_pc = pc + 100; /* Magic. */
+ limit_pc = pc + 100; /* Magic. */
+ /* FIXME: could do what rs6000-tdep.c does here */

if (mips_pc_is_mips16 (gdbarch, pc))
return mips16_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c
index 7926927..8b1fdfd 100644
--- a/gdb/moxie-tdep.c
+++ b/gdb/moxie-tdep.c
@@ -215,49 +215,43 @@ moxie_analyze_prologue (CORE_ADDR start_addr, CORE_ADDR end_addr,
static CORE_ADDR
moxie_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- CORE_ADDR func_addr = 0, func_end = 0;
+ CORE_ADDR func_addr, func_end;
+ CORE_ADDR post_prologue_pc;
const char *func_name;

/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
is greater. */
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+
if (find_pc_partial_function (pc, &func_name, &func_addr, &func_end))
{
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- else
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+ struct symtab_and_line sal;
+ struct symbol *sym;
+ struct moxie_frame_cache cache;
+ CORE_ADDR plg_end;
+
+ memset (&cache, 0, sizeof cache);
+
+ plg_end = moxie_analyze_prologue (func_addr, func_end, &cache, gdbarch);
+ /* Found a function. */
+ sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
+ /* Don't use line number debug info for assembly source files. */
+ if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
{
- /* Can't determine prologue from the symbol table, need to examine
- instructions. */
- struct symtab_and_line sal;
- struct symbol *sym;
- struct moxie_frame_cache cache;
- CORE_ADDR plg_end;
-
- memset (&cache, 0, sizeof cache);
-
- plg_end = moxie_analyze_prologue (func_addr,
- func_end, &cache, gdbarch);
- /* Found a function. */
- sym = lookup_symbol (func_name, NULL, VAR_DOMAIN, NULL);
- /* Don't use line number debug info for assembly source
- files. */
- if (sym && SYMBOL_LANGUAGE (sym) != language_asm)
+ sal = find_pc_line (func_addr, 0);
+ if (sal.end && sal.end < func_end)
{
- sal = find_pc_line (func_addr, 0);
- if (sal.end && sal.end < func_end)
- {
- /* Found a line number, use it as end of
- prologue. */
- return sal.end;
- }
+ /* Found a line number, use it as end of prologue. */
+ return sal.end;
}
- /* No useable line symbol. Use result of prologue parsing
- method. */
- return plg_end;
}
+ /* No useable line symbol. Use result of prologue parsing method. */
+ return plg_end;
}

/* No function symbol -- just return the PC. */
diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c
index 18a5913..b7ffa1d 100644
--- a/gdb/nios2-tdep.c
+++ b/gdb/nios2-tdep.c
@@ -945,20 +945,15 @@ nios2_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
CORE_ADDR limit_pc;
CORE_ADDR func_addr;
-
+ CORE_ADDR post_prologue_pc;
struct nios2_unwind_cache cache;

/* See if we can determine the end of the prologue via the symbol
table. If so, then return either PC, or the PC after the
prologue, whichever is greater. */
- if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
-
- if (post_prologue_pc != 0)
- return max (start_pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+ if (post_prologue_pc != 0)
+ return max (start_pc, post_prologue_pc);

/* Prologue analysis does the rest.... */
nios2_init_cache (&cache, start_pc);
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 730afe7..94c9908 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -2108,33 +2108,29 @@ static CORE_ADDR
rs6000_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
struct rs6000_framedata frame;
- CORE_ADDR limit_pc, func_addr, func_end_addr = 0;
+ CORE_ADDR limit_pc, func_addr, func_end_addr;
+ CORE_ADDR post_prologue_pc;

/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */

- /* Find an upper limit on the function prologue using the debug
- information. If the debug information could not be used to provide
- that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
- limit_pc = pc + 100; /* Magic. */
+ /* Use an arbitrary large number as the upper bound. */
+ limit_pc = pc + 100; /* Magic. */

/* Do not allow limit_pc to be past the function end, if we know
where that end is... */
- if (func_end_addr && limit_pc > func_end_addr)
- limit_pc = func_end_addr;
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
+ {
+ if (func_end_addr && limit_pc > func_end_addr)
+ limit_pc = func_end_addr;
+ }

pc = skip_prologue (gdbarch, pc, limit_pc, &frame);
return pc;
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index c8c36db..0124062 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -724,12 +724,9 @@ sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever
is greater. */
- if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
- {
- post_prologue_pc = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, pc);
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */
@@ -737,15 +734,16 @@ sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* Find an upper limit on the function prologue using the debug
information. If the debug information could not be used to provide
that bound, then use an arbitrary large number as the upper bound. */
- limit_pc = skip_prologue_using_sal (gdbarch, pc);
- if (limit_pc == 0)
- /* Don't go any further than 28 instructions. */
- limit_pc = pc + (2 * 28);
+ /* Don't go any further than 28 instructions. */
+ limit_pc = pc + (2 * 28);

/* Do not allow limit_pc to be past the function end, if we know
where that end is... */
- if (func_end_addr != 0)
- limit_pc = min (limit_pc, func_end_addr);
+ if (find_pc_partial_function (pc, NULL, &func_addr, &func_end_addr))
+ {
+ if (func_end_addr && limit_pc > func_end_addr)
+ limit_pc = func_end_addr;
+ }

cache.sp_offset = -4;
post_prologue_pc = sh_analyze_prologue (gdbarch, pc, limit_pc, &cache, 0);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index c530d50..bdaa81a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -3107,7 +3107,7 @@ in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start)
return func_addr <= pc && pc < sal.end;
}

-/* Given PC at the function's start address, attempt to find the
+/* Given FUNC_ADDR, 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
@@ -3133,7 +3133,8 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
const struct block *bl;

/* Get an initial range for the function. */
- find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
+ if (!find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc))
+ return 0;
start_pc += gdbarch_deprecated_function_start_offset (gdbarch);

prologue_sal = find_pc_line (start_pc, 0);
diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c
index ae3138e..eaa50eb 100644
--- a/gdb/tic6x-tdep.c
+++ b/gdb/tic6x-tdep.c
@@ -300,19 +300,15 @@ tic6x_analyze_prologue (struct gdbarch *gdbarch, const CORE_ADDR start_pc,
static CORE_ADDR
tic6x_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
- CORE_ADDR func_addr;
+ CORE_ADDR post_prologue_pc;
struct tic6x_unwind_cache cache;

/* See if we can determine the end of the prologue via the symbol table.
If so, then return either PC, or the PC after the prologue, whichever is
greater. */
- if (find_pc_partial_function (start_pc, NULL, &func_addr, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_addr);
- if (post_prologue_pc != 0)
- return max (start_pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+ if (post_prologue_pc != 0)
+ return max (start_pc, post_prologue_pc);

/* Can't determine prologue from the symbol table, need to examine
instructions. */
diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c
index befab56..d8b9c89 100644
--- a/gdb/tilegx-tdep.c
+++ b/gdb/tilegx-tdep.c
@@ -744,19 +744,14 @@ tilegx_analyze_prologue (struct gdbarch* gdbarch,
static CORE_ADDR
tilegx_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
- CORE_ADDR func_start, end_pc;
+ CORE_ADDR post_prologue_pc, end_pc;
struct obj_section *s;

/* This is the preferred method, find the end of the prologue by
using the debugging information. */
- if (find_pc_partial_function (start_pc, NULL, &func_start, NULL))
- {
- CORE_ADDR post_prologue_pc
- = skip_prologue_using_sal (gdbarch, func_start);
-
- if (post_prologue_pc != 0)
- return max (start_pc, post_prologue_pc);
- }
+ post_prologue_pc = skip_prologue_using_sal (gdbarch, start_pc);
+ if (post_prologue_pc != 0)
+ return max (start_pc, post_prologue_pc);

/* Don't straddle a section boundary. */
s = find_pc_section (start_pc);