📄 symbol.c
字号:
/* * mpatrol * A library for controlling and tracing dynamic memory allocations. * Copyright (C) 1997-2002 Graeme S. Roy <graeme.roy@analog.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307, USA. *//* * Symbol tables. The implementation of reading symbols from executable files * may also interface with access libraries which support other file formats. * This module may also have to liaise with the dynamic linker (or equivalent) * in order to obtain symbols from shared objects. A very useful book on the * various different object file and library formats that exist is Linkers & * Loaders, First Edition by John R. Levine (Morgan Kaufmann Publishers, 2000, * ISBN 1-558-60496-0). */#include "symbol.h"#include "diag.h"#include "utils.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#if FORMAT == FORMAT_AOUT || FORMAT == FORMAT_COFF || \ FORMAT == FORMAT_XCOFF || FORMAT == FORMAT_ELF32 || \ FORMAT == FORMAT_ELF64 || FORMAT == FORMAT_BFD#include <fcntl.h>#include <unistd.h>#if FORMAT == FORMAT_AOUT#include <a.out.h>#elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF#include <a.out.h>#if SYSTEM == SYSTEM_LYNXOS#include <coff.h>#ifndef ISCOFF#define ISCOFF(m) ((m) == COFFMAGICNUM)#endif /* ISCOFF */#ifndef ISFCN#define ISFCN(t) (((t) & 0x30) == (DT_FCN << 4))#endif /* ISFCN */#ifndef n_name#define n_name _n._n_name#endif /* n_name */#else /* SYSTEM */#if SYSTEM == SYSTEM_AIX#ifdef FREAD#undef FREAD#endif /* FREAD */#ifdef FWRITE#undef FWRITE#endif /* FWRITE */#ifndef ISCOFF#define ISCOFF(m) (((m) == U800TOCMAGIC) || ((m) == U802TOCMAGIC))#endif /* ISCOFF */#endif /* SYSTEM */#include <ldfcn.h>#endif /* SYSTEM */#elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64#include <libelf.h>#elif FORMAT == FORMAT_BFD#include <bfd.h>#endif /* FORMAT */#endif /* FORMAT */#if DYNLINK == DYNLINK_AIX/* The shared libraries that an AIX executable has loaded can be obtained via * the loadquery() function. */#include <sys/types.h>#include <sys/ldr.h>#elif DYNLINK == DYNLINK_BSD/* The BSD a.out dynamic linker is based on the original SunOS implementation * and is the precursor to the SVR4 ELF dynamic linker. Most BSD systems now * use ELF so this is for SunOS and the BSD systems that still use a.out. */#include <sys/types.h>#include <link.h>#elif DYNLINK == DYNLINK_HPUX/* The HP/UX dynamic linker support routines are available for use even by * statically linked programs. */#include <dl.h>#elif DYNLINK == DYNLINK_IRIX/* IRIX doesn't have a conventional SVR4 dynamic linker and so does not have the * same interface for accessing information about any required shared objects at * run-time. */#include <obj.h>#include <obj_list.h>#elif DYNLINK == DYNLINK_OSF/* The shared libraries that an OSF executable has loaded can be obtained via * the ldr_inq_module() and ldr_inq_region() functions. */#include <loader.h>#elif DYNLINK == DYNLINK_SVR4/* Despite the fact that Linux is now ELF-based, libelf seems to be missing from * many recent distributions and so we must use the GNU BFD library to read the * symbols from the object files and libraries. However, we still need the ELF * definitions for reading the internal structures of the dynamic linker. */#include <elf.h>#elif DYNLINK == DYNLINK_WINDOWS/* We use the imagehlp library on Windows platforms to obtain information about * the symbols loaded from third-party and system DLLs. We can also use it to * obtain information about any symbols contained in the executable file and * program database if COFF or CodeView debugging information is being used. */#include <windows.h>#include <imagehlp.h>#endif /* DYNLINK */#if MP_IDENT_SUPPORT#ident "$Id: symbol.c,v 1.62 2002/01/08 20:13:59 graeme Exp $"#else /* MP_IDENT_SUPPORT */static MP_CONST MP_VOLATILE char *symbol_id = "$Id: symbol.c,v 1.62 2002/01/08 20:13:59 graeme Exp $";#endif /* MP_IDENT_SUPPORT */#if DYNLINK == DYNLINK_SVR4/* These definitions are not always defined in ELF header files on all * systems so we define them here as they are documented in most * System V ABI documents. */#ifndef DT_NULL#define DT_NULL 0#define DT_DEBUG 21#if ENVIRON == ENVIRON_64typedef struct Elf64_Dyn{ Elf64_Xword d_tag; /* tag indicating type of data stored */ union { Elf64_Xword d_val; /* data is a value */ Elf64_Addr d_ptr; /* data is a pointer */ } d_un;}Elf64_Dyn;#else /* ENVIRON */typedef struct Elf32_Dyn{ Elf32_Sword d_tag; /* tag indicating type of data stored */ union { Elf32_Word d_val; /* data is a value */ Elf32_Addr d_ptr; /* data is a pointer */ } d_un;}Elf32_Dyn;#endif /* ENVIRON */#endif /* DT_NULL */#endif /* DYNLINK */#if DYNLINK == DYNLINK_IRIX/* This structure represents an N32 ABI shared object as opposed to an O32 ABI * shared object, and is defined on IRIX 6.0 and above platforms as * Elf32_Obj_Info. In order for us to compile on earlier IRIX platforms we * define this structure here, but under a different name so as to avoid a * naming clash on IRIX 6.0 and later. */typedef struct objectinfo{ Elf32_Word magic; /* N32 ABI shared object */ Elf32_Word size; /* size of this structure */ Elf32_Addr next; /* next shared object */ Elf32_Addr prev; /* previous shared object */ Elf32_Addr ehdr; /* address of object file header */ Elf32_Addr ohdr; /* original address of object file header */ Elf32_Addr name; /* filename of shared object */ Elf32_Word length; /* length of filename of shared object */}objectinfo;#elif DYNLINK == DYNLINK_SVR4/* This is a structure that is internal to the dynamic linker on ELF systems, * and so it is not always guaranteed to be the same. We try to rely on this * definition here for portability's sake as it is not publicly declared in * all ELF header files. */typedef struct dynamiclink{ size_t base; /* virtual address of shared object */ char *name; /* filename of shared object */#if ENVIRON == ENVIRON_64 Elf64_Dyn *dyn; /* dynamic linking information */#else /* ENVIRON */ Elf32_Dyn *dyn; /* dynamic linking information */#endif /* ENVIRON */ struct dynamiclink *next; /* pointer to next shared object */}dynamiclink;#elif DYNLINK == DYNLINK_WINDOWS/* This structure is used to pass information to the callback function * called by SymEnumerateSymbols(). */typedef struct syminfo{ symhead *syms; /* pointer to symbol table */ char *file; /* filename of module */}syminfo;/* This structure is used to pass information to the callback function * called by SymEnumerateModules(). */typedef struct modinfo{ symhead *syms; /* pointer to symbol table */ size_t index; /* index of module */ char libs; /* only read DLLs */}modinfo;#endif /* DYNLINK */#if FORMAT == FORMAT_BFD/* This structure is used to maintain a list of access library handles for * the purposes of mapping return addresses to line numbers. */typedef struct objectfile{ struct objectfile *next; /* pointer to next object file */ bfd *file; /* access library handle */ asymbol **symbols; /* pointer to symbols */ size_t base; /* virtual address of object file */}objectfile;/* This structure is used when searching for source locations corresponding * to virtual addresses by looking at debugging information embedded in an * object file. */typedef struct sourcepos{ bfd_vma addr; /* virtual address to search for */ asymbol **symbols; /* pointer to symbols */ size_t base; /* virtual address of object file */ char *func; /* function name */ char *file; /* file name */ unsigned int line; /* line number */ char found; /* found flag */}sourcepos;#endif /* FORMAT */#ifdef __cplusplusextern "C"{#endif /* __cplusplus */#if DYNLINK == DYNLINK_BSD/* The declaration of the _DYNAMIC symbol, which allows us direct access to the * dynamic linker's internal data structures. This is set up in crt0 and will * be NULL in an object that does not need dynamic linking. */#if SYSTEM == SYSTEM_SUNOSextern struct link_dynamic _DYNAMIC;#else /* SYSTEM */extern struct _dynamic _DYNAMIC;#endif /* SYSTEM */#elif DYNLINK == DYNLINK_IRIX/* The __rld_obj_head symbol is always defined in IRIX and points to the first * entry in a list of shared object files that are required by the program. For * statically linked programs this will either be NULL or will only contain the * entry for the program itself. */extern struct obj_list *__rld_obj_head;#elif DYNLINK == DYNLINK_SVR4/* The declaration of the _DYNAMIC symbol, which allows us direct access to the * dynamic linker's internal data structures. We make it have weak visibility * so that it is always defined, even in the statically linked case. It is * declared as a function because some compilers only allow weak function * symbols. Another alternative would be to declare it as a common symbol, but * that wouldn't work under C++ and many libc shared objects have it defined as * a text symbol. */#pragma weak _DYNAMICvoid _DYNAMIC(void);#endif /* DYNLINK *//* Initialise the fields of a symhead so that the symbol table becomes empty. */MP_GLOBALvoid__mp_newsymbols(symhead *y, heaphead *h, void *i){ struct { char x; symnode y; } z; long n; y->heap = h; /* Determine the minimum alignment for a symbol node on this system * and force the alignment to be a power of two. This information * is used when initialising the slot table. */ n = (char *) &z.y - &z.x; __mp_newstrtab(&y->strings, h); __mp_newslots(&y->table, sizeof(symnode), __mp_poweroftwo(n)); __mp_newtree(&y->itree); __mp_newtree(&y->dtree); y->size = 0; y->hhead = y->htail = NULL; y->inits = i; y->prot = MA_NOACCESS; y->protrecur = 0; y->lineinfo = 0;}/* Close all access library handles. */MP_GLOBALvoid__mp_closesymbols(symhead *y){#if FORMAT == FORMAT_BFD objectfile *n, *p;#endif /* FORMAT */#if FORMAT == FORMAT_BFD for (n = (objectfile *) y->hhead; n != NULL; n = p) { p = n->next; bfd_close(n->file); free(n->symbols); free(n); }#endif /* FORMAT */ y->hhead = y->htail = NULL;}/* Forget all data currently in the symbol table. */MP_GLOBALvoid__mp_deletesymbols(symhead *y){ /* We don't need to explicitly free any memory as this is dealt with * at a lower level by the heap manager. */ y->heap = NULL; __mp_deletestrtab(&y->strings); y->table.free = NULL; y->table.size = 0; __mp_newtree(&y->itree); __mp_newtree(&y->dtree); y->size = 0; y->inits = NULL; y->prot = MA_NOACCESS; y->protrecur = 0;}/* Allocate a new symbol node. */staticsymnode *getsymnode(symhead *y){ symnode *n; heapnode *p; /* If we have no more symbol node slots left then we must allocate * some more memory for them. An extra MP_ALLOCFACTOR pages of memory * should suffice. */ if ((n = (symnode *) __mp_getslot(&y->table)) == NULL) { if ((p = __mp_heapalloc(y->heap, y->heap->memory.page * MP_ALLOCFACTOR, y->table.entalign, 1)) == NULL) return NULL; __mp_initslots(&y->table, p->block, p->size); n = (symnode *) __mp_getslot(&y->table); __mp_treeinsert(&y->itree, &n->index.node, (unsigned long) p->block); n->index.block = p->block;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -