1 /*
2  * mpatrol
3  * A library for controlling and tracing dynamic memory allocations.
4  * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19  * MA 02111-1307, USA.
20  */
21 
22 
23 /*
24  * Symbol tables.  The implementation of reading symbols from executable files
25  * may also interface with access libraries which support other file formats.
26  * This module may also have to liaise with the dynamic linker (or equivalent)
27  * in order to obtain symbols from shared objects.  A very useful book on the
28  * various different object file and library formats that exist is Linkers &
29  * Loaders, First Edition by John R. Levine (Morgan Kaufmann Publishers, 2000,
30  * ISBN 1-558-60496-0).
31  */
32 
33 
34 #include "symbol.h"
35 #include "diag.h"
36 #include "utils.h"
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #if FORMAT == FORMAT_AOUT || FORMAT == FORMAT_COFF || \
41     FORMAT == FORMAT_XCOFF || FORMAT == FORMAT_ELF32 || \
42     FORMAT == FORMAT_ELF64 || FORMAT == FORMAT_BFD
43 #include <fcntl.h>
44 #include <unistd.h>
45 #if FORMAT == FORMAT_AOUT
46 #include <a.out.h>
47 #elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF
48 #include <a.out.h>
49 #if SYSTEM == SYSTEM_LYNXOS
50 #include <coff.h>
51 #ifndef ISCOFF
52 #define ISCOFF(m) ((m) == COFFMAGICNUM)
53 #endif /* ISCOFF */
54 #ifndef ISFCN
55 #define ISFCN(t) (((t) & 0x30) == (DT_FCN << 4))
56 #endif /* ISFCN */
57 #ifndef n_name
58 #define n_name _n._n_name
59 #endif /* n_name */
60 #else /* SYSTEM */
61 #if SYSTEM == SYSTEM_AIX
62 #ifdef FREAD
63 #undef FREAD
64 #endif /* FREAD */
65 #ifdef FWRITE
66 #undef FWRITE
67 #endif /* FWRITE */
68 #ifndef ISCOFF
69 #define ISCOFF(m) (((m) == U800TOCMAGIC) || ((m) == U802TOCMAGIC))
70 #endif /* ISCOFF */
71 #endif /* SYSTEM */
72 #include <ldfcn.h>
73 #endif /* SYSTEM */
74 #elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64
75 #include <libelf/libelf.h>
76 #elif FORMAT == FORMAT_BFD
77 #include <bfd.h>
78 #endif /* FORMAT */
79 #endif /* FORMAT */
80 #if DYNLINK == DYNLINK_AIX
81 /* The shared libraries that an AIX executable has loaded can be obtained via
82  * the loadquery() function.
83  */
84 #include <sys/types.h>
85 #include <sys/ldr.h>
86 #elif DYNLINK == DYNLINK_BSD
87 /* The BSD a.out dynamic linker is based on the original SunOS implementation
88  * and is the precursor to the SVR4 ELF dynamic linker.  Most BSD systems now
89  * use ELF so this is for SunOS and the BSD systems that still use a.out.
90  */
91 #include <sys/types.h>
92 #include <link.h>
93 #elif DYNLINK == DYNLINK_HPUX
94 /* The HP/UX dynamic linker support routines are available for use even by
95  * statically linked programs.
96  */
97 #include <dl.h>
98 #elif DYNLINK == DYNLINK_IRIX
99 /* IRIX doesn't have a conventional SVR4 dynamic linker and so does not have the
100  * same interface for accessing information about any required shared objects at
101  * run-time.
102  */
103 #include <obj.h>
104 #include <obj_list.h>
105 #elif DYNLINK == DYNLINK_OSF
106 /* The shared libraries that an OSF executable has loaded can be obtained via
107  * the ldr_inq_module() and ldr_inq_region() functions.
108  */
109 #include <loader.h>
110 #elif DYNLINK == DYNLINK_SVR4
111 /* Despite the fact that Linux is now ELF-based, libelf seems to be missing from
112  * many recent distributions and so we must use the GNU BFD library to read the
113  * symbols from the object files and libraries.  However, we still need the ELF
114  * definitions for reading the internal structures of the dynamic linker.
115  */
116 /*#include <elf.h>*/
117 #elif DYNLINK == DYNLINK_WINDOWS
118 /* We use the imagehlp library on Windows platforms to obtain information about
119  * the symbols loaded from third-party and system DLLs.  We can also use it to
120  * obtain information about any symbols contained in the executable file and
121  * program database if COFF or CodeView debugging information is being used.
122  */
123 #include <windows.h>
124 #include <imagehlp.h>
125 #endif /* DYNLINK */
126 
127 
128 #if MP_IDENT_SUPPORT
129 #ident "$Id: symbol.c,v 1.62 2002/01/08 20:13:59 graeme Exp $"
130 #else /* MP_IDENT_SUPPORT */
131 static MP_CONST MP_VOLATILE char *symbol_id = "$Id: symbol.c,v 1.62 2002/01/08 20:13:59 graeme Exp $";
132 #endif /* MP_IDENT_SUPPORT */
133 
134 
135 #if DYNLINK == DYNLINK_SVR4
136 /* These definitions are not always defined in ELF header files on all
137  * systems so we define them here as they are documented in most
138  * System V ABI documents.
139  */
140 
141 #ifndef DT_NULL
142 #define DT_NULL  0
143 #define DT_DEBUG 21
144 
145 #if ENVIRON == ENVIRON_64
146 typedef struct Elf64_Dyn
147 {
148     Elf64_Xword d_tag;     /* tag indicating type of data stored */
149     union
150     {
151         Elf64_Xword d_val; /* data is a value */
152         Elf64_Addr d_ptr;  /* data is a pointer */
153     }
154     d_un;
155 }
156 Elf64_Dyn;
157 #else /* ENVIRON */
158 typedef struct Elf32_Dyn
159 {
160     Elf32_Sword d_tag;    /* tag indicating type of data stored */
161     union
162     {
163         Elf32_Word d_val; /* data is a value */
164         Elf32_Addr d_ptr; /* data is a pointer */
165     }
166     d_un;
167 }
168 Elf32_Dyn;
169 #endif /* ENVIRON */
170 #endif /* DT_NULL */
171 #endif /* DYNLINK */
172 
173 
174 #if DYNLINK == DYNLINK_IRIX
175 /* This structure represents an N32 ABI shared object as opposed to an O32 ABI
176  * shared object, and is defined on IRIX 6.0 and above platforms as
177  * Elf32_Obj_Info.  In order for us to compile on earlier IRIX platforms we
178  * define this structure here, but under a different name so as to avoid a
179  * naming clash on IRIX 6.0 and later.
180  */
181 
182 typedef struct objectinfo
183 {
184     Elf32_Word magic;  /* N32 ABI shared object */
185     Elf32_Word size;   /* size of this structure */
186     Elf32_Addr next;   /* next shared object */
187     Elf32_Addr prev;   /* previous shared object */
188     Elf32_Addr ehdr;   /* address of object file header */
189     Elf32_Addr ohdr;   /* original address of object file header */
190     Elf32_Addr name;   /* filename of shared object */
191     Elf32_Word length; /* length of filename of shared object */
192 }
193 objectinfo;
194 #elif DYNLINK == DYNLINK_SVR4
195 /* This is a structure that is internal to the dynamic linker on ELF systems,
196  * and so it is not always guaranteed to be the same.  We try to rely on this
197  * definition here for portability's sake as it is not publicly declared in
198  * all ELF header files.
199  */
200 
201 typedef struct dynamiclink
202 {
203     size_t base;              /* virtual address of shared object */
204     char *name;               /* filename of shared object */
205 #if ENVIRON == ENVIRON_64
206     Elf64_Dyn *dyn;           /* dynamic linking information */
207 #else /* ENVIRON */
208     Elf32_Dyn *dyn;           /* dynamic linking information */
209 #endif /* ENVIRON */
210     struct dynamiclink *next; /* pointer to next shared object */
211 }
212 dynamiclink;
213 #elif DYNLINK == DYNLINK_WINDOWS
214 /* This structure is used to pass information to the callback function
215  * called by SymEnumerateSymbols().
216  */
217 
218 typedef struct syminfo
219 {
220     symhead *syms; /* pointer to symbol table */
221     char *file;    /* filename of module */
222 }
223 syminfo;
224 
225 
226 /* This structure is used to pass information to the callback function
227  * called by SymEnumerateModules().
228  */
229 
230 typedef struct modinfo
231 {
232     symhead *syms; /* pointer to symbol table */
233     size_t index;  /* index of module */
234     char libs;     /* only read DLLs */
235 }
236 modinfo;
237 #endif /* DYNLINK */
238 
239 
240 #if FORMAT == FORMAT_BFD
241 /* This structure is used to maintain a list of access library handles for
242  * the purposes of mapping return addresses to line numbers.
243  */
244 
245 typedef struct objectfile
246 {
247     struct objectfile *next;  /* pointer to next object file */
248     bfd *file;                /* access library handle */
249     asymbol **symbols;        /* pointer to symbols */
250     size_t base;              /* virtual address of object file */
251 }
252 objectfile;
253 
254 
255 /* This structure is used when searching for source locations corresponding
256  * to virtual addresses by looking at debugging information embedded in an
257  * object file.
258  */
259 
260 typedef struct sourcepos
261 {
262     bfd_vma addr;       /* virtual address to search for */
263     asymbol **symbols;  /* pointer to symbols */
264     size_t base;        /* virtual address of object file */
265     char *func;         /* function name */
266     char *file;         /* file name */
267     unsigned int line;  /* line number */
268     char found;         /* found flag */
269 }
270 sourcepos;
271 #endif /* FORMAT */
272 
273 
274 #ifdef __cplusplus
275 extern "C"
276 {
277 #endif /* __cplusplus */
278 
279 
280 #if DYNLINK == DYNLINK_BSD
281 /* The declaration of the _DYNAMIC symbol, which allows us direct access to the
282  * dynamic linker's internal data structures.  This is set up in crt0 and will
283  * be NULL in an object that does not need dynamic linking.
284  */
285 #if SYSTEM == SYSTEM_SUNOS
286 extern struct link_dynamic _DYNAMIC;
287 #else /* SYSTEM */
288 extern struct _dynamic _DYNAMIC;
289 #endif /* SYSTEM */
290 #elif DYNLINK == DYNLINK_IRIX
291 /* The __rld_obj_head symbol is always defined in IRIX and points to the first
292  * entry in a list of shared object files that are required by the program.  For
293  * statically linked programs this will either be NULL or will only contain the
294  * entry for the program itself.
295  */
296 extern struct obj_list *__rld_obj_head;
297 #elif DYNLINK == DYNLINK_SVR4
298 /* The declaration of the _DYNAMIC symbol, which allows us direct access to the
299  * dynamic linker's internal data structures.  We make it have weak visibility
300  * so that it is always defined, even in the statically linked case.  It is
301  * declared as a function because some compilers only allow weak function
302  * symbols.  Another alternative would be to declare it as a common symbol, but
303  * that wouldn't work under C++ and many libc shared objects have it defined as
304  * a text symbol.
305  */
306 
307 #pragma weak _DYNAMIC
308 void _DYNAMIC(void);
309 #endif /* DYNLINK */
310 
311 
312 /* Initialise the fields of a symhead so that the symbol table becomes empty.
313  */
314 
315 MP_GLOBAL
316 void
__mp_newsymbols(symhead * y,heaphead * h,void * i)317 __mp_newsymbols(symhead *y, heaphead *h, void *i)
318 {
319     struct { char x; symnode y; } z;
320     long n;
321 
322     y->heap = h;
323     /* Determine the minimum alignment for a symbol node on this system
324      * and force the alignment to be a power of two.  This information
325      * is used when initialising the slot table.
326      */
327     n = (char *) &z.y - &z.x;
328     __mp_newstrtab(&y->strings, h);
329     __mp_newslots(&y->table, sizeof(symnode), __mp_poweroftwo(n));
330     __mp_newtree(&y->itree);
331     __mp_newtree(&y->dtree);
332     y->size = 0;
333     y->hhead = y->htail = NULL;
334     y->inits = i;
335     y->prot = MA_NOACCESS;
336     y->protrecur = 0;
337     y->lineinfo = 0;
338 }
339 
340 
341 /* Close all access library handles.
342  */
343 
344 MP_GLOBAL
345 void
__mp_closesymbols(symhead * y)346 __mp_closesymbols(symhead *y)
347 {
348 #if FORMAT == FORMAT_BFD
349     objectfile *n, *p;
350 #endif /* FORMAT */
351 
352 #if FORMAT == FORMAT_BFD
353     for (n = (objectfile *) y->hhead; n != NULL; n = p)
354     {
355         p = n->next;
356         bfd_close(n->file);
357         free(n->symbols);
358         free(n);
359     }
360 #endif /* FORMAT */
361     y->hhead = y->htail = NULL;
362 }
363 
364 
365 /* Forget all data currently in the symbol table.
366  */
367 
368 MP_GLOBAL
369 void
__mp_deletesymbols(symhead * y)370 __mp_deletesymbols(symhead *y)
371 {
372     /* We don't need to explicitly free any memory as this is dealt with
373      * at a lower level by the heap manager.
374      */
375     y->heap = NULL;
376     __mp_deletestrtab(&y->strings);
377     y->table.free = NULL;
378     y->table.size = 0;
379     __mp_newtree(&y->itree);
380     __mp_newtree(&y->dtree);
381     y->size = 0;
382     y->inits = NULL;
383     y->prot = MA_NOACCESS;
384     y->protrecur = 0;
385 }
386 
387 
388 /* Allocate a new symbol node.
389  */
390 
391 static
392 symnode *
getsymnode(symhead * y)393 getsymnode(symhead *y)
394 {
395     symnode *n;
396     heapnode *p;
397 
398     /* If we have no more symbol node slots left then we must allocate
399      * some more memory for them.  An extra MP_ALLOCFACTOR pages of memory
400      * should suffice.
401      */
402     if ((n = (symnode *) __mp_getslot(&y->table)) == NULL)
403     {
404         if ((p = __mp_heapalloc(y->heap, y->heap->memory.page * MP_ALLOCFACTOR,
405               y->table.entalign, 1)) == NULL)
406             return NULL;
407         __mp_initslots(&y->table, p->block, p->size);
408         n = (symnode *) __mp_getslot(&y->table);
409         __mp_treeinsert(&y->itree, &n->index.node, (unsigned long) p->block);
410         n->index.block = p->block;
411         n->index.size = p->size;
412         y->size += p->size;
413         n = (symnode *) __mp_getslot(&y->table);
414     }
415     return n;
416 }
417 
418 
419 #if FORMAT == FORMAT_AOUT || FORMAT == FORMAT_COFF || \
420     FORMAT == FORMAT_XCOFF || FORMAT == FORMAT_ELF32 || \
421     FORMAT == FORMAT_ELF64 || FORMAT == FORMAT_BFD
422 /* Decide whether to store a symbol by looking at its name.
423  */
424 
425 static
426 int
addsymname(char ** s)427 addsymname(char **s)
428 {
429     /* We don't bother storing a symbol which has no name or whose name
430      * contains a '$', '@' or a '.', although GNU C++ destructors begin
431      * with `_._'.  However, in XCOFF the symbol name is likely to be the
432      * name of a CSECT beginning with a '.' and not the original name of
433      * the function, so we skip the first character.  In addition, the
434      * HP/UX $START$ symbol contains dollar characters but we don't want
435      * to bother allowing any other symbols containing dollars.
436      */
437     if ((*s != NULL) && (**s != '\0') &&
438 #if ((SYSTEM == SYSTEM_AIX || SYSTEM == SYSTEM_LYNXOS) && \
439      (ARCH == ARCH_POWER || ARCH == ARCH_POWERPC)) || FORMAT == FORMAT_XCOFF
440         (*(*s)++ == '.') && (strcmp(*s, "text") != 0) &&
441 #endif /* SYSTEM && ARCH && FORMAT */
442         ((strncmp(*s, "_._", 3) == 0) ||
443 #if SYSTEM == SYSTEM_HPUX
444          (strcmp(*s, "$START$") == 0) ||
445 #endif /* SYSTEM */
446          !strpbrk(*s, "$@.")))
447         return 1;
448     return 0;
449 }
450 #endif /* FORMAT */
451 
452 
453 #if FORMAT == FORMAT_AOUT
454 /* Allocate a new symbol node for a given a.out symbol.
455  */
456 
457 static
458 int
addsymbol(symhead * y,struct nlist * p,char * f,char * s,size_t b)459 addsymbol(symhead *y, struct nlist *p, char *f, char *s, size_t b)
460 {
461     symnode *n;
462     char *r;
463     size_t a;
464 
465     a = b + p->n_value;
466     /* We don't allocate a symbol node for symbols which have a virtual
467      * address of zero.
468      */
469     if (addsymname(&s) && (a > 0))
470     {
471         if ((n = getsymnode(y)) == NULL)
472             return 0;
473         if ((r = __mp_addstring(&y->strings, s)) == NULL)
474         {
475             __mp_freeslot(&y->table, n);
476             return 0;
477         }
478         __mp_treeinsert(&y->dtree, &n->data.node, a);
479         n->data.file = f;
480         n->data.name = r;
481         n->data.addr = (void *) a;
482         /* The a.out file format doesn't record symbol sizes, so we have
483          * to rely on the assumption that a function symbol ends at the
484          * beginning of the next function symbol.  This will be calculated
485          * in __mp_fixsymbols().
486          */
487         n->data.size = 0;
488         n->data.index = 0;
489         n->data.offset = 0;
490         /* The linkage information is required for when we look up a symbol.
491          */
492         n->data.flags = p->n_type;
493 #if MP_INITFUNC_SUPPORT
494         /* Check to see if this function should be called when the mpatrol
495          * library is initialised or terminated.
496          */
497         if ((strncmp(r, "__mp_init_", 10) == 0) && (r[10] != '\0'))
498             __mp_atinit((infohead *) y->inits, (void (*)(void)) a);
499         else if ((strncmp(r, "__mp_fini_", 10) == 0) && (r[10] != '\0'))
500             __mp_atfini((infohead *) y->inits, (void (*)(void)) a);
501 #endif /* MP_INITFUNC_SUPPORT */
502     }
503     return 1;
504 }
505 #elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF
506 /* Allocate a new symbol node for a given COFF or XCOFF symbol.
507  */
508 
509 static
510 int
addsymbol(symhead * y,SYMENT * p,char * f,char * s,size_t b)511 addsymbol(symhead *y, SYMENT *p, char *f, char *s, size_t b)
512 {
513     AUXENT *e;
514     symnode *n;
515     char *r;
516     size_t a;
517 
518     a = b + p->n_value;
519     /* We don't allocate a symbol node for symbols which have a virtual
520      * address of zero and we only remember symbols that are declared
521      * statically or externally visible.
522      */
523     if (addsymname(&s) && (a > 0) &&
524 #if FORMAT == FORMAT_XCOFF
525         (ISFCN(p->n_type) || (p->n_sclass == C_EXT)))
526 #else /* FORMAT */
527         ((p->n_sclass == C_STAT) || (p->n_sclass == C_EXT)))
528 #endif /* FORMAT */
529     {
530         if ((n = getsymnode(y)) == NULL)
531             return 0;
532         if ((r = __mp_addstring(&y->strings, s)) == NULL)
533         {
534             __mp_freeslot(&y->table, n);
535             return 0;
536         }
537         __mp_treeinsert(&y->dtree, &n->data.node, a);
538         n->data.file = f;
539         n->data.name = r;
540         n->data.addr = (void *) a;
541         /* Attempt to figure out the size of the symbol.
542          */
543         if (p->n_numaux > 0)
544         {
545             e = (AUXENT *) ((char *) p + SYMESZ);
546             if (ISFCN(p->n_type))
547                 n->data.size = e->x_sym.x_misc.x_fsize;
548             else
549                 n->data.size = e->x_sym.x_misc.x_lnsz.x_size;
550         }
551         else
552             n->data.size = 0;
553         n->data.index = 0;
554         n->data.offset = 0;
555         /* The linkage information is required for when we look up a symbol.
556          */
557         n->data.flags = p->n_sclass;
558 #if MP_INITFUNC_SUPPORT
559         /* Check to see if this function should be called when the mpatrol
560          * library is initialised or terminated.
561          */
562         if ((strncmp(r, "__mp_init_", 10) == 0) && (r[10] != '\0'))
563             __mp_atinit((infohead *) y->inits, (void (*)(void)) a);
564         else if ((strncmp(r, "__mp_fini_", 10) == 0) && (r[10] != '\0'))
565             __mp_atfini((infohead *) y->inits, (void (*)(void)) a);
566 #endif /* MP_INITFUNC_SUPPORT */
567     }
568     return 1;
569 }
570 #elif FORMAT == FORMAT_ELF32
571 /* Allocate a new symbol node for a given ELF32 symbol.
572  */
573 
574 static
575 int
addsymbol(symhead * y,Elf32_Sym * p,char * f,char * s,size_t b)576 addsymbol(symhead *y, Elf32_Sym *p, char *f, char *s, size_t b)
577 {
578     symnode *n;
579     char *r;
580     size_t a;
581     unsigned char t;
582 
583     a = b + p->st_value;
584     /* We don't allocate a symbol node for symbols which have a virtual
585      * address of zero or are of object type.
586      */
587     if (addsymname(&s) && (a > 0) &&
588         (((t = ELF32_ST_TYPE(p->st_info)) == STT_NOTYPE) || (t == STT_FUNC)))
589     {
590         if ((n = getsymnode(y)) == NULL)
591             return 0;
592         if ((r = __mp_addstring(&y->strings, s)) == NULL)
593         {
594             __mp_freeslot(&y->table, n);
595             return 0;
596         }
597         __mp_treeinsert(&y->dtree, &n->data.node, a);
598         n->data.file = f;
599         n->data.name = r;
600         n->data.addr = (void *) a;
601         n->data.size = p->st_size;
602         n->data.index = 0;
603         n->data.offset = 0;
604         /* The linkage information is required for when we look up a symbol.
605          */
606         n->data.flags = ELF32_ST_BIND(p->st_info);
607 #if MP_INITFUNC_SUPPORT
608         /* Check to see if this function should be called when the mpatrol
609          * library is initialised or terminated.
610          */
611         if ((strncmp(r, "__mp_init_", 10) == 0) && (r[10] != '\0'))
612             __mp_atinit((infohead *) y->inits, (void (*)(void)) a);
613         else if ((strncmp(r, "__mp_fini_", 10) == 0) && (r[10] != '\0'))
614             __mp_atfini((infohead *) y->inits, (void (*)(void)) a);
615 #endif /* MP_INITFUNC_SUPPORT */
616     }
617     return 1;
618 }
619 #elif FORMAT == FORMAT_ELF64
620 /* Allocate a new symbol node for a given ELF64 symbol.
621  */
622 
623 static
624 int
addsymbol(symhead * y,Elf64_Sym * p,char * f,char * s,size_t b)625 addsymbol(symhead *y, Elf64_Sym *p, char *f, char *s, size_t b)
626 {
627     symnode *n;
628     char *r;
629     size_t a;
630     unsigned char t;
631 
632     a = b + p->st_value;
633     /* We don't allocate a symbol node for symbols which have a virtual
634      * address of zero or are of object type.
635      */
636     if (addsymname(&s) && (a > 0) &&
637         (((t = ELF64_ST_TYPE(p->st_info)) == STT_NOTYPE) || (t == STT_FUNC)))
638     {
639         if ((n = getsymnode(y)) == NULL)
640             return 0;
641         if ((r = __mp_addstring(&y->strings, s)) == NULL)
642         {
643             __mp_freeslot(&y->table, n);
644             return 0;
645         }
646         __mp_treeinsert(&y->dtree, &n->data.node, a);
647         n->data.file = f;
648         n->data.name = r;
649         n->data.addr = (void *) a;
650         n->data.size = p->st_size;
651         n->data.index = 0;
652         n->data.offset = 0;
653         /* The linkage information is required for when we look up a symbol.
654          */
655         n->data.flags = ELF64_ST_BIND(p->st_info);
656 #if MP_INITFUNC_SUPPORT
657         /* Check to see if this function should be called when the mpatrol
658          * library is initialised or terminated.
659          */
660         if ((strncmp(r, "__mp_init_", 10) == 0) && (r[10] != '\0'))
661             __mp_atinit((infohead *) y->inits, (void (*)(void)) a);
662         else if ((strncmp(r, "__mp_fini_", 10) == 0) && (r[10] != '\0'))
663             __mp_atfini((infohead *) y->inits, (void (*)(void)) a);
664 #endif /* MP_INITFUNC_SUPPORT */
665     }
666     return 1;
667 }
668 #elif FORMAT == FORMAT_BFD
669 /* Allocate a new symbol node for a given BFD symbol.
670  */
671 
672 static
673 int
addsymbol(symhead * y,asymbol * p,char * f,char * s,size_t b)674 addsymbol(symhead *y, asymbol *p, char *f, char *s, size_t b)
675 {
676     symnode *n;
677     char *r;
678     size_t a;
679 
680     a = b + (size_t) p->value;
681     /* We don't allocate a symbol node for symbols which have a virtual
682      * address of zero and we only remember symbols that are declared
683      * statically, externally or weakly visible.
684      */
685     if (addsymname(&s) && (a > 0) &&
686         (p->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_WEAK)))
687     {
688         if ((n = getsymnode(y)) == NULL)
689             return 0;
690         if ((r = __mp_addstring(&y->strings, s)) == NULL)
691         {
692             __mp_freeslot(&y->table, n);
693             return 0;
694         }
695         __mp_treeinsert(&y->dtree, &n->data.node, a);
696         n->data.file = f;
697         n->data.name = r;
698         n->data.addr = (void *) a;
699         /* The BFD library doesn't seem to support reading symbol sizes,
700          * so we have to rely on the assumption that a function symbol
701          * ends at the beginning of the next function symbol.  This will
702          * be calculated in __mp_fixsymbols().
703          */
704         n->data.size = 0;
705         n->data.index = 0;
706         n->data.offset = 0;
707         /* The linkage information is required for when we look up a symbol.
708          */
709         n->data.flags = p->flags;
710 #if MP_INITFUNC_SUPPORT
711         /* Check to see if this function should be called when the mpatrol
712          * library is initialised or terminated.
713          */
714         if ((strncmp(r, "__mp_init_", 10) == 0) && (r[10] != '\0'))
715             __mp_atinit((infohead *) y->inits, (void (*)(void)) a);
716         else if ((strncmp(r, "__mp_fini_", 10) == 0) && (r[10] != '\0'))
717             __mp_atfini((infohead *) y->inits, (void (*)(void)) a);
718 #endif /* MP_INITFUNC_SUPPORT */
719     }
720     return 1;
721 }
722 #endif /* FORMAT */
723 
724 
725 #if DYNLINK == DYNLINK_WINDOWS
726 /* The callback function called to allocate a new symbol node for each
727  * symbol located in a module by the imagehlp library.
728  */
729 
730 static
731 int __stdcall
addsym(char * s,unsigned long a,unsigned long l,void * p)732 addsym(char *s, unsigned long a, unsigned long l, void *p)
733 {
734     syminfo *i;
735     symhead *y;
736     symnode *n;
737     char *r;
738 
739     i = (syminfo *) p;
740     y = i->syms;
741     /* We don't bother storing a symbol which has no name or which has a
742      * virtual address of zero.  Unfortunately, the imagehlp library does
743      * not provide information about the types of symbols so we will just
744      * have to add any symbols representing objects here as well.
745      */
746     if ((s != NULL) && (*s != '\0') && (a > 0))
747     {
748         if ((n = getsymnode(y)) == NULL)
749             return 0;
750         if ((r = __mp_addstring(&y->strings, s)) == NULL)
751         {
752             __mp_freeslot(&y->table, n);
753             return 0;
754         }
755         __mp_treeinsert(&y->dtree, &n->data.node, a);
756         n->data.file = i->file;
757         n->data.name = r;
758         n->data.addr = (void *) a;
759         n->data.size = l;
760         n->data.index = 0;
761         n->data.offset = 0;
762         /* Unfortunately, the imagehlp library does not provide information
763          * about the visibility of symbols.
764          */
765         n->data.flags = 0;
766     }
767     return 1;
768 }
769 #endif /* DYNLINK */
770 
771 
772 #if FORMAT == FORMAT_AOUT
773 /* Allocate a set of symbol nodes for an a.out executable file.
774  */
775 
776 static
777 int
addsymbols(symhead * y,char * e,char * l,char * f,size_t b,size_t a)778 addsymbols(symhead *y, char *e, char *l, char *f, size_t b, size_t a)
779 {
780     struct exec *o;
781     struct nlist *p;
782     char *c, *m;
783     size_t i, n;
784 
785     /* Check that we have a valid a.out executable file.
786      */
787     if (b < sizeof(struct exec))
788     {
789         c = "not an object file";
790         if (l != NULL)
791             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
792         else
793             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
794         return 1;
795     }
796     o = (struct exec *) e;
797     if (N_BADMAG(*o))
798     {
799         c = "not an executable file";
800         if (l != NULL)
801             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
802         else
803             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
804         return 1;
805     }
806     /* Look for the symbol table.
807      */
808     i = N_SYMOFF(*o);
809     n = o->a_syms;
810     if ((i == 0) || (n == 0) || (b < i + n))
811     {
812         c = "missing symbol table";
813         if (l != NULL)
814             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
815         else
816             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
817         return 1;
818     }
819     p = (struct nlist *) (e + i);
820     b -= i + n;
821     n /= sizeof(struct nlist);
822     /* Look for the string table.
823      */
824     m = e + N_STROFF(*o);
825     if (b < 4)
826         i = 0;
827     else
828         i = *((size_t *) m);
829     if ((i == 0) || (b < i))
830     {
831         c = "missing string table";
832         if (l != NULL)
833             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
834         else
835             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
836         return 1;
837     }
838     if (l != NULL)
839         f = l;
840     /* Cycle through every symbol contained in the executable file.
841      */
842     for (i = 0; i < n; i++, p++)
843         /* We only need to bother looking at text symbols.
844          */
845         if ((((p->n_type & N_TYPE) == N_TEXT) && !(p->n_type & N_STAB)) &&
846             !addsymbol(y, p, f, m + p->n_un.n_strx, a))
847             return 0;
848     return 1;
849 }
850 #elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF
851 /* Allocate a set of symbol nodes for a COFF or XCOFF executable file.
852  */
853 
854 static
855 int
addsymbols(symhead * y,char * e,char * l,char * f,size_t b,size_t a)856 addsymbols(symhead *y, char *e, char *l, char *f, size_t b, size_t a)
857 {
858     char n[SYMNMLEN + 1];
859     FILHDR *o;
860     AOUTHDR *v;
861     SCNHDR *h;
862     SYMENT *p;
863     char *c, *m, *s;
864     size_t i, t;
865 
866     /* Check that we have a valid COFF or XCOFF executable file.
867      */
868     if (b < FILHSZ)
869     {
870         c = "not an object file";
871         if (l != NULL)
872             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
873         else
874             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
875         return 1;
876     }
877     o = (FILHDR *) e;
878     b -= FILHSZ;
879     if (!ISCOFF(o->f_magic) || (o->f_opthdr == 0) || (b < o->f_opthdr))
880     {
881         c = "not an executable file";
882         if (l != NULL)
883             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
884         else
885             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
886         return 1;
887     }
888     /* COFF and XCOFF dynamic linkers don't record the original start
889      * address of the text section so we must adjust the base address here
890      * if necessary.
891      */
892     if ((a != 0) && (o->f_opthdr >= sizeof(AOUTHDR)))
893     {
894         v = (AOUTHDR *) (e + FILHSZ);
895         if (a > v->text_start)
896             a -= (v->text_start & ~0xFFFF);
897     }
898     b -= o->f_opthdr;
899     if ((o->f_nscns == 0) || (b < o->f_nscns * SCNHSZ))
900     {
901         c = "missing section table";
902         if (l != NULL)
903             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
904         else
905             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
906         return 1;
907     }
908     /* Look for the section index of the text section.  This is
909      * usually 1, but we should really make sure.
910      */
911     h = (SCNHDR *) (e + FILHSZ + o->f_opthdr);
912     b += FILHSZ + o->f_opthdr - o->f_symptr;
913     for (i = t = 0; i < o->f_nscns; i++)
914         if ((h[i].s_flags & STYP_TEXT) ||
915             (strncmp(h[i].s_name, ".text", 8) == 0))
916         {
917             t = i + 1;
918             break;
919         }
920     if (t == 0)
921         t = 1;
922     /* Look for the symbol table.
923      */
924     i = o->f_nsyms * SYMESZ;
925     if ((o->f_symptr == 0) || (o->f_nsyms == 0) || (b < i))
926     {
927         c = "missing symbol table";
928         if (l != NULL)
929             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
930         else
931             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
932         return 1;
933     }
934     p = (SYMENT *) (e + o->f_symptr);
935     b -= i;
936     /* Look for the string table.
937      */
938     m = (char *) p + i;
939     if (b < 4)
940         i = 0;
941     else
942         i = *((size_t *) m);
943     if ((i == 0) || (b < i))
944     {
945         c = "missing string table";
946         if (l != NULL)
947             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", l, f, c);
948         else
949             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, c);
950         return 1;
951     }
952     if (l != NULL)
953         f = l;
954     /* Cycle through every symbol contained in the executable file.
955      */
956     for (i = 0; i < o->f_nsyms; i += p->n_numaux + 1,
957          p = (SYMENT *) ((char *) p + (p->n_numaux + 1) * SYMESZ))
958         /* We only need to bother looking at text symbols.
959          */
960         if (p->n_scnum == t)
961         {
962             if (p->n_zeroes)
963             {
964                 /* Symbol name is stored in structure.
965                  */
966                 strncpy(n, p->n_name, SYMNMLEN);
967                 n[SYMNMLEN] = '\0';
968                 s = n;
969             }
970             else
971                 /* Symbol name is stored in string table.
972                  */
973                 s = m + p->n_offset;
974             if (!addsymbol(y, p, f, s, a))
975                 return 0;
976         }
977     return 1;
978 }
979 #elif FORMAT == FORMAT_ELF32
980 /* Allocate a set of symbol nodes for an ELF32 object file.
981  */
982 
983 static
984 int
addsymbols(symhead * y,Elf * e,char * a,char * f,size_t b)985 addsymbols(symhead *y, Elf *e, char *a, char *f, size_t b)
986 {
987     Elf_Scn *s;
988     Elf32_Shdr *h;
989     Elf32_Sym *p;
990     Elf_Data *d;
991     char *m;
992     size_t i, l, n, t;
993 
994     /* Look for the symbol table.
995      */
996     for (s = elf_nextscn(e, NULL), d = NULL; s != NULL; s = elf_nextscn(e, s))
997         if ((h = elf32_getshdr(s)) && (h->sh_type == SHT_SYMTAB) &&
998             (d = elf_getdata(s, NULL)))
999             break;
1000     if (d == NULL)
1001         /* If we couldn't find the symbol table then it is likely that the file
1002          * has been stripped.  However, if the file was dynamically linked then
1003          * we may be able to obtain some symbols from its dynamic symbol table.
1004          */
1005         for (s = elf_nextscn(e, NULL), d = NULL; s != NULL;
1006              s = elf_nextscn(e, s))
1007             if ((h = elf32_getshdr(s)) && (h->sh_type == SHT_DYNSYM) &&
1008                 (d = elf_getdata(s, NULL)))
1009                 break;
1010     if ((d == NULL) || (d->d_buf == NULL) || (d->d_size == 0))
1011     {
1012         m = "missing symbol table";
1013         if (a != NULL)
1014             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1015         else
1016             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1017         return 1;
1018     }
1019     t = h->sh_link;
1020     /* Look for the string table.
1021      */
1022     if (((s = elf_getscn(e, t)) == NULL) || ((h = elf32_getshdr(s)) == NULL) ||
1023         (h->sh_type != SHT_STRTAB))
1024     {
1025         m = "missing string table";
1026         if (a != NULL)
1027             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1028         else
1029             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1030         return 1;
1031     }
1032     if (a != NULL)
1033         f = a;
1034     p = (Elf32_Sym *) d->d_buf + 1;
1035     l = d->d_size / sizeof(Elf32_Sym);
1036     /* Cycle through every symbol contained in the object file.
1037      */
1038     for (i = 1; i < l; i++, p++)
1039         /* We don't need to bother looking at undefined, absolute or common
1040          * symbols, and we only need to store non-data symbols.  However, on
1041          * IRIX the section index for a symbol in a linked object file does
1042          * not always refer to the ELF section it was defined in so we skip
1043          * the last check.
1044          */
1045 #if SYSTEM == SYSTEM_IRIX
1046         if (((n = p->st_shndx) != SHN_UNDEF) && (n != SHN_ABS) &&
1047             (n != SHN_COMMON))
1048 #else /* SYSTEM */
1049         if (((n = p->st_shndx) != SHN_UNDEF) && (n != SHN_ABS) &&
1050             (n != SHN_COMMON) && (s = elf_getscn(e, n)) &&
1051             (h = elf32_getshdr(s)) && (h->sh_flags & SHF_EXECINSTR))
1052 #endif /* SYSTEM */
1053             if (!addsymbol(y, p, f, elf_strptr(e, t, p->st_name), b))
1054                 return 0;
1055     return 1;
1056 }
1057 #elif FORMAT == FORMAT_ELF64
1058 /* Allocate a set of symbol nodes for an ELF64 object file.
1059  */
1060 
1061 static
1062 int
addsymbols(symhead * y,Elf * e,char * a,char * f,size_t b)1063 addsymbols(symhead *y, Elf *e, char *a, char *f, size_t b)
1064 {
1065     Elf_Scn *s;
1066     Elf64_Shdr *h;
1067     Elf64_Sym *p;
1068     Elf_Data *d;
1069     char *m;
1070     size_t i, l, n, t;
1071 
1072     /* Look for the symbol table.
1073      */
1074     for (s = elf_nextscn(e, NULL), d = NULL; s != NULL; s = elf_nextscn(e, s))
1075         if ((h = elf64_getshdr(s)) && (h->sh_type == SHT_SYMTAB) &&
1076             (d = elf_getdata(s, NULL)))
1077             break;
1078     if (d == NULL)
1079         /* If we couldn't find the symbol table then it is likely that the file
1080          * has been stripped.  However, if the file was dynamically linked then
1081          * we may be able to obtain some symbols from its dynamic symbol table.
1082          */
1083         for (s = elf_nextscn(e, NULL), d = NULL; s != NULL;
1084              s = elf_nextscn(e, s))
1085             if ((h = elf64_getshdr(s)) && (h->sh_type == SHT_DYNSYM) &&
1086                 (d = elf_getdata(s, NULL)))
1087                 break;
1088     if ((d == NULL) || (d->d_buf == NULL) || (d->d_size == 0))
1089     {
1090         m = "missing symbol table";
1091         if (a != NULL)
1092             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1093         else
1094             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1095         return 1;
1096     }
1097     t = h->sh_link;
1098     /* Look for the string table.
1099      */
1100     if (((s = elf_getscn(e, t)) == NULL) || ((h = elf64_getshdr(s)) == NULL) ||
1101         (h->sh_type != SHT_STRTAB))
1102     {
1103         m = "missing string table";
1104         if (a != NULL)
1105             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1106         else
1107             __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1108         return 1;
1109     }
1110     if (a != NULL)
1111         f = a;
1112     p = (Elf64_Sym *) d->d_buf + 1;
1113     l = d->d_size / sizeof(Elf64_Sym);
1114     /* Cycle through every symbol contained in the object file.
1115      */
1116     for (i = 1; i < l; i++, p++)
1117         /* We don't need to bother looking at undefined, absolute or common
1118          * symbols, and we only need to store non-data symbols.  However, on
1119          * IRIX the section index for a symbol in a linked object file does
1120          * not always refer to the ELF section it was defined in so we skip
1121          * the last check.
1122          */
1123 #if SYSTEM == SYSTEM_IRIX
1124         if (((n = p->st_shndx) != SHN_UNDEF) && (n != SHN_ABS) &&
1125             (n != SHN_COMMON))
1126 #else /* SYSTEM */
1127         if (((n = p->st_shndx) != SHN_UNDEF) && (n != SHN_ABS) &&
1128             (n != SHN_COMMON) && (s = elf_getscn(e, n)) &&
1129             (h = elf64_getshdr(s)) && (h->sh_flags & SHF_EXECINSTR))
1130 #endif /* SYSTEM */
1131             if (!addsymbol(y, p, f, elf_strptr(e, t, p->st_name), b))
1132                 return 0;
1133     return 1;
1134 }
1135 #elif FORMAT == FORMAT_BFD
1136 /* Allocate a set of symbol nodes for a BFD object file.
1137  */
1138 
1139 static
1140 int
addsymbols(symhead * y,bfd * h,char * a,char * f,size_t b)1141 addsymbols(symhead *y, bfd *h, char *a, char *f, size_t b)
1142 {
1143     asymbol **p;
1144     char *m;
1145     long i, n;
1146     int d, r;
1147 
1148     /* Look for the symbol table.
1149      */
1150     d = 0;
1151     if ((n = bfd_get_symtab_upper_bound(h)) < 0)
1152     {
1153         m = (char *) bfd_errmsg(bfd_get_error());
1154         if (a != NULL)
1155             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1156         else
1157             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1158         return 0;
1159     }
1160     if (n == 0)
1161     {
1162         /* If we couldn't find the symbol table then it is likely that the file
1163          * has been stripped.  However, if the file was dynamically linked then
1164          * we may be able to obtain some symbols from its dynamic symbol table.
1165          */
1166         if ((n = bfd_get_dynamic_symtab_upper_bound(h)) < 0)
1167         {
1168             m = (char *) bfd_errmsg(bfd_get_error());
1169             if (a != NULL)
1170                 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1171             else
1172                 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1173             return 0;
1174         }
1175         if (n == 0)
1176         {
1177             m = "missing symbol table";
1178             if (a != NULL)
1179                 __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1180             else
1181                 __mp_warn(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1182             return 1;
1183         }
1184         d = 1;
1185     }
1186     /* It's actually safe to call malloc() here since the library checks
1187      * for recursive behaviour.
1188      */
1189     if ((p = (asymbol **) malloc(n)) == NULL)
1190     {
1191         m = "no memory for symbols";
1192         if (a != NULL)
1193             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1194         else
1195             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1196         return 0;
1197     }
1198     r = 1;
1199     if (((d == 0) && ((n = bfd_canonicalize_symtab(h, p)) < 0)) ||
1200         ((d == 1) && ((n = bfd_canonicalize_dynamic_symtab(h, p)) < 0)))
1201     {
1202         m = (char *) bfd_errmsg(bfd_get_error());
1203         if (a != NULL)
1204             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", a, f, m);
1205         else
1206             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", f, m);
1207         r = 0;
1208     }
1209     else
1210     {
1211         /* Cycle through every symbol contained in the object file.
1212          */
1213         if (a != NULL)
1214             f = a;
1215         for (i = 0; i < n; i++)
1216             /* We don't need to bother looking at undefined, absolute or common
1217              * symbols, and we only need to store non-data symbols.
1218              */
1219             if (!bfd_is_und_section(p[i]->section) &&
1220                 !bfd_is_abs_section(p[i]->section) &&
1221                 !bfd_is_com_section(p[i]->section) &&
1222                 (p[i]->section->flags & SEC_CODE))
1223                 if (!addsymbol(y, p[i], f, (char *) p[i]->name,
1224                     (size_t) p[i]->section->vma + b))
1225                 {
1226                     r = 0;
1227                     break;
1228                 }
1229     }
1230     /* If we are making use of line number information in the object files then
1231      * we store the symbol table along with the access library handle; otherwise
1232      * we can free the symbol table now.
1233      */
1234     if (y->lineinfo && (r == 1))
1235         ((objectfile *) y->htail)->symbols = p;
1236     else
1237         free(p);
1238     return r;
1239 }
1240 #endif /* FORMAT */
1241 
1242 
1243 #if DYNLINK == DYNLINK_WINDOWS
1244 /* The callback function called to allocate a set of symbol nodes for each
1245  * module located by the imagehlp library.
1246  */
1247 
1248 static
1249 int __stdcall
addsyms(char * f,unsigned long b,void * p)1250 addsyms(char *f, unsigned long b, void *p)
1251 {
1252     modinfo *i;
1253     symhead *y;
1254     char *t;
1255     syminfo s;
1256     IMAGEHLP_MODULE m;
1257     size_t l;
1258     int r;
1259 
1260     r = 1;
1261     i = (modinfo *) p;
1262     y = i->syms;
1263     l = y->dtree.size;
1264     /* The executable file is the first module, so we only want to examine it
1265      * if we are not looking for external symbols.  The DLLs are the subsequent
1266      * modules, so we only want to examine them if we are looking for external
1267      * symbols.
1268      */
1269     if ((!i->libs && !i->index) || (i->libs && i->index))
1270     {
1271         /* Attempt to determine the full path of the current module.
1272          */
1273         m.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
1274         if (SymGetModuleInfo(GetCurrentProcess(), b, &m))
1275             f = m.LoadedImageName;
1276         if ((t = __mp_addstring(&y->strings, f)) == NULL)
1277             r = 0;
1278         else
1279         {
1280             /* Cycle through every symbol contained in the module.
1281              */
1282             s.syms = y;
1283             s.file = t;
1284             r = SymEnumerateSymbols(GetCurrentProcess(), b, addsym, &s);
1285         }
1286         if (i->libs)
1287         {
1288             if (r == 1)
1289             {
1290                 l = y->dtree.size - l;
1291                 __mp_diag("read %lu symbol%s from ", l, (l == 1) ? "" : "s");
1292             }
1293             else
1294                 __mp_diag("problem reading symbols from ");
1295             if (__mp_diagflags & FLG_HTML)
1296                 __mp_diagtag("<TT>");
1297             __mp_diag("%s", f);
1298             if (__mp_diagflags & FLG_HTML)
1299             {
1300                 __mp_diagtag("</TT>\n");
1301                 __mp_diagtag("<BR>");
1302             }
1303             __mp_diag("\n");
1304         }
1305     }
1306     i->index++;
1307     return r;
1308 }
1309 #endif /* DYNLINK */
1310 
1311 
1312 /* Read a file and add all relevant symbols contained within it to the
1313  * symbol table.
1314  */
1315 
1316 MP_GLOBAL
1317 int
__mp_addsymbols(symhead * y,char * s,char * v,size_t b)1318 __mp_addsymbols(symhead *y, char *s, char *v, size_t b)
1319 {
1320 #if FORMAT == FORMAT_AOUT || FORMAT == FORMAT_COFF || \
1321     FORMAT == FORMAT_XCOFF || FORMAT == FORMAT_ELF32 || \
1322     FORMAT == FORMAT_ELF64 || FORMAT == FORMAT_BFD
1323 #if FORMAT == FORMAT_AOUT || (SYSTEM == SYSTEM_LYNXOS && \
1324      (FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF))
1325     char *m;
1326     off_t o;
1327     int f;
1328 #elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF
1329     LDFILE *f;
1330     char *c, *m, *n;
1331     ARCHDR a;
1332     size_t o;
1333 #elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64
1334     Elf *a, *e;
1335     Elf_Arhdr *h;
1336     int f;
1337 #elif FORMAT == FORMAT_BFD
1338     objectfile *p, *q;
1339     bfd *a, *g, *h;
1340 #endif /* FORMAT */
1341     char *t;
1342 #elif FORMAT == FORMAT_PE
1343     modinfo m;
1344 #endif /* FORMAT */
1345     size_t l;
1346     int r;
1347 
1348     r = 1;
1349     l = y->dtree.size;
1350 #if FORMAT == FORMAT_AOUT || (SYSTEM == SYSTEM_LYNXOS && \
1351      (FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF))
1352     /* This is a very simple, yet portable, way to read symbols from a.out
1353      * executable files, or from COFF or XCOFF executable files when libld
1354      * is not available.
1355      */
1356     if ((f = open(s, O_RDONLY)) == -1)
1357     {
1358         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s);
1359         r = 0;
1360     }
1361     else
1362     {
1363         /* Find out the size of the file by doing a seek to the end of the file
1364          * and then a seek back to the start of the file.  Unfortunately, on
1365          * some systems off_t is a structure, so the code below may not work
1366          * for them.
1367          */
1368         if (((o = lseek(f, 0, SEEK_END)) == (off_t) -1) ||
1369             (lseek(f, 0, SEEK_SET) == (off_t) -1))
1370         {
1371             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot seek file\n", s);
1372             r = 0;
1373         }
1374         else if ((m = (char *) malloc((size_t) o)) == NULL)
1375         {
1376             /* It's actually safe to call malloc() here since the library
1377              * checks for recursive behaviour.
1378              */
1379             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: no memory for symbols\n",
1380                        s);
1381             r = 0;
1382         }
1383         else
1384         {
1385             if (read(f, m, (size_t) o) != (size_t) o)
1386             {
1387                 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot read file\n",
1388                            s);
1389                 r = 0;
1390             }
1391             else if ((t = __mp_addstring(&y->strings, s)) == NULL)
1392                 r = 0;
1393             else
1394                 r = addsymbols(y, m, NULL, t, (size_t) o, b);
1395             free(m);
1396         }
1397         close(f);
1398     }
1399 #elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF
1400     /* We use the libld COFF and XCOFF access library in order to simplify
1401      * the reading of symbols.  If this library is not available on a certain
1402      * platform then use the above code for reading a.out files and comment
1403      * this code out.  However, a better solution would be to use the GNU
1404      * BFD library if it is available.
1405      */
1406     t = NULL;
1407     if ((f = ldopen(s, NULL)) == NULL)
1408     {
1409         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s);
1410         r = 0;
1411     }
1412     while (r == 1)
1413     {
1414         if (ldahread(f, &a))
1415         {
1416             n = a.ar_name;
1417             o = a.ar_size;
1418             if (((v != NULL) && (strcmp(n, v) != 0)) ||
1419                 (FSEEK(f, 0, BEGINNING) == -1))
1420             {
1421                 if (ldclose(f))
1422                     break;
1423                 if ((f = ldopen(s, f)) == NULL)
1424                     r = 0;
1425                 continue;
1426             }
1427         }
1428         else
1429             n = NULL;
1430         /* Find out the size of the file by doing a seek to the end of the file
1431          * and then a seek back to the start of the file, but only if this is
1432          * not an archive member.
1433          */
1434         if ((n == NULL) && ((FSEEK(f, 0, END) == -1) ||
1435              ((o = FTELL(f)) == (size_t) -1) || (FSEEK(f, 0, BEGINNING) == -1)))
1436         {
1437             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot seek file\n", s);
1438             r = 0;
1439         }
1440         else if ((m = (char *) malloc(o)) == NULL)
1441         {
1442             /* It's actually safe to call malloc() here since the library
1443              * checks for recursive behaviour.
1444              */
1445             c = "no memory for symbols";
1446             if (n != NULL)
1447                 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s, n, c);
1448             else
1449                 __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, c);
1450             r = 0;
1451         }
1452         else
1453         {
1454             if (FREAD(m, sizeof(char), o, f) != o)
1455             {
1456                 c = "cannot read file";
1457                 if (n != NULL)
1458                     __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s, n,
1459                                c);
1460                 else
1461                     __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, c);
1462                 r = 0;
1463             }
1464             else if ((t == NULL) &&
1465                      ((t = __mp_addstring(&y->strings, s)) == NULL))
1466                 r = 0;
1467             else if (n != NULL)
1468                 r = addsymbols(y, m, t, n, o, b);
1469             else
1470                 r = addsymbols(y, m, NULL, t, o, b);
1471             free(m);
1472         }
1473         if (ldclose(f))
1474             break;
1475         if ((r == 1) && ((f = ldopen(s, f)) == NULL))
1476             r = 0;
1477     }
1478 #elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64
1479     /* We use the libelf ELF access library in order to simplify the reading
1480      * of symbols.  At the moment, this solution is better than using the
1481      * GNU BFD library as it currently has no support for symbol sizes or
1482      * liaising with the dynamic linker.
1483      */
1484     if (elf_version(EV_CURRENT) == EV_NONE)
1485     {
1486         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: wrong version of libelf\n", s);
1487         r = 0;
1488     }
1489     else if ((f = open(s, O_RDONLY)) == -1)
1490     {
1491         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s);
1492         r = 0;
1493     }
1494     else
1495     {
1496         if ((e = elf_begin(f, ELF_C_READ, NULL)) == NULL)
1497         {
1498             __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, elf_errmsg(-1));
1499             r = 0;
1500         }
1501         else if ((t = __mp_addstring(&y->strings, s)) == NULL)
1502             r = 0;
1503         else
1504         {
1505             if (elf_kind(e) == ELF_K_AR)
1506                 /* Normally we wouldn't ever need to read symbols from an
1507                  * archive library, but this is just provided for
1508                  * completeness.
1509                  */
1510                 while ((r == 1) && (a = elf_begin(f, ELF_C_READ, e)))
1511                 {
1512                     if ((h = elf_getarhdr(a)) == NULL)
1513                     {
1514                         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s,
1515                                    elf_errmsg(-1));
1516                         r = 0;
1517                     }
1518                     else if ((*h->ar_name != '/') && ((v == NULL) ||
1519                               (strcmp(h->ar_name, v) == 0)))
1520                         r = addsymbols(y, a, t, h->ar_name, b);
1521                     if (r == 1)
1522                         elf_next(a);
1523                     elf_end(a);
1524                 }
1525             else
1526                 r = addsymbols(y, e, NULL, t, b);
1527             elf_end(e);
1528         }
1529         close(f);
1530     }
1531 #elif FORMAT == FORMAT_BFD
1532     /* Using the GNU BFD library allows us to read weird and wonderful file
1533      * formats that would otherwise be hard to support.  This is probably a
1534      * better choice to use than the in-built a.out, COFF and XCOFF
1535      * implementations but currently has no support for symbol sizes, so the
1536      * ELF access library is still worth using for ELF file formats, but the
1537      * BFD library comes with support for debugging information.  So take
1538      * your pick!
1539      */
1540     t = NULL;
1541     bfd_init();
1542     if ((h = bfd_openr(s, NULL)) == NULL)
1543     {
1544         __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s,
1545                    bfd_errmsg(bfd_get_error()));
1546         r = 0;
1547     }
1548     else
1549     {
1550         /* Normally we wouldn't ever need to read symbols from an archive
1551          * library, but this is just provided for completeness, and for AIX
1552          * where shared libraries can be embedded within archive libraries.
1553          */
1554         if (bfd_check_format(h, bfd_archive))
1555         {
1556             a = h;
1557             h = bfd_openr_next_archived_file(a, NULL);
1558         }
1559         else
1560             a = NULL;
1561         while (h != NULL)
1562         {
1563             p = NULL;
1564             if ((a != NULL) && (v != NULL) && (strcmp(h->filename, v) != 0))
1565             {
1566                 g = h;
1567                 h = bfd_openr_next_archived_file(a, g);
1568                 bfd_close(g);
1569                 continue;
1570             }
1571             if (!bfd_check_format(h, bfd_object))
1572             {
1573                 if (a != NULL)
1574                     __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s,
1575                                h->filename, bfd_errmsg(bfd_get_error()));
1576                 else
1577                     __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s,
1578                                bfd_errmsg(bfd_get_error()));
1579                 r = 0;
1580             }
1581             else if (y->lineinfo &&
1582                      ((p = (objectfile *) malloc(sizeof(objectfile))) == NULL))
1583                 r = 0;
1584             else if ((t == NULL) &&
1585                      ((t = __mp_addstring(&y->strings, s)) == NULL))
1586                 r = 0;
1587             else
1588             {
1589                 if (y->lineinfo)
1590                 {
1591                     if (y->hhead == NULL)
1592                         y->hhead = p;
1593                     else
1594                     {
1595                         q = (objectfile *) y->htail;
1596                         q->next = p;
1597                     }
1598                     y->htail = p;
1599                     p->next = NULL;
1600                     p->file = h;
1601                     p->symbols = NULL;
1602                     p->base = b;
1603                 }
1604                 if (a != NULL)
1605                     r = addsymbols(y, h, t, (char *) h->filename, b);
1606                 else
1607                     r = addsymbols(y, h, NULL, t, b);
1608                 if (y->lineinfo && (r == 0))
1609                     if (y->hhead == p)
1610                         y->hhead = y->htail = NULL;
1611                     else
1612                     {
1613                         y->htail = q;
1614                         q->next = NULL;
1615                     }
1616             }
1617             g = h;
1618             if ((a != NULL) && (r == 1))
1619                 h = bfd_openr_next_archived_file(a, g);
1620             else
1621                 h = NULL;
1622             if (!y->lineinfo || (r == 0))
1623             {
1624                 if (p != NULL)
1625                     free(p);
1626                 bfd_close(g);
1627             }
1628         }
1629         if (a != NULL)
1630             bfd_close(a);
1631     }
1632 #elif FORMAT == FORMAT_PE
1633     /* We only want to obtain the symbols from the executable file using the
1634      * imagehlp library if we are not using another object file access library,
1635      * such as GNU BFD.
1636      */
1637     m.syms = y;
1638     m.index = 0;
1639     m.libs = 0;
1640     r = SymEnumerateModules(GetCurrentProcess(), addsyms, &m);
1641 #endif /* FORMAT */
1642     if (r == 1)
1643     {
1644         l = y->dtree.size - l;
1645         __mp_diag("read %lu symbol%s from ", l, (l == 1) ? "" : "s");
1646     }
1647     else
1648         __mp_diag("problem reading symbols from ");
1649     if (__mp_diagflags & FLG_HTML)
1650         __mp_diagtag("<TT>");
1651     __mp_diag("%s", s);
1652     if (__mp_diagflags & FLG_HTML)
1653         __mp_diagtag("</TT>");
1654     if (v != NULL)
1655         if (__mp_diagflags & FLG_HTML)
1656         {
1657             __mp_diag(" [");
1658             __mp_diagtag("<TT>");
1659             __mp_diag("%s", v);
1660             __mp_diagtag("</TT>");
1661             __mp_diag("]");
1662         }
1663         else
1664             __mp_diag(" [%s]", v);
1665     __mp_diag("\n");
1666     if (__mp_diagflags & FLG_HTML)
1667         __mp_diagtag("<BR>\n");
1668     return r;
1669 }
1670 
1671 
1672 /* Add any external or additional symbols to the symbol table.
1673  */
1674 
1675 MP_GLOBAL
1676 int
__mp_addextsymbols(symhead * y,meminfo * e)1677 __mp_addextsymbols(symhead *y, meminfo *e)
1678 {
1679 #if DYNLINK == DYNLINK_AIX
1680     static char b[4096];
1681     struct ld_info *l;
1682     char *s;
1683 #elif DYNLINK == DYNLINK_BSD
1684 #if SYSTEM == SYSTEM_SUNOS
1685     struct link_dynamic *d;
1686     struct link_map *l;
1687 #else /* SYSTEM */
1688     struct _dynamic *d;
1689     struct so_map *l;
1690 #endif /* SYSTEM */
1691 #elif DYNLINK == DYNLINK_HPUX
1692     struct shl_descriptor d;
1693     size_t i;
1694     unsigned int o;
1695 #elif DYNLINK == DYNLINK_IRIX
1696     struct obj_list *l;
1697     struct obj *o;
1698     objectinfo *i;
1699     char *s;
1700     size_t b;
1701 #elif DYNLINK == DYNLINK_OSF
1702     ldr_region_info_t r;
1703     ldr_module_info_t i;
1704     ldr_module_t m;
1705     ldr_process_t p;
1706     size_t c, l, n;
1707     size_t b;
1708 #elif DYNLINK == DYNLINK_SVR4
1709 #if ENVIRON == ENVIRON_64
1710     Elf64_Dyn *d;
1711 #else /* ENVIRON */
1712     Elf32_Dyn *d;
1713 #endif /* ENVIRON */
1714     dynamiclink *l;
1715 #elif DYNLINK == DYNLINK_WINDOWS
1716     modinfo m;
1717 #endif /* DYNLINK */
1718 
1719     /* This function liaises with the dynamic linker when a program is
1720      * dynamically linked in order to read symbols from any required shared
1721      * objects.
1722      */
1723 #if DYNLINK == DYNLINK_AIX
1724     if (loadquery(L_GETINFO, b, sizeof(b)) != -1)
1725     {
1726         /* We skip past the first item on the list since it represents the
1727          * executable file, but we may wish to record the name of the file
1728          * if we haven't already determined it.
1729          */
1730         l = (struct ld_info *) b;
1731         s = l->ldinfo_filename;
1732         if ((e->prog == NULL) && (*s != '\0'))
1733             e->prog = __mp_addstring(&y->strings, s);
1734         while (l = l->ldinfo_next ? (struct ld_info *)
1735                                     ((char *) l + l->ldinfo_next) : NULL)
1736             if (*l->ldinfo_filename != '\0')
1737             {
1738                 /* If the filename represents an archive file then the member
1739                  * name within the archive will follow immediately after it.
1740                  */
1741                 s = l->ldinfo_filename + strlen(l->ldinfo_filename) + 1;
1742                 if (*s == '\0')
1743                     s = NULL;
1744                 if (!__mp_addsymbols(y, l->ldinfo_filename, s,
1745                                      (unsigned long) l->ldinfo_textorg))
1746                     return 0;
1747             }
1748     }
1749 #elif DYNLINK == DYNLINK_BSD
1750     /* Check to see if the dynamic linker has set up the _DYNAMIC symbol
1751      * and also check that it is a valid structure.
1752      */
1753     if ((d = &_DYNAMIC) &&
1754 #if SYSTEM == SYSTEM_SUNOS
1755         (d->ld_version > 1) && (d->ld_version <= 3) && (d->ld_un.ld_1 != NULL))
1756 #else /* SYSTEM */
1757         (d->d_version == LD_VERSION_BSD) && (d->d_un.d_sdt != NULL))
1758 #endif /* SYSTEM */
1759     {
1760 #if SYSTEM == SYSTEM_SUNOS
1761         l = d->ld_un.ld_1->ld_loaded;
1762 #else /* SYSTEM */
1763         l = d->d_un.d_sdt->sdt_loaded;
1764 #endif /* SYSTEM */
1765         while (l != NULL)
1766         {
1767 #if SYSTEM == SYSTEM_SUNOS
1768             if ((l->lm_name != NULL) && (*l->lm_name != '\0') &&
1769                 !__mp_addsymbols(y, l->lm_name, NULL, l->lm_addr))
1770 #else /* SYSTEM */
1771             if ((l->som_path != NULL) && (*l->som_path != '\0') &&
1772                 !__mp_addsymbols(y, l->som_path, NULL, l->som_addr))
1773 #endif /* SYSTEM */
1774                 return 0;
1775 #if SYSTEM == SYSTEM_SUNOS
1776             l = l->lm_next;
1777 #else /* SYSTEM */
1778             l = l->som_next;
1779 #endif /* SYSTEM */
1780         }
1781     }
1782 #elif DYNLINK == DYNLINK_HPUX
1783     /* An index of -1 indicates the dynamic linker and an index of 0 indicates
1784      * the main executable program.  We are interested in all other object files
1785      * that the program depends on, but we may wish to record the name of the
1786      * executable file if we haven't already determined it.
1787      */
1788     if ((e->prog == NULL) && (shl_get_r(0, &d) != -1) &&
1789         (d.filename[0] != '\0'))
1790         e->prog = __mp_addstring(&y->strings, d.filename);
1791     for (i = 1; shl_get_r(i, &d) != -1; i++)
1792     {
1793         /* Determine the offset of the first text symbol in the library.  This
1794          * is normally 0x1000 but may be something else on later systems.  The
1795          * handle structure is not documented anywhere, but the fourth word
1796          * appears to contain the information we need, based on trial and error.
1797          */
1798         if (d.handle != NULL)
1799             o = ((unsigned int *) d.handle)[3];
1800         else
1801             o = 0;
1802         if ((d.filename[0] != '\0') &&
1803             !__mp_addsymbols(y, d.filename, NULL, d.tstart - o))
1804             return 0;
1805     }
1806 #elif DYNLINK == DYNLINK_IRIX
1807     if (l = __rld_obj_head)
1808         /* Determine if the shared object list we are looking at contains O32
1809          * ABI object files or N32 ABI object files.
1810          */
1811         if (l->data == 0xFFFFFFFF)
1812         {
1813             /* We skip past the first item on the list since it represents the
1814              * executable file, but we may wish to record the name of the file
1815              * if we haven't already determined it.
1816              */
1817             i = (objectinfo *) l;
1818             s = (char *) i->name;
1819             if ((e->prog == NULL) && (s != NULL) && (*s != '\0'))
1820                 e->prog = __mp_addstring(&y->strings, s);
1821             while (i = (objectinfo *) i->next)
1822             {
1823                 s = (char *) i->name;
1824                 b = (long) i->ehdr - (long) i->ohdr;
1825                 if ((s != NULL) && (*s != '\0') &&
1826                     !__mp_addsymbols(y, s, NULL, b))
1827                     return 0;
1828             }
1829         }
1830         else
1831         {
1832             /* We skip past the first item on the list since it represents the
1833              * executable file, but we may wish to record the name of the file
1834              * if we haven't already determined it.
1835              */
1836             o = (struct obj *) l->data;
1837             s = o->o_path;
1838             if ((e->prog == NULL) && (s != NULL) && (*s != '\0'))
1839                 e->prog = __mp_addstring(&y->strings, s);
1840             while (l = l->next)
1841             {
1842                 o = (struct obj *) l->data;
1843                 s = o->o_path;
1844                 b = (long) o->o_text_start - (long) o->o_base_address;
1845                 if ((s != NULL) && (*s != '\0') &&
1846                     !__mp_addsymbols(y, s, NULL, b))
1847                     return 0;
1848             }
1849         }
1850 #elif DYNLINK == DYNLINK_OSF
1851     c = 0;
1852     p = ldr_my_process();
1853     m = LDR_NULL_MODULE;
1854     while ((ldr_next_module(p, &m) == 0) && (m != LDR_NULL_MODULE))
1855         if (ldr_inq_module(p, m, &i, sizeof(i), &l) == 0)
1856         {
1857             /* We skip past the first item on the list since it represents the
1858              * executable file, but we may wish to record the name of the file
1859              * if we haven't already determined it.
1860              */
1861             if (c++ == 0)
1862             {
1863                 if ((e->prog == NULL) && (i.lmi_name[0] != '\0'))
1864                     e->prog = __mp_addstring(&y->strings, i.lmi_name);
1865                 continue;
1866             }
1867             for (n = 0; n < (size_t) i.lmi_nregion; n++)
1868                 if ((ldr_inq_region(p, m, (ldr_region_t) n, &r, sizeof(r),
1869                       &l) == 0) && (strcmp(r.lri_name, ".text") == 0))
1870                 {
1871                     b = (long) r.lri_mapaddr - (long) r.lri_vaddr;
1872                     if ((i.lmi_name[0] != '\0') && !__mp_addsymbols(y,
1873                          i.lmi_name, NULL, b))
1874                         return 0;
1875                     break;
1876                 }
1877         }
1878 #elif DYNLINK == DYNLINK_SVR4
1879 #if ENVIRON == ENVIRON_64
1880     if ((&_DYNAMIC != NULL) && (d = (Elf64_Dyn *) _DYNAMIC))
1881 #else /* ENVIRON */
1882     if ((&_DYNAMIC != NULL) && (d = (Elf32_Dyn *) _DYNAMIC))
1883 #endif /* ENVIRON */
1884     {
1885         /* Search for the DT_DEBUG tag in the _DYNAMIC symbol.
1886          */
1887         for (l = NULL; d->d_tag != DT_NULL; d++)
1888             if (d->d_tag == DT_DEBUG)
1889             {
1890                 if (!d->d_un.d_ptr)
1891                     l = NULL;
1892                 else
1893                     l = (dynamiclink *) *((unsigned long *) d->d_un.d_ptr + 1);
1894                 break;
1895             }
1896         /* We skip past the first item on the list since it represents the
1897          * executable file, but we may wish to record the name of the file
1898          * if we haven't already determined it.
1899          */
1900         if (l != NULL)
1901         {
1902             if ((e->prog == NULL) && (l->name != NULL) && (*l->name != '\0'))
1903                 e->prog = __mp_addstring(&y->strings, l->name);
1904             l = l->next;
1905         }
1906         while (l != NULL)
1907         {
1908             if ((l->name != NULL) && (*l->name != '\0') &&
1909                 !__mp_addsymbols(y, l->name, NULL, l->base))
1910                 return 0;
1911             l = l->next;
1912         }
1913     }
1914 #elif DYNLINK == DYNLINK_WINDOWS
1915     /* We always want to initialise the imagehlp library here since we will
1916      * be using it to obtain the symbols from any loaded DLLs here and
1917      * possibly also from the executable file if we are not using any other
1918      * object file access library.  In any case we can set the demangling
1919      * option in the imagehlp library and also instruct it to load line number
1920      * information if the USEDEBUG option is given.
1921      */
1922     if (y->lineinfo)
1923         SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
1924     else
1925         SymSetOptions(SYMOPT_UNDNAME);
1926     SymInitialize(GetCurrentProcess(), NULL, 1);
1927     /* The imagehlp library allows us to locate the symbols contained in
1928      * all of the loaded DLLs without having to actually read the files
1929      * themselves.
1930      */
1931     m.syms = y;
1932     m.index = 0;
1933     m.libs = 1;
1934     if (!SymEnumerateModules(GetCurrentProcess(), addsyms, &m))
1935         return 0;
1936 #endif /* DYNLINK */
1937     return 1;
1938 }
1939 
1940 
1941 /* Attempt to tidy up the symbol table by correcting any potential errors or
1942  * conflicts from the symbols that have been read.
1943  */
1944 
1945 MP_GLOBAL
1946 void
__mp_fixsymbols(symhead * y)1947 __mp_fixsymbols(symhead *y)
1948 {
1949     symnode *n, *p;
1950     void *l, *m;
1951 #if TARGET == TARGET_AMIGA
1952     unsigned long o;
1953 #endif /* TARGET */
1954 
1955 #if TARGET == TARGET_AMIGA
1956     o = 0;
1957 #endif /* TARGET */
1958     l = NULL;
1959     for (n = (symnode *) __mp_minimum(y->dtree.root); n != NULL; n = p)
1960     {
1961         /* If a symbol has a zero size and it is closely followed by another
1962          * symbol then the likelihood is that the symbol really has a non-zero
1963          * size so we fix that here.  This commonly occurs with system startup
1964          * files.
1965          */
1966         p = (symnode *) __mp_successor(&n->data.node);
1967         if ((n->data.size == 0) && (n->data.addr >= l))
1968             if ((p == NULL) || (n->data.file != p->data.file))
1969                 n->data.size = 256;
1970             else
1971                 n->data.size = (char *) p->data.addr - (char *) n->data.addr;
1972         if ((m = (char *) n->data.addr + n->data.size) > l)
1973             l = m;
1974 #if TARGET == TARGET_AMIGA
1975         /* On AmigaOS, sections are scatter-loaded into memory and will occupy
1976          * different addresses each time a program is loaded.  One easy way to
1977          * determine the run-time address of each function is to find the
1978          * offset for one function and add it to all functions, but this means
1979          * that this function must be compiled with symbolic information and
1980          * assumes that all text symbols are in the one hunk.
1981          */
1982         if ((o == 0) && (strcmp(n->data.name, "___mp_fixsymbols") == 0))
1983             o = (char *) __mp_fixsymbols - (char *) n->data.addr;
1984 #endif /* TARGET */
1985     }
1986 #if TARGET == TARGET_AMIGA
1987     if (o != 0)
1988     {
1989 #if FORMAT == FORMAT_BFD
1990         if (y->hhead != NULL)
1991             ((objectfile *) y->hhead)->base = o;
1992 #endif /* FORMAT */
1993         for (n = (symnode *) __mp_minimum(y->dtree.root); n != NULL;
1994              n = (symnode *) __mp_successor(&n->index.node))
1995         {
1996             n->data.node.key += o;
1997             n->data.addr = (char *) n->data.addr + o;
1998         }
1999     }
2000 #endif /* TARGET */
2001 }
2002 
2003 
2004 /* Protect the memory blocks used by the symbol table with the supplied access
2005  * permission.
2006  */
2007 
2008 MP_GLOBAL
2009 int
__mp_protectsymbols(symhead * y,memaccess a)2010 __mp_protectsymbols(symhead *y, memaccess a)
2011 {
2012     symnode *n;
2013 
2014     /* The library already knows what its protection status is so we don't
2015      * need to do anything if the request has already been done.
2016      */
2017     if (y->prot == a)
2018     {
2019         y->protrecur++;
2020         return 1;
2021     }
2022     else if (y->protrecur > 0)
2023     {
2024         y->protrecur--;
2025         return 1;
2026     }
2027     y->prot = a;
2028     for (n = (symnode *) __mp_minimum(y->itree.root); n != NULL;
2029          n = (symnode *) __mp_successor(&n->index.node))
2030         if (!__mp_memprotect(&y->heap->memory, n->index.block, n->index.size,
2031              a))
2032             return 0;
2033     return 1;
2034 }
2035 
2036 
2037 /* Attempt to find the symbol located at a particular address.
2038  */
2039 
2040 MP_GLOBAL
2041 symnode *
__mp_findsymbol(symhead * y,void * p)2042 __mp_findsymbol(symhead *y, void *p)
2043 {
2044     symnode *m, *n, *r;
2045 
2046     /* This function does not deal completely correctly with nested symbols
2047      * but that occurrence does not happen frequently so the current
2048      * implementation should suffice.
2049      */
2050     r = NULL;
2051     if (n = (symnode *) __mp_searchlower(y->dtree.root, (unsigned long) p))
2052     {
2053         while ((m = (symnode *) __mp_predecessor(&n->data.node)) &&
2054                (m->data.addr == n->data.addr))
2055             n = m;
2056         for (m = n; (n != NULL) && (n->data.addr == m->data.addr);
2057              n = (symnode *) __mp_successor(&n->data.node))
2058             if ((char *) n->data.addr + n->data.size > (char *) p)
2059             {
2060 #if FORMAT == FORMAT_AOUT
2061                 /* We give precedence to global symbols, then local symbols.
2062                  */
2063                 if ((r == NULL) || (!(r->data.flags & N_EXT) &&
2064                      (n->data.flags & N_EXT)))
2065                     r = n;
2066 #elif FORMAT == FORMAT_COFF
2067                 /* We give precedence to global symbols, then local symbols.
2068                  */
2069                 if ((r == NULL) || ((r->data.flags == C_STAT) &&
2070                      (n->data.flags == C_EXT)))
2071                     r = n;
2072 #elif FORMAT == FORMAT_XCOFF
2073                 /* We give precedence to global symbols, then hidden external
2074                  * symbols, then local symbols.
2075                  */
2076                 if ((r == NULL) || ((r->data.flags & C_STAT) &&
2077                      ((n->data.flags & C_HIDEXT) || (n->data.flags & C_EXT))) ||
2078                     ((r->data.flags & C_HIDEXT) && (n->data.flags & C_EXT)))
2079                     r = n;
2080 #elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64
2081                 /* We give precedence to global symbols, then weak symbols,
2082                  * then local symbols.
2083                  */
2084                 if ((r == NULL) || ((r->data.flags == STB_LOCAL) &&
2085                      ((n->data.flags == STB_WEAK) ||
2086                       (n->data.flags == STB_GLOBAL))) ||
2087                     ((r->data.flags == STB_WEAK) &&
2088                      (n->data.flags == STB_GLOBAL)))
2089                     r = n;
2090 #elif FORMAT == FORMAT_BFD
2091                 /* We give precedence to global symbols, then weak symbols,
2092                  * then local symbols.
2093                  */
2094                 if ((r == NULL) || ((r->data.flags & BSF_LOCAL) &&
2095                      ((n->data.flags & BSF_WEAK) ||
2096                       (n->data.flags & BSF_GLOBAL))) ||
2097                     ((r->data.flags & BSF_WEAK) &&
2098                      (n->data.flags & BSF_GLOBAL)))
2099                     r = n;
2100 #else /* FORMAT */
2101                 r = n;
2102                 break;
2103 #endif /* FORMAT */
2104             }
2105     }
2106     return r;
2107 }
2108 
2109 
2110 #if FORMAT == FORMAT_BFD
2111 /* Search a BFD section for a specific virtual memory address and attempt
2112  * to match it up with source position information.
2113  */
2114 
2115 static
2116 void
findsource(bfd * h,asection * p,void * d)2117 findsource(bfd *h, asection *p, void *d)
2118 {
2119     sourcepos *s;
2120     bfd_vma v;
2121     size_t l;
2122 
2123     s = (sourcepos *) d;
2124     if (!s->found && !bfd_is_und_section(p) &&
2125         !bfd_is_abs_section(p) && !bfd_is_com_section(p) &&
2126         (p->flags & SEC_ALLOC) && (p->flags & SEC_CODE))
2127     {
2128         v = bfd_section_vma(h, p) + s->base;
2129         l = bfd_section_size(h, p);
2130         if ((s->addr >= v) && (s->addr < v + l))
2131         {
2132             s->file = s->func = NULL;
2133             s->line = 0;
2134             s->found = bfd_find_nearest_line(h, p, s->symbols, s->addr - v,
2135                                              (const char **) &s->file,
2136                                              (const char **) &s->func,
2137                                              &s->line);
2138         }
2139     }
2140 }
2141 #endif /* FORMAT */
2142 
2143 
2144 /* Attempt to find the source correspondence for a machine instruction located
2145  * at a particular address.
2146  */
2147 
2148 MP_GLOBAL
2149 int
__mp_findsource(symhead * y,void * p,char ** s,char ** t,unsigned long * u)2150 __mp_findsource(symhead *y, void *p, char **s, char **t, unsigned long *u)
2151 {
2152 #if FORMAT == FORMAT_BFD
2153     objectfile *n;
2154     sourcepos m;
2155 #endif /* FORMAT */
2156 #if DYNLINK == DYNLINK_WINDOWS
2157     static char b[1024];
2158     IMAGEHLP_SYMBOL *i;
2159     IMAGEHLP_LINE l;
2160     unsigned long d;
2161 #endif /* DYNLINK */
2162 
2163 #if FORMAT == FORMAT_BFD
2164     m.addr = (bfd_vma) p;
2165     m.found = 0;
2166     for (n = (objectfile *) y->hhead; n != NULL; n = n->next)
2167     {
2168         m.symbols = n->symbols;
2169         m.base = n->base;
2170         bfd_map_over_sections(n->file, findsource, &m);
2171         if (m.found)
2172         {
2173             *s = m.func;
2174             *t = m.file;
2175             *u = m.line;
2176             return 1;
2177         }
2178     }
2179 #endif /* FORMAT */
2180     *s = *t = NULL;
2181     *u = 0;
2182 #if DYNLINK == DYNLINK_WINDOWS
2183     if (y->lineinfo)
2184     {
2185         i = (IMAGEHLP_SYMBOL *) b;
2186         i->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
2187         i->MaxNameLength = sizeof(b) - sizeof(IMAGEHLP_SYMBOL);
2188         if (SymGetSymFromAddr(GetCurrentProcess(), (unsigned long) p, &d, i))
2189             *s = i->Name;
2190         l.SizeOfStruct = sizeof(IMAGEHLP_LINE);
2191         if (SymGetLineFromAddr(GetCurrentProcess(), (unsigned long) p, &d, &l))
2192         {
2193             *t = l.FileName;
2194             *u = l.LineNumber;
2195         }
2196         if ((*s != NULL) || (*t != NULL))
2197             return 1;
2198     }
2199 #endif /* DYNLINK */
2200     return 0;
2201 }
2202 
2203 
2204 #ifdef __cplusplus
2205 }
2206 #endif /* __cplusplus */
2207