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