A good friend has started reversing an old 16bit Borland C++ (3.1?) program, and had lots of stack push data segment offsets that were not correctly cross referencing.
After telling him the shortcuts for manually fixing the issue (press O for the data segment, or Alt-R for any segment offset), he wrote an IDC script to do it en mass.
Thus (made up example code)
push ds;
mov ax, 0x1234;
push ax
should look like:
push ds;
mov ax, ds:dword_1234;
push ax
Here’s his script:
#include <idc.idc>
static main()
{
auto seg, loc;
auto movloc, movtarget;
auto xref;
auto dsegbase;
dsegbase = SegByName("dseg") * 16;
Message("dsegbase=%x\\n", dsegbase);
Message("========================================\\n");
seg = FirstSeg();
while(seg != BADADDR )
{
Message("----------------------------------------\\n");
loc = SegStart(seg);
if( Byte(loc) != 0xCD || Byte(loc+1) != 0x3F)
{
Message("Fixing indirect push [ds:xx] refs from %s\\n", SegName(seg));
while(loc != BADADDR && loc < SegEnd(seg))
{
if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != "ds")
{
loc = NextHead(loc, BADADDR);
continue;
}
loc = NextHead(loc, BADADDR);
if (GetMnem(loc) != "mov" || GetOpType(loc, 1) != o_imm)
{
loc = NextHead(loc, BADADDR);
continue;
}
movloc = loc;
movtarget = GetOpnd(movloc, 0);
loc = NextHead(loc, BADADDR);
if (GetMnem(loc) != "push" || GetOpnd(loc, 0) != movtarget)
{
continue;
}
// At this point, we know we're pushing a [ds:x] combo.
//Message("%x: mov %s, %s\\n", movloc, movtarget, GetOpnd(movloc, 1));
// Abort if there already exists a Dxref
xref = Dfirst(movloc);
if (xref != BADADDR)
{
continue;
}
Message(" Updating %s:%04x\\n", SegName(seg), (movloc - seg) & 0xffff);
OpOff(movloc, 1, dsegbase);
}
}
seg = NextSeg(seg);
}
}