readelf.c revision bfd892f0b1161e0a36fc7277041d1b5460083b79
1
2/*--------------------------------------------------------------------*/
3/*--- Reading of syms & debug info from ELF .so/executable files.  ---*/
4/*---                                                    readelf.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2000-2008 Julian Seward
12      jseward@acm.org
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31/*
32   Stabs reader greatly improved by Nick Nethercote, Apr 02.
33   This module was also extensively hacked on by Jeremy Fitzhardinge
34   and Tom Hughes.
35*/
36
37#include "pub_core_basics.h"
38#include "pub_core_vki.h"
39#include "pub_core_debuginfo.h"
40#include "pub_core_libcbase.h"
41#include "pub_core_libcprint.h"
42#include "pub_core_libcassert.h"
43#include "pub_core_libcfile.h"
44#include "pub_core_aspacemgr.h"    /* for mmaping debuginfo files */
45#include "pub_core_machine.h"      /* VG_ELF_CLASS */
46#include "pub_core_options.h"
47#include "pub_core_oset.h"
48#include "pub_core_tooliface.h"    /* VG_(needs) */
49#include "pub_core_xarray.h"
50#include "priv_misc.h"             /* dinfo_zalloc/free/strdup */
51#include "priv_d3basics.h"
52#include "priv_tytypes.h"
53#include "priv_storage.h"
54#include "priv_readelf.h"          /* self */
55#include "priv_readdwarf.h"        /* 'cos ELF contains DWARF */
56#include "priv_readdwarf3.h"
57#include "priv_readstabs.h"        /* and stabs, if we're unlucky */
58
59/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
60#include <elf.h>
61/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
62
63/*------------------------------------------------------------*/
64/*--- 32/64-bit parameterisation                           ---*/
65/*------------------------------------------------------------*/
66
67/* For all the ELF macros and types which specify '32' or '64',
68   select the correct variant for this platform and give it
69   an 'XX' name.  Then use the 'XX' variant consistently in
70   the rest of this file.
71*/
72#if VG_WORDSIZE == 4
73#  define  ElfXX_Ehdr     Elf32_Ehdr
74#  define  ElfXX_Shdr     Elf32_Shdr
75#  define  ElfXX_Phdr     Elf32_Phdr
76#  define  ElfXX_Sym      Elf32_Sym
77#  define  ElfXX_Word     Elf32_Word
78#  define  ElfXX_Addr     Elf32_Addr
79#  define  ElfXX_Dyn      Elf32_Dyn
80#  define  ELFXX_ST_BIND  ELF32_ST_BIND
81#  define  ELFXX_ST_TYPE  ELF32_ST_TYPE
82
83#elif VG_WORDSIZE == 8
84#  define  ElfXX_Ehdr     Elf64_Ehdr
85#  define  ElfXX_Shdr     Elf64_Shdr
86#  define  ElfXX_Phdr     Elf64_Phdr
87#  define  ElfXX_Sym      Elf64_Sym
88#  define  ElfXX_Word     Elf64_Word
89#  define  ElfXX_Addr     Elf64_Addr
90#  define  ElfXX_Dyn      Elf64_Dyn
91#  define  ELFXX_ST_BIND  ELF64_ST_BIND
92#  define  ELFXX_ST_TYPE  ELF64_ST_TYPE
93
94#else
95# error "VG_WORDSIZE should be 4 or 8"
96#endif
97
98
99/*------------------------------------------------------------*/
100/*---                                                      ---*/
101/*--- Read symbol table and line info from ELF files.      ---*/
102/*---                                                      ---*/
103/*------------------------------------------------------------*/
104
105/* readelf.c parses ELF files and acquires symbol table info from
106   them.  It calls onwards to readdwarf.c to read DWARF2/3 line number
107   and call frame info found. */
108
109
110/* Identify an ELF object file by peering at the first few bytes of
111   it. */
112
113Bool ML_(is_elf_object_file)( void* image, SizeT n_image )
114{
115   ElfXX_Ehdr* ehdr = (ElfXX_Ehdr*)image;
116   Int ok = 1;
117
118   if (n_image < sizeof(ElfXX_Ehdr))
119      return False;
120
121   ok &= (ehdr->e_ident[EI_MAG0] == 0x7F
122          && ehdr->e_ident[EI_MAG1] == 'E'
123          && ehdr->e_ident[EI_MAG2] == 'L'
124          && ehdr->e_ident[EI_MAG3] == 'F');
125   ok &= (ehdr->e_ident[EI_CLASS] == VG_ELF_CLASS
126          && ehdr->e_ident[EI_DATA] == VG_ELF_DATA2XXX
127          && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
128   ok &= (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN);
129   ok &= (ehdr->e_machine == VG_ELF_MACHINE);
130   ok &= (ehdr->e_version == EV_CURRENT);
131   ok &= (ehdr->e_shstrndx != SHN_UNDEF);
132   ok &= (ehdr->e_shoff != 0 && ehdr->e_shnum != 0);
133   ok &= (ehdr->e_phoff != 0 && ehdr->e_phnum != 0);
134
135   if (ok)
136      return True;
137   else
138      return False;
139}
140
141
142/* Show a raw ELF symbol, given its in-image address and name. */
143
144static
145void show_raw_elf_symbol ( Int i,
146                           ElfXX_Sym* sym, Char* sym_name, Addr sym_svma,
147                           Bool ppc64_linux_format )
148{
149   HChar* space = ppc64_linux_format ? "                  " : "";
150   VG_(printf)("raw symbol [%4d]: ", i);
151   switch (ELFXX_ST_BIND(sym->st_info)) {
152      case STB_LOCAL:  VG_(printf)("LOC "); break;
153      case STB_GLOBAL: VG_(printf)("GLO "); break;
154      case STB_WEAK:   VG_(printf)("WEA "); break;
155      case STB_LOPROC: VG_(printf)("lop "); break;
156      case STB_HIPROC: VG_(printf)("hip "); break;
157      default:         VG_(printf)("??? "); break;
158   }
159   switch (ELFXX_ST_TYPE(sym->st_info)) {
160      case STT_NOTYPE:  VG_(printf)("NOT "); break;
161      case STT_OBJECT:  VG_(printf)("OBJ "); break;
162      case STT_FUNC:    VG_(printf)("FUN "); break;
163      case STT_SECTION: VG_(printf)("SEC "); break;
164      case STT_FILE:    VG_(printf)("FIL "); break;
165      case STT_LOPROC:  VG_(printf)("lop "); break;
166      case STT_HIPROC:  VG_(printf)("hip "); break;
167      default:          VG_(printf)("??? "); break;
168   }
169   VG_(printf)(": svma %#010lx, %ssz %4ld  %s\n",
170               sym_svma, space, sym->st_size + 0UL,
171               ( sym->st_name ? sym_name : (Char*)"NONAME" ) );
172}
173
174
175/* Decide whether SYM is something we should collect, and if so, copy
176   relevant info to the _OUT arguments.  For {x86,amd64,ppc32}-linux
177   this is straightforward - the name, address, size are copied out
178   unchanged.
179
180   There is a bit of a kludge re data symbols (see KLUDGED BSS CHECK
181   below): we assume that the .bss is mapped immediately after .data,
182   and so accept any data symbol which exists in the range [start of
183   .data, size of .data + size of .bss).  I don't know if this is
184   really correct/justifiable, or not.
185
186   For ppc64-linux it's more complex.  If the symbol is seen to be in
187   the .opd section, it is taken to be a function descriptor, and so
188   a dereference is attempted, in order to get hold of the real entry
189   point address.  Also as part of the dereference, there is an attempt
190   to calculate the TOC pointer (R2 value) associated with the symbol.
191
192   To support the ppc64-linux pre-"dotless" ABI (prior to gcc 4.0.0),
193   if the symbol is seen to be outside the .opd section and its name
194   starts with a dot, an .opd deference is not attempted, and no TOC
195   pointer is calculated, but the the leading dot is removed from the
196   name.
197
198   As a result, on ppc64-linux, the caller of this function may have
199   to piece together the real size, address, name of the symbol from
200   multiple calls to this function.  Ugly and confusing.
201*/
202static
203Bool get_elf_symbol_info (
204        /* INPUTS */
205        struct _DebugInfo* di, /* containing DebugInfo */
206        ElfXX_Sym* sym,        /* ELF symbol */
207        Char*      sym_name,   /* name */
208        Addr       sym_svma,   /* address as stated in the object file */
209        UChar*     opd_img,    /* oimage of .opd sec (ppc64-linux only) */
210        PtrdiffT   opd_bias,   /* for biasing AVMAs found in .opd */
211        /* OUTPUTS */
212        Char** sym_name_out,   /* name we should record */
213        Addr*  sym_avma_out,   /* addr we should record */
214        Int*   sym_size_out,   /* symbol size */
215        Addr*  sym_tocptr_out, /* ppc64-linux only: R2 value to be
216                                  used on entry */
217        Bool*  from_opd_out,   /* ppc64-linux only: did we deref an
218                                  .opd entry? */
219        Bool*  is_text_out     /* is this a text symbol? */
220     )
221{
222   Bool plausible, is_in_opd;
223   Bool in_text, in_data, in_sdata, in_bss;
224
225   /* Set defaults */
226   *sym_name_out   = sym_name;
227   *sym_avma_out   = sym_svma; /* we will bias this shortly */
228   *is_text_out    = True;
229   *sym_size_out   = (Int)sym->st_size;
230   *sym_tocptr_out = 0; /* unknown/inapplicable */
231   *from_opd_out   = False;
232
233   /* Figure out if we're interested in the symbol.  Firstly, is it of
234      the right flavour?  */
235   plausible
236      = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL
237         || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL
238         || ELFXX_ST_BIND(sym->st_info) == STB_WEAK
239        )
240        &&
241        (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC
242         || ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT
243        );
244
245   /* Now bias sym_avma_out accordingly */
246#if 0
247   /* This works, but seems a bit crude */
248   if (ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT) {
249      *is_text_out = False;
250      *sym_avma_out += di->data_bias;
251   } else {
252      *is_text_out = True;
253      *sym_avma_out += di->text_bias;
254   }
255#else
256   /* Try to figure out exactly which section the symbol is from and
257      bias accordingly.  Screws up if the previously deduced section
258      svma address ranges are wrong. */
259   if (di->text_present
260       && di->text_size > 0
261       && sym_svma >= di->text_svma
262       && sym_svma < di->text_svma + di->text_size) {
263      *is_text_out = True;
264      *sym_avma_out += di->text_bias;
265   } else
266   if (di->data_present
267       && di->data_size > 0
268       && sym_svma >= di->data_svma
269       && sym_svma < di->data_svma + di->data_size) {
270      *is_text_out = False;
271      *sym_avma_out += di->data_bias;
272   } else
273   if (di->sdata_present
274       && di->sdata_size > 0
275       && sym_svma >= di->sdata_svma
276       && sym_svma < di->sdata_svma + di->sdata_size) {
277      *is_text_out = False;
278      *sym_avma_out += di->sdata_bias;
279   } else
280   if (di->bss_present
281       && di->bss_size > 0
282       && sym_svma >= di->bss_svma
283       && sym_svma < di->bss_svma + di->bss_size) {
284      *is_text_out = False;
285      *sym_avma_out += di->bss_bias;
286   } else {
287      /* Assume it's in .text.  Is this a good idea? */
288      *is_text_out = True;
289      *sym_avma_out += di->text_bias;
290   }
291#endif
292
293#  if defined(VGP_ppc64_linux)
294   /* Allow STT_NOTYPE in the very special case where we're running on
295      ppc64-linux and the symbol is one which the .opd-chasing hack
296      below will chase. */
297   if (!plausible
298       && *is_text_out
299       && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE
300       && sym->st_size > 0
301       && di->opd_present
302       && di->opd_size > 0
303       && *sym_avma_out >= di->opd_avma
304       && *sym_avma_out <  di->opd_avma + di->opd_size)
305      plausible = True;
306#  endif
307
308   if (!plausible)
309      return False;
310
311   /* Ignore if nameless, or zero-sized. */
312   if (sym->st_name == (ElfXX_Word)0
313       || /* VG_(strlen)(sym_name) == 0 */
314          /* equivalent but cheaper ... */
315          sym_name[0] == 0
316       || sym->st_size == 0) {
317      TRACE_SYMTAB("    ignore -- size=0: %s\n", sym_name);
318      return False;
319   }
320
321   /* This seems to significantly reduce the number of junk
322      symbols, and particularly reduces the number of
323      overlapping address ranges.  Don't ask me why ... */
324   if ((Int)sym->st_value == 0) {
325      TRACE_SYMTAB( "    ignore -- valu=0: %s\n", sym_name);
326      return False;
327   }
328
329   /* If it's apparently in a GOT or PLT, it's really a reference to a
330      symbol defined elsewhere, so ignore it. */
331   if (di->got_present
332       && di->got_size > 0
333       && *sym_avma_out >= di->got_avma
334       && *sym_avma_out <  di->got_avma + di->got_size) {
335      TRACE_SYMTAB("    ignore -- in GOT: %s\n", sym_name);
336      return False;
337   }
338   if (di->plt_present
339       && di->plt_size > 0
340       && *sym_avma_out >= di->plt_avma
341       && *sym_avma_out <  di->plt_avma + di->plt_size) {
342      TRACE_SYMTAB("    ignore -- in PLT: %s\n", sym_name);
343      return False;
344   }
345
346   /* ppc64-linux nasty hack: if the symbol is in an .opd section,
347      then really what we have is the address of a function
348      descriptor.  So use the first word of that as the function's
349      text.
350
351      See thread starting at
352      http://gcc.gnu.org/ml/gcc-patches/2004-08/msg00557.html
353   */
354   is_in_opd = False;
355
356   if (di->opd_present
357       && di->opd_size > 0
358       && *sym_avma_out >= di->opd_avma
359       && *sym_avma_out <  di->opd_avma + di->opd_size) {
360#     if !defined(VGP_ppc64_linux)
361      TRACE_SYMTAB("    ignore -- in OPD: %s\n", sym_name);
362      return False;
363#     else
364      Int    offset_in_opd;
365      ULong* fn_descr;
366      Bool   details = 1||False;
367
368      if (details)
369         TRACE_SYMTAB("opdXXX: opd_bias %p, sym_svma_out %p\n",
370                      (void*)(opd_bias), (void*)*sym_avma_out);
371
372      if (!VG_IS_8_ALIGNED(*sym_avma_out)) {
373         TRACE_SYMTAB("    ignore -- not 8-aligned: %s\n", sym_name);
374         return False;
375      }
376
377      /* *sym_avma_out is a vma pointing into the .opd section.  We
378         know the vma of the opd section start, so we can figure out
379         how far into the opd section this is. */
380
381      offset_in_opd = (Addr)(*sym_avma_out) - (Addr)(di->opd_avma);
382      if (offset_in_opd < 0 || offset_in_opd >= di->opd_size) {
383         TRACE_SYMTAB("    ignore -- invalid OPD offset: %s\n", sym_name);
384         return False;
385      }
386
387      /* Now we want to know what's at that offset in the .opd
388         section.  We can't look in the running image since it won't
389         necessarily have been mapped.  But we can consult the oimage.
390         opd_img is the start address of the .opd in the oimage.
391         Hence: */
392
393      fn_descr = (ULong*)(opd_img + offset_in_opd);
394
395      if (details)
396         TRACE_SYMTAB("opdXXY: offset %d,  fn_descr %p\n",
397                      offset_in_opd, fn_descr);
398      if (details)
399         TRACE_SYMTAB("opdXXZ: *fn_descr %p\n", (void*)(fn_descr[0]));
400
401      /* opd_bias is the what we have to add to SVMAs found in .opd to
402         get plausible .text AVMAs for the entry point, and .data
403         AVMAs (presumably) for the TOC locations.  We use the caller
404         supplied value (which is di->text_bias) for both of these.
405         Not sure why that is correct - it seems to work, and sounds
406         OK for fn_descr[0], but surely we need to use the data bias
407         and not the text bias for fn_descr[1] ?  Oh Well.
408      */
409      *sym_avma_out   = fn_descr[0] + opd_bias;
410      *sym_tocptr_out = fn_descr[1] + opd_bias;
411      *from_opd_out   = True;
412      is_in_opd = True;
413
414      /* Do a final sanity check: if the symbol falls outside the
415         DebugInfo's mapped range, ignore it.  Since *sym_avma_out has
416         been updated, that can be achieved simply by falling through
417         to the test below. */
418
419#     endif /* ppc64-linux nasty hack */
420   }
421
422   /* Here's yet another ppc64-linux hack.  Get rid of leading dot if
423      the symbol is outside .opd. */
424#  if defined(VGP_ppc64_linux)
425   if (di->opd_size > 0
426       && !is_in_opd
427       && sym_name[0] == '.') {
428      vg_assert(!(*from_opd_out));
429      *sym_name_out = &sym_name[1];
430   }
431#  endif
432
433   /* If no part of the symbol falls within the mapped range,
434      ignore it. */
435
436   in_text
437      = di->text_present
438        && di->text_size > 0
439        && !(*sym_avma_out + *sym_size_out <= di->text_avma
440             || *sym_avma_out >= di->text_avma + di->text_size);
441
442   in_data
443      = di->data_present
444        && di->data_size > 0
445        && !(*sym_avma_out + *sym_size_out <= di->data_avma
446             || *sym_avma_out >= di->data_avma + di->data_size);
447
448   in_sdata
449      = di->sdata_present
450        && di->sdata_size > 0
451        && !(*sym_avma_out + *sym_size_out <= di->sdata_avma
452             || *sym_avma_out >= di->sdata_avma + di->sdata_size);
453
454   in_bss
455      = di->bss_present
456        && di->bss_size > 0
457        && !(*sym_avma_out + *sym_size_out <= di->bss_avma
458             || *sym_avma_out >= di->bss_avma + di->bss_size);
459
460
461   if (*is_text_out) {
462      /* This used to reject any symbol falling outside the text
463         segment ("if (!in_text) ...").  Now it is relaxed slightly,
464         to reject only symbols which fall outside the area mapped
465         r-x.  This is in accordance with r7427.  See
466         "Comment_Regarding_Text_Range_Checks" in storage.c for
467         background. */
468      Bool in_rx;
469      vg_assert(di->have_rx_map);
470      in_rx = (!(*sym_avma_out + *sym_size_out <= di->rx_map_avma
471                 || *sym_avma_out >= di->rx_map_avma + di->rx_map_size));
472      if (in_text)
473         vg_assert(in_rx);
474      if (!in_rx) {
475         TRACE_SYMTAB(
476            "ignore -- %#lx .. %#lx outside .text svma range %#lx .. %#lx\n",
477            *sym_avma_out, *sym_avma_out + *sym_size_out,
478            di->text_avma,
479            di->text_avma + di->text_size);
480         return False;
481      }
482   } else {
483     if (!(in_data || in_sdata || in_bss)) {
484         TRACE_SYMTAB(
485            "ignore -- %#lx .. %#lx outside .data / .sdata / .bss svma ranges\n",
486            *sym_avma_out, *sym_avma_out + *sym_size_out);
487         return False;
488      }
489   }
490
491#  if defined(VGP_ppc64_linux)
492   /* It's crucial that we never add symbol addresses in the .opd
493      section.  This would completely mess up function redirection and
494      intercepting.  This assert ensures that any symbols that make it
495      into the symbol table on ppc64-linux don't point into .opd. */
496   if (di->opd_present && di->opd_size > 0) {
497      vg_assert(*sym_avma_out + *sym_size_out <= di->opd_avma
498                || *sym_avma_out >= di->opd_avma + di->opd_size);
499   }
500#  endif
501
502   /* Acquire! */
503   return True;
504}
505
506
507/* Read an ELF symbol table (normal or dynamic).  This one is for the
508   "normal" case ({x86,amd64,ppc32}-linux). */
509static
510__attribute__((unused)) /* not referred to on all targets */
511void read_elf_symtab__normal(
512        struct _DebugInfo* di, UChar* tab_name,
513        ElfXX_Sym* symtab_img, SizeT symtab_szB,
514        UChar*     strtab_img, SizeT strtab_szB,
515        UChar*     opd_img /* ppc64-linux only */
516     )
517{
518   Word       i;
519   Addr       sym_svma, sym_avma_really;
520   Char      *sym_name, *sym_name_really;
521   Int        sym_size;
522   Addr       sym_tocptr;
523   Bool       from_opd, is_text;
524   DiSym      risym;
525   ElfXX_Sym *sym;
526
527   if (strtab_img == NULL || symtab_img == NULL) {
528      Char buf[80];
529      vg_assert(VG_(strlen)(tab_name) < 40);
530      VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
531      ML_(symerr)(di, False, buf);
532      return;
533   }
534
535   TRACE_SYMTAB("\n--- Reading (ELF, standard) %s (%ld entries) ---\n",
536                tab_name, symtab_szB/sizeof(ElfXX_Sym) );
537
538   /* Perhaps should start at i = 1; ELF docs suggest that entry
539      0 always denotes 'unknown symbol'. */
540   for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
541      sym      = & symtab_img[i];
542      sym_name = (UChar*)(strtab_img + sym->st_name);
543      sym_svma = sym->st_value;
544
545      if (di->trace_symtab)
546         show_raw_elf_symbol(i, sym, sym_name, sym_svma, False);
547
548      if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
549                              opd_img, di->text_bias,
550                              &sym_name_really,
551                              &sym_avma_really,
552                              &sym_size,
553                              &sym_tocptr,
554                              &from_opd, &is_text)) {
555
556         risym.addr   = sym_avma_really;
557         risym.size   = sym_size;
558         risym.name   = ML_(addStr) ( di, sym_name_really, -1 );
559         risym.tocptr = sym_tocptr;
560         risym.isText = is_text;
561         vg_assert(risym.name != NULL);
562         vg_assert(risym.tocptr == 0); /* has no role except on ppc64-linux */
563         ML_(addSym) ( di, &risym );
564
565         if (di->trace_symtab) {
566            VG_(printf)("    rec(%c) [%4ld]:          "
567                        "  val %#010lx, sz %4d  %s\n",
568                        is_text ? 't' : 'd',
569                        i,
570                        risym.addr,
571                        (Int)risym.size,
572                        (HChar*)risym.name
573            );
574         }
575
576      }
577   }
578}
579
580
581/* Read an ELF symbol table (normal or dynamic).  This one is for
582   ppc64-linux, which requires special treatment. */
583
584typedef
585   struct {
586      Addr   addr;
587      UChar* name;
588   }
589   TempSymKey;
590
591typedef
592   struct {
593      TempSymKey key;
594      Addr       tocptr;
595      Int        size;
596      Bool       from_opd;
597      Bool       is_text;
598   }
599   TempSym;
600
601static Word cmp_TempSymKey ( TempSymKey* key1, TempSym* elem2 ) {
602   if (key1->addr < elem2->key.addr) return -1;
603   if (key1->addr > elem2->key.addr) return 1;
604   return (Word)VG_(strcmp)(key1->name, elem2->key.name);
605}
606
607static
608__attribute__((unused)) /* not referred to on all targets */
609void read_elf_symtab__ppc64_linux(
610        struct _DebugInfo* di, UChar* tab_name,
611        ElfXX_Sym* symtab_img, SizeT symtab_szB,
612        UChar*     strtab_img, SizeT strtab_szB,
613        UChar*     opd_img /* ppc64-linux only */
614     )
615{
616   Word        i;
617   Int         old_size;
618   Addr        sym_svma, sym_avma_really;
619   Char       *sym_name, *sym_name_really;
620   Int         sym_size;
621   Addr        sym_tocptr, old_tocptr;
622   Bool        from_opd, modify_size, modify_tocptr, is_text;
623   DiSym       risym;
624   ElfXX_Sym  *sym;
625   OSet       *oset;
626   TempSymKey  key;
627   TempSym    *elem;
628   TempSym    *prev;
629
630   if (strtab_img == NULL || symtab_img == NULL) {
631      Char buf[80];
632      vg_assert(VG_(strlen)(tab_name) < 40);
633      VG_(sprintf)(buf, "   object doesn't have a %s", tab_name);
634      ML_(symerr)(di, False, buf);
635      return;
636   }
637
638   TRACE_SYMTAB("\n--- Reading (ELF, ppc64-linux) %s (%ld entries) ---\n",
639                tab_name, symtab_szB/sizeof(ElfXX_Sym) );
640
641   oset = VG_(OSetGen_Create)( offsetof(TempSym,key),
642                               (OSetCmp_t)cmp_TempSymKey,
643                               ML_(dinfo_zalloc), "di.respl.1",
644                               ML_(dinfo_free) );
645   vg_assert(oset);
646
647   /* Perhaps should start at i = 1; ELF docs suggest that entry
648      0 always denotes 'unknown symbol'. */
649   for (i = 1; i < (Word)(symtab_szB/sizeof(ElfXX_Sym)); i++) {
650      sym      = & symtab_img[i];
651      sym_name = (Char*)(strtab_img + sym->st_name);
652      sym_svma = sym->st_value;
653
654      if (di->trace_symtab)
655         show_raw_elf_symbol(i, sym, sym_name, sym_svma, True);
656
657      if (get_elf_symbol_info(di, sym, sym_name, sym_svma,
658                              opd_img, di->text_bias,
659                              &sym_name_really,
660                              &sym_avma_really,
661                              &sym_size,
662                              &sym_tocptr,
663                              &from_opd, &is_text)) {
664
665         /* Check if we've seen this (name,addr) key before. */
666         key.addr = sym_avma_really;
667         key.name = sym_name_really;
668         prev = VG_(OSetGen_Lookup)( oset, &key );
669
670         if (prev) {
671
672            /* Seen it before.  Fold in whatever new info we can. */
673            modify_size   = False;
674            modify_tocptr = False;
675            old_size   = 0;
676            old_tocptr = 0;
677
678            if (prev->from_opd && !from_opd
679                && (prev->size == 24 || prev->size == 16)
680                && sym_size != prev->size) {
681               /* Existing one is an opd-redirect, with a bogus size,
682                  so the only useful new fact we have is the real size
683                  of the symbol. */
684               modify_size = True;
685               old_size = prev->size;
686               prev->size = sym_size;
687            }
688            else
689            if (!prev->from_opd && from_opd
690                && (sym_size == 24 || sym_size == 16)) {
691               /* Existing one is non-opd, new one is opd.  What we
692                  can acquire from the new one is the TOC ptr to be
693                  used.  Since the existing sym is non-toc, it
694                  shouldn't currently have an known TOC ptr. */
695               vg_assert(prev->tocptr == 0);
696               modify_tocptr = True;
697               old_tocptr = prev->tocptr;
698               prev->tocptr = sym_tocptr;
699            }
700            else {
701               /* ignore. can we do better here? */
702            }
703
704            /* Only one or the other is possible (I think) */
705            vg_assert(!(modify_size && modify_tocptr));
706
707            if (modify_size && di->trace_symtab) {
708               VG_(printf)("    modify (old sz %4d)    "
709                           " val %#010lx, toc %#010lx, sz %4d  %s\n",
710                           old_size,
711                           prev->key.addr,
712                           prev->tocptr,
713                           (Int)   prev->size,
714                           (HChar*)prev->key.name
715               );
716            }
717            if (modify_tocptr && di->trace_symtab) {
718               VG_(printf)("    modify (upd tocptr)     "
719                           " val %#010lx, toc %#010lx, sz %4d  %s\n",
720                           prev->key.addr,
721                           prev->tocptr,
722                           (Int)   prev->size,
723                           (HChar*)prev->key.name
724               );
725            }
726
727         } else {
728
729            /* A new (name,addr) key.  Add and continue. */
730            elem = VG_(OSetGen_AllocNode)(oset, sizeof(TempSym));
731            vg_assert(elem);
732            elem->key      = key;
733            elem->tocptr   = sym_tocptr;
734            elem->size     = sym_size;
735            elem->from_opd = from_opd;
736            elem->is_text  = is_text;
737            VG_(OSetGen_Insert)(oset, elem);
738            if (di->trace_symtab) {
739               VG_(printf)("   to-oset [%4ld]:          "
740                           "  val %#010lx, toc %#010lx, sz %4d  %s\n",
741                           i,
742                           elem->key.addr,
743                           elem->tocptr,
744                           (Int)   elem->size,
745                           (HChar*)elem->key.name
746               );
747            }
748
749         }
750      }
751   }
752
753   /* All the syms that matter are in the oset.  Now pull them out,
754      build a "standard" symbol table, and nuke the oset. */
755
756   i = 0;
757   VG_(OSetGen_ResetIter)( oset );
758
759   while ( (elem = VG_(OSetGen_Next)(oset)) ) {
760      risym.addr   = elem->key.addr;
761      risym.size   = elem->size;
762      risym.name   = ML_(addStr) ( di, elem->key.name, -1 );
763      risym.tocptr = elem->tocptr;
764      risym.isText = elem->is_text;
765      vg_assert(risym.name != NULL);
766
767      ML_(addSym) ( di, &risym );
768      if (di->trace_symtab) {
769         VG_(printf)("    rec(%c) [%4ld]:          "
770                     "   val %#010lx, toc %#010lx, sz %4d  %s\n",
771                     risym.isText ? 't' : 'd',
772                     i,
773                     risym.addr,
774                     risym.tocptr,
775                     (Int)   risym.size,
776                     (HChar*)risym.name
777               );
778      }
779      i++;
780   }
781
782   VG_(OSetGen_Destroy)( oset );
783}
784
785
786/*
787 * This routine for calculating the CRC for a separate debug file
788 * is GPLed code borrowed from GNU binutils.
789 */
790static UInt
791calc_gnu_debuglink_crc32(UInt crc, const UChar *buf, Int len)
792{
793  static const UInt crc32_table[256] =
794    {
795      0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
796      0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
797      0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
798      0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
799      0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
800      0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
801      0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
802      0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
803      0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
804      0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
805      0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
806      0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
807      0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
808      0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
809      0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
810      0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
811      0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
812      0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
813      0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
814      0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
815      0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
816      0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
817      0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
818      0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
819      0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
820      0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
821      0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
822      0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
823      0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
824      0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
825      0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
826      0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
827      0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
828      0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
829      0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
830      0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
831      0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
832      0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
833      0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
834      0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
835      0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
836      0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
837      0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
838      0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
839      0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
840      0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
841      0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
842      0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
843      0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
844      0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
845      0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
846      0x2d02ef8d
847    };
848  const UChar *end;
849
850  crc = ~crc & 0xffffffff;
851  for (end = buf + len; buf < end; ++ buf)
852    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
853  return ~crc & 0xffffffff;;
854}
855
856/*
857 * Try and open a separate debug file, ignoring any where the CRC does
858 * not match the value from the main object file.
859 */
860static
861Addr open_debug_file( Char* name, UInt crc, /*OUT*/UWord* size )
862{
863   SysRes fd, sres;
864   struct vg_stat stat_buf;
865   UInt calccrc;
866
867   fd = VG_(open)(name, VKI_O_RDONLY, 0);
868   if (fd.isError)
869      return 0;
870
871   if (VG_(fstat)(fd.res, &stat_buf) != 0) {
872      VG_(close)(fd.res);
873      return 0;
874   }
875
876   if (VG_(clo_verbosity) > 1)
877      VG_(message)(Vg_DebugMsg, "Reading debug info from %s ..", name);
878
879   *size = stat_buf.st_size;
880
881   sres = VG_(am_mmap_file_float_valgrind)
882             ( *size, VKI_PROT_READ, fd.res, 0 );
883
884   VG_(close)(fd.res);
885
886   if (sres.isError)
887      return 0;
888
889   calccrc = calc_gnu_debuglink_crc32(0, (UChar*)sres.res, *size);
890   if (calccrc != crc) {
891      SysRes res = VG_(am_munmap_valgrind)(sres.res, *size);
892      vg_assert(!res.isError);
893      if (VG_(clo_verbosity) > 1)
894         VG_(message)(Vg_DebugMsg,
895            ".. CRC mismatch (computed %08x wanted %08x)", calccrc, crc);
896      return 0;
897   }
898
899   return sres.res;
900}
901
902/*
903 * Try to find a separate debug file for a given object file.
904 */
905static
906Addr find_debug_file( struct _DebugInfo* di,
907                      Char* objpath, Char* debugname,
908                      UInt crc, /*OUT*/UWord* size )
909{
910   Char *objdir = ML_(dinfo_strdup)("di.fdf.1", objpath);
911   Char *objdirptr;
912   Char *debugpath;
913   Addr addr = 0;
914
915   if ((objdirptr = VG_(strrchr)(objdir, '/')) != NULL)
916      *objdirptr = '\0';
917
918   debugpath = ML_(dinfo_zalloc)(
919                  "di.fdf.2",
920                  VG_(strlen)(objdir) + VG_(strlen)(debugname) + 32);
921
922   VG_(sprintf)(debugpath, "%s/%s", objdir, debugname);
923
924   if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
925      VG_(sprintf)(debugpath, "%s/.debug/%s", objdir, debugname);
926      if ((addr = open_debug_file(debugpath, crc, size)) == 0) {
927         VG_(sprintf)(debugpath, "/usr/lib/debug%s/%s", objdir, debugname);
928         addr = open_debug_file(debugpath, crc, size);
929      }
930   }
931
932   if (addr) {
933      TRACE_SYMTAB("\n");
934      TRACE_SYMTAB("------ Found a debuginfo file: %s\n", debugpath);
935   }
936
937   ML_(dinfo_free)(debugpath);
938   ML_(dinfo_free)(objdir);
939
940   return addr;
941}
942
943
944static Bool contained_within ( Addr outer, UWord n_outer,
945                               Addr inner, UWord n_inner )
946{
947   if (n_outer == 0 || n_inner == 0)
948      return False;
949   /* Simplistic .. assumes no wraparound (reasonably enough) */
950   if (inner >= outer && inner+n_inner <= outer+n_outer)
951      return True;
952   return False;
953}
954
955static void* INDEX_BIS ( void* base, Word idx, Word scale ) {
956   return (void*)( ((UChar*)base) + idx * scale );
957}
958
959
960/* Find the file offset corresponding to SVMA by using the program
961   headers.  This is taken from binutils-2.17/binutils/readelf.c
962   offset_from_vma(). */
963static
964Word file_offset_from_svma ( /*OUT*/Bool* ok,
965                             Addr         svma,
966                             ElfXX_Phdr*  phdr_img,
967                             Word         phdr_nent,
968                             Word         phdr_ent_szB )
969{
970   Word        i;
971   ElfXX_Phdr* seg;
972   for (i = 0; i < phdr_nent; i++) {
973      seg = INDEX_BIS( phdr_img, i, phdr_ent_szB );
974      if (seg->p_type != PT_LOAD)
975         continue;
976      if (svma >= (seg->p_vaddr & -seg->p_align)
977          && svma + 1 <= seg->p_vaddr + seg->p_filesz) {
978         *ok = True;
979         return svma - seg->p_vaddr + seg->p_offset;
980      }
981   }
982   *ok = False;
983   return 0;
984}
985
986/* The central function for reading ELF debug info.  For the
987   object/exe specified by the DebugInfo, find ELF sections, then read
988   the symbols, line number info, file name info, CFA (stack-unwind
989   info) and anything else we want, into the tables within the
990   supplied DebugInfo.
991*/
992Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
993{
994   Bool          res, ok;
995   SysRes        fd, sres;
996   Word          i;
997
998   /* Image addresses for the ELF file we're working with. */
999   Addr          oimage   = 0;
1000   UWord         n_oimage = 0;
1001
1002   /* Ditto for any ELF debuginfo file that we might happen to load. */
1003   Addr          dimage   = 0;
1004   UWord         n_dimage = 0;
1005
1006   /* ELF header for the main file.  Should == oimage since is at
1007      start of file. */
1008   ElfXX_Ehdr* ehdr_img = NULL;
1009
1010   /* Program header table image addr, # entries, entry size */
1011   ElfXX_Phdr* phdr_img     = NULL;
1012   UWord       phdr_nent    = 0;
1013   UWord       phdr_ent_szB = 0;
1014
1015   /* Section header image addr, # entries, entry size.  Also the
1016      associated string table. */
1017   ElfXX_Shdr* shdr_img        = NULL;
1018   UWord       shdr_nent       = 0;
1019   UWord       shdr_ent_szB    = 0;
1020   UChar*      shdr_strtab_img = NULL;
1021
1022   /* SVMAs covered by rx and rw segments and corresponding bias. */
1023   Addr     rx_svma_base = 0;
1024   Addr     rx_svma_limit = 0;
1025   PtrdiffT rx_bias = 0;
1026   Addr     rw_svma_base = 0;
1027   Addr     rw_svma_limit = 0;
1028   PtrdiffT rw_bias = 0;
1029
1030   vg_assert(di);
1031   vg_assert(di->have_rx_map == True);
1032   vg_assert(di->have_rw_map == True);
1033   vg_assert(di->rx_map_size > 0);
1034   vg_assert(di->rw_map_size > 0);
1035   vg_assert(di->have_dinfo == False);
1036   vg_assert(di->filename);
1037   vg_assert(!di->memname);
1038   vg_assert(!di->symtab);
1039   vg_assert(!di->loctab);
1040   vg_assert(!di->cfsi);
1041   vg_assert(!di->cfsi_exprs);
1042   vg_assert(!di->strchunks);
1043   vg_assert(!di->soname);
1044
1045   /* If these don't hold true, it means that m_syswrap/m_aspacemgr
1046      managed to do a mapping where the start isn't page aligned.
1047      Which sounds pretty bogus to me. */
1048   vg_assert(VG_IS_PAGE_ALIGNED(di->rx_map_avma));
1049   vg_assert(VG_IS_PAGE_ALIGNED(di->rw_map_avma));
1050
1051   /* ----------------------------------------------------------
1052      At this point, there is very little information in the
1053      DebugInfo.  We only know that something that looks like an ELF
1054      file has been mapped rx-ishly as recorded with the di->*rx_map*
1055      fields and has also been mapped rw-ishly as recorded with the
1056      di->*rw_map* fields.  First we examine the file's ELF Program
1057      Header, and, by comparing that against the di->*r{w,x}_map*
1058      info, try to figure out the AVMAs for the sections we care
1059      about, that should have been mapped: text, data, sdata, bss got,
1060      plt, and toc.
1061      ---------------------------------------------------------- */
1062
1063   oimage = (Addr)NULL;
1064   if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir))
1065      VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)",
1066                                di->filename, di->rx_map_avma );
1067
1068   /* mmap the object image aboard, so that we can read symbols and
1069      line number info out of it.  It will be munmapped immediately
1070      thereafter; it is only aboard transiently. */
1071
1072   fd = VG_(open)(di->filename, VKI_O_RDONLY, 0);
1073   if (fd.isError) {
1074      ML_(symerr)(di, True, "Can't open .so/.exe to read symbols?!");
1075      return False;
1076   }
1077
1078   { Long n_oimageLL = VG_(fsize)(fd.res);
1079     if (n_oimageLL <= 0) {
1080        ML_(symerr)(di, True, "Can't stat .so/.exe (to determine its size)?!");
1081        VG_(close)(fd.res);
1082        return False;
1083     }
1084     n_oimage = (UWord)(ULong)n_oimageLL;
1085   }
1086
1087   sres = VG_(am_mmap_file_float_valgrind)
1088             ( n_oimage, VKI_PROT_READ, fd.res, 0 );
1089
1090   VG_(close)(fd.res);
1091
1092   if (sres.isError) {
1093      VG_(message)(Vg_UserMsg, "warning: mmap failed on %s", di->filename );
1094      VG_(message)(Vg_UserMsg, "         no symbols or debug info loaded" );
1095      return False;
1096   }
1097
1098   oimage = sres.res;
1099   /* Check against wraparound.  am_mmap_file_float_valgrind should
1100      not produce a wrapped-around mapping. */
1101   vg_assert(n_oimage > 0);
1102   vg_assert(oimage + n_oimage > oimage);
1103
1104   if (0) {
1105      VG_(printf)("read_elf_debug_info: OIMAGE = %p - %p\n",
1106                  (void*)oimage, (void*)(oimage + (UWord)n_oimage));
1107   }
1108
1109   /* Ok, the object image is safely in oimage[0 .. n_oimage-1].  Now
1110      verify that it is a valid ELF .so or executable image. */
1111   res      = False;
1112   ok       = (n_oimage >= sizeof(ElfXX_Ehdr));
1113   ehdr_img = (ElfXX_Ehdr*)oimage;
1114
1115   if (ok)
1116      ok &= ML_(is_elf_object_file)(ehdr_img, n_oimage);
1117
1118   if (!ok) {
1119      ML_(symerr)(di, True, "Invalid ELF Header");
1120      goto out;
1121   }
1122
1123   /* Find where the program and section header tables are, and give
1124      up if either is missing or outside the image (bogus). */
1125   phdr_img     = (ElfXX_Phdr*)( ((UChar*)ehdr_img) + ehdr_img->e_phoff );
1126   phdr_nent    = ehdr_img->e_phnum;
1127   phdr_ent_szB = ehdr_img->e_phentsize;
1128
1129   shdr_img     = (ElfXX_Shdr*)( ((UChar*)ehdr_img) + ehdr_img->e_shoff );
1130   shdr_nent    = ehdr_img->e_shnum;
1131   shdr_ent_szB = ehdr_img->e_shentsize;
1132
1133   TRACE_SYMTAB("------ Basic facts about the object ------\n");
1134   TRACE_SYMTAB("object: img %p n_oimage %ld\n",
1135               (void*)oimage, n_oimage);
1136   TRACE_SYMTAB("phdr:   img %p nent %ld ent_szB %ld\n",
1137               phdr_img, phdr_nent, phdr_ent_szB);
1138   TRACE_SYMTAB("shdr:   img %p nent %ld ent_szB %ld\n",
1139               shdr_img, shdr_nent, shdr_ent_szB);
1140
1141   if (phdr_nent == 0
1142       || !contained_within(
1143             oimage, n_oimage,
1144             (Addr)phdr_img, phdr_nent * phdr_ent_szB)) {
1145      ML_(symerr)(di, True, "Missing or invalid ELF Program Header Table");
1146      goto out;
1147   }
1148
1149   if (shdr_nent == 0
1150       || !contained_within(
1151             oimage, n_oimage,
1152             (Addr)shdr_img, shdr_nent * shdr_ent_szB)) {
1153      ML_(symerr)(di, True, "Missing or invalid ELF Section Header Table");
1154      goto out;
1155   }
1156
1157   /* Also find the section header's string table, and validate. */
1158   /* checked previously by is_elf_object_file: */
1159   vg_assert( ehdr_img->e_shstrndx != SHN_UNDEF );
1160
1161   shdr_strtab_img
1162      = (UChar*)( ((UChar*)ehdr_img)
1163                  + shdr_img[ehdr_img->e_shstrndx].sh_offset);
1164   if (!contained_within( oimage, n_oimage,
1165                          (Addr)shdr_strtab_img,
1166                          1/*bogus, but we don't know the real size*/ )) {
1167      ML_(symerr)(di, True, "Invalid ELF Section Header String Table");
1168      goto out;
1169   }
1170
1171   TRACE_SYMTAB("shdr:   string table at %p\n", shdr_strtab_img );
1172
1173   /* Do another amazingly tedious thing: find out the .soname for
1174      this object.  Apparently requires looking through the program
1175      header table. */
1176   TRACE_SYMTAB("\n");
1177   TRACE_SYMTAB("------ Looking for the soname ------\n");
1178   vg_assert(di->soname == NULL);
1179   {
1180      ElfXX_Addr prev_svma = 0;
1181
1182      for (i = 0; i < phdr_nent; i++) {
1183         ElfXX_Phdr* phdr = INDEX_BIS( phdr_img, i, phdr_ent_szB );
1184
1185         /* Make sure the PT_LOADable entries are in order */
1186         if (phdr->p_type == PT_LOAD) {
1187            TRACE_SYMTAB("PT_LOAD in order?: %#lx %#lx\n",
1188                         prev_svma + 0UL,
1189                         phdr->p_vaddr + 0UL);
1190            if (phdr->p_vaddr < prev_svma) {
1191               ML_(symerr)(di, True,
1192                           "ELF Program Headers are not in ascending order");
1193               goto out;
1194            }
1195            prev_svma = phdr->p_vaddr;
1196            if (rx_svma_limit == 0
1197                && phdr->p_offset >= di->rx_map_foff
1198                && phdr->p_offset < di->rx_map_foff + di->rx_map_size
1199                && phdr->p_offset + phdr->p_filesz <= di->rx_map_foff + di->rx_map_size) {
1200               rx_svma_base = phdr->p_vaddr;
1201               rx_svma_limit = phdr->p_vaddr + phdr->p_memsz;
1202               rx_bias = di->rx_map_avma - di->rx_map_foff + phdr->p_offset - phdr->p_vaddr;
1203            }
1204            else if (rw_svma_limit == 0
1205                     && phdr->p_offset >= di->rw_map_foff
1206                     && phdr->p_offset < di->rw_map_foff + di->rw_map_size
1207                     && phdr->p_offset + phdr->p_filesz <= di->rw_map_foff + di->rw_map_size) {
1208               rw_svma_base = phdr->p_vaddr;
1209               rw_svma_limit = phdr->p_vaddr + phdr->p_memsz;
1210               rw_bias = di->rw_map_avma - di->rw_map_foff + phdr->p_offset - phdr->p_vaddr;
1211            }
1212         }
1213
1214         /* Try to get the soname.  If there isn't one, use "NONE".
1215            The seginfo needs to have some kind of soname in order to
1216            facilitate writing redirect functions, since all redirect
1217            specifications require a soname (pattern). */
1218         if (phdr->p_type == PT_DYNAMIC && di->soname == NULL) {
1219            ElfXX_Dyn* dyn_img = (ElfXX_Dyn*)( ((UChar*)ehdr_img)
1220                                               + phdr->p_offset);
1221            Word   stroff = -1;
1222            UChar* strtab = NULL;
1223            Word   j;
1224            for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) {
1225               switch (dyn_img[j].d_tag) {
1226                  case DT_SONAME: {
1227                     stroff = dyn_img[j].d_un.d_val;
1228                     break;
1229                  }
1230                  case DT_STRTAB: {
1231                     Bool ok2 = False;
1232                     Word offset = file_offset_from_svma(
1233                                      &ok2,
1234                                      dyn_img[j].d_un.d_ptr,
1235                                      phdr_img,
1236                                      phdr_nent, phdr_ent_szB
1237                                   );
1238                     if (ok2 && strtab == NULL) {
1239                        vg_assert(offset >= 0 && offset <= n_oimage);
1240                        strtab = ((UChar*)ehdr_img) + offset;
1241                     }
1242                     break;
1243                  }
1244                  default:
1245                     break;
1246               }
1247            }
1248            if (stroff != -1 && strtab != NULL) {
1249               TRACE_SYMTAB("Found soname = %s\n", strtab+stroff);
1250               di->soname = ML_(dinfo_strdup)("di.redi.1", strtab+stroff);
1251            }
1252         }
1253      } /* for (i = 0; i < phdr_nent; i++) ... */
1254   } /* look for the soname */
1255
1256   /* If, after looking at all the program headers, we still didn't
1257      find a soname, add a fake one. */
1258   if (di->soname == NULL) {
1259      TRACE_SYMTAB("No soname found; using (fake) \"NONE\"\n");
1260      di->soname = "NONE";
1261   }
1262
1263   vg_assert(rx_svma_limit != 0);
1264   vg_assert(rw_svma_limit != 0);
1265
1266   /* Now read the section table. */
1267   TRACE_SYMTAB("\n");
1268   TRACE_SYMTAB("------ Examining the section headers "
1269                "and program headers ------\n");
1270   TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n",
1271               di->rx_map_avma,
1272               di->rx_map_foff, di->rx_map_foff + di->rx_map_size - 1 );
1273   TRACE_SYMTAB("rx: contains svmas %#lx .. %#lx with bias %#lx\n",
1274                rx_svma_base, rx_svma_limit - 1, rx_bias );
1275   TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n",
1276               di->rw_map_avma,
1277               di->rw_map_foff, di->rw_map_foff + di->rw_map_size - 1 );
1278   TRACE_SYMTAB("rw: contains svmas %#lx .. %#lx with bias %#lx\n",
1279                rw_svma_base, rw_svma_limit - 1, rw_bias );
1280
1281   for (i = 0; i < shdr_nent; i++) {
1282      ElfXX_Shdr* shdr = INDEX_BIS( shdr_img, i, shdr_ent_szB );
1283      UChar* name = shdr_strtab_img + shdr->sh_name;
1284      Addr   svma = shdr->sh_addr;
1285      OffT   foff = shdr->sh_offset;
1286      UWord  size = shdr->sh_size;
1287      UInt   alyn = shdr->sh_addralign;
1288      Bool   bits = !(shdr->sh_type == SHT_NOBITS);
1289      Bool   inrx = svma >= rx_svma_base && svma < rx_svma_limit;
1290      Bool   inrw = svma >= rw_svma_base && svma < rw_svma_limit;
1291
1292      TRACE_SYMTAB(" [sec %2ld]  %s %s  al%2u  foff %6ld .. %6ld  "
1293                  "  svma %p  name \"%s\"\n",
1294                  i, inrx ? "rx" : "  ", inrw ? "rw" : "  ", alyn,
1295                  foff, foff+size-1, (void*)svma, name );
1296
1297      /* Check for sane-sized segments.  SHT_NOBITS sections have zero
1298         size in the file. */
1299      if ((foff >= n_oimage) || (foff + (bits ? size : 0) > n_oimage)) {
1300         ML_(symerr)(di, True, "ELF Section extends beyond image end");
1301         goto out;
1302      }
1303
1304      /* Check for a sane alignment value. */
1305      if (alyn > 0 && -1 == VG_(log2)(alyn)) {
1306         ML_(symerr)(di, True, "ELF Section contains invalid "
1307                               ".sh_addralign value");
1308         goto out;
1309      }
1310
1311#     define BAD(_secname)                                 \
1312         do { ML_(symerr)(di, True,                        \
1313                          "Can't make sense of " _secname  \
1314                          " section mapping");             \
1315              goto out;                                    \
1316         } while (0)
1317
1318      /* Find avma-s for: .text .data .sdata .bss .plt .got .opd
1319         and .eh_frame */
1320
1321      /* Accept .text where mapped as rx (code) */
1322      if (0 == VG_(strcmp)(name, ".text")) {
1323         if (inrx && size > 0 && !di->text_present) {
1324            di->text_present = True;
1325            di->text_svma = svma;
1326            di->text_avma = svma + rx_bias;
1327            di->text_size = size;
1328            di->text_bias = rx_bias;
1329            TRACE_SYMTAB("acquiring .text svma = %#lx .. %#lx\n",
1330                         di->text_svma,
1331                         di->text_svma + di->text_size - 1);
1332            TRACE_SYMTAB("acquiring .text avma = %#lx .. %#lx\n",
1333                         di->text_avma,
1334                         di->text_avma + di->text_size - 1);
1335            TRACE_SYMTAB("acquiring .text bias = %#lx\n", di->text_bias);
1336         } else {
1337            BAD(".text");
1338         }
1339      }
1340
1341      /* Accept .data where mapped as rw (data), even if zero-sized */
1342      if (0 == VG_(strcmp)(name, ".data")) {
1343         if (inrw && size >= 0 && !di->data_present) {
1344            di->data_present = True;
1345            di->data_svma = svma;
1346            di->data_avma = svma + rw_bias;
1347            di->data_size = size;
1348            di->data_bias = rw_bias;
1349            TRACE_SYMTAB("acquiring .data svma = %#lx .. %#lx\n",
1350                         di->data_svma,
1351                         di->data_svma + di->data_size - 1);
1352            TRACE_SYMTAB("acquiring .data avma = %#lx .. %#lx\n",
1353                         di->data_avma,
1354                         di->data_avma + di->data_size - 1);
1355            TRACE_SYMTAB("acquiring .data bias = %#lx\n", di->data_bias);
1356         } else {
1357            BAD(".data");
1358         }
1359      }
1360
1361      /* Accept .sdata where mapped as rw (data) */
1362      if (0 == VG_(strcmp)(name, ".sdata")) {
1363         if (inrw && size > 0 && !di->sdata_present) {
1364            di->sdata_present = True;
1365            di->sdata_svma = svma;
1366            di->sdata_avma = svma + rw_bias;
1367            di->sdata_size = size;
1368            di->sdata_bias = rw_bias;
1369            TRACE_SYMTAB("acquiring .sdata svma = %#lx .. %#lx\n",
1370                         di->sdata_svma,
1371                         di->sdata_svma + di->sdata_size - 1);
1372            TRACE_SYMTAB("acquiring .sdata avma = %#lx .. %#lx\n",
1373                         di->sdata_avma,
1374                         di->sdata_avma + di->sdata_size - 1);
1375            TRACE_SYMTAB("acquiring .sdata bias = %#lx\n", di->sdata_bias);
1376         } else {
1377            BAD(".sdata");
1378         }
1379      }
1380
1381      /* Accept .bss where mapped as rw (data), even if zero-sized */
1382      if (0 == VG_(strcmp)(name, ".bss")) {
1383         if (inrw && size >= 0 && !di->bss_present) {
1384            di->bss_present = True;
1385            di->bss_svma = svma;
1386            di->bss_avma = svma + rw_bias;
1387            di->bss_size = size;
1388            di->bss_bias = rw_bias;
1389            TRACE_SYMTAB("acquiring .bss svma = %#lx .. %#lx\n",
1390                         di->bss_svma,
1391                         di->bss_svma + di->bss_size - 1);
1392            TRACE_SYMTAB("acquiring .bss avma = %#lx .. %#lx\n",
1393                         di->bss_avma,
1394                         di->bss_avma + di->bss_size - 1);
1395            TRACE_SYMTAB("acquiring .bss bias = %#lx\n", di->bss_bias);
1396         } else
1397
1398         /* Now one from the wtf?! department ... */
1399         if (inrx && (!inrw) && size >= 0 && !di->bss_present) {
1400            /* File contains a .bss, but it got mapped as rx only.
1401               This is very strange.  For now, just pretend we didn't
1402               see it :-) */
1403            di->bss_present = False;
1404            di->bss_svma = 0;
1405            di->bss_avma = 0;
1406            di->bss_size = 0;
1407            di->bss_bias = 0;
1408            if (!VG_(clo_xml)) {
1409               VG_(message)(Vg_UserMsg, "Warning: the following file's .bss is "
1410                                       "mapped r-x only - ignoring .bss syms");
1411               VG_(message)(Vg_UserMsg,   " %s", di->filename
1412                                                    ? di->filename
1413                                                    : (UChar*)"(null?!)" );
1414            }
1415         } else
1416
1417         if ((!inrw) && (!inrx) && size > 0 && !di->bss_present) {
1418            /* File contains a .bss, but it didn't get mapped.  Ignore. */
1419            di->bss_present = False;
1420            di->bss_svma = 0;
1421            di->bss_avma = 0;
1422            di->bss_size = 0;
1423            di->bss_bias = 0;
1424         } else {
1425            BAD(".bss");
1426         }
1427      }
1428
1429      /* Accept .got where mapped as rw (data) */
1430      if (0 == VG_(strcmp)(name, ".got")) {
1431         if (inrw && size > 0 && !di->got_present) {
1432            di->got_present = True;
1433            di->got_avma = svma + rw_bias;
1434            di->got_size = size;
1435            TRACE_SYMTAB("acquiring .got avma = %#lx\n", di->got_avma);
1436         } else {
1437            BAD(".got");
1438         }
1439      }
1440
1441      /* Accept .got.plt where mapped as rw (data) */
1442      if (0 == VG_(strcmp)(name, ".got.plt")) {
1443         if (inrw && size > 0 && !di->gotplt_present) {
1444            di->gotplt_present = True;
1445            di->gotplt_avma = svma + rw_bias;
1446            di->gotplt_size = size;
1447            TRACE_SYMTAB("acquiring .got.plt avma = %#lx\n", di->gotplt_avma);
1448         } else if (size != 0) {
1449            BAD(".got.plt");
1450         }
1451      }
1452
1453      /* PLT is different on different platforms, it seems. */
1454#     if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
1455      /* Accept .plt where mapped as rx (code) */
1456      if (0 == VG_(strcmp)(name, ".plt")) {
1457         if (inrx && size > 0 && !di->plt_present) {
1458            di->plt_present = True;
1459            di->plt_avma = svma + rx_bias;
1460            di->plt_size = size;
1461            TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1462         } else {
1463            BAD(".plt");
1464         }
1465      }
1466#     elif defined(VGP_ppc32_linux)
1467      /* Accept .plt where mapped as rw (data) */
1468      if (0 == VG_(strcmp)(name, ".plt")) {
1469         if (inrw && size > 0 && !di->plt_present) {
1470            di->plt_present = True;
1471            di->plt_avma = svma + rw_bias;
1472            di->plt_size = size;
1473            TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1474         } else {
1475            BAD(".plt");
1476         }
1477      }
1478#     elif defined(VGP_ppc64_linux)
1479      /* Accept .plt where mapped as rw (data), or unmapped */
1480      if (0 == VG_(strcmp)(name, ".plt")) {
1481         if (inrw && size > 0 && !di->plt_present) {
1482            di->plt_present = True;
1483            di->plt_avma = svma + rw_bias;
1484            di->plt_size = size;
1485            TRACE_SYMTAB("acquiring .plt avma = %#lx\n", di->plt_avma);
1486         } else
1487         if ((!inrw) && (!inrx) && size > 0 && !di->plt_present) {
1488            /* File contains a .plt, but it didn't get mapped.
1489               Presumably it is not required on this platform.  At
1490               least don't reject the situation as invalid. */
1491            di->plt_present = True;
1492            di->plt_avma = 0;
1493            di->plt_size = 0;
1494         } else {
1495            BAD(".plt");
1496         }
1497      }
1498#     else
1499#       error "Unsupported platform"
1500#     endif
1501
1502      /* Accept .opd where mapped as rw (data) */
1503      if (0 == VG_(strcmp)(name, ".opd")) {
1504         if (inrw && size > 0 && !di->opd_present) {
1505            di->opd_present = True;
1506            di->opd_avma = svma + rw_bias;
1507            di->opd_size = size;
1508            TRACE_SYMTAB("acquiring .opd avma = %#lx\n", di->opd_avma);
1509         } else {
1510            BAD(".opd");
1511         }
1512      }
1513
1514      /* Accept .eh_frame where mapped as rx (code).  This seems to be
1515         the common case.  However, if that doesn't pan out, try for
1516         rw (data) instead. */
1517      if (0 == VG_(strcmp)(name, ".eh_frame")) {
1518         if (inrx && size > 0 && !di->ehframe_present) {
1519            di->ehframe_present = True;
1520            di->ehframe_avma = svma + rx_bias;
1521            di->ehframe_size = size;
1522            TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", di->ehframe_avma);
1523         } else
1524         if (inrw && size > 0 && !di->ehframe_present) {
1525            di->ehframe_present = True;
1526            di->ehframe_avma = svma + rw_bias;
1527            di->ehframe_size = size;
1528            TRACE_SYMTAB("acquiring .eh_frame avma = %#lx\n", di->ehframe_avma);
1529         } else {
1530            BAD(".eh_frame");
1531         }
1532      }
1533
1534#    undef BAD
1535
1536   }
1537
1538   if (0) VG_(printf)("YYYY text_: avma %#lx  size %ld  bias %#lx\n",
1539                      di->text_avma, di->text_size, di->text_bias);
1540
1541   if (VG_(clo_verbosity) > 2 || VG_(clo_trace_redir))
1542      VG_(message)(Vg_DebugMsg, "   svma %#010lx, avma %#010lx",
1543                                di->text_avma - di->text_bias,
1544                                di->text_avma );
1545
1546   TRACE_SYMTAB("\n");
1547   TRACE_SYMTAB("------ Finding image addresses "
1548                "for debug-info sections ------\n");
1549
1550   /* Find interesting sections, read the symbol table(s), read any debug
1551      information */
1552   {
1553      /* IMAGE addresses: pointers to start of sections in the
1554         transiently loaded oimage, not in the fragments of the file
1555         mapped in by the guest's dynamic linker. */
1556      UChar*     strtab_img       = NULL; /* .strtab */
1557      ElfXX_Sym* symtab_img       = NULL; /* .symtab */
1558      UChar*     dynstr_img       = NULL; /* .dynstr */
1559      ElfXX_Sym* dynsym_img       = NULL; /* .dynsym */
1560      UChar*     debuglink_img    = NULL; /* .gnu_debuglink */
1561      UChar*     stab_img         = NULL; /* .stab         (stabs)  */
1562      UChar*     stabstr_img      = NULL; /* .stabstr      (stabs)  */
1563      UChar*     debug_line_img   = NULL; /* .debug_line   (dwarf2) */
1564      UChar*     debug_info_img   = NULL; /* .debug_info   (dwarf2) */
1565      UChar*     debug_abbv_img   = NULL; /* .debug_abbrev (dwarf2) */
1566      UChar*     debug_str_img    = NULL; /* .debug_str    (dwarf2) */
1567      UChar*     debug_ranges_img = NULL; /* .debug_ranges (dwarf2) */
1568      UChar*     debug_loc_img    = NULL; /* .debug_loc    (dwarf2) */
1569      UChar*     dwarf1d_img      = NULL; /* .debug        (dwarf1) */
1570      UChar*     dwarf1l_img      = NULL; /* .line         (dwarf1) */
1571      UChar*     ehframe_img      = NULL; /* .eh_frame     (dwarf2) */
1572      UChar*     opd_img          = NULL; /* .opd (dwarf2,
1573                                                   ppc64-linux) */
1574      /* Section sizes, in bytes */
1575      SizeT      strtab_sz       = 0;
1576      SizeT      symtab_sz       = 0;
1577      SizeT      dynstr_sz       = 0;
1578      SizeT      dynsym_sz       = 0;
1579      SizeT      debuglink_sz    = 0;
1580      SizeT      stab_sz         = 0;
1581      SizeT      stabstr_sz      = 0;
1582      SizeT      debug_line_sz   = 0;
1583      SizeT      debug_info_sz   = 0;
1584      SizeT      debug_abbv_sz   = 0;
1585      SizeT      debug_str_sz    = 0;
1586      SizeT      debug_ranges_sz = 0;
1587      SizeT      debug_loc_sz    = 0;
1588      SizeT      dwarf1d_sz      = 0;
1589      SizeT      dwarf1l_sz      = 0;
1590      SizeT      ehframe_sz      = 0;
1591      SizeT      opd_sz_unused   = 0;
1592
1593      /* Find all interesting sections */
1594
1595      /* What FIND does: it finds the section called SEC_NAME.  The
1596         size of it is assigned to SEC_SIZE.  The address of the
1597         section in the transiently loaded oimage is assigned to
1598         SEC_FILEA.  Even for sections which are marked loadable, the
1599         client's ld.so may not have loaded them yet, so there is no
1600         guarantee that we can safely prod around in any such area).
1601         Because the entire object file is transiently mapped aboard
1602         for inspection, it's always safe to inspect that area. */
1603
1604      for (i = 0; i < ehdr_img->e_shnum; i++) {
1605
1606#        define FIND(sec_name, sec_size, sec_img) \
1607         do { ElfXX_Shdr* shdr \
1608                 = INDEX_BIS( shdr_img, i, shdr_ent_szB ); \
1609            if (0 == VG_(strcmp)(sec_name, shdr_strtab_img \
1610                                           + shdr->sh_name)) { \
1611               Bool nobits; \
1612               sec_img  = (void*)(oimage + shdr->sh_offset); \
1613               sec_size = shdr->sh_size; \
1614               nobits   = shdr->sh_type == SHT_NOBITS; \
1615               TRACE_SYMTAB( "%18s:  img %p .. %p\n", \
1616                             sec_name, (UChar*)sec_img, \
1617                             ((UChar*)sec_img) + sec_size - 1); \
1618               /* SHT_NOBITS sections have zero size in the file. */ \
1619               if ( shdr->sh_offset \
1620                    + (nobits ? 0 : sec_size) > n_oimage ) { \
1621                  ML_(symerr)(di, True, \
1622                              "   section beyond image end?!"); \
1623                  goto out; \
1624               } \
1625            } \
1626         } while (0);
1627
1628         /*   NAME              SIZE             IMAGE addr */
1629         FIND(".dynsym",        dynsym_sz,       dynsym_img)
1630         FIND(".dynstr",        dynstr_sz,       dynstr_img)
1631         FIND(".symtab",        symtab_sz,       symtab_img)
1632         FIND(".strtab",        strtab_sz,       strtab_img)
1633
1634         FIND(".gnu_debuglink", debuglink_sz,    debuglink_img)
1635
1636         FIND(".stab",          stab_sz,         stab_img)
1637         FIND(".stabstr",       stabstr_sz,      stabstr_img)
1638
1639         FIND(".debug_line",    debug_line_sz,   debug_line_img)
1640         FIND(".debug_info",    debug_info_sz,   debug_info_img)
1641         FIND(".debug_abbrev",  debug_abbv_sz,   debug_abbv_img)
1642         FIND(".debug_str",     debug_str_sz,    debug_str_img)
1643         FIND(".debug_ranges",  debug_ranges_sz, debug_ranges_img)
1644         FIND(".debug_loc",     debug_loc_sz,    debug_loc_img)
1645
1646         FIND(".debug",         dwarf1d_sz,      dwarf1d_img)
1647         FIND(".line",          dwarf1l_sz,      dwarf1l_img)
1648         FIND(".eh_frame",      ehframe_sz,      ehframe_img)
1649
1650         FIND(".opd",           opd_sz_unused,   opd_img)
1651
1652#        undef FIND
1653      }
1654
1655      /* Did we find a debuglink section? */
1656      if (debuglink_img != NULL) {
1657         UInt crc_offset = VG_ROUNDUP(VG_(strlen)(debuglink_img)+1, 4);
1658         UInt crc;
1659
1660         vg_assert(crc_offset + sizeof(UInt) <= debuglink_sz);
1661
1662         /* Extract the CRC from the debuglink section */
1663         crc = *(UInt *)(debuglink_img + crc_offset);
1664
1665         /* See if we can find a matching debug file */
1666         dimage = find_debug_file( di, di->filename, debuglink_img,
1667                                   crc, &n_dimage );
1668
1669         if (dimage != 0
1670             && n_dimage >= sizeof(ElfXX_Ehdr)
1671             && ML_(is_elf_object_file)((void*)dimage, n_dimage)) {
1672
1673            /* Pull out and validate program header and section header info */
1674            ElfXX_Ehdr* ehdr_dimg     = (ElfXX_Ehdr*)dimage;
1675            ElfXX_Phdr* phdr_dimg     = (ElfXX_Phdr*)( ((UChar*)ehdr_dimg)
1676                                                       + ehdr_dimg->e_phoff );
1677            UWord       phdr_dnent    = ehdr_dimg->e_phnum;
1678            UWord       phdr_dent_szB = ehdr_dimg->e_phentsize;
1679            ElfXX_Shdr* shdr_dimg     = (ElfXX_Shdr*)( ((UChar*)ehdr_dimg)
1680                                                       + ehdr_dimg->e_shoff );
1681            UWord       shdr_dnent       = ehdr_dimg->e_shnum;
1682            UWord       shdr_dent_szB    = ehdr_dimg->e_shentsize;
1683            UChar*      shdr_strtab_dimg = NULL;
1684
1685            Bool need_symtab, need_stabs, need_dwarf2, need_dwarf1;
1686
1687            if (phdr_dnent == 0
1688                || !contained_within(
1689                       dimage, n_dimage,
1690                       (Addr)phdr_dimg, phdr_dnent * phdr_dent_szB)) {
1691               ML_(symerr)(di, True,
1692                           "Missing or invalid ELF Program Header Table"
1693                           " (debuginfo file)");
1694               goto out;
1695            }
1696
1697            if (shdr_dnent == 0
1698                || !contained_within(
1699                       dimage, n_dimage,
1700                       (Addr)shdr_dimg, shdr_dnent * shdr_dent_szB)) {
1701               ML_(symerr)(di, True,
1702                           "Missing or invalid ELF Section Header Table"
1703                           " (debuginfo file)");
1704               goto out;
1705            }
1706
1707            /* Also find the section header's string table, and validate. */
1708            /* checked previously by is_elf_object_file: */
1709            vg_assert( ehdr_dimg->e_shstrndx != SHN_UNDEF );
1710
1711            shdr_strtab_dimg
1712               = (UChar*)( ((UChar*)ehdr_dimg)
1713                           + shdr_dimg[ehdr_dimg->e_shstrndx].sh_offset);
1714            if (!contained_within(
1715                    dimage, n_dimage,
1716                    (Addr)shdr_strtab_dimg,
1717                    1/*bogus, but we don't know the real size*/ )) {
1718               ML_(symerr)(di, True,
1719                           "Invalid ELF Section Header String Table"
1720                           " (debuginfo file)");
1721               goto out;
1722            }
1723
1724            need_symtab = (NULL == symtab_img);
1725            need_stabs  = (NULL == stab_img);
1726            need_dwarf2 = (NULL == debug_info_img);
1727            need_dwarf1 = (NULL == dwarf1d_img);
1728
1729            for (i = 0; i < ehdr_dimg->e_phnum; i++) {
1730               ElfXX_Phdr* phdr
1731                  = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff),
1732                                          i, phdr_ent_szB );
1733               if (phdr->p_type == PT_LOAD) {
1734                  //offset_dimage = di->text_avma - phdr->p_vaddr;
1735                  // FIXME: update di->text_bias at this point?
1736                  // or can we assume the SVMAs in the debuginfo
1737                  // file (hence, the biases) are the same as
1738                  // established from the main file?
1739                  break;
1740               }
1741            }
1742
1743            /* Same deal as previous FIND, except only do it for those
1744               sections for which we didn't find anything useful in
1745               the main file. */
1746
1747            /* Find all interesting sections */
1748            for (i = 0; i < ehdr_dimg->e_shnum; i++) {
1749
1750#              define FIND(condition, sec_name, sec_size, sec_img) \
1751               do { ElfXX_Shdr* shdr \
1752                       = INDEX_BIS( shdr_dimg, i, shdr_dent_szB ); \
1753                  if (condition \
1754                      && 0 == VG_(strcmp)(sec_name, \
1755                                          shdr_strtab_dimg + shdr->sh_name)) { \
1756                     Bool nobits; \
1757                     if (0 != sec_img) \
1758                        VG_(core_panic)("repeated section!\n"); \
1759                     sec_img  = (void*)(dimage + shdr->sh_offset); \
1760                     sec_size = shdr->sh_size; \
1761                     nobits   = shdr->sh_type == SHT_NOBITS; \
1762                     TRACE_SYMTAB( "%18s: dimg %p .. %p\n", \
1763                                   sec_name, \
1764                                   (UChar*)sec_img, \
1765                                   ((UChar*)sec_img) + sec_size - 1); \
1766                     /* SHT_NOBITS sections have zero size in the file. */ \
1767                     if ( shdr->sh_offset \
1768                          + (nobits ? 0 : sec_size) > n_dimage ) { \
1769                        ML_(symerr)(di, True, \
1770                                    "   section beyond image end?!"); \
1771                        goto out; \
1772                     } \
1773                  } \
1774               } while (0);
1775
1776               /* NEEDED?        NAME             SIZE           IMAGE addr */
1777               FIND(need_symtab, ".symtab",       symtab_sz,     symtab_img)
1778               FIND(need_symtab, ".strtab",       strtab_sz,     strtab_img)
1779               FIND(need_stabs,  ".stab",         stab_sz,       stab_img)
1780               FIND(need_stabs,  ".stabstr",      stabstr_sz,    stabstr_img)
1781               FIND(need_dwarf2, ".debug_line",   debug_line_sz, debug_line_img)
1782               FIND(need_dwarf2, ".debug_info",   debug_info_sz, debug_info_img)
1783               FIND(need_dwarf2, ".debug_abbrev", debug_abbv_sz, debug_abbv_img)
1784               FIND(need_dwarf2, ".debug_str",    debug_str_sz,  debug_str_img)
1785               FIND(need_dwarf2, ".debug_ranges", debug_ranges_sz,
1786                                                               debug_ranges_img)
1787               FIND(need_dwarf2, ".debug_loc",    debug_loc_sz,  debug_loc_img)
1788               FIND(need_dwarf1, ".debug",        dwarf1d_sz,    dwarf1d_img)
1789               FIND(need_dwarf1, ".line",         dwarf1l_sz,    dwarf1l_img)
1790
1791#              undef FIND
1792            }
1793         }
1794      }
1795
1796      /* Check some sizes */
1797      vg_assert((dynsym_sz % sizeof(ElfXX_Sym)) == 0);
1798      vg_assert((symtab_sz % sizeof(ElfXX_Sym)) == 0);
1799
1800      /* Read symbols */
1801      {
1802         void (*read_elf_symtab)(struct _DebugInfo*,UChar*,
1803                                 ElfXX_Sym*,SizeT,
1804                                 UChar*,SizeT,
1805                                 UChar*);
1806#        if defined(VGP_ppc64_linux)
1807         read_elf_symtab = read_elf_symtab__ppc64_linux;
1808#        else
1809         read_elf_symtab = read_elf_symtab__normal;
1810#        endif
1811         read_elf_symtab(di, "symbol table",
1812                         symtab_img, symtab_sz,
1813                         strtab_img, strtab_sz,
1814                         opd_img);
1815
1816         read_elf_symtab(di, "dynamic symbol table",
1817                         dynsym_img, dynsym_sz,
1818                         dynstr_img, dynstr_sz,
1819                         opd_img);
1820      }
1821
1822      /* Read .eh_frame (call-frame-info) if any */
1823      if (ehframe_img) {
1824         vg_assert(ehframe_sz == di->ehframe_size);
1825         ML_(read_callframe_info_dwarf3)( di, ehframe_img );
1826      }
1827
1828      /* Read the stabs and/or dwarf2 debug information, if any.  It
1829         appears reading stabs stuff on amd64-linux doesn't work, so
1830         we ignore it. */
1831#     if !defined(VGP_amd64_linux)
1832      if (stab_img && stabstr_img) {
1833         ML_(read_debuginfo_stabs) ( di, di->text_bias, stab_img, stab_sz,
1834                                         stabstr_img, stabstr_sz );
1835      }
1836#     endif
1837      /* jrs 2006-01-01: icc-8.1 has been observed to generate
1838         binaries without debug_str sections.  Don't preclude
1839         debuginfo reading for that reason, but, in
1840         read_unitinfo_dwarf2, do check that debugstr is non-NULL
1841         before using it. */
1842      if (debug_info_img && debug_abbv_img && debug_line_img
1843                                           /* && debug_str_img */) {
1844
1845         /* The old reader: line numbers and unwind info only */
1846         ML_(read_debuginfo_dwarf3) ( di,
1847                                      debug_info_img, debug_info_sz,
1848                                      debug_abbv_img, debug_abbv_sz,
1849                                      debug_line_img, debug_line_sz,
1850                                      debug_str_img,  debug_str_sz );
1851
1852         /* The new reader: read the DIEs in .debug_info to acquire
1853            information on variable types and locations.  But only if
1854            the tool asks for it, or the user requests it on the
1855            command line. */
1856         if (VG_(needs).var_info /* the tool requires it */
1857             || VG_(clo_read_var_info) /* the user asked for it */) {
1858            ML_(new_dwarf3_reader)(
1859               di, debug_info_img,   debug_info_sz,
1860                   debug_abbv_img,   debug_abbv_sz,
1861                   debug_line_img,   debug_line_sz,
1862                   debug_str_img,    debug_str_sz,
1863                   debug_ranges_img, debug_ranges_sz,
1864                   debug_loc_img,    debug_loc_sz
1865            );
1866         }
1867      }
1868      if (dwarf1d_img && dwarf1l_img) {
1869         ML_(read_debuginfo_dwarf1) ( di, dwarf1d_img, dwarf1d_sz,
1870                                          dwarf1l_img, dwarf1l_sz );
1871      }
1872   }
1873   res = True;
1874
1875  out: {
1876   SysRes m_res;
1877
1878   /* Last, but not least, heave the image(s) back overboard. */
1879   if (dimage) {
1880      m_res = VG_(am_munmap_valgrind) ( dimage, n_dimage );
1881      vg_assert(!m_res.isError);
1882   }
1883   m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage );
1884   vg_assert(!m_res.isError);
1885   return res;
1886  }
1887}
1888
1889
1890/*--------------------------------------------------------------------*/
1891/*--- end                                                          ---*/
1892/*--------------------------------------------------------------------*/
1893