89 lines
2.8 KiB
C++
89 lines
2.8 KiB
C++
/*
|
|
Android specific functions.
|
|
*/
|
|
|
|
// r_brk():
|
|
// B0003050 70 47 BX LR
|
|
static const uchar bxlr_thumb[] = { 0x70, 0x47 };
|
|
|
|
#define LINKER "/system/bin/linker"
|
|
|
|
//--------------------------------------------------------------------------
|
|
// on android /system/bin/linker comes without any symbols.
|
|
// Since there is no other way, we scan the data segment for
|
|
// dcd 1, ?, r_brk, 0, 0
|
|
// r_debug is located very close to the beginning of the data segment,
|
|
// we should find it fine. In any case, we check only the first 4KB.
|
|
bool linux_debmod_t::add_android_shlib_bpt(const meminfo_vec_t &miv, bool attaching)
|
|
{
|
|
// find read/writable linker memory range
|
|
meminfo_vec_t::const_iterator p;
|
|
ea_t linker_base = BADADDR;
|
|
for ( p=miv.begin(); p != miv.end(); ++p )
|
|
{
|
|
if ( p->name == LINKER )
|
|
{
|
|
if ( linker_base == BADADDR )
|
|
linker_base = p->start_ea;
|
|
// assume the data segment to be readable and writable
|
|
if ( (p->perm & 6) == 6 )
|
|
break;
|
|
}
|
|
}
|
|
if ( p == miv.end() )
|
|
{
|
|
msg("Failed to find data segment of " LINKER "\n");
|
|
return false;
|
|
}
|
|
|
|
// read max 2KB
|
|
uint32 buf[2048];
|
|
int nbytes = qmin(p->size(), sizeof(buf));
|
|
ea_t dataseg = p->start_ea;
|
|
nbytes = dbg_read_memory(dataseg, buf, nbytes, NULL);
|
|
|
|
uint32 *ptr = buf;
|
|
for ( int i=0; i < nbytes/4-5; i++, ptr++ )
|
|
{
|
|
if ( ptr[0] == 1 // version
|
|
&& (attaching || ptr[1] == 0) // r_map, 0 at the beginning
|
|
&& (ptr[2] & 1) != 0 && ptr[2] < dataseg // r_brk (Thumb pointer)
|
|
&& (attaching || ptr[3] == 0) // r_state: RT_CONSISTENT
|
|
&& ptr[4] == 0 ) // linker baseaddr: always zero?
|
|
{
|
|
ea_t r_brk = ptr[2] & ~1;
|
|
// check if linker is not relocated yet
|
|
if ( r_brk < linker_base )
|
|
r_brk += linker_base; // adjust address
|
|
uchar opcode[2];
|
|
if ( dbg_read_memory(r_brk, opcode, 2, NULL) == 2
|
|
&& memcmp(opcode, bxlr_thumb, 2) == 0 )
|
|
{
|
|
// found it!
|
|
if ( add_internal_bp(shlib_bpt, r_brk+1) )
|
|
{
|
|
dmsg("found r_debug (r_brk=%a)\n", r_brk);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
msg("Failed to find r_debug in " LINKER "\n");
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Android reports shared objects without any path. Try to find full path.
|
|
void linux_debmod_t::make_android_abspath(qstring *in_out_path)
|
|
{
|
|
if ( qisabspath(in_out_path->c_str()) )
|
|
return;
|
|
|
|
// Apparently /proc didn't return an absolute path. Check /system/lib.
|
|
// Normally we should not arrive here, this is just for safety.
|
|
char path[QMAXPATH];
|
|
qmakepath(path, sizeof(path), "/system/lib", in_out_path->c_str(), NULL);
|
|
if ( qfileexist(path) )
|
|
*in_out_path = path;
|
|
}
|