diff --git a/bfd/i386omf.c b/bfd/i386omf.c index f211a8c914e..076d81465cf 100644 --- a/bfd/i386omf.c +++ b/bfd/i386omf.c @@ -971,6 +971,8 @@ i386omf_read_segdef(bfd *abfd, bfd_byte const *p, bfd_size_type reclen, int is32 char const *segment_name; bfd_vma absolute_addr, seglen; bfd_byte attr; + int seg_count; + char *seg_name; attr = *p; @@ -1034,6 +1036,7 @@ i386omf_read_segdef(bfd *abfd, bfd_byte const *p, bfd_size_type reclen, int is32 if (seg->linnums == NULL) return false; + seg_count = strtab_size(tdata->segdef); strtab_add(tdata->segdef, seg); segment_name = i386omf_lookup_string(tdata->lnames, @@ -1044,13 +1047,14 @@ i386omf_read_segdef(bfd *abfd, bfd_byte const *p, bfd_size_type reclen, int is32 return false; } - seg->asect = bfd_make_section_anyway(abfd, segment_name); + seg_name = bfd_alloc(abfd, strlen(segment_name)+16); + sprintf(seg_name, "%s%d", segment_name, seg_count); + seg->asect = bfd_make_section_anyway(abfd, seg_name); seg_sym = (struct i386omf_symbol *) seg->asect->symbol; - seg_sym->name.len = strlen(segment_name); - seg_sym->name.data = bfd_alloc(abfd, seg_sym->name.len + 1); + seg_sym->name.len = strlen(seg_name); + seg_sym->name.data = seg_name; if (seg_sym->name.data == NULL) return false; - strcpy(seg_sym->name.data, segment_name); seg_sym->type_index = 0; seg_sym->seg = seg; seg_sym->group = NULL; @@ -1838,6 +1842,34 @@ i386omf_teardown_tdata (bfd *abfd) #endif } +static int +find_jump_table_size (struct i386omf_relent *relocs, int jpt_offset) +{ + struct i386omf_relent *relent; + int i; + int size = 0; + + /*Assume relocs are ordered by addr*/ + for (i = 0; (relent = strtab_lookup (relocs, i)) != NULL; i++) + { + if (relent->base.howto->type == R_I386OMF_WRT_FRAME) + continue; + + if (relent->base.address == jpt_offset) + { + size = 1<base.howto); + } + else if(size != 0) + { + if (relent->base.address == jpt_offset+size) + size += 1<base.howto); + else + return size; + } + } + return size; +} + static bool add_fake_jump_table_sym (bfd *abfd) { @@ -1852,34 +1884,66 @@ add_fake_jump_table_sym (bfd *abfd) { for (j = 0; (relent = strtab_lookup (seg->relocs, j)) != NULL; j++) { - /*OFF16 CODE_SEGMENT_TEXT*/ - if (relent->base.howto->type == R_I386OMF_OFF16 && - !relent->base.howto->pc_relative && - !strcmp(relent->symbol->name, seg->asect->name)) - { - pp = &seg->asect->contents[relent->base.address]; + if (relent->base.howto->type != R_I386OMF_OFF16 && relent->base.howto->type != R_I386OMF_OFF32) + continue; + + if (relent->base.howto->pc_relative || strcmp(relent->symbol->name, seg->asect->name)) + continue; + + pp = &seg->asect->contents[relent->base.address]; - /*jmp *%cs:offset(%reg)*/ - if(bfd_get_8(abfd, pp-3) != 0x2E) /*cs prefix*/ - continue; - if(bfd_get_8(abfd, pp-2) != 0xFF) /*jmp*/ - continue; + /*jmp *%cs:offset(%reg)*/ + if(bfd_get_8(abfd, pp-3) != 0x2E) /*cs prefix*/ + continue; + if(bfd_get_8(abfd, pp-2) != 0xFF) /*jmp*/ + continue; + + pubdef = (struct i386omf_symbol *) bfd_make_empty_symbol (abfd); + pubdef->base.name = bfd_alloc (abfd, 32); + if (pubdef->base.name == NULL) + continue; + if (relent->base.howto->type == R_I386OMF_OFF16) + { offset = bfd_get_16(abfd, pp); - pubdef = (struct i386omf_symbol *) bfd_make_empty_symbol (abfd); - - pubdef->base.name = bfd_alloc (abfd, 16); - if (pubdef->base.name == NULL) - break; - - sprintf(pubdef->base.name, "jpt_%.4X", offset); - pubdef->base.flags |= BSF_OBJECT; - pubdef->base.value = offset; - pubdef->seg = seg; - pubdef->base.section = pubdef->seg->asect; - pubdef->group = NULL; /*TODO?*/ - strtab_add (seg->pubdef, pubdef); + sprintf(pubdef->base.name, "jpt_%.4X_start", offset); + } + else + { + offset = bfd_get_32(abfd, pp); + sprintf(pubdef->base.name, "jpt_%.8X_start", offset); } + + pubdef->name.data = pubdef->base.name; + pubdef->name.len = strlen(pubdef->base.name); + pubdef->base.flags |= BSF_OBJECT; + pubdef->base.value = offset; + pubdef->seg = seg; + pubdef->base.section = pubdef->seg->asect; + pubdef->group = NULL; /*TODO?*/ + strtab_add (seg->pubdef, pubdef); + + offset = find_jump_table_size(seg->relocs, offset); + offset += pubdef->base.value; + + pubdef = (struct i386omf_symbol *) bfd_make_empty_symbol (abfd); + pubdef->base.name = bfd_alloc (abfd, 32); + if (pubdef->base.name == NULL) + continue; + + if (relent->base.howto->type == R_I386OMF_OFF16) + sprintf(pubdef->base.name, "jpt_%.4X_end", offset); + else + sprintf(pubdef->base.name, "jpt_%.8X_end", offset); + + pubdef->name.data = pubdef->base.name; + pubdef->name.len = strlen(pubdef->base.name); + pubdef->base.flags |= BSF_FUNCTION; + pubdef->base.value = offset; + pubdef->seg = seg; + pubdef->base.section = pubdef->seg->asect; + pubdef->group = NULL; /*TODO?*/ + strtab_add (seg->pubdef, pubdef); } } } diff --git a/binutils/objdump.c b/binutils/objdump.c index 143c3aef9e8..1cf631190cc 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -3991,6 +3991,7 @@ disassemble_section (bfd *abfd, asection *section, void *inf) #define is_valid_next_sym(SYM) \ (strcmp (bfd_section_name ((SYM)->section), bfd_section_name (section)) == 0 \ && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \ + /*&& (sym_ok (true, abfd, place, section, inf))*/ \ && pinfo->symbol_is_valid (SYM, pinfo)) /* Search forward for the next appropriate symbol in