|
From: <sv...@va...> - 2006-01-05 14:11:49
|
Author: sewardj
Date: 2006-01-05 14:11:31 +0000 (Thu, 05 Jan 2006)
New Revision: 5501
Log:
Make symbol table reading understand the .opd section conventions used
for ppc64-linux on gcc 4.0.0 and above.
As part of this, simplify the FIND macros and rename some fields in
SegInfo to be a bit clearer.
Modified:
trunk/coregrind/m_debuginfo/symtab.c
Modified: trunk/coregrind/m_debuginfo/symtab.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/symtab.c 2006-01-05 14:09:46 UTC (rev 550=
0)
+++ trunk/coregrind/m_debuginfo/symtab.c 2006-01-05 14:11:31 UTC (rev 550=
1)
@@ -1105,9 +1105,22 @@
return False;
}
=20
-static Bool is_interesting_symbol(SegInfo* si, ElfXX_Sym* sym,=20
- Char* sym_name, Addr sym_addr)
+/* Decide whether SYM is something we should collect. It may also
+ decide to change the stated address of the symbol, in which case a
+ different value is assigned to *SYM_ADDR_REALLY; otherwise SYM is
+ copied to *SYM_ADDR_REALLY. */
+
+static Bool is_interesting_symbol( SegInfo* si,=20
+ ElfXX_Sym* sym,=20
+ Char* sym_name,=20
+ Addr sym_addr,
+ UChar* opd_filea, /* oimage addr =
of .opd sec
+ (ppc64-linux=
only) */
+ /*OUT*/Addr* sym_addr_really )
{
+ /* Set default real address for the symbol. */
+ *sym_addr_really =3D sym_addr;
+
/* Figure out if we're interested in the symbol.
Firstly, is it of the right flavour? */
if ( ! ( (ELFXX_ST_BIND(sym->st_info) =3D=3D STB_GLOBAL ||
@@ -1123,15 +1136,15 @@
=20
/* Secondly, if it's apparently in a GOT or PLT, it's really
a reference to a symbol defined elsewhere, so ignore it. */
- if (si->got_start !=3D 0
- && sym_addr >=3D si->got_start=20
- && sym_addr < si->got_start + si->got_size) {
+ if (si->got_start_vma !=3D 0
+ && sym_addr >=3D si->got_start_vma=20
+ && sym_addr < si->got_start_vma + si->got_size) {
TRACE_SYMTAB("ignore -- in GOT: %s\n", sym_name);
return False;
}
- if (si->plt_start !=3D 0
- && sym_addr >=3D si->plt_start
- && sym_addr < si->plt_start + si->plt_size) {
+ if (si->plt_start_vma !=3D 0
+ && sym_addr >=3D si->plt_start_vma
+ && sym_addr < si->plt_start_vma + si->plt_size) {
TRACE_SYMTAB("ignore -- in PLT: %s\n", sym_name);
return False;
}
@@ -1154,6 +1167,67 @@
return False;
}
=20
+ /* ppc64-linux nasty hack: if the symbol is in a .opd section, then
+ really what we have is the address of a function descriptor. So
+ use the first word of that as the function's text.
+
+ See thread starting at
+ http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
+ */
+ if (si->opd_start_vma !=3D 0
+ && sym_addr >=3D si->opd_start_vma
+ && sym_addr < si->opd_start_vma + si->opd_size) {
+# if !defined(VGP_ppc64_linux)
+ TRACE_SYMTAB("ignore -- in OPD: %s\n", sym_name);
+ return False;
+# else
+ Int offset_in_opd;
+ ULong* fn_descr;
+
+ if (0) VG_(printf)("opdXXX: si->offset %p, sym_addr %p\n",=20
+ (void*)(si->offset), (void*)sym_addr);
+
+ if (!VG_IS_8_ALIGNED(sym_addr))
+ return False;
+
+ /* sym_addr is a vma pointing into the .opd section. We know
+ the vma of the opd section start, so we can figure out how
+ far into the opd section this is. */
+
+ offset_in_opd =3D (Addr)sym_addr - (Addr)(si->opd_start_vma);
+ if (offset_in_opd < 0 || offset_in_opd >=3D si->opd_size)
+ return False;
+
+ /* Now we want to know what's at that offset in the .opd
+ section. We can't look in the running image since it won't
+ necessarily have been mapped. But we can consult the oimage.
+ opd_filea is the start address of the .opd in the oimage.
+ Hence: */
+
+ fn_descr =3D (ULong*)(opd_filea + offset_in_opd);
+
+ if (0) VG_(printf)("opdXXY: offset %d, fn_descr %p\n", offset_in_=
opd, fn_descr);
+ if (0) VG_(printf)("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]))=
;
+
+ sym_addr =3D fn_descr[0];
+
+ /* Hopefully sym_addr is now an offset into the text section.
+ Problem is, where did the text section get mapped? Well,
+ this SegInfo (si) exists because a text section got mapped,
+ and it got mapped to si->start. Hence add si->start to the
+ sym_addr to get the real vma. */
+
+ sym_addr +=3D si->offset;
+ *sym_addr_really =3D sym_addr;
+
+ /* Do a final sanity check: if the symbol falls outside the
+ SegInfo's mapped range, ignore it. Since sym_addr has been
+ updated, that can be achieved simply by falling through to
+ the test below. */
+
+# endif /* ppc64-linux nasty hack */
+ }
+
/* If no part of the symbol falls within the mapped range,
ignore it. */
if (sym_addr+sym->st_size <=3D si->start
@@ -1170,10 +1244,11 @@
static
void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts,
ElfXX_Sym* o_symtab, UInt o_symtab_sz,
- UChar* o_strtab, UInt o_strtab_sz )
+ UChar* o_strtab, UInt o_strtab_sz,
+ UChar* opd_filea /* ppc64-linux only */ )
{
Int i;
- Addr sym_addr;
+ Addr sym_addr, sym_addr_really;
Char* sym_name;
RiSym risym;
Char* name;
@@ -1224,9 +1299,18 @@
} =20
=20
// Record interesting symbols in our symtab.
- if ( is_interesting_symbol(si, sym, sym_name, sym_addr) ) {
+ if ( is_interesting_symbol(si, sym, sym_name, sym_addr, opd_filea,=
&sym_addr_really) ) {
vg_assert(sym->st_name !=3D 0);
vg_assert(sym_name[0] !=3D 0);
+# if defined(VGP_ppc64_linux)
+ /* It's crucial that we never add symbol addresses in the
+ .opd section. This would completely mess up function
+ redirection and intercepting. This assert ensures that
+ any symbols that make it into the symbol table on
+ ppc64-linux don't point into .opd. */
+ vg_assert(sym_addr_really + sym->st_size <=3D si->opd_start_vma
+ || sym_addr_really >=3D si->opd_start_vma + si->opd_s=
ize);
+# endif
name =3D ML_(addStr) ( si, sym_name, -1 );
vg_assert(name !=3D NULL);
=20
@@ -1238,10 +1322,10 @@
* the string table. Importantly, it never makes it bigger.
*/
if (do_intercepts) {
- VG_(maybe_redir_or_notify)( name, sym_addr );
+ VG_(maybe_redir_or_notify)( name, sym_addr_really );
}
=20
- risym.addr =3D sym_addr;
+ risym.addr =3D sym_addr_really;
risym.size =3D sym->st_size;
risym.name =3D name;
addSym ( si, &risym );
@@ -1531,11 +1615,11 @@
// Get the data and bss start/size if appropriate
mapped =3D o_phdr->p_vaddr + si->offset;
mapped_end =3D mapped + o_phdr->p_memsz;
- if (si->data_start =3D=3D 0 &&
+ if (si->data_start_vma =3D=3D 0 &&
(o_phdr->p_flags & (PF_R|PF_W|PF_X)) =3D=3D (PF_R|PF_W)) {
- si->data_start =3D mapped;
- si->data_size =3D o_phdr->p_filesz;
- si->bss_start =3D mapped + o_phdr->p_filesz;
+ si->data_start_vma =3D mapped;
+ si->data_size =3D o_phdr->p_filesz;
+ si->bss_start_vma =3D mapped + o_phdr->p_filesz;
if (o_phdr->p_memsz > o_phdr->p_filesz)
si->bss_size =3D o_phdr->p_memsz - o_phdr->p_filesz;
else
@@ -1575,7 +1659,8 @@
/* Find interesting sections, read the symbol table(s), read any debu=
g
information */
{
- /* Pointers to start of sections */
+ /* Pointers to start of sections (in the oimage, not in the
+ running image) */
UChar* o_strtab =3D NULL; /* .strtab */
ElfXX_Sym* o_symtab =3D NULL; /* .symtab */
UChar* o_dynstr =3D NULL; /* .dynstr */
@@ -1590,6 +1675,8 @@
UChar* dwarf1d =3D NULL; /* .debug (dwarf1) */
UChar* dwarf1l =3D NULL; /* .line (dwarf1) */
UChar* ehframe =3D NULL; /* .eh_frame (dwarf2) */
+ UChar* opd_filea =3D NULL; /* .opd (dwarf2, ppc64-=
linux) */
+ UChar* dummy_filea =3D NULL;
=20
/* Section sizes, in bytes */
UInt o_strtab_sz =3D 0;
@@ -1608,25 +1695,36 @@
UInt ehframe_sz =3D 0;
=20
/* Section virtual addresses */
- Addr dummy_addr =3D 0;
- Addr ehframe_addr =3D 0;
+ Addr dummy_vma =3D 0;
+ Addr ehframe_vma =3D 0;
=20
/* Find all interesting sections */
+
+ /* What FIND does: it finds the section called SEC_NAME. The
+ size of it is assigned to SEC_SIZE. The address that it will
+ appear in the running image is assigned to SEC_VMA (note,
+ this will be meaningless for sections which are not marked
+ loadable. Even for sections which are marked loadable, the
+ client's ld.so may not have loaded them yet, so there is no
+ guarantee that we can safely prod around in any such area)
+ The address of the section in the transiently loaded oimage
+ is assigned to SEC_FILEA. Because the entire object file is
+ transiently mapped aboard for inspection, it's always safe to
+ inspect that area. */
+
for (i =3D 0; i < ehdr->e_shnum; i++) {
-# define FIND(sec_name, sec_data, sec_size, sec_addr, in_exec, ty=
pe) \
+
+# define FIND(sec_name, sec_size, sec_filea, sec_vma) \
if (0 =3D=3D VG_(strcmp)(sec_name, sh_strtab + shdr[i].sh_name)=
) { \
Bool nobits; \
- if (0 !=3D sec_data) \
- VG_(core_panic)("repeated section!\n"); \
- if (in_exec) \
- sec_data =3D (type)(si->offset + shdr[i].sh_addr); \
- else \
- sec_data =3D (type)(oimage + shdr[i].sh_offset); \
- sec_size =3D shdr[i].sh_size; \
+ sec_vma =3D (Addr)(si->offset + shdr[i].sh_addr); \
+ sec_filea =3D (void*)(oimage + shdr[i].sh_offset); \
+ sec_size =3D shdr[i].sh_size; \
nobits =3D shdr[i].sh_type =3D=3D SHT_NOBITS; \
- sec_addr =3D si->offset + shdr[i].sh_addr; \
- TRACE_SYMTAB( "%18s: %p .. %p\n", \
- sec_name, sec_data, sec_data + sec_size - 1); =
\
+ TRACE_SYMTAB( "%18s: filea %p .. %p, vma %p .. %p\n", \
+ sec_name, (UChar*)sec_filea, \
+ ((UChar*)sec_filea) + sec_size - 1, =
\
+ sec_vma, sec_vma + sec_size - 1); \
/* SHT_NOBITS sections have zero size in the file. */ \
if ( shdr[i].sh_offset + (nobits ? 0 : sec_size) > n_oimage =
) { \
ML_(symerr)(" section beyond image end?!"); \
@@ -1636,27 +1734,29 @@
=20
/* Nb: must find where .got and .plt sections will be in the
* executable image, not in the object image transiently loaded=
. */
- FIND(".dynsym", o_dynsym, o_dynsym_sz, dummy_a=
ddr, 0, ElfXX_Sym*)
- else FIND(".dynstr", o_dynstr, o_dynstr_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".symtab", o_symtab, o_symtab_sz, dummy_a=
ddr, 0, ElfXX_Sym*)
- else FIND(".strtab", o_strtab, o_strtab_sz, dummy_a=
ddr, 0, UChar*)
+ /* NAME SIZE ADDR_IN_OIMAGE ADDR_WHEN=
_MAPPED */
+ FIND(".dynsym", o_dynsym_sz, o_dynsym, dummy_vma=
)
+ FIND(".dynstr", o_dynstr_sz, o_dynstr, dummy_vma=
)
+ FIND(".symtab", o_symtab_sz, o_symtab, dummy_vma=
)
+ FIND(".strtab", o_strtab_sz, o_strtab, dummy_vma=
)
=20
- else FIND(".gnu_debuglink", debuglink, debuglink_sz, dummy_a=
ddr, 0, Char*)
+ FIND(".gnu_debuglink", debuglink_sz, debuglink, dummy_vma=
)
=20
- else FIND(".stab", stab, stab_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".stabstr", stabstr, stabstr_sz, dummy_a=
ddr, 0, UChar*)
+ FIND(".stab", stab_sz, stab, dummy_vma=
)
+ FIND(".stabstr", stabstr_sz, stabstr, dummy_vma=
)
=20
- else FIND(".debug_line", debug_line, debug_line_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".debug_info", debug_info, debug_info_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".debug_abbrev", debug_abbv, debug_abbv_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".debug_str", debug_str, debug_str_sz, dummy_a=
ddr, 0, UChar*)
+ FIND(".debug_line", debug_line_sz, debug_line, dummy_vma=
)
+ FIND(".debug_info", debug_info_sz, debug_info, dummy_vma=
)
+ FIND(".debug_abbrev", debug_abbv_sz, debug_abbv, dummy_vma=
)
+ FIND(".debug_str", debug_str_sz, debug_str, dummy_vma=
)
=20
- else FIND(".debug", dwarf1d, dwarf1d_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".line", dwarf1l, dwarf1l_sz, dummy_a=
ddr, 0, UChar*)
- else FIND(".eh_frame", ehframe, ehframe_sz, ehframe=
_addr, 0, UChar*)
+ FIND(".debug", dwarf1d_sz, dwarf1d, dummy_vma=
)
+ FIND(".line", dwarf1l_sz, dwarf1l, dummy_vma=
)
+ FIND(".eh_frame", ehframe_sz, ehframe, ehframe_v=
ma)
=20
- else FIND(".got", si->got_start, si->got_size, dummy_a=
ddr, 1, Addr)
- else FIND(".plt", si->plt_start, si->plt_size, dummy_a=
ddr, 1, Addr)
+ FIND(".got", si->got_size, dummy_filea, si->got_s=
tart_vma)
+ FIND(".plt", si->plt_size, dummy_filea, si->plt_s=
tart_vma)
+ FIND(".opd", si->opd_size, opd_filea, si->opd_s=
tart_vma)
=20
# undef FIND
}
@@ -1679,23 +1779,27 @@
if ((dimage =3D find_debug_file(si->filename, debuglink, crc, &=
n_dimage)) !=3D 0) {
ehdr =3D (ElfXX_Ehdr*)dimage;
=20
- if (n_dimage >=3D sizeof(ElfXX_Ehdr) && is_elf_object_file(e=
hdr))
- {
+ if (n_dimage >=3D sizeof(ElfXX_Ehdr) && is_elf_object_file(e=
hdr)) {
shdr =3D (ElfXX_Shdr*)(dimage + ehdr->e_shoff);
sh_strtab =3D (UChar*)(dimage + shdr[ehdr->e_shstrndx].sh=
_offset);
=20
+ /* Same deal as previous FIND, except simpler - doesn't
+ look for vma, only oimage address. */
+
/* Find all interesting sections */
for (i =3D 0; i < ehdr->e_shnum; i++) {
-# define FIND(sec_name, sec_data, sec_size, type) \
+
+# define FIND(sec_name, sec_size, sec_filea) \
if (0 =3D=3D VG_(strcmp)(sec_name, sh_strtab + shdr[i]=
.sh_name)) { \
Bool nobits; \
- if (0 !=3D sec_data) \
+ if (0 !=3D sec_filea) \
VG_(core_panic)("repeated section!\n"); \
- sec_data =3D (type)(dimage + shdr[i].sh_offset); \
- sec_size =3D shdr[i].sh_size; \
+ sec_filea =3D (void*)(dimage + shdr[i].sh_offset); =
\
+ sec_size =3D shdr[i].sh_size; \
nobits =3D shdr[i].sh_type =3D=3D SHT_NOBITS; \
- TRACE_SYMTAB( "%18s: %p .. %p\n", \
- sec_name, sec_data, sec_data + sec_si=
ze - 1); \
+ TRACE_SYMTAB( "%18s: filea %p .. %p\n", \
+ sec_name, (UChar*)sec_filea, \
+ ((UChar*)sec_filea) + sec_s=
ize - 1); \
/* SHT_NOBITS sections have zero size in the file. =
*/ \
if ( shdr[i].sh_offset + (nobits ? 0 : sec_size) > =
n_dimage ) { \
ML_(symerr)(" section beyond image end?!"); \
@@ -1703,16 +1807,14 @@
} \
}
=20
- /* Nb: must find where .got and .plt sections will be =
in the
- * executable image, not in the object image transient=
ly loaded. */
- FIND(".stab", stab, stab_sz, =
UChar*)
- else FIND(".stabstr", stabstr, stabstr_sz, =
UChar*)
- else FIND(".debug_line", debug_line, debug_line_sz=
, UChar*)
- else FIND(".debug_info", debug_info, debug_info_sz=
, UChar*)
- else FIND(".debug_abbrev", debug_abbv, debug_abbv_sz=
, UChar*)
- else FIND(".debug_str", debug_str, debug_str_sz,=
UChar*)
- else FIND(".debug", dwarf1d, dwarf1d_sz, =
UChar*)
- else FIND(".line", dwarf1l, dwarf1l_sz, =
UChar*)
+ FIND(".stab", stab_sz, stab)
+ FIND(".stabstr", stabstr_sz, stabstr)
+ FIND(".debug_line", debug_line_sz, debug_line)
+ FIND(".debug_info", debug_info_sz, debug_info)
+ FIND(".debug_abbrev", debug_abbv_sz, debug_abbv)
+ FIND(".debug_str", debug_str_sz, debug_str)
+ FIND(".debug", dwarf1d_sz, dwarf1d)
+ FIND(".line", dwarf1l_sz, dwarf1l)
=20
# undef FIND
}
@@ -1723,15 +1825,15 @@
/* Read symbols */
read_symtab(si, "symbol table", False,
o_symtab, o_symtab_sz,
- o_strtab, o_strtab_sz);
+ o_strtab, o_strtab_sz, opd_filea);
=20
read_symtab(si, "dynamic symbol table", True,
o_dynsym, o_dynsym_sz,
- o_dynstr, o_dynstr_sz);
+ o_dynstr, o_dynstr_sz, opd_filea);
=20
/* Read .eh_frame (call-frame-info) if any */
if (ehframe) {
- ML_(read_callframe_info_dwarf2) ( si, ehframe, ehframe_sz, ehfr=
ame_addr );
+ ML_(read_callframe_info_dwarf2) ( si, ehframe, ehframe_sz, ehfr=
ame_vma );
}
=20
/* Read the stabs and/or dwarf2 debug information, if any. It
@@ -2748,19 +2850,22 @@
if (0)
VG_(printf)("addr=3D%p si=3D%p %s got=3D%p %d plt=3D%p %d data=3D%=
p %d bss=3D%p %d\n",
a, si, si->filename,=20
- si->got_start, si->got_size,
- si->plt_start, si->plt_size,
- si->data_start, si->data_size,
- si->bss_start, si->bss_size);
+ si->got_start_vma, si->got_size,
+ si->plt_start_vma, si->plt_size,
+ si->data_start_vma, si->data_size,
+ si->bss_start_vma, si->bss_size);
ret =3D Vg_SectText;
=20
- if (a >=3D si->data_start && a < (si->data_start + si->data_size))
+ if (a >=3D si->data_start_vma && a < (si->data_start_vma + si->data_si=
ze))
ret =3D Vg_SectData;
- else if (a >=3D si->bss_start && a < (si->bss_start + si->bss_size))
+ else=20
+ if (a >=3D si->bss_start_vma && a < (si->bss_start_vma + si->bs=
s_size))
ret =3D Vg_SectBSS;
- else if (a >=3D si->plt_start && a < (si->plt_start + si->plt_size))
+ else=20
+ if (a >=3D si->plt_start_vma && a < (si->plt_start_vma + si->pl=
t_size))
ret =3D Vg_SectPLT;
- else if (a >=3D si->got_start && a < (si->got_start + si->got_size))
+ else=20
+ if (a >=3D si->got_start_vma && a < (si->got_start_vma + si->go=
t_size))
ret =3D Vg_SectGOT;
}
}
|