Re: [rfc/rfa] Use ARM exception tables as GDB unwinder

Daniel Jacobowitz
2010-10-20T13:27:11Z

Thanks for doing this!

On Wed, Oct 20, 2010 at 02:00:56AM +0200, Ulrich Weigand wrote:
> In addition, one minor change was necessary to the prologue unwinder:
> the this_id routine no longer uses get_frame_func to retrieve the
> function start address; instead, this value is stored in the cache.
> This allows the exception unwinder to provide this information from
> the exception table, instead of having to rely on symbol data.

Like Matthew, I have some concern about this; unwind regions are not
1:1 with functions. Not only will the linker combine identical
regions, but hand-written code (or, hypothetically,
-fnon-call-exceptions) can have multiple regions in a function.
But we can probably ignore the latter case; the former can be handled
by using whichever is larger, the symbol or exception region address.

> + /* See if we have an ARM exception table entry covering this address. */
> + addr_in_block = get_frame_address_in_block (this_frame);
> + entry = arm_find_exidx_entry (addr_in_block, &func_exidx);
> + if (!entry)
> + return 0;

I assume you're deliberately treating can't-unwind and no-information
the same. We use can't-unwind to mark _start, but it also shows up in
exception handling in some cases.

> + /* The ARM exception index does not mark the *end* of the function
> + covered by the entry, and some functions will not have any entry.
> + Therefore, the entry we found above may not actually be correct
> + for this PC. As a sanity check, also try to determine the function
> + covering PC via the symbol table. If this finds a function start
> + address *closer* to PC than the one found via the exception table,
> + ignore the exception record, and fall back to prologue parsing.
> +
> + (Note that if we don't find a function via the symbol table, the
> + exception table may still be wrong. But in this case, prologue
> + parsing wouldn't work anyway, so we use the exception table and
> + hope for the best.) */
> + if (find_pc_partial_function (addr_in_block, NULL, &func_symtab, NULL)
> + && func_symtab > func_exidx)
> + return 0;

This doesn't go well with the discussion above about combined
exception regions... did you encounter this problem in practice? The
linker used to have this problem, but hasn't for a while (circa
2009-05-05).

The actual unwinder looks OK to me. If you want to handle C++ code
with exceptions (or C with cleanups), you'll need to check the name of
the referenced personality routine; it is __gxx_personality_v0 (et
cetera). Readelf has a sample of that. Code which doesn't throw or
catch uses the standard personality routines, as you've implemented.

--
Daniel Jacobowitz
CodeSourcery