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; }
static long get_symbol_value (asymbol *symbol) { long relocation = 0; if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value + symbol->section->output_section->vma + symbol->section->output_offset; return relocation; }
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; }
/* 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 {
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; }
/* This is just like the standard perform_relocation except we * use get_data and put_data which know about the ns32k * storage methods. * This is probably a lot more complicated than it needs to be! */ static bfd_reloc_status_type do_ns32k_reloc (bfd *abfd, arelent *reloc_entry, struct symbol_cache_entry *symbol, PTR data, asection *input_section, bfd *output_bfd, char **error_message, long (*get_data)(), int (*put_data)()) { int overflow = 0; bfd_vma relocation; bfd_reloc_status_type flag = bfd_reloc_ok; bfd_size_type addr = reloc_entry->address; bfd_vma output_base = 0; const reloc_howto_type *howto = reloc_entry->howto; asection *reloc_target_output_section; if ((symbol->section == &bfd_abs_section) && output_bfd != (bfd *) NULL) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* If we are not producing relocateable output, return an error if the symbol is not defined. An undefined weak symbol is considered to have a value of zero (SVR4 ABI, p. 4-27). */ if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0 && output_bfd == (bfd *) NULL) flag = bfd_reloc_undefined; /* Is the address of the relocation really within the section? */ if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; /* Work out which section the relocation is targetted at and the initial relocation command value. */ /* Get symbol value. (Common symbols are special.) */ if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value; reloc_target_output_section = symbol->section->output_section; /* Convert input-section-relative symbol value to absolute. */ if (output_bfd && howto->partial_inplace == false) output_base = 0; else output_base = reloc_target_output_section->vma; relocation += output_base + symbol->section->output_offset; /* Add in supplied addend. */ relocation += reloc_entry->addend; /* Here the variable relocation holds the final address of the symbol we are relocating against, plus any addend. */ if (howto->pc_relative == true) { /* This is a PC relative relocation. We want to set RELOCATION to the distance between the address of the symbol and the location. RELOCATION is already the address of the symbol. We start by subtracting the address of the section containing the location. If pcrel_offset is set, we must further subtract the position of the location within the section. Some targets arrange for the addend to be the negative of the position of the location within the section; for example, i386-aout does this. For i386-aout, pcrel_offset is false. Some other targets do not include the position of the location; for example, m88kbcs, or ELF. For those targets, pcrel_offset is true. If we are producing relocateable output, then we must ensure that this reloc will be correctly computed when the final relocation is done. If pcrel_offset is false we want to wind up with the negative of the location within the section, which means we must adjust the existing addend by the change in the location within the section. If pcrel_offset is true we do not want to adjust the existing addend at all. FIXME: This seems logical to me, but for the case of producing relocateable output it is not what the code actually does. I don't want to change it, because it seems far too likely that something will break. */ relocation -= input_section->output_section->vma + input_section->output_offset; if (howto->pcrel_offset == true) relocation -= reloc_entry->address; } if (output_bfd != (bfd *) NULL) { if (howto->partial_inplace == false) { /* This is a partial relocation, and we want to apply the relocation to the reloc entry rather than the raw data. Modify the reloc inplace to reflect what we now know. */ reloc_entry->addend = relocation; reloc_entry->address += input_section->output_offset; return flag; } else { /* This is a partial relocation, but inplace, so modify the reloc record a bit. If we've relocated with a symbol with a section, change into a ref to the section belonging to the symbol. */ reloc_entry->address += input_section->output_offset; /* WTF?? */ if (abfd->xvec->flavour == bfd_target_coff_flavour && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 0) { #if 1 /* For m68k-coff, the addend was being subtracted twice during relocation with -r. Removing the line below this comment fixes that problem; see PR 2953. However, Ian wrote the following, regarding removing the line below, which explains why it is still enabled: --djm If you put a patch like that into BFD you need to check all the COFF linkers. I am fairly certain that patch will break coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c where I worked around the problem in a different way. There may very well be a reason that the code works as it does. Hmmm. The first obvious point is that bfd_perform_relocation should not have any tests that depend upon the flavour. It's seem like entirely the wrong place for such a thing. The second obvious point is that the current code ignores the reloc addend when producing relocateable output for COFF. That's peculiar. In fact, I really have no idea what the point of the line you want to remove is. A typical COFF reloc subtracts the old value of the symbol and adds in the new value to the location in the object file (if it's a pc relative reloc it adds the difference between the symbol value and the location). When relocating we need to preserve that property. BFD handles this by setting the addend to the negative of the old value of the symbol. Unfortunately it handles common symbols in a non-standard way (it doesn't subtract the old value) but that's a different story (we can't change it without losing backward compatibility with old object files) (coff-i386 does subtract the old value, to be compatible with existing coff-i386 targets, like SCO). So everything works fine when not producing relocateable output. When we are producing relocateable output, logically we should do exactly what we do when not producing relocateable output. Therefore, your patch is correct. In fact, it should probably always just set reloc_entry->addend to 0 for all cases, since it is, in fact, going to add the value into the object file. This won't hurt the COFF code, which doesn't use the addend; I'm not sure what it will do to other formats (the thing to check for would be whether any formats both use the addend and set partial_inplace). When I wanted to make coff-i386 produce relocateable output, I ran into the problem that you are running into: I wanted to remove that line. Rather than risk it, I made the coff-i386 relocs use a special function; it's coff_i386_reloc in coff-i386.c. The function specifically adds the addend field into the object file, knowing that bfd_perform_relocation is not going to. If you remove that line, then coff-i386.c will wind up adding the addend field in twice. It's trivial to fix; it just needs to be done. The problem with removing the line is just that it may break some working code. With BFD it's hard to be sure of anything. The right way to deal with this is simply to build and test at least all the supported COFF targets. It should be straightforward if time and disk space consuming. For each target: 1) build the linker 2) generate some executable, and link it using -r (I would probably use paranoia.o and link against newlib/libc.a, which for all the supported targets would be available in /usr/cygnus/progressive/H-host/target/lib/libc.a). 3) make the change to reloc.c 4) rebuild the linker 5) repeat step 2 6) if the resulting object files are the same, you have at least made it no worse 7) if they are different you have to figure out which version is right */ relocation -= reloc_entry->addend; #endif reloc_entry->addend = 0; } else { reloc_entry->addend = relocation; } } } else { reloc_entry->addend = 0; } /* FIXME: This overflow checking is incomplete, because the value might have overflowed before we get here. For a correct check we need to compute the value in a size larger than bitsize, but we can't reasonably do that for a reloc the same size as a host machine word. FIXME: We should also do overflow checking on the result after adding in the value contained in the object file. */ if (howto->complain_on_overflow != complain_overflow_dont) { bfd_vma check; /* Get the value that will be used for the relocation, but starting at bit position zero. */ if (howto->rightshift > howto->bitpos) check = relocation >> (howto->rightshift - howto->bitpos); else
/* * 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 }