📄 symbol.c
字号:
* we store the symbol table along with the access library handle; otherwise * we can free the symbol table now. */ if (y->lineinfo && (r == 1)) ((objectfile *) y->htail)->symbols = p; else free(p); return r;}#endif /* FORMAT */#if DYNLINK == DYNLINK_WINDOWS/* The callback function called to allocate a set of symbol nodes for each * module located by the imagehlp library. */staticint __stdcalladdsyms(char *f, unsigned long b, void *p){ modinfo *i; symhead *y; char *t; syminfo s; IMAGEHLP_MODULE m; size_t l; int r; r = 1; i = (modinfo *) p; y = i->syms; l = y->dtree.size; /* The executable file is the first module, so we only want to examine it * if we are not looking for external symbols. The DLLs are the subsequent * modules, so we only want to examine them if we are looking for external * symbols. */ if ((!i->libs && !i->index) || (i->libs && i->index)) { /* Attempt to determine the full path of the current module. */ m.SizeOfStruct = sizeof(IMAGEHLP_MODULE); if (SymGetModuleInfo(GetCurrentProcess(), b, &m)) f = m.LoadedImageName; if ((t = __mp_addstring(&y->strings, f)) == NULL) r = 0; else { /* Cycle through every symbol contained in the module. */ s.syms = y; s.file = t; r = SymEnumerateSymbols(GetCurrentProcess(), b, addsym, &s); } if (i->libs) { if (r == 1) { l = y->dtree.size - l; __mp_diag("read %lu symbol%s from ", l, (l == 1) ? "" : "s"); } else __mp_diag("problem reading symbols from "); if (__mp_diagflags & FLG_HTML) __mp_diagtag("<TT>"); __mp_diag("%s", f); if (__mp_diagflags & FLG_HTML) { __mp_diagtag("</TT>\n"); __mp_diagtag("<BR>"); } __mp_diag("\n"); } } i->index++; return r;}#endif /* DYNLINK *//* Read a file and add all relevant symbols contained within it to the * symbol table. */MP_GLOBALint__mp_addsymbols(symhead *y, char *s, char *v, size_t b){#if FORMAT == FORMAT_AOUT || FORMAT == FORMAT_COFF || \ FORMAT == FORMAT_XCOFF || FORMAT == FORMAT_ELF32 || \ FORMAT == FORMAT_ELF64 || FORMAT == FORMAT_BFD#if FORMAT == FORMAT_AOUT || (SYSTEM == SYSTEM_LYNXOS && \ (FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF)) char *m; off_t o; int f;#elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF LDFILE *f; char *c, *m, *n; ARCHDR a; size_t o;#elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64 Elf *a, *e; Elf_Arhdr *h; int f;#elif FORMAT == FORMAT_BFD objectfile *p, *q; bfd *a, *g, *h;#endif /* FORMAT */ char *t;#elif FORMAT == FORMAT_PE modinfo m;#endif /* FORMAT */ size_t l; int r; r = 1; l = y->dtree.size;#if FORMAT == FORMAT_AOUT || (SYSTEM == SYSTEM_LYNXOS && \ (FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF)) /* This is a very simple, yet portable, way to read symbols from a.out * executable files, or from COFF or XCOFF executable files when libld * is not available. */ if ((f = open(s, O_RDONLY)) == -1) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s); r = 0; } else { /* Find out the size of the file by doing a seek to the end of the file * and then a seek back to the start of the file. Unfortunately, on * some systems off_t is a structure, so the code below may not work * for them. */ if (((o = lseek(f, 0, SEEK_END)) == (off_t) -1) || (lseek(f, 0, SEEK_SET) == (off_t) -1)) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot seek file\n", s); r = 0; } else if ((m = (char *) malloc((size_t) o)) == NULL) { /* It's actually safe to call malloc() here since the library * checks for recursive behaviour. */ __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: no memory for symbols\n", s); r = 0; } else { if (read(f, m, (size_t) o) != (size_t) o) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot read file\n", s); r = 0; } else if ((t = __mp_addstring(&y->strings, s)) == NULL) r = 0; else r = addsymbols(y, m, NULL, t, (size_t) o, b); free(m); } close(f); }#elif FORMAT == FORMAT_COFF || FORMAT == FORMAT_XCOFF /* We use the libld COFF and XCOFF access library in order to simplify * the reading of symbols. If this library is not available on a certain * platform then use the above code for reading a.out files and comment * this code out. However, a better solution would be to use the GNU * BFD library if it is available. */ t = NULL; if ((f = ldopen(s, NULL)) == NULL) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s); r = 0; } while (r == 1) { if (ldahread(f, &a)) { n = a.ar_name; o = a.ar_size; if (((v != NULL) && (strcmp(n, v) != 0)) || (FSEEK(f, 0, BEGINNING) == -1)) { if (ldclose(f)) break; if ((f = ldopen(s, f)) == NULL) r = 0; continue; } } else n = NULL; /* Find out the size of the file by doing a seek to the end of the file * and then a seek back to the start of the file, but only if this is * not an archive member. */ if ((n == NULL) && ((FSEEK(f, 0, END) == -1) || ((o = FTELL(f)) == (size_t) -1) || (FSEEK(f, 0, BEGINNING) == -1))) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot seek file\n", s); r = 0; } else if ((m = (char *) malloc(o)) == NULL) { /* It's actually safe to call malloc() here since the library * checks for recursive behaviour. */ c = "no memory for symbols"; if (n != NULL) __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s, n, c); else __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, c); r = 0; } else { if (FREAD(m, sizeof(char), o, f) != o) { c = "cannot read file"; if (n != NULL) __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s, n, c); else __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, c); r = 0; } else if ((t == NULL) && ((t = __mp_addstring(&y->strings, s)) == NULL)) r = 0; else if (n != NULL) r = addsymbols(y, m, t, n, o, b); else r = addsymbols(y, m, NULL, t, o, b); free(m); } if (ldclose(f)) break; if ((r == 1) && ((f = ldopen(s, f)) == NULL)) r = 0; }#elif FORMAT == FORMAT_ELF32 || FORMAT == FORMAT_ELF64 /* We use the libelf ELF access library in order to simplify the reading * of symbols. At the moment, this solution is better than using the * GNU BFD library as it currently has no support for symbol sizes or * liaising with the dynamic linker. */ if (elf_version(EV_CURRENT) == EV_NONE) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: wrong version of libelf\n", s); r = 0; } else if ((f = open(s, O_RDONLY)) == -1) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: cannot open file\n", s); r = 0; } else { if ((e = elf_begin(f, ELF_C_READ, NULL)) == NULL) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, elf_errmsg(-1)); r = 0; } else if ((t = __mp_addstring(&y->strings, s)) == NULL) r = 0; else { if (elf_kind(e) == ELF_K_AR) /* Normally we wouldn't ever need to read symbols from an * archive library, but this is just provided for * completeness. */ while ((r == 1) && (a = elf_begin(f, ELF_C_READ, e))) { if ((h = elf_getarhdr(a)) == NULL) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, elf_errmsg(-1)); r = 0; } else if ((*h->ar_name != '/') && ((v == NULL) || (strcmp(h->ar_name, v) == 0))) r = addsymbols(y, a, t, h->ar_name, b); if (r == 1) elf_next(a); elf_end(a); } else r = addsymbols(y, e, NULL, t, b); elf_end(e); } close(f); }#elif FORMAT == FORMAT_BFD /* Using the GNU BFD library allows us to read weird and wonderful file * formats that would otherwise be hard to support. This is probably a * better choice to use than the in-built a.out, COFF and XCOFF * implementations but currently has no support for symbol sizes, so the * ELF access library is still worth using for ELF file formats, but the * BFD library comes with support for debugging information. So take * your pick! */ t = NULL; bfd_init(); if ((h = bfd_openr(s, NULL)) == NULL) { __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, bfd_errmsg(bfd_get_error())); r = 0; } else { /* Normally we wouldn't ever need to read symbols from an archive * library, but this is just provided for completeness, and for AIX * where shared libraries can be embedded within archive libraries. */ if (bfd_check_format(h, bfd_archive)) { a = h; h = bfd_openr_next_archived_file(a, NULL); } else a = NULL; while (h != NULL) { p = NULL; if ((a != NULL) && (v != NULL) && (strcmp(h->filename, v) != 0)) { g = h; h = bfd_openr_next_archived_file(a, g); bfd_close(g); continue; } if (!bfd_check_format(h, bfd_object)) { if (a != NULL) __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s [%s]: %s\n", s, h->filename, bfd_errmsg(bfd_get_error())); else __mp_error(ET_MAX, AT_MAX, NULL, 0, "%s: %s\n", s, bfd_errmsg(bfd_get_error())); r = 0; } else if (y->lineinfo && ((p = (objectfile *) malloc(sizeof(objectfile))) == NULL)) r = 0; else if ((t == NULL) && ((t = __mp_addstring(&y->strings, s)) == NULL)) r = 0; else { if (y->lineinfo) { if (y->hhead == NULL) y->hhead = p; else { q = (objectfile *) y->htail; q->next = p; } y->htail = p; p->next = NULL; p->file = h; p->symbols = NULL; p->base = b; } if (a != NULL) r = addsymbols(y, h, t, (char *) h->filename, b); else r = addsymbols(y, h, NULL, t, b); if (y->lineinfo && (r == 0)) if (y->hhead == p) y->hhead = y->htail = NULL; else { y->htail = q; q->next = NULL; } } g = h; if ((a != NULL) && (r == 1)) h = bfd_openr_next_archived_file(a, g); else h = NULL; if (!y->lineinfo || (r == 0)) { if (p != NULL) free(p); bfd_close(g); } } if (a != NULL) bfd_close(a); }#elif FORMAT == FORMAT_PE /* We only want to obtain the symbols from the executable file using the * imagehlp library if we are not using another object file access library, * such as GNU BFD. */ m.syms = y; m.index = 0; m.libs = 0; r = SymEnumerateModules(GetCurrentProcess(), addsyms, &m);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -