/* * Print name of symbol. Return number of characters printed. */ int print_name_only (Sym *self) { const char *name = self->name; const char *filename; char *demangled = 0; char buf[PATH_MAX]; int size = 0; if (name) { if (!bsd_style_output && demangle) { demangled = bfd_demangle (core_bfd[0], name, DMGL_ANSI | DMGL_PARAMS); if (demangled) name = demangled; } printf ("%s", name); size = strlen (name); if (line_granularity && self->file) { filename = self->file->name; if (!print_path) { filename = strrchr (filename, '/'); if (filename) { ++filename; } else { filename = self->file->name; } } sprintf (buf, " (%s:%d @ %lx)", filename, self->line_num, (unsigned long) self->addr); printf ("%s", buf); size += strlen (buf); } if (demangled) { free (demangled); } DBG (DFNDEBUG, printf ("{%d} ", self->cg.top_order)); DBG (PROPDEBUG, printf ("%4.0f%% ", 100.0 * self->cg.prop.fract)); } return size; }
int BFDmanager_translateAddress (bfd *bfdImage, asymbol **bfdSymbols, void *address, char **function, char **file, int *line) { BFDmanager_symbolInfo_t syminfo; char caddress[32]; #if defined(DEBUG) printf ("DEBUG: BFDmanager_translateAddress (%p, %p, address = %p)\n", bfdImage, bfdSymbols, address); #endif syminfo.found = FALSE; if (bfdImage && bfdSymbols) { /* Convert the address into hexadecimal string format */ sprintf (caddress, "%p", address); /* Prepare the query for BFD */ syminfo.pc = bfd_scan_vma (caddress, NULL, 16); syminfo.symbols = bfdSymbols; /* Iterate through sections of the given bfd image */ bfd_map_over_sections (bfdImage, BFDmanager_findAddressInSection, &syminfo); /* Found the symbol ? If so, copy the data */ if (syminfo.found) { char *demangled = NULL; *file = (char*) syminfo.filename; *line = syminfo.line; #if defined(HAVE_BFD_DEMANGLE) if (syminfo.function) demangled = bfd_demangle (bfdImage, syminfo.function, 0); if (demangled) *function = demangled; else *function = (char*) syminfo.function; #else *function = (char*) syminfo.function; #endif } } return syminfo.found; }
static void wpa_trace_bfd_addr(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; const char *name; char *aname = NULL; const char *filename; if (abfd == NULL) return; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return; do { if (data.function) aname = bfd_demangle(abfd, data.function, DMGL_ANSI | DMGL_PARAMS); name = aname ? aname : data.function; filename = data.filename; if (filename) { char *end = os_strrchr(filename, '/'); int i = 0; while (*filename && *filename == prg_fname[i] && filename <= end) { filename++; i++; } } wpa_printf(MSG_INFO, " %s() %s:%u", name, filename, data.line); free(aname); data.found = bfd_find_inliner_info(abfd, &data.filename, &data.function, &data.line); } while (data.found); }
void vfinfo (FILE *fp, const char *fmt, va_list ap, bfd_boolean is_warning) { bfd_boolean fatal = FALSE; const char *scan; int arg_type; unsigned int arg_count = 0; unsigned int arg_no; union vfinfo_args { int i; long l; void *p; bfd_vma v; struct { bfd *abfd; asection *sec; bfd_vma off; } reladdr; enum { Bad, Int, Long, Ptr, Vma, RelAddr } type; } args[9]; for (arg_no = 0; arg_no < sizeof (args) / sizeof (args[0]); arg_no++) args[arg_no].type = Bad; arg_count = 0; scan = fmt; while (*scan != '\0') { while (*scan != '%' && *scan != '\0') scan++; if (*scan == '%') { scan++; arg_no = arg_count; if (*scan != '0' && ISDIGIT (*scan) && scan[1] == '$') { arg_no = *scan - '1'; scan += 2; } arg_type = Bad; switch (*scan++) { case '\0': --scan; break; case 'V': case 'v': case 'W': arg_type = Vma; break; case 's': arg_type = Ptr; break; case 'p': if (*scan == 'A' || *scan == 'B' || *scan == 'I' || *scan == 'R' || *scan == 'S' || *scan == 'T') scan++; arg_type = Ptr; break; case 'C': case 'D': case 'G': case 'H': arg_type = RelAddr; break; case 'd': case 'u': arg_type = Int; break; case 'l': if (*scan == 'd' || *scan == 'u') { ++scan; arg_type = Long; } break; default: break; } if (arg_type != Bad) { if (arg_no >= sizeof (args) / sizeof (args[0])) abort (); args[arg_no].type = arg_type; ++arg_count; } } } for (arg_no = 0; arg_no < arg_count; arg_no++) { switch (args[arg_no].type) { case Int: args[arg_no].i = va_arg (ap, int); break; case Long: args[arg_no].l = va_arg (ap, long); break; case Ptr: args[arg_no].p = va_arg (ap, void *); break; case Vma: args[arg_no].v = va_arg (ap, bfd_vma); break; case RelAddr: args[arg_no].reladdr.abfd = va_arg (ap, bfd *); args[arg_no].reladdr.sec = va_arg (ap, asection *); args[arg_no].reladdr.off = va_arg (ap, bfd_vma); break; default: abort (); } } arg_count = 0; while (*fmt != '\0') { const char *str = fmt; while (*fmt != '%' && *fmt != '\0') fmt++; if (fmt != str) if (fwrite (str, 1, fmt - str, fp)) { /* Ignore. */ } if (*fmt == '%') { fmt++; arg_no = arg_count; if (*fmt != '0' && ISDIGIT (*fmt) && fmt[1] == '$') { arg_no = *fmt - '1'; fmt += 2; } switch (*fmt++) { case '\0': --fmt; /* Fall through. */ case '%': /* literal % */ putc ('%', fp); break; case 'X': /* no object output, fail return */ config.make_executable = FALSE; break; case 'V': /* hex bfd_vma */ { bfd_vma value = args[arg_no].v; ++arg_count; fprintf_vma (fp, value); } break; case 'v': /* hex bfd_vma, no leading zeros */ { char buf[100]; char *p = buf; bfd_vma value = args[arg_no].v; ++arg_count; sprintf_vma (p, value); while (*p == '0') p++; if (!*p) p--; fputs (p, fp); } break; case 'W': /* hex bfd_vma with 0x with no leading zeroes taking up 8 spaces. */ { char buf[100]; bfd_vma value; char *p; int len; value = args[arg_no].v; ++arg_count; sprintf_vma (buf, value); for (p = buf; *p == '0'; ++p) ; if (*p == '\0') --p; len = strlen (p); while (len < 8) { putc (' ', fp); ++len; } fprintf (fp, "0x%s", p); } break; case 'F': /* Error is fatal. */ fatal = TRUE; break; case 'P': /* Print program name. */ fprintf (fp, "%s", program_name); break; case 'E': /* current bfd error or errno */ fprintf (fp, "%s", bfd_errmsg (bfd_get_error ())); break; case 'C': case 'D': case 'G': case 'H': /* Clever filename:linenumber with function name if possible. The arguments are a BFD, a section, and an offset. */ { static bfd *last_bfd; static char *last_file; static char *last_function; bfd *abfd; asection *section; bfd_vma offset; asymbol **asymbols = NULL; const char *filename; const char *functionname; unsigned int linenumber; bfd_boolean discard_last; bfd_boolean done; abfd = args[arg_no].reladdr.abfd; section = args[arg_no].reladdr.sec; offset = args[arg_no].reladdr.off; ++arg_count; if (abfd != NULL) { if (!bfd_generic_link_read_symbols (abfd)) einfo (_("%F%P: %pB: could not read symbols: %E\n"), abfd); asymbols = bfd_get_outsymbols (abfd); } /* The GNU Coding Standard requires that error messages be of the form: source-file-name:lineno: message We do not always have a line number available so if we cannot find them we print out the section name and offset instead. */ discard_last = TRUE; if (abfd != NULL && bfd_find_nearest_line (abfd, section, asymbols, offset, &filename, &functionname, &linenumber)) { if (functionname != NULL && (fmt[-1] == 'C' || fmt[-1] == 'H')) { /* Detect the case where we are printing out a message for the same function as the last call to vinfo ("%C"). In this situation do not print out the ABFD filename or the function name again. Note - we do still print out the source filename, as this will allow programs that parse the linker's output (eg emacs) to correctly locate multiple errors in the same source file. */ if (last_bfd == NULL || last_function == NULL || last_bfd != abfd || (last_file == NULL) != (filename == NULL) || (filename != NULL && filename_cmp (last_file, filename) != 0) || strcmp (last_function, functionname) != 0) { lfinfo (fp, _("%pB: in function `%pT':\n"), abfd, functionname); last_bfd = abfd; if (last_file != NULL) free (last_file); last_file = NULL; if (filename) last_file = xstrdup (filename); if (last_function != NULL) free (last_function); last_function = xstrdup (functionname); } discard_last = FALSE; } else lfinfo (fp, "%pB:", abfd); if (filename != NULL) fprintf (fp, "%s:", filename); done = fmt[-1] != 'H'; if (functionname != NULL && fmt[-1] == 'G') lfinfo (fp, "%pT", functionname); else if (filename != NULL && linenumber != 0) fprintf (fp, "%u%s", linenumber, done ? "" : ":"); else done = FALSE; } else { lfinfo (fp, "%pB:", abfd); done = FALSE; } if (!done) lfinfo (fp, "(%pA+0x%v)", section, offset); if (discard_last) { last_bfd = NULL; if (last_file != NULL) { free (last_file); last_file = NULL; } if (last_function != NULL) { free (last_function); last_function = NULL; } } } break; case 'p': if (*fmt == 'A') { /* section name from a section */ asection *sec; bfd *abfd; const char *group = NULL; struct coff_comdat_info *ci; fmt++; sec = (asection *) args[arg_no].p; ++arg_count; abfd = sec->owner; fprintf (fp, "%s", sec->name); if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_elf_flavour && elf_next_in_group (sec) != NULL && (sec->flags & SEC_GROUP) == 0) group = elf_group_name (sec); else if (abfd != NULL && bfd_get_flavour (abfd) == bfd_target_coff_flavour && (ci = bfd_coff_get_comdat_section (sec->owner, sec)) != NULL) group = ci->name; if (group != NULL) fprintf (fp, "[%s]", group); } else if (*fmt == 'B') { /* filename from a bfd */ bfd *abfd = (bfd *) args[arg_no].p; fmt++; ++arg_count; if (abfd == NULL) fprintf (fp, "%s generated", program_name); else if (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) fprintf (fp, "%s(%s)", abfd->my_archive->filename, abfd->filename); else fprintf (fp, "%s", abfd->filename); } else if (*fmt == 'I') { /* filename from a lang_input_statement_type */ lang_input_statement_type *i; fmt++; i = (lang_input_statement_type *) args[arg_no].p; ++arg_count; if (i->the_bfd != NULL && i->the_bfd->my_archive != NULL && !bfd_is_thin_archive (i->the_bfd->my_archive)) fprintf (fp, "(%s)%s", i->the_bfd->my_archive->filename, i->local_sym_name); else fprintf (fp, "%s", i->filename); } else if (*fmt == 'R') { /* Print all that's interesting about a relent. */ arelent *relent = (arelent *) args[arg_no].p; fmt++; ++arg_count; lfinfo (fp, "%s+0x%v (type %s)", (*(relent->sym_ptr_ptr))->name, relent->addend, relent->howto->name); } else if (*fmt == 'S') { /* Print script file and linenumber. */ etree_type node; etree_type *tp = (etree_type *) args[arg_no].p; fmt++; ++arg_count; if (tp == NULL) { tp = &node; tp->type.filename = ldlex_filename (); tp->type.lineno = lineno; } if (tp->type.filename != NULL) fprintf (fp, "%s:%u", tp->type.filename, tp->type.lineno); } else if (*fmt == 'T') { /* Symbol name. */ const char *name = (const char *) args[arg_no].p; fmt++; ++arg_count; if (name == NULL || *name == 0) { fprintf (fp, _("no symbol")); break; } else if (demangling) { char *demangled; demangled = bfd_demangle (link_info.output_bfd, name, DMGL_ANSI | DMGL_PARAMS); if (demangled != NULL) { fprintf (fp, "%s", demangled); free (demangled); break; } } fprintf (fp, "%s", name); } else { /* native (host) void* pointer, like printf */ fprintf (fp, "%p", args[arg_no].p); ++arg_count; } break; case 's': /* arbitrary string, like printf */ fprintf (fp, "%s", (char *) args[arg_no].p); ++arg_count; break; case 'd': /* integer, like printf */ fprintf (fp, "%d", args[arg_no].i); ++arg_count; break; case 'u': /* unsigned integer, like printf */ fprintf (fp, "%u", args[arg_no].i); ++arg_count; break; case 'l': if (*fmt == 'd') { fprintf (fp, "%ld", args[arg_no].l); ++arg_count; ++fmt; break; } else if (*fmt == 'u') { fprintf (fp, "%lu", args[arg_no].l); ++arg_count; ++fmt; break; } /* Fallthru */ default: fprintf (fp, "%%%c", fmt[-1]); break; } } } if (is_warning && config.fatal_warnings) config.make_executable = FALSE; if (fatal) xexit (1); }
char* getDemangledNameRaw(bfd* abfd, const char* name) { char* result = bfd_demangle(abfd, name, DMGL_PARAMS | DMGL_ANSI | DMGL_RET_POSTFIX); return result ? result : strdup(name); }
int BinaryFile::InitRelsym(relsym_dict &rels) { ELFManager elf; //open elf.elf_open(_abfd->filename); //rel symbol int rel_count; long relsym_needed = elf.elf_get_relsym_upper_bound (&rel_count); if (relsym_needed <= 0) { fprintf(stderr, "elf_get_relsym_upper_bound: SHT_REL\n"); return -1; } erelsym **rel_table = (erelsym **) malloc (relsym_needed); if (rel_table == NULL) { perror("malloc"); return -1; } long number_of_relsym = elf.elf_canonicalize_relsym (rel_table, rel_count); if (number_of_relsym < 0) { fprintf(stderr, "elf_canonicalize_symtab"); return -1; } //获取符号表所需大小 long dynsym_needed = elf.elf_get_section_upper_bound (SHT_DYNSYM); if (dynsym_needed <= 0) { fprintf(stderr, "elf_get_section_upper_bound: SHT_DYNSYM\n"); return -1; } esymbol **symbol_table = NULL; symbol_table = (esymbol **) malloc (dynsym_needed); if (symbol_table == NULL) { perror("malloc"); return -1; } long number_of_symbols = elf.elf_canonicalize_symbol (symbol_table, SHT_DYNSYM); if (number_of_symbols < 0) { fprintf(stderr, "elf_canonicalize_symtab"); return -1; } //do something /* for(long i=0; i<number_of_symbols; i++) { char *name = symbol_table[i]->name; //bfd_vma value = symbol_table[i]->value; if (symbol_table[i]->type != type) { continue; } printf("[idx:%ld] name:%s\n", i, name); } */ for(long i=0; i<number_of_relsym; i++) { if(rel_table[i]->type != R_X86_64_JUMP_SLOT) { continue; } char *name = symbol_table[rel_table[i]->symid]->name; #ifdef HAVE_BFD_DEMANGLE char *demangle_name = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); if (demangle_name != NULL) { name = demangle_name; } #else //demangle int status; char *demangle_name = abi::__cxa_demangle(name, NULL, NULL, &status); if (status == 0) { name = demangle_name; } #endif rels[name].realname = symbol_table[rel_table[i]->symid]->name; rels[name].pgot = (void *)rel_table[i]->offset; //printf("[idx:%ld] name:%s, pgot:0x%lx, addr:0x%lx\n", // i, name, rels[name].pgot, rels[name].realname.c_str()); if (demangle_name != NULL) { free(demangle_name); } } //free if (rel_table) { free(rel_table); } if (symbol_table) { free(symbol_table); } elf.elf_close(); return 0; }
int BinaryFile::InitSymbols(symbol_dict &symbols, int sym_flag) { ELFManager elf; //open elf.elf_open(_abfd->filename); //获取符号表所需大小 long storage_needed = elf.elf_get_symtab_upper_bound (); if (storage_needed < 0) { fprintf(stderr, "elf_get_symtab_upper_bound\n"); return -1; } if (storage_needed == 0) { fprintf(stderr, "storage_needed is 0\n"); return -1; } esymbol **symbol_table = NULL; symbol_table = (esymbol **) malloc (storage_needed); if (symbol_table == NULL) { perror("malloc"); return -1; } long number_of_symbols = elf.elf_canonicalize_symtab (symbol_table); if (number_of_symbols < 0) { fprintf(stderr, "elf_canonicalize_symtab"); return -1; } int type = 0; if (sym_flag & SYM_FUNC) { type = STT_FUNC; } for(long i=0; i<number_of_symbols; i++) { char *name = symbol_table[i]->name; bfd_vma value = symbol_table[i]->value; if (symbol_table[i]->type != type || value == 0 //|| symbol_table[i]->size < minsize //小于跳转指令长度则忽略 || symbol_table[i]->shndx == 0) { continue; } #ifdef HAVE_BFD_DEMANGLE char *demangle_name = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); if (demangle_name != NULL) { name = demangle_name; } #else //FIXME: 规避libstd++低版本demangle("FT_SUPERDOC_cmp")出core的bug if(strcmp(name, "FT_SUPERDOC_cmp") == 0) { symbols[name].addr = (void *)value; symbols[name].size = symbol_table[i]->size; continue; } //demangle int status; char *demangle_name = abi::__cxa_demangle(name, NULL, NULL, &status); if (status == 0) { name = demangle_name; } #endif symbols[name].addr = (void *)value; symbols[name].size = symbol_table[i]->size; if (demangle_name != NULL) { free(demangle_name); } } //free if (symbol_table) { free(symbol_table); } elf.elf_close(); return 0; }