* [branch patch] dwarf-frame.c support for .eh_frame_hdr
@ 2003-05-12 9:47 Roland McGrath
2003-05-13 3:27 ` Elena Zannoni
2003-05-15 21:49 ` Mark Kettenis
0 siblings, 2 replies; 8+ messages in thread
From: Roland McGrath @ 2003-05-12 9:47 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
[Please note that I am not on the mailing list, and keep me CC'd.]
These patches to kettenis_i386newframe-20030419-branch gdb make
dwarf-frame.c support .eh_frame_hdr format.
This is more complex than what I had anticipated writing. I had expected to
decode the .eh_frame_hdr contents only to locate the .eh_frame section and
then just read that as is done when the section is known by name. However,
AFAICT there is no way to tell from the contents of .eh_frame where it ends.
When you don't know the exact bounds of the section, you can try to read off
the end of it and become confused. When you have only .eh_frame_hdr
information to go on, you know where .eh_frame starts but not where it ends,
so you don't know how much to decode. The only thing I can find that works
is to follow the FDE quick-lookup table in the .eh_frame_hdr section,
reading the FDEs pointed to and the CIEs they point to, rather than reading
the whole .eh_frame section from start to finish. I implemented that.
(Though the description of the .eh_frame_hdr format calls the lookup table
"optional", from looking at the libgcc code, I think it may well wind up
crashing in some cases if there is an .eh_frame_hdr section without a lookup
table, because it can read off the end of the .eh_frame section.)
The symfile.c change is necessary for "add-symbol-file" to be usable, which
is how I tested the new code. The following snippet of a gdb session using
this patch demonstrates how adding the core file as a symfile and thus
reading its .eh_frame_hdr table makes backtraces from vsyscall PCs suddenly
start working right. (I editted out some boring messges.)
(gdb) core ./core.23363
Core was generated by `/home/roland/build/newthreads-libc/elf/ld-linux.so.2 --library-path /home/rolan'.
Program terminated with signal 3, Quit.
#0 0xffffe410 in ?? ()
(gdb) bt
#0 0xffffe410 in ?? ()
(gdb) i fr 0
Stack frame at 0x0:
eip = 0xffffe410; saved eip 0xbffff698
Arglist at 0xbffff664, args:
Locals at 0xbffff664, Previous frame's sp is 0xbffff66c
Saved registers:
eip at 0xbffff668
(gdb) add-symbol-file core.23363
add symbol table from file "core.23363" at
(y or n) y
Reading symbols from core.23363...done.
(gdb) bt
#0 0xffffe410 in _r_debug ()
#1 0x400cd473 in read () at ctype.h:51
#2 0x40070012 in _IO_file_read (fp=0xfffffe00, buf=0xfffffe00, size=-512) at fileops.c:1208
#3 0x4006ed9c in _IO_new_file_underflow (fp=0x401294a0) at fileops.c:591
#4 0x4007122d in _IO_default_uflow (fp=0x401294a0) at genops.c:430
#5 0x40071076 in *__GI___uflow (fp=0x401294a0) at genops.c:384
#6 0x4006af9f in getchar () at getchar.c:44
#7 0x0804834d in main () at loser.c:1
(gdb) i fr 0
Stack frame at 0xbffff678:
eip = 0xffffe410 in _r_debug; saved eip 0x400cd473
called by frame at 0xbffff680
Arglist at 0xbffff664, args:
Locals at 0xbffff664, Previous frame's sp is 0xbffff678
Saved registers:
ebp at 0xbffff668, eip at 0xbffff674
(gdb)
(Of course "_r_debug" is bogus, it's just the highest-addressed candidate
symbol or something or other. gdb really ought to notice that it's not in
the same symfile section and not use that symbol for that address.)
Thanks,
Roland
2003-05-12 Roland McGrath <roland@redhat.com>
* dwarf2read.c (dwarf_eh_frame_hdr_offset, dwarf_eh_frame_hdr_size,
dwarf_eh_frame_hdr_section): New variables.
(dwarf2_locate_sections): Match a section whose name starts with
"eh_frame_hdr", and set those.
(dwarf2_has_info): Clear dwarf_eh_frame_hdr_offset here.
* dwarf-frame.c (decode_eh_frame_hdr): New function.
(dwarf2_build_frame_info): Call it when dwarf_eh_frame_hdr_offset
is set but dwarf_eh_frame_offset is not.
* symfile.c (symfile_bfd_open): Try bfd_check_format with bfd_core
if bfd_object fails.
Index: dwarf-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/Attic/dwarf-frame.c,v
retrieving revision 1.1.2.3
diff -b -B -p -u -r1.1.2.3 dwarf-frame.c
--- dwarf-frame.c 10 May 2003 15:49:09 -0000 1.1.2.3
+++ dwarf-frame.c 12 May 2003 09:17:02 -0000
@@ -697,8 +697,9 @@ struct comp_unit
/* Length of the loaded .debug_frame section. */
unsigned long dwarf_frame_size;
- /* Pointer to the .debug_frame section. */
- asection *dwarf_frame_section;
+ /* VMA corresponding to the beginning of the buffer,
+ for relative addressing calculations. */
+ bfd_vma dwarf_frame_vma;
};
static unsigned int
@@ -851,8 +852,7 @@ read_encoded_value (struct comp_unit *un
base = 0;
break;
case DW_EH_PE_pcrel:
- base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
- base += (buf - unit->dwarf_frame_buffer);
+ base = unit->dwarf_frame_vma + (buf - unit->dwarf_frame_buffer);
break;
default:
internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
@@ -958,7 +958,7 @@ add_fde (struct comp_unit *unit, struct
#define DW64_CIE_ID ~0
#endif
-/* Read and the CIE or FDE in BUF and decode it. */
+/* Read the CIE or FDE in BUF and decode it. */
static char *
decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
@@ -1161,11 +1161,170 @@ extern asection *dwarf_frame_section;
extern file_ptr dwarf_eh_frame_offset;
extern unsigned int dwarf_eh_frame_size;
extern asection *dwarf_eh_frame_section;
+extern file_ptr dwarf_eh_frame_hdr_offset;
+extern unsigned int dwarf_eh_frame_hdr_size;
+extern asection *dwarf_eh_frame_hdr_section;
/* Imported from dwarf2read.c. */
extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
unsigned int size, asection *sectp);
+/* Decode .eh_frame_hdr format in dwarf_eh_frame_hdr_section. */
+static void
+decode_eh_frame_hdr (struct comp_unit *unit)
+{
+ char hdr[4], buf[16];
+ ufile_ptr posn;
+ CORE_ADDR eh_frame_addr;
+ CORE_ADDR fde_count;
+ unsigned int len, element_size;
+ asection *sec;
+ struct comp_unit dummy;
+
+ if (bfd_seek (unit->abfd, dwarf_eh_frame_hdr_offset, SEEK_SET)
+ || bfd_bread (hdr, sizeof hdr, unit->abfd) != sizeof hdr)
+ {
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (unit->abfd));
+ return;
+ }
+ if (hdr[0] != 1)
+ {
+ warning ("Dwarf Error: %s: %s header version %d (expected %d)",
+ bfd_get_filename (unit->abfd),
+ dwarf_eh_frame_hdr_section->name,
+ hdr[0], 1);
+ return;
+ }
+
+ len = size_of_encoded_value (hdr[1]);
+ gdb_assert (len <= sizeof buf);
+ if (bfd_bread (buf, len, unit->abfd) != len)
+ {
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (unit->abfd));
+ return;
+ }
+
+ /* read_encoded_value uses these to calculate the vma. */
+ dummy.abfd = unit->abfd;
+ dummy.dwarf_frame_vma = (bfd_get_section_vma (unit->abfd,
+ dwarf_eh_frame_hdr_section)
+ + sizeof hdr);
+ dummy.dwarf_frame_buffer = buf;
+
+ eh_frame_addr = read_encoded_value (&dummy, hdr[1], buf, &len);
+ gdb_assert (len <= sizeof buf);
+
+ len = size_of_encoded_value (hdr[2]);
+ if (len == 0)
+ /* No FDE table, and no way to know where .eh_frame ends!
+ We cannot use this. */
+ return;
+
+ dummy.dwarf_frame_vma += len;
+ gdb_assert (len <= sizeof buf);
+ if (bfd_bread (buf, len, unit->abfd) != len)
+ {
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (unit->abfd));
+ return;
+ }
+ fde_count = read_encoded_value (&dummy, hdr[2], buf, &len);
+ gdb_assert (len <= sizeof buf);
+ dummy.dwarf_frame_vma += len;
+
+ element_size = size_of_encoded_value (hdr[3]);
+ if (element_size == 0 || fde_count == 0)
+ /* No FDE table, and no way to know where .eh_frame ends!
+ We cannot use this. */
+ return;
+
+ /* Save the position of the FDE table. */
+ posn = bfd_tell (unit->abfd);
+
+ /* Now EH_FRAME_ADDR tells us where a .eh_frame section lies. We
+ presumably don't have real section headers or we would have seen
+ it by the name ".eh_frame" already. The BFD sections we have are
+ probably synthesized from ELF phdrs, as for a core file or a
+ stripped executable or DSO, i.e. the section we find corresponds
+ to our whole text segment. We have no way of knowing how large
+ the .eh_frame section should be, so we have to read through til
+ the end of the segment. Fortunately, .eh_frame_hdr is usually
+ the last thing in text, so we likely won't read much extra. */
+ for (sec = unit->abfd->sections; sec != NULL; sec = sec->next)
+ if ((sec->flags & SEC_ALLOC)
+ && sec->vma <= eh_frame_addr
+ && (sec->vma + bfd_get_section_size_before_reloc (sec)
+ > eh_frame_addr))
+ break;
+ if (sec == NULL)
+ {
+ warning ("\
+Dwarf Error: No section contains eh_frame address 0x%08lx [in module %s]",
+ (long) eh_frame_addr, bfd_get_filename (unit->abfd));
+ return;
+ }
+
+ unit->dwarf_frame_vma = eh_frame_addr;
+ eh_frame_addr -= bfd_get_section_vma (unit->abfd, sec);
+ unit->dwarf_frame_size = (bfd_get_section_size_before_reloc (sec)
+ - eh_frame_addr);
+ unit->dwarf_frame_buffer = dwarf2_read_section (unit->objfile,
+ sec->filepos + eh_frame_addr,
+ unit->dwarf_frame_size,
+ sec);
+
+
+ /* Now that we have read in the whole .eh_frame section, we cannot
+ just feed it all to decode_frame_entry, unfortunately. We don't
+ actually know where the .eh_frame section ends, and it contains
+ no internal end marker. So instead we have to work from the FDE
+ quick-lookup table in .eh_frame_hdr, whose size we do know. */
+ if (bfd_seek (unit->abfd, posn, SEEK_SET))
+ {
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (unit->abfd));
+ return;
+ }
+ while (fde_count-- > 0)
+ {
+ CORE_ADDR fde_pointer;
+
+ if (bfd_bread (buf, element_size * 2, unit->abfd) != element_size * 2)
+ {
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (unit->abfd));
+ return;
+ }
+
+ if ((hdr[3] & 0x70) == DW_EH_PE_datarel)
+ /* In this case, it's relative to the vma of .eh_frame_hdr. */
+ fde_pointer = (bfd_get_section_vma (unit->abfd,
+ dwarf_eh_frame_hdr_section)
+ + read_encoded_value (&dummy,
+ DW_EH_PE_absptr | (hdr[3] & 0x0f),
+ &buf[element_size], &len));
+ else
+ fde_pointer = read_encoded_value (&dummy, hdr[3],
+ &buf[element_size], &len);
+ gdb_assert (len == element_size);
+ dummy.dwarf_frame_vma += element_size * 2;
+
+ if (fde_pointer < unit->dwarf_frame_vma
+ || fde_pointer > unit->dwarf_frame_vma + unit->dwarf_frame_size)
+ {
+ warning ("Dwarf Error: \
+Bogus FDE pointer 0x%08lx from .eh_frame_hdr table [in module %s]",
+ (long) fde_pointer, bfd_get_filename (unit->abfd));
+ continue;
+ }
+ fde_pointer -= unit->dwarf_frame_vma;
+ (void) decode_frame_entry (unit,
+ unit->dwarf_frame_buffer + fde_pointer, 1);
+ }
+}
+
void
dwarf2_build_frame_info (struct objfile *objfile)
{
@@ -1176,34 +1335,39 @@ dwarf2_build_frame_info (struct objfile
unit.abfd = objfile->obfd;
unit.objfile = objfile;
unit.addr_size = objfile->obfd->arch_info->bits_per_address / 8;
+ unit.cie = NULL;
/* First add the information from the .eh_frame section. That way,
the FDEs from that section are searched last. */
if (dwarf_eh_frame_offset)
{
- unit.cie = NULL;
unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
dwarf_eh_frame_offset,
dwarf_eh_frame_size,
dwarf_eh_frame_section);
unit.dwarf_frame_size = dwarf_eh_frame_size;
- unit.dwarf_frame_section = dwarf_eh_frame_section;
+ unit.dwarf_frame_vma = bfd_get_section_vma (unit.bfd,
+ dwarf_eh_frame_section);
frame_ptr = unit.dwarf_frame_buffer;
while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
frame_ptr = decode_frame_entry (&unit, frame_ptr, 1);
}
+ else if (dwarf_eh_frame_hdr_offset)
+ /* We didn't find the .eh_frame section but found .eh_frame_hdr,
+ decode it to locate the .eh_frame section that actually exists. */
+ decode_eh_frame_hdr (&unit);
if (dwarf_frame_offset)
{
- unit.cie = NULL;
unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
dwarf_frame_offset,
dwarf_frame_size,
dwarf_frame_section);
unit.dwarf_frame_size = dwarf_frame_size;
- unit.dwarf_frame_section = dwarf_frame_section;
+ unit.dwarf_frame_vma = bfd_get_section_vma (unit.bfd,
+ dwarf_frame_section);
frame_ptr = unit.dwarf_frame_buffer;
while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.90
diff -b -B -p -u -r1.90 dwarf2read.c
--- dwarf2read.c 15 Apr 2003 23:07:11 -0000 1.90
+++ dwarf2read.c 12 May 2003 09:17:06 -0000
@@ -139,6 +139,7 @@ static file_ptr dwarf_str_offset;
static file_ptr dwarf_ranges_offset;
file_ptr dwarf_frame_offset;
file_ptr dwarf_eh_frame_offset;
+file_ptr dwarf_eh_frame_hdr_offset;
static unsigned int dwarf_info_size;
static unsigned int dwarf_abbrev_size;
@@ -151,6 +152,7 @@ static unsigned int dwarf_str_size;
static unsigned int dwarf_ranges_size;
unsigned int dwarf_frame_size;
unsigned int dwarf_eh_frame_size;
+unsigned int dwarf_eh_frame_hdr_size;
static asection *dwarf_info_section;
static asection *dwarf_abbrev_section;
@@ -163,6 +165,7 @@ static asection *dwarf_str_section;
static asection *dwarf_ranges_section;
asection *dwarf_frame_section;
asection *dwarf_eh_frame_section;
+asection *dwarf_eh_frame_hdr_section;
/* names of the debugging sections */
@@ -944,6 +947,7 @@ dwarf2_has_info (bfd *abfd)
dwarf_macinfo_offset = 0;
dwarf_frame_offset = 0;
dwarf_eh_frame_offset = 0;
+ dwarf_eh_frame_hdr_offset = 0;
dwarf_ranges_offset = 0;
dwarf_loc_offset = 0;
@@ -1025,6 +1029,12 @@ dwarf2_locate_sections (bfd *ignore_abfd
dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
dwarf_eh_frame_section = sectp;
}
+ else if (!strncmp (sectp->name, "eh_frame_hdr", 12))
+ {
+ dwarf_eh_frame_hdr_offset = sectp->filepos;
+ dwarf_eh_frame_hdr_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_eh_frame_hdr_section = sectp;
+ }
else if (STREQ (sectp->name, RANGES_SECTION))
{
dwarf_ranges_offset = sectp->filepos;
Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.93
diff -b -B -p -u -r1.93 symfile.c
--- symfile.c 1 Apr 2003 14:17:20 -0000 1.93
+++ symfile.c 12 May 2003 09:17:08 -0000
@@ -1338,7 +1338,9 @@ symfile_bfd_open (char *name)
}
sym_bfd->cacheable = 1;
- if (!bfd_check_format (sym_bfd, bfd_object))
+ if (!bfd_check_format (sym_bfd, bfd_object)
+ /* Yes, Virginia, core files can have symbols! */
+ && !bfd_check_format (sym_bfd, bfd_core))
{
/* FIXME: should be checking for errors from bfd_close (for one thing,
on error it does not free all the storage associated with the
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [branch patch] dwarf-frame.c support for .eh_frame_hdr
2003-05-12 9:47 [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
@ 2003-05-13 3:27 ` Elena Zannoni
2003-05-13 3:42 ` Roland McGrath
2003-05-15 21:49 ` Mark Kettenis
1 sibling, 1 reply; 8+ messages in thread
From: Elena Zannoni @ 2003-05-13 3:27 UTC (permalink / raw)
To: Roland McGrath; +Cc: Mark Kettenis, gdb-patches
Roland McGrath writes:
> [Please note that I am not on the mailing list, and keep me CC'd.]
>
> These patches to kettenis_i386newframe-20030419-branch gdb make
> dwarf-frame.c support .eh_frame_hdr format.
>
> This is more complex than what I had anticipated writing. I had expected to
> decode the .eh_frame_hdr contents only to locate the .eh_frame section and
> then just read that as is done when the section is known by name. However,
> AFAICT there is no way to tell from the contents of .eh_frame where it ends.
> When you don't know the exact bounds of the section, you can try to read off
> the end of it and become confused. When you have only .eh_frame_hdr
> information to go on, you know where .eh_frame starts but not where it ends,
> so you don't know how much to decode. The only thing I can find that works
> is to follow the FDE quick-lookup table in the .eh_frame_hdr section,
> reading the FDEs pointed to and the CIEs they point to, rather than reading
> the whole .eh_frame section from start to finish. I implemented that.
> (Though the description of the .eh_frame_hdr format calls the lookup table
> "optional", from looking at the libgcc code, I think it may well wind up
> crashing in some cases if there is an .eh_frame_hdr section without a lookup
> table, because it can read off the end of the .eh_frame section.)
Is there a way to tell if there is a table? I think that if the
fde_count_enc has a value of 0xff (DW_EH_PE_omit) it means that there
is no table. Same for the table_enc field. (If that's what you mean,
that is).
>
> The symfile.c change is necessary for "add-symbol-file" to be usable, which
> is how I tested the new code. The following snippet of a gdb session using
> this patch demonstrates how adding the core file as a symfile and thus
> reading its .eh_frame_hdr table makes backtraces from vsyscall PCs suddenly
> start working right. (I editted out some boring messges.)
>
I see that the symfile.c change is a good way to test the code, and to
verify that the stuff that ends up in the core file makes sense. This
new add-symbol-file command required to read the symbols info from the
core file is however a bit of a departure from the standard way core
files are treated in gdb. It also not entirely clear to a user that
it would be necessary to issue it.
elena
>
> (gdb) core ./core.23363
> Core was generated by `/home/roland/build/newthreads-libc/elf/ld-linux.so.2 --library-path /home/rolan'.
> Program terminated with signal 3, Quit.
> #0 0xffffe410 in ?? ()
> (gdb) bt
> #0 0xffffe410 in ?? ()
> (gdb) i fr 0
> Stack frame at 0x0:
> eip = 0xffffe410; saved eip 0xbffff698
> Arglist at 0xbffff664, args:
> Locals at 0xbffff664, Previous frame's sp is 0xbffff66c
> Saved registers:
> eip at 0xbffff668
> (gdb) add-symbol-file core.23363
> add symbol table from file "core.23363" at
> (y or n) y
> Reading symbols from core.23363...done.
> (gdb) bt
> #0 0xffffe410 in _r_debug ()
> #1 0x400cd473 in read () at ctype.h:51
> #2 0x40070012 in _IO_file_read (fp=0xfffffe00, buf=0xfffffe00, size=-512) at fileops.c:1208
> #3 0x4006ed9c in _IO_new_file_underflow (fp=0x401294a0) at fileops.c:591
> #4 0x4007122d in _IO_default_uflow (fp=0x401294a0) at genops.c:430
> #5 0x40071076 in *__GI___uflow (fp=0x401294a0) at genops.c:384
> #6 0x4006af9f in getchar () at getchar.c:44
> #7 0x0804834d in main () at loser.c:1
> (gdb) i fr 0
> Stack frame at 0xbffff678:
> eip = 0xffffe410 in _r_debug; saved eip 0x400cd473
> called by frame at 0xbffff680
> Arglist at 0xbffff664, args:
> Locals at 0xbffff664, Previous frame's sp is 0xbffff678
> Saved registers:
> ebp at 0xbffff668, eip at 0xbffff674
> (gdb)
>
>
> (Of course "_r_debug" is bogus, it's just the highest-addressed candidate
> symbol or something or other. gdb really ought to notice that it's not in
> the same symfile section and not use that symbol for that address.)
>
>
> Thanks,
> Roland
>
>
> 2003-05-12 Roland McGrath <roland@redhat.com>
>
> * dwarf2read.c (dwarf_eh_frame_hdr_offset, dwarf_eh_frame_hdr_size,
> dwarf_eh_frame_hdr_section): New variables.
> (dwarf2_locate_sections): Match a section whose name starts with
> "eh_frame_hdr", and set those.
> (dwarf2_has_info): Clear dwarf_eh_frame_hdr_offset here.
> * dwarf-frame.c (decode_eh_frame_hdr): New function.
> (dwarf2_build_frame_info): Call it when dwarf_eh_frame_hdr_offset
> is set but dwarf_eh_frame_offset is not.
>
> * symfile.c (symfile_bfd_open): Try bfd_check_format with bfd_core
> if bfd_object fails.
>
> Index: dwarf-frame.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/Attic/dwarf-frame.c,v
> retrieving revision 1.1.2.3
> diff -b -B -p -u -r1.1.2.3 dwarf-frame.c
> --- dwarf-frame.c 10 May 2003 15:49:09 -0000 1.1.2.3
> +++ dwarf-frame.c 12 May 2003 09:17:02 -0000
> @@ -697,8 +697,9 @@ struct comp_unit
> /* Length of the loaded .debug_frame section. */
> unsigned long dwarf_frame_size;
>
> - /* Pointer to the .debug_frame section. */
> - asection *dwarf_frame_section;
> + /* VMA corresponding to the beginning of the buffer,
> + for relative addressing calculations. */
> + bfd_vma dwarf_frame_vma;
> };
>
> static unsigned int
> @@ -851,8 +852,7 @@ read_encoded_value (struct comp_unit *un
> base = 0;
> break;
> case DW_EH_PE_pcrel:
> - base = bfd_get_section_vma (unit->bfd, unit->dwarf_frame_section);
> - base += (buf - unit->dwarf_frame_buffer);
> + base = unit->dwarf_frame_vma + (buf - unit->dwarf_frame_buffer);
> break;
> default:
> internal_error (__FILE__, __LINE__, "Invalid or unsupported encoding");
> @@ -958,7 +958,7 @@ add_fde (struct comp_unit *unit, struct
> #define DW64_CIE_ID ~0
> #endif
>
> -/* Read and the CIE or FDE in BUF and decode it. */
> +/* Read the CIE or FDE in BUF and decode it. */
>
> static char *
> decode_frame_entry (struct comp_unit *unit, char *buf, int eh_frame_p)
> @@ -1161,11 +1161,170 @@ extern asection *dwarf_frame_section;
> extern file_ptr dwarf_eh_frame_offset;
> extern unsigned int dwarf_eh_frame_size;
> extern asection *dwarf_eh_frame_section;
> +extern file_ptr dwarf_eh_frame_hdr_offset;
> +extern unsigned int dwarf_eh_frame_hdr_size;
> +extern asection *dwarf_eh_frame_hdr_section;
>
> /* Imported from dwarf2read.c. */
> extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
> unsigned int size, asection *sectp);
>
> +/* Decode .eh_frame_hdr format in dwarf_eh_frame_hdr_section. */
> +static void
> +decode_eh_frame_hdr (struct comp_unit *unit)
> +{
> + char hdr[4], buf[16];
> + ufile_ptr posn;
> + CORE_ADDR eh_frame_addr;
> + CORE_ADDR fde_count;
> + unsigned int len, element_size;
> + asection *sec;
> + struct comp_unit dummy;
> +
> + if (bfd_seek (unit->abfd, dwarf_eh_frame_hdr_offset, SEEK_SET)
> + || bfd_bread (hdr, sizeof hdr, unit->abfd) != sizeof hdr)
> + {
> + error ("Dwarf Error: Can't read DWARF data from '%s'",
> + bfd_get_filename (unit->abfd));
> + return;
> + }
> + if (hdr[0] != 1)
> + {
> + warning ("Dwarf Error: %s: %s header version %d (expected %d)",
> + bfd_get_filename (unit->abfd),
> + dwarf_eh_frame_hdr_section->name,
> + hdr[0], 1);
> + return;
> + }
> +
> + len = size_of_encoded_value (hdr[1]);
> + gdb_assert (len <= sizeof buf);
> + if (bfd_bread (buf, len, unit->abfd) != len)
> + {
> + error ("Dwarf Error: Can't read DWARF data from '%s'",
> + bfd_get_filename (unit->abfd));
> + return;
> + }
> +
> + /* read_encoded_value uses these to calculate the vma. */
> + dummy.abfd = unit->abfd;
> + dummy.dwarf_frame_vma = (bfd_get_section_vma (unit->abfd,
> + dwarf_eh_frame_hdr_section)
> + + sizeof hdr);
> + dummy.dwarf_frame_buffer = buf;
> +
> + eh_frame_addr = read_encoded_value (&dummy, hdr[1], buf, &len);
> + gdb_assert (len <= sizeof buf);
> +
> + len = size_of_encoded_value (hdr[2]);
> + if (len == 0)
> + /* No FDE table, and no way to know where .eh_frame ends!
> + We cannot use this. */
> + return;
> +
> + dummy.dwarf_frame_vma += len;
> + gdb_assert (len <= sizeof buf);
> + if (bfd_bread (buf, len, unit->abfd) != len)
> + {
> + error ("Dwarf Error: Can't read DWARF data from '%s'",
> + bfd_get_filename (unit->abfd));
> + return;
> + }
> + fde_count = read_encoded_value (&dummy, hdr[2], buf, &len);
> + gdb_assert (len <= sizeof buf);
> + dummy.dwarf_frame_vma += len;
> +
> + element_size = size_of_encoded_value (hdr[3]);
> + if (element_size == 0 || fde_count == 0)
> + /* No FDE table, and no way to know where .eh_frame ends!
> + We cannot use this. */
> + return;
> +
> + /* Save the position of the FDE table. */
> + posn = bfd_tell (unit->abfd);
> +
> + /* Now EH_FRAME_ADDR tells us where a .eh_frame section lies. We
> + presumably don't have real section headers or we would have seen
> + it by the name ".eh_frame" already. The BFD sections we have are
> + probably synthesized from ELF phdrs, as for a core file or a
> + stripped executable or DSO, i.e. the section we find corresponds
> + to our whole text segment. We have no way of knowing how large
> + the .eh_frame section should be, so we have to read through til
> + the end of the segment. Fortunately, .eh_frame_hdr is usually
> + the last thing in text, so we likely won't read much extra. */
> + for (sec = unit->abfd->sections; sec != NULL; sec = sec->next)
> + if ((sec->flags & SEC_ALLOC)
> + && sec->vma <= eh_frame_addr
> + && (sec->vma + bfd_get_section_size_before_reloc (sec)
> + > eh_frame_addr))
> + break;
> + if (sec == NULL)
> + {
> + warning ("\
> +Dwarf Error: No section contains eh_frame address 0x%08lx [in module %s]",
> + (long) eh_frame_addr, bfd_get_filename (unit->abfd));
> + return;
> + }
> +
> + unit->dwarf_frame_vma = eh_frame_addr;
> + eh_frame_addr -= bfd_get_section_vma (unit->abfd, sec);
> + unit->dwarf_frame_size = (bfd_get_section_size_before_reloc (sec)
> + - eh_frame_addr);
> + unit->dwarf_frame_buffer = dwarf2_read_section (unit->objfile,
> + sec->filepos + eh_frame_addr,
> + unit->dwarf_frame_size,
> + sec);
> +
> +
> + /* Now that we have read in the whole .eh_frame section, we cannot
> + just feed it all to decode_frame_entry, unfortunately. We don't
> + actually know where the .eh_frame section ends, and it contains
> + no internal end marker. So instead we have to work from the FDE
> + quick-lookup table in .eh_frame_hdr, whose size we do know. */
> + if (bfd_seek (unit->abfd, posn, SEEK_SET))
> + {
> + error ("Dwarf Error: Can't read DWARF data from '%s'",
> + bfd_get_filename (unit->abfd));
> + return;
> + }
> + while (fde_count-- > 0)
> + {
> + CORE_ADDR fde_pointer;
> +
> + if (bfd_bread (buf, element_size * 2, unit->abfd) != element_size * 2)
> + {
> + error ("Dwarf Error: Can't read DWARF data from '%s'",
> + bfd_get_filename (unit->abfd));
> + return;
> + }
> +
> + if ((hdr[3] & 0x70) == DW_EH_PE_datarel)
> + /* In this case, it's relative to the vma of .eh_frame_hdr. */
> + fde_pointer = (bfd_get_section_vma (unit->abfd,
> + dwarf_eh_frame_hdr_section)
> + + read_encoded_value (&dummy,
> + DW_EH_PE_absptr | (hdr[3] & 0x0f),
> + &buf[element_size], &len));
> + else
> + fde_pointer = read_encoded_value (&dummy, hdr[3],
> + &buf[element_size], &len);
> + gdb_assert (len == element_size);
> + dummy.dwarf_frame_vma += element_size * 2;
> +
> + if (fde_pointer < unit->dwarf_frame_vma
> + || fde_pointer > unit->dwarf_frame_vma + unit->dwarf_frame_size)
> + {
> + warning ("Dwarf Error: \
> +Bogus FDE pointer 0x%08lx from .eh_frame_hdr table [in module %s]",
> + (long) fde_pointer, bfd_get_filename (unit->abfd));
> + continue;
> + }
> + fde_pointer -= unit->dwarf_frame_vma;
> + (void) decode_frame_entry (unit,
> + unit->dwarf_frame_buffer + fde_pointer, 1);
> + }
> +}
> +
> void
> dwarf2_build_frame_info (struct objfile *objfile)
> {
> @@ -1176,34 +1335,39 @@ dwarf2_build_frame_info (struct objfile
> unit.abfd = objfile->obfd;
> unit.objfile = objfile;
> unit.addr_size = objfile->obfd->arch_info->bits_per_address / 8;
> + unit.cie = NULL;
>
> /* First add the information from the .eh_frame section. That way,
> the FDEs from that section are searched last. */
> if (dwarf_eh_frame_offset)
> {
> - unit.cie = NULL;
> unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
> dwarf_eh_frame_offset,
> dwarf_eh_frame_size,
> dwarf_eh_frame_section);
>
> unit.dwarf_frame_size = dwarf_eh_frame_size;
> - unit.dwarf_frame_section = dwarf_eh_frame_section;
> + unit.dwarf_frame_vma = bfd_get_section_vma (unit.bfd,
> + dwarf_eh_frame_section);
>
> frame_ptr = unit.dwarf_frame_buffer;
> while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
> frame_ptr = decode_frame_entry (&unit, frame_ptr, 1);
> }
> + else if (dwarf_eh_frame_hdr_offset)
> + /* We didn't find the .eh_frame section but found .eh_frame_hdr,
> + decode it to locate the .eh_frame section that actually exists. */
> + decode_eh_frame_hdr (&unit);
>
> if (dwarf_frame_offset)
> {
> - unit.cie = NULL;
> unit.dwarf_frame_buffer = dwarf2_read_section (objfile,
> dwarf_frame_offset,
> dwarf_frame_size,
> dwarf_frame_section);
> unit.dwarf_frame_size = dwarf_frame_size;
> - unit.dwarf_frame_section = dwarf_frame_section;
> + unit.dwarf_frame_vma = bfd_get_section_vma (unit.bfd,
> + dwarf_frame_section);
>
> frame_ptr = unit.dwarf_frame_buffer;
> while (frame_ptr < unit.dwarf_frame_buffer + unit.dwarf_frame_size)
> Index: dwarf2read.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2read.c,v
> retrieving revision 1.90
> diff -b -B -p -u -r1.90 dwarf2read.c
> --- dwarf2read.c 15 Apr 2003 23:07:11 -0000 1.90
> +++ dwarf2read.c 12 May 2003 09:17:06 -0000
> @@ -139,6 +139,7 @@ static file_ptr dwarf_str_offset;
> static file_ptr dwarf_ranges_offset;
> file_ptr dwarf_frame_offset;
> file_ptr dwarf_eh_frame_offset;
> +file_ptr dwarf_eh_frame_hdr_offset;
>
> static unsigned int dwarf_info_size;
> static unsigned int dwarf_abbrev_size;
> @@ -151,6 +152,7 @@ static unsigned int dwarf_str_size;
> static unsigned int dwarf_ranges_size;
> unsigned int dwarf_frame_size;
> unsigned int dwarf_eh_frame_size;
> +unsigned int dwarf_eh_frame_hdr_size;
>
> static asection *dwarf_info_section;
> static asection *dwarf_abbrev_section;
> @@ -163,6 +165,7 @@ static asection *dwarf_str_section;
> static asection *dwarf_ranges_section;
> asection *dwarf_frame_section;
> asection *dwarf_eh_frame_section;
> +asection *dwarf_eh_frame_hdr_section;
>
> /* names of the debugging sections */
>
> @@ -944,6 +947,7 @@ dwarf2_has_info (bfd *abfd)
> dwarf_macinfo_offset = 0;
> dwarf_frame_offset = 0;
> dwarf_eh_frame_offset = 0;
> + dwarf_eh_frame_hdr_offset = 0;
> dwarf_ranges_offset = 0;
> dwarf_loc_offset = 0;
>
> @@ -1025,6 +1029,12 @@ dwarf2_locate_sections (bfd *ignore_abfd
> dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
> dwarf_eh_frame_section = sectp;
> }
> + else if (!strncmp (sectp->name, "eh_frame_hdr", 12))
> + {
> + dwarf_eh_frame_hdr_offset = sectp->filepos;
> + dwarf_eh_frame_hdr_size = bfd_get_section_size_before_reloc (sectp);
> + dwarf_eh_frame_hdr_section = sectp;
> + }
> else if (STREQ (sectp->name, RANGES_SECTION))
> {
> dwarf_ranges_offset = sectp->filepos;
> Index: symfile.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/symfile.c,v
> retrieving revision 1.93
> diff -b -B -p -u -r1.93 symfile.c
> --- symfile.c 1 Apr 2003 14:17:20 -0000 1.93
> +++ symfile.c 12 May 2003 09:17:08 -0000
> @@ -1338,7 +1338,9 @@ symfile_bfd_open (char *name)
> }
> sym_bfd->cacheable = 1;
>
> - if (!bfd_check_format (sym_bfd, bfd_object))
> + if (!bfd_check_format (sym_bfd, bfd_object)
> + /* Yes, Virginia, core files can have symbols! */
> + && !bfd_check_format (sym_bfd, bfd_core))
> {
> /* FIXME: should be checking for errors from bfd_close (for one thing,
> on error it does not free all the storage associated with the
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [branch patch] dwarf-frame.c support for .eh_frame_hdr
2003-05-13 3:27 ` Elena Zannoni
@ 2003-05-13 3:42 ` Roland McGrath
0 siblings, 0 replies; 8+ messages in thread
From: Roland McGrath @ 2003-05-13 3:42 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Mark Kettenis, gdb-patches
> Is there a way to tell if there is a table?
Sure, my code does check that (size_of_encoded_value returns 0 in that
case). It's just that if there is no table, I don't think there is
anything else useful to try. AFAIK it's not a practical concern. It's
just something that struck me when I came across it.
> I see that the symfile.c change is a good way to test the code, and to
> verify that the stuff that ends up in the core file makes sense. This
> new add-symbol-file command required to read the symbols info from the
> core file is however a bit of a departure from the standard way core
> files are treated in gdb. It also not entirely clear to a user that
> it would be necessary to issue it.
I never suggested that users do such a thing. I did it myself to test the
dwarf-frame.c changes, and included the symfile.c patch so that other could
demonstrate for themselves that the .eh_frame_hdr decoding in fact works.
(If you catch up with your mailbox, you'll notice that today I posted the
patch I wrote later last night to implicitly do it for all core files.)
Thanks,
Roland
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [branch patch] dwarf-frame.c support for .eh_frame_hdr
2003-05-12 9:47 [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
2003-05-13 3:27 ` Elena Zannoni
@ 2003-05-15 21:49 ` Mark Kettenis
2003-05-15 22:00 ` Elena Zannoni
2003-05-15 22:06 ` [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
1 sibling, 2 replies; 8+ messages in thread
From: Mark Kettenis @ 2003-05-15 21:49 UTC (permalink / raw)
To: roland; +Cc: gdb-patches
Date: Mon, 12 May 2003 02:46:54 -0700
From: Roland McGrath <roland@redhat.com>
2003-05-12 Roland McGrath <roland@redhat.com>
* dwarf2read.c (dwarf_eh_frame_hdr_offset, dwarf_eh_frame_hdr_size,
dwarf_eh_frame_hdr_section): New variables.
(dwarf2_locate_sections): Match a section whose name starts with
"eh_frame_hdr", and set those.
(dwarf2_has_info): Clear dwarf_eh_frame_hdr_offset here.
* dwarf-frame.c (decode_eh_frame_hdr): New function.
(dwarf2_build_frame_info): Call it when dwarf_eh_frame_hdr_offset
is set but dwarf_eh_frame_offset is not.
Having to build a "dummy" `struct comp_unit' probably indicates that I
should change read_encoded_value()'s signature. Well, I'll worry
about that later.
The error messages in dwarf-frame.c should probably be harmonized
before we check merge this into mailine. I wonder whether we should
complaint() instead of error().
Is there a particular reason why you don't read in the .eh_frame_hdr
section as a whole as the other parts of GDB's "symbol reader" do (and
which I just blindly copied when I wrote the guts of dwarf-frame.c)?
* symfile.c (symfile_bfd_open): Try bfd_check_format with bfd_core
if bfd_object fails.
I think a more elaborate comment on why core files might have
"symbols" is appropriate.
Mark
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [branch patch] dwarf-frame.c support for .eh_frame_hdr
2003-05-15 21:49 ` Mark Kettenis
@ 2003-05-15 22:00 ` Elena Zannoni
2003-05-15 22:19 ` [branch patch] core files as symfiles Roland McGrath
2003-05-15 22:06 ` [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
1 sibling, 1 reply; 8+ messages in thread
From: Elena Zannoni @ 2003-05-15 22:00 UTC (permalink / raw)
To: Mark Kettenis; +Cc: roland, gdb-patches
Mark Kettenis writes:
> Date: Mon, 12 May 2003 02:46:54 -0700
> From: Roland McGrath <roland@redhat.com>
>
> 2003-05-12 Roland McGrath <roland@redhat.com>
>
> * dwarf2read.c (dwarf_eh_frame_hdr_offset, dwarf_eh_frame_hdr_size,
> dwarf_eh_frame_hdr_section): New variables.
> (dwarf2_locate_sections): Match a section whose name starts with
> "eh_frame_hdr", and set those.
> (dwarf2_has_info): Clear dwarf_eh_frame_hdr_offset here.
> * dwarf-frame.c (decode_eh_frame_hdr): New function.
> (dwarf2_build_frame_info): Call it when dwarf_eh_frame_hdr_offset
> is set but dwarf_eh_frame_offset is not.
>
> Having to build a "dummy" `struct comp_unit' probably indicates that I
> should change read_encoded_value()'s signature. Well, I'll worry
> about that later.
>
> The error messages in dwarf-frame.c should probably be harmonized
> before we check merge this into mailine. I wonder whether we should
> complaint() instead of error().
>
> Is there a particular reason why you don't read in the .eh_frame_hdr
> section as a whole as the other parts of GDB's "symbol reader" do (and
> which I just blindly copied when I wrote the guts of dwarf-frame.c)?
>
> * symfile.c (symfile_bfd_open): Try bfd_check_format with bfd_core
> if bfd_object fails.
>
> I think a more elaborate comment on why core files might have
> "symbols" is appropriate.
>
Did we settle on this being the solution though? I think the
/proc/PID/auxv approach is a bit cleaner. Not to say that there aren't
things here that are probably necessary anyway, but the debate is
still ongoing.
elena
> Mark
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [branch patch] core files as symfiles
2003-05-15 22:00 ` Elena Zannoni
@ 2003-05-15 22:19 ` Roland McGrath
2003-05-15 23:58 ` Andrew Cagney
0 siblings, 1 reply; 8+ messages in thread
From: Roland McGrath @ 2003-05-15 22:19 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Mark Kettenis, gdb-patches
> Did we settle on this being the solution though? I think the
> /proc/PID/auxv approach is a bit cleaner.
We're talking about core files, so what you mean is an NT_AUXV note that
would give the same information that /proc/PID/auxv would give for a live
process. It remains to see whether the auxv approach will be accepted in
the kernel.
If that is done, then the corelow.c patch will be superfluous. I would
like feedback on the implementation issue of this patch regardless. That
is, if anyone sees any potential problems with adding the core bfd as a
symfile (AFAIK it's a no-op to all cases but the new vsyscall issues), or
with my specific code changes. Then I can address any nits, and verify
that it is a safe change for gdb generically speaking. It is useful to
know ASAP that this very simple change works acceptably, even if it turns
out not to be necessary in the end.
Using the core file's phdrs (which is what happens implicitly using this
patch) has the benefit that it works now, i.e. with kernel support already
merged into Linux 2.5, and with gdb code I have already finished enough to
be in submittable form. If the generic auxv exporting support is not
accepted in the kernel, then it is quite likely that some other way to know
the vsyscall DSO address in a live process (e.g. via /proc/PID/maps) *will*
be accepted, but no other core dump changes will go in and the existing
phdrs will be the only method for the core dump case.
Thanks,
Roland
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [branch patch] core files as symfiles
2003-05-15 22:19 ` [branch patch] core files as symfiles Roland McGrath
@ 2003-05-15 23:58 ` Andrew Cagney
0 siblings, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2003-05-15 23:58 UTC (permalink / raw)
To: Roland McGrath; +Cc: Elena Zannoni, Mark Kettenis, gdb-patches
>> Did we settle on this being the solution though?
Not as far as I know.
> I think the
>> /proc/PID/auxv approach is a bit cleaner.
Yep. More importantly it solves the general case.
> We're talking about core files, so what you mean is an NT_AUXV note that
> would give the same information that /proc/PID/auxv would give for a live
> process. It remains to see whether the auxv approach will be accepted in
> the kernel.
Perhaphs someone should find out. What's the best mailing list?
> If that is done, then the corelow.c patch will be superfluous.
Right. And I think both GDB and the Linux kernel will be the better for it.
Andrew
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [branch patch] dwarf-frame.c support for .eh_frame_hdr
2003-05-15 21:49 ` Mark Kettenis
2003-05-15 22:00 ` Elena Zannoni
@ 2003-05-15 22:06 ` Roland McGrath
1 sibling, 0 replies; 8+ messages in thread
From: Roland McGrath @ 2003-05-15 22:06 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
> Having to build a "dummy" `struct comp_unit' probably indicates that I
> should change read_encoded_value()'s signature. Well, I'll worry
> about that later.
Yeah, it was ok. Since you need to provide several things for it to work
in all cases (the bfd for byteorder, dwarf_frame_* for relative calculation)
using that struct seems about as good as anything.
> The error messages in dwarf-frame.c should probably be harmonized
> before we check merge this into mailine. I wonder whether we should
> complaint() instead of error().
I have no opinion on that. The style of the messages I added was pretty
much copied from dwarf2read.c and/or dwarf2cfi.c. I can update the code I
added following whatever model of similar error reporting you point me at.
> Is there a particular reason why you don't read in the .eh_frame_hdr
> section as a whole as the other parts of GDB's "symbol reader" do (and
> which I just blindly copied when I wrote the guts of dwarf-frame.c)?
Not really. It was as easy to write it that way as anything else.
bfd_bread is already going through stdio (or even BFD_IN_MEMORY), so the
buffering of the reads is not really an issue (in copying the whole section
you are just copying from one memory buffer to another). I may have had it
in the back of my head that I wouldn't know the size until I decoded the
header and FDE count, but the section bounds do already suffice and just
reading the whole section in one chunk would be fine. I can rewrite it
that way if people prefer it.
> * symfile.c (symfile_bfd_open): Try bfd_check_format with bfd_core
> if bfd_object fails.
>
> I think a more elaborate comment on why core files might have
> "symbols" is appropriate.
Yes, I hadn't really intended this patch to go in without further vetting.
I included it in the posting because it lets you do the test I demonstrated
to exercise the new dwarf-frame.c code. I included it with the posting of
the corelow.c patch that makes it really relevant, which also deserves more
comments in its code. I haven't yet gotten any feedback on that patch, and
hadn't bothered to polish it up before it becoming clear the code itself
would be taken in the form I wrote it.
Thanks,
Roland
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2003-05-15 23:58 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-12 9:47 [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
2003-05-13 3:27 ` Elena Zannoni
2003-05-13 3:42 ` Roland McGrath
2003-05-15 21:49 ` Mark Kettenis
2003-05-15 22:00 ` Elena Zannoni
2003-05-15 22:19 ` [branch patch] core files as symfiles Roland McGrath
2003-05-15 23:58 ` Andrew Cagney
2003-05-15 22:06 ` [branch patch] dwarf-frame.c support for .eh_frame_hdr Roland McGrath
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox