Skip to content

Commit

Permalink
Add jpt_end symbol for jpt in middle of code
Browse files Browse the repository at this point in the history
  • Loading branch information
Gillou68310 committed Feb 12, 2025
1 parent 93420e8 commit bb481af
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 28 deletions.
120 changes: 92 additions & 28 deletions bfd/i386omf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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<<bfd_get_reloc_size (relent->base.howto);
}
else if(size != 0)
{
if (relent->base.address == jpt_offset+size)
size += 1<<bfd_get_reloc_size (relent->base.howto);
else
return size;
}
}
return size;
}

static bool
add_fake_jump_table_sym (bfd *abfd)
{
Expand All @@ -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);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions binutils/objdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit bb481af

Please sign in to comment.