static long remove_useless_symbols (asymbol ** symbols, long count) { asymbol **in_ptr = symbols, **out_ptr = symbols; while (-- count >= 0) { asymbol *sym = *in_ptr ++; if (strstr (sym->name, "gcc2_compiled")) continue; if (sym->name == NULL || sym->name[0] == '\0') continue; if (sym->flags & (BSF_DEBUGGING)) continue; if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) continue; if (sym->name[0] == '.' && sym->name[1] == 'L') continue; /* If the symbol ends in ^A or ^B it is an assembler generated local label. */ if (sym->name[strlen (sym->name) - 1] < 32) continue; *out_ptr++ = sym; } return out_ptr - symbols; }
bfd_vma bfd_coff_reloc16_get_value (arelent *reloc, struct bfd_link_info *link_info, asection *input_section) { bfd_vma value; asymbol *symbol = *(reloc->sym_ptr_ptr); /* A symbol holds a pointer to a section, and an offset from the base of the section. To relocate, we find where the section will live in the output and add that in. */ if (bfd_is_und_section (symbol->section) || bfd_is_com_section (symbol->section)) { struct bfd_link_hash_entry *h; /* The symbol is undefined in this BFD. Look it up in the global linker hash table. FIXME: This should be changed when we convert this stuff to use a specific final_link function and change the interface to bfd_relax_section to not require the generic symbols. */ h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info, bfd_asymbol_name (symbol), FALSE, FALSE, TRUE); if (h != (struct bfd_link_hash_entry *) NULL && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak)) value = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); else if (h != (struct bfd_link_hash_entry *) NULL && h->type == bfd_link_hash_common) value = h->u.c.size; else if (h != (struct bfd_link_hash_entry *) NULL && h->type == bfd_link_hash_undefweak) /* This is a GNU extension. */ value = 0; else { if (!((*link_info->callbacks->undefined_symbol) (link_info, bfd_asymbol_name (symbol), input_section->owner, input_section, reloc->address, TRUE))) abort (); value = 0; } } else { value = symbol->value + symbol->section->output_offset + symbol->section->output_section->vma; } /* Add the value contained in the relocation. */ value += reloc->addend; return value; }
void add_cref (const char *name, bfd *abfd, asection *section, bfd_vma value ATTRIBUTE_UNUSED) { struct cref_hash_entry *h; struct cref_ref *r; if (! cref_initialized) { if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc, sizeof (struct cref_hash_entry))) einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n")); cref_initialized = TRUE; } h = cref_hash_lookup (&cref_table, name, TRUE, FALSE); if (h == NULL) einfo (_("%X%P: cref_hash_lookup failed: %E\n")); for (r = h->refs; r != NULL; r = r->next) if (r->abfd == abfd) break; if (r == NULL) { r = bfd_hash_allocate (&cref_table.root, sizeof *r); if (r == NULL) einfo (_("%X%P: cref alloc failed: %E\n")); r->next = h->refs; h->refs = r; r->abfd = abfd; r->def = FALSE; r->common = FALSE; r->undef = FALSE; } if (bfd_is_und_section (section)) r->undef = TRUE; else if (bfd_is_com_section (section)) r->common = TRUE; else r->def = TRUE; }
long remove_useless_symbols_local (asymbol *symbols, long count) { asymbol *in_ptr = symbols, *out_ptr = symbols; while (--count >= 0) { asymbol *sym = in_ptr++; if (sym->name == NULL || sym->name[0] == '\0') continue; if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) continue; if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) continue; *out_ptr++ = *sym; } return out_ptr - symbols; }
void ELFFile::remove_useless_symbols () { long count = this->sorted_symcount; asymbol** in_ptr = this->sorted_syms; asymbol** out_ptr = this->sorted_syms; while (--count >= 0) { asymbol *sym = *in_ptr++; if (sym->name == NULL || sym->name[0] == '\0') continue; if (sym->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) continue; if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) continue; *out_ptr++ = sym; } this->sorted_symcount = out_ptr - this->sorted_syms; }
static long remove_useless_symbols (asymbol ** symbols, long count) { register asymbol **in_ptr = symbols, **out_ptr = symbols; while (--count >= 0) { asymbol *sym = *in_ptr++; if (strstr (sym->name, "gcc2_compiled")) continue; if (sym->name == NULL || sym->name[0] == '\0') continue; if (sym->flags & (BSF_DEBUGGING)) continue; if (bfd_is_und_section (sym->section) || bfd_is_com_section (sym->section)) continue; *out_ptr++ = sym; } return out_ptr - symbols; }
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as the linker adds them to the linker hash table. Mark those referenced from a non-IR file with non_ir_ref. We have to notice_all symbols, because we won't necessarily know until later which ones will be contributed by IR files. */ static bfd_boolean plugin_notice (struct bfd_link_info *info, struct bfd_link_hash_entry *h, bfd *abfd, asection *section, bfd_vma value, flagword flags, const char *string) { if (h != NULL) { bfd *sym_bfd; /* No further processing if this def/ref is from an IR dummy BFD. */ if (is_ir_dummy_bfd (abfd)) return TRUE; /* Making an indirect symbol counts as a reference unless this is a brand new symbol. */ if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) { if (h->type != bfd_link_hash_new) { struct bfd_link_hash_entry *inh; h->non_ir_ref = TRUE; inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE, FALSE, FALSE); if (inh != NULL) inh->non_ir_ref = TRUE; } } /* Nothing to do here for warning symbols. */ else if ((flags & BSF_WARNING) != 0) ; /* Nothing to do here for constructor symbols. */ else if ((flags & BSF_CONSTRUCTOR) != 0) ; /* If this is a ref, set non_ir_ref. */ else if (bfd_is_und_section (section)) h->non_ir_ref = TRUE; /* Otherwise, it must be a new def. Ensure any symbol defined in an IR dummy BFD takes on a new value from a real BFD. Weak symbols are not normally overridden by a new weak definition, and strong symbols will normally cause multiple definition errors. Avoid this by making the symbol appear to be undefined. */ else if (((h->type == bfd_link_hash_defweak || h->type == bfd_link_hash_defined) && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) || (h->type == bfd_link_hash_common && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) { h->type = bfd_link_hash_undefweak; h->u.undef.abfd = sym_bfd; } } /* Continue with cref/nocrossref/trace-sym processing. */ if (h == NULL || orig_notice_all || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, h->root.string, FALSE, FALSE) != NULL)) return (*orig_callbacks->notice) (info, h, abfd, section, value, flags, string); return TRUE; }
/* FUNCTION bfd_decode_symclass DESCRIPTION Return a character corresponding to the symbol class of @var{symbol}, or '?' for an unknown class. SYNOPSIS int bfd_decode_symclass (asymbol *symbol); */ int bfd_decode_symclass (asymbol *symbol) { char c; if (symbol->section && bfd_is_com_section (symbol->section)) return 'C'; if (bfd_is_und_section (symbol->section)) { if (symbol->flags & BSF_WEAK) { /* If weak, determine if it's specifically an object or non-object weak. */ if (symbol->flags & BSF_OBJECT) return 'v'; else return 'w'; } else return 'U'; } if (bfd_is_ind_section (symbol->section)) return 'I'; if (symbol->flags & BSF_GNU_INDIRECT_FUNCTION) return 'i'; if (symbol->flags & BSF_WEAK) { /* If weak, determine if it's specifically an object or non-object weak. */ if (symbol->flags & BSF_OBJECT) return 'V'; else return 'W'; } if (symbol->flags & BSF_GNU_UNIQUE) return 'u'; if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL))) return '?'; if (bfd_is_abs_section (symbol->section)) c = 'a'; else if (symbol->section) { c = coff_section_type (symbol->section->name); if (c == '?') c = decode_section_type (symbol->section); } else return '?'; if (symbol->flags & BSF_GLOBAL) c = TOUPPER (c); return c; /* We don't have to handle these cases just yet, but we will soon: N_SETV: 'v'; N_SETA: 'l'; N_SETT: 'x'; N_SETD: 'z'; N_SETB: 's'; N_INDR: 'i'; */ }
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as the linker adds them to the linker hash table. Mark those referenced from a non-IR file with non_ir_ref. We have to notice_all symbols, because we won't necessarily know until later which ones will be contributed by IR files. */ static bfd_boolean plugin_notice (struct bfd_link_info *info, struct bfd_link_hash_entry *h, struct bfd_link_hash_entry *inh, bfd *abfd, asection *section, bfd_vma value, flagword flags) { struct bfd_link_hash_entry *orig_h = h; if (h != NULL) { bfd *sym_bfd; if (h->type == bfd_link_hash_warning) h = h->u.i.link; /* Nothing to do here if this def/ref is from an IR dummy BFD. */ if (is_ir_dummy_bfd (abfd)) ; /* Making an indirect symbol counts as a reference unless this is a brand new symbol. */ else if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) { /* ??? Some of this is questionable. See comments in _bfd_generic_link_add_one_symbol for case IND. */ if (h->type != bfd_link_hash_new) { h->non_ir_ref = TRUE; inh->non_ir_ref = TRUE; } else if (inh->type == bfd_link_hash_new) inh->non_ir_ref = TRUE; } /* Nothing to do here for warning symbols. */ else if ((flags & BSF_WARNING) != 0) ; /* Nothing to do here for constructor symbols. */ else if ((flags & BSF_CONSTRUCTOR) != 0) ; /* If this is a ref, set non_ir_ref. */ else if (bfd_is_und_section (section)) { /* Replace the undefined dummy bfd with the real one. */ if ((h->type == bfd_link_hash_undefined || h->type == bfd_link_hash_undefweak) && (h->u.undef.abfd == NULL || (h->u.undef.abfd->flags & BFD_PLUGIN) != 0)) h->u.undef.abfd = abfd; h->non_ir_ref = TRUE; } /* Otherwise, it must be a new def. */ else { /* A common symbol should be merged with other commons or defs with the same name. In particular, a common ought to be overridden by a def in a -flto object. In that sense a common is also a ref. */ if (bfd_is_com_section (section)) h->non_ir_ref = TRUE; /* Ensure any symbol defined in an IR dummy BFD takes on a new value from a real BFD. Weak symbols are not normally overridden by a new weak definition, and strong symbols will normally cause multiple definition errors. Avoid this by making the symbol appear to be undefined. */ if (((h->type == bfd_link_hash_defweak || h->type == bfd_link_hash_defined) && is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner)) || (h->type == bfd_link_hash_common && is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner))) { h->type = bfd_link_hash_undefweak; h->u.undef.abfd = sym_bfd; } } } /* Continue with cref/nocrossref/trace-sym processing. */ if (orig_h == NULL || orig_notice_all || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, orig_h->root.string, FALSE, FALSE) != NULL)) return (*orig_callbacks->notice) (info, orig_h, inh, abfd, section, value, flags); return TRUE; }
static void NAME(lynx,swap_std_reloc_out) (bfd *abfd, arelent *g, struct reloc_std_external *natptr) { int r_index; asymbol *sym = *(g->sym_ptr_ptr); int r_extern; unsigned int r_length; int r_pcrel; int r_baserel, r_jmptable, r_relative; asection *output_section = sym->section->output_section; PUT_WORD (abfd, g->address, natptr->r_address); r_length = g->howto->size; /* Size as a power of two */ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */ /* r_baserel, r_jmptable, r_relative??? FIXME-soon */ r_baserel = 0; r_jmptable = 0; r_relative = 0; /* name was clobbered by aout_write_syms to be symbol index */ /* If this relocation is relative to a symbol then set the r_index to the symbols index, and the r_extern bit. Absolute symbols can come in in two ways, either as an offset from the abs section, or as a symbol which has an abs value. check for that here */ if (bfd_is_com_section (output_section) || bfd_is_abs_section (output_section) || bfd_is_und_section (output_section)) { if (bfd_abs_section_ptr->symbol == sym) { /* Whoops, looked like an abs symbol, but is really an offset from the abs section */ r_index = 0; r_extern = 0; } else { /* Fill in symbol */ r_extern = 1; r_index = (*g->sym_ptr_ptr)->KEEPIT; } } else { /* Just an ordinary section */ r_extern = 0; r_index = output_section->target_index; } /* now the fun stuff */ if (bfd_header_big_endian (abfd)) { natptr->r_index[0] = r_index >> 16; natptr->r_index[1] = r_index >> 8; natptr->r_index[2] = r_index; natptr->r_type[0] = (r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0) | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0) | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0) | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0) | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0) | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG); } else {
bfd_reloc_status_type pmbfd_perform_relocation(bfd *abfd, pmbfd_arelent *r, asymbol *psym, asection *input_section) { Elf32_Word pc; int64_t val, msk; int32_t oval,nval; int16_t sval; int8_t bval; int64_t llim,ulim; Elf32_Rela *rela = &r->rela32; uint8_t type = ELF32_R_TYPE(rela->r_info); struct sparc_rel_desc *dsc; if ( R_SPARC_NONE == type ) { /* No-op; BFD uses a zero dst_mask... */ return bfd_reloc_ok; } /* use R_SPARC_NONE as a dummy for 'unsupported' */ dsc = type >= sizeof(sparc_rels) ? &sparc_rels[R_SPARC_NONE] : &sparc_rels[type]; if ( 0 == dsc->nbytes ) { ERRPR("pmbfd_perform_relocation_sparc(): unsupported relocation type : %"PRIu8"\n", type); return bfd_reloc_notsupported; } if ( bfd_is_und_section(bfd_get_section(psym)) ) return bfd_reloc_undefined; pc = bfd_get_section_vma(abfd, input_section) + rela->r_offset; if ( ! dsc->unaligned && (pc & (dsc->nbytes - 1)) ) { ERRPR("pmbfd_perform_relocation_sparc(): location to relocate (0x%08"PRIx32") not properly aligned\n", pc); return bfd_reloc_other; } val = (int64_t)bfd_asymbol_value(psym) + (int64_t)rela->r_addend; if ( dsc->pc_relative ) val -= (int64_t)pc; val >>= dsc->shift; /* works also if the left shift is 32 */ msk = (1LL << dsc->width); msk--; switch ( dsc->sparc_rel_check ) { default: case sparc_rel_check_none: ulim = ~(1LL<<63); llim = ~ulim; break; case sparc_rel_check_unsg: ulim = msk; llim = 0; break; case sparc_rel_check_bits: ulim = msk; llim = ~ulim; break; case sparc_rel_check_sign: ulim = msk>>1; llim = ~ulim; break; } #if (DEBUG & DEBUG_RELOC) fprintf(stderr,"Relocating val: 0x%08"PRIx64", ulim: 0x%08"PRIx64", pc: 0x%08"PRIx32", sym: 0x%08lx\n", val, ulim, pc, bfd_asymbol_value(psym)); #endif if ( val < llim || val > ulim ) { return bfd_reloc_overflow; } if ( 1 == dsc->nbytes ) { memcpy(&bval, (void*)pc, sizeof(bval)); oval = bval; } else if ( 2 == dsc->nbytes ) { memcpy(&sval, (void*)pc, sizeof(sval)); oval = sval; } else { memcpy(&oval, (void*)pc, sizeof(oval)); } nval = ( oval & ~msk ) | (val & msk); /* patch back */ if ( 1 == dsc->nbytes ) { bval = nval; memcpy((void*)pc, &bval, sizeof(bval)); } else if ( 2 == dsc->nbytes ) { sval = nval; memcpy((void*)pc, &sval, sizeof(sval)); } else { memcpy((void*)pc, &nval, sizeof(nval)); } return bfd_reloc_ok; }
int _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) { asection *section; asymbol *symbol; unsigned int symnum; int last_index = -1; char dummy_name[10]; char *sname; flagword new_flags, old_flags; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); #endif /* Output sections. */ section = abfd->sections; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "%d sections found\n", abfd->section_count); #endif /* Egsd is quadword aligned. */ _bfd_vms_output_alignment (abfd, 8); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); while (section != 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size); #endif /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ if (_bfd_vms_output_check (abfd, 64) < 0) { _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); } /* Create dummy sections to keep consecutive indices. */ while (section->index - last_index > 1) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "index %d, last %d\n", section->index, last_index); #endif _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); _bfd_vms_output_short (abfd, 0); _bfd_vms_output_short (abfd, 0); _bfd_vms_output_long (abfd, 0); sprintf (dummy_name, ".DUMMY%02d", last_index); _bfd_vms_output_counted (abfd, dummy_name); _bfd_vms_output_flush (abfd); last_index++; } /* Don't know if this is necessary for the linker but for now it keeps vms_slurp_gsd happy */ sname = (char *)section->name; if (*sname == '.') { sname++; if ((*sname == 't') && (strcmp (sname, "text") == 0)) sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME; else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME; else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) sname = EVAX_BSS_NAME; else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) sname = EVAX_LINK_NAME; else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) sname = EVAX_READONLY_NAME; else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) sname = EVAX_LITERAL_NAME; else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) sname = EVAX_COMMON_NAME; else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) sname = EVAX_LOCAL_NAME; } else sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); _bfd_vms_output_short (abfd, section->alignment_power & 0xff); if (bfd_is_com_section (section)) new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM); else new_flags = vms_esecflag_by_name (evax_section_flags, sname, section->size > 0); _bfd_vms_output_short (abfd, new_flags); _bfd_vms_output_long (abfd, (unsigned long) section->size); _bfd_vms_output_counted (abfd, sname); _bfd_vms_output_flush (abfd); last_index = section->index; section = section->next; } /* Output symbols. */ #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "%d symbols found\n", abfd->symcount); #endif bfd_set_start_address (abfd, (bfd_vma) -1); for (symnum = 0; symnum < abfd->symcount; symnum++) { char *hash; symbol = abfd->outsymbols[symnum]; if (*(symbol->name) == '_') { if (strcmp (symbol->name, "__main") == 0) bfd_set_start_address (abfd, (bfd_vma)symbol->value); } old_flags = symbol->flags; if (old_flags & BSF_FILE) continue; if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0) /* Not xdef... */ && (!bfd_is_und_section (symbol->section))) /* ...and not xref. */ continue; /* Dont output. */ /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */ if (_bfd_vms_output_check (abfd, 80) < 0) { _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); } _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1); /* Data type, alignment. */ _bfd_vms_output_short (abfd, 0); new_flags = 0; if (old_flags & BSF_WEAK) new_flags |= EGSY_S_V_WEAK; if (bfd_is_com_section (symbol->section)) new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM); if (old_flags & BSF_FUNCTION) { new_flags |= EGSY_S_V_NORM; new_flags |= EGSY_S_V_REL; } if (old_flags & (BSF_GLOBAL | BSF_WEAK)) { new_flags |= EGSY_S_V_DEF; if (!bfd_is_abs_section (symbol->section)) new_flags |= EGSY_S_V_REL; } _bfd_vms_output_short (abfd, new_flags); if (old_flags & (BSF_GLOBAL | BSF_WEAK)) { /* Symbol definition. */ uquad code_address = 0; unsigned long ca_psindx = 0; unsigned long psindx; if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) { code_address = ((asymbol *) (symbol->udata.p))->value; ca_psindx = ((asymbol *) (symbol->udata.p))->section->index; } psindx = symbol->section->index; _bfd_vms_output_quad (abfd, symbol->value); _bfd_vms_output_quad (abfd, code_address); _bfd_vms_output_long (abfd, ca_psindx); _bfd_vms_output_long (abfd, psindx); } hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ); _bfd_vms_output_counted (abfd, hash); _bfd_vms_output_flush (abfd); } _bfd_vms_output_alignment (abfd, 8); _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); return 0; }
/* * Implementation */ void jit_init_debug(const char *progname) { #if DISASSEMBLER bfd_init(); if (progname) disasm_bfd = bfd_openr(progname, NULL); if (disasm_bfd == NULL) { #if defined(__linux__) disasm_bfd = bfd_openr("/proc/self/exe", NULL); if (disasm_bfd == NULL) #endif return; } bfd_check_format(disasm_bfd, bfd_object); bfd_check_format(disasm_bfd, bfd_archive); disasm_print = disassembler(disasm_bfd); assert(disasm_print); INIT_DISASSEMBLE_INFO(disasm_info, disasm_stream, fprintf); # if defined(__i386__) || defined(__x86_64__) disasm_info.arch = bfd_arch_i386; # if defined(__x86_64__) # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_x64_32; # else disasm_info.mach = bfd_mach_x86_64; # endif # else disasm_info.mach = bfd_mach_i386_i386; # endif # endif # if defined(__powerpc__) disasm_info.arch = bfd_arch_powerpc; disasm_info.mach = bfd_mach_ppc64; # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # if defined(__powerpc64__) disasm_info.disassembler_options = "64"; # endif # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # endif # if defined(__sparc__) disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; # endif # if defined(__s390__) || defined(__s390x__) disasm_info.arch = bfd_arch_s390; # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_s390_31; # else disasm_info.mach = bfd_mach_s390_64; # endif disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; disasm_info.disassembler_options = "zarch"; # endif # if defined(__alpha__) disasm_info.arch = bfd_arch_alpha; disasm_info.mach = bfd_mach_alpha_ev6; # endif disasm_info.print_address_func = disasm_print_address; if (bfd_get_file_flags(disasm_bfd) & HAS_SYMS) { asymbol **in; asymbol **out; asymbol *symbol; long offset; long sym_count; long dyn_count; long sym_storage; long dyn_storage; if ((sym_storage = bfd_get_symtab_upper_bound(disasm_bfd)) >= 0) { if (bfd_get_file_flags(disasm_bfd) & DYNAMIC) { dyn_storage = bfd_get_dynamic_symtab_upper_bound(disasm_bfd); # if defined(__alpha__) /* XXX */ if (dyn_storage < 0) dyn_storage = 0; # else assert(dyn_storage >= 0); # endif } else dyn_storage = 0; jit_alloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *)); sym_count = bfd_canonicalize_symtab(disasm_bfd, disasm_symbols); assert(sym_count >= 0); if (dyn_storage) { dyn_count = bfd_canonicalize_dynamic_symtab(disasm_bfd, disasm_symbols + sym_count); assert(dyn_count >= 0); } else dyn_count = 0; disasm_num_symbols = sym_count + dyn_count; disasm_num_synthetic = bfd_get_synthetic_symtab(disasm_bfd, sym_count, disasm_symbols, dyn_count, disasm_symbols + sym_count, &disasm_synthetic); if (disasm_num_synthetic > 0) { jit_realloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *), (sym_storage + dyn_storage + disasm_num_synthetic) * sizeof(asymbol *)); for (offset = 0; offset < disasm_num_synthetic; offset++) disasm_symbols[disasm_num_symbols++] = disasm_synthetic + offset; } /* remove symbols not useful for disassemble */ in = out = disasm_symbols; for (offset = 0; offset < disasm_num_symbols; offset++) { symbol = *in++; if (symbol->name && symbol->name[0] != '\0' && !(symbol->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) && !bfd_is_und_section(symbol->section) && !bfd_is_com_section(symbol->section)) *out++ = symbol; } disasm_num_symbols = out - disasm_symbols; qsort(disasm_symbols, disasm_num_symbols, sizeof(asymbol *), disasm_compare_symbols); } } #endif }