[lldb-dev] Further Linux adventures
Greg Clayton
gclayton at apple.com
Thu Oct 27 09:54:45 PDT 2011
On Oct 26, 2011, at 3:34 PM, Joel Dillon wrote:
> I now have lldb compiling and attempting to execute a program. There seems to be an assumption in the code that sizeof(int) is 8 on a 64 bit platform. This is not the case with Linux/gcc 4.6, leading to some rather nasty bugs (the return value of ptrace() was being assigned to an int, truncating data from peeks, for instance!). I've fixed the ptrace() issue but another one is happening somewhere around breakpoints. I added some logging which displays the problem -
>
> Process 4017 launched: '/home/jo/reader/calliope' (x86_64)
> (lldb) Looking for address 406780, list size is 1
> Entry 0 is 406780 sizeof 8
> Looking for address 270f9300, list size is 2
> Entry 0 is 406780 sizeof 8
> Entry 1 is 7ffb270f9300 sizeof 8
> lldb: /home/jo/lldb/llvm/tools/lldb/source/Plugins/Process/Linux/LinuxThread.cpp:249: void LinuxThread::BreakNotify(const ProcessMessage&): Assertion `bp_site' failed.
>
> Clearly the second breakpoint address is being truncated down to 32 bits somewhere in the code. Before I go spelunking in the Linux subdirectories, is sizeof(int)==8 something that the development team is assuming based on MacOS X? If so, after all, it would be more worth my time to make gcc comply with the OS X definition.
No it isn't. "int" is 4 bytes on MacOSX. We have 4 byte ints, 8 byte longs, and 8 byte long longs.
The darwin ptrace call looks from <sys/ptrace.h> looks like:
int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
I never try to use "int" "long" as types when programming in LLDB and we would try to exclusively use "uint*_t" and "int*_t" where the type is explicit. The only exception to the rule is if you are wrapping an API (like say "ptrace") where it returns a specific type in the header file ("int" in our header file). If the return types differ from system to system, we should templatize the code the uses it.
So overall we should try to use the explicitly sized integer typedefs from stdint.h (uint8_t, uint16_t, uint32_t, etc) to avoid any such issues. It sounds like there are some issues in the Linux plug-in. The function is:
void
LinuxThread::BreakNotify(const ProcessMessage &message)
{
bool status;
LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD));
assert(GetRegisterContextLinux());
status = GetRegisterContextLinux()->UpdateAfterBreakpoint();
assert(status && "Breakpoint update failed!");
// With our register state restored, resolve the breakpoint object
// corresponding to our current PC.
assert(GetRegisterContext());
lldb::addr_t pc = GetRegisterContext()->GetPC();
if (log)
log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc);
lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
assert(bp_site);
lldb::break_id_t bp_id = bp_site->GetID();
assert(bp_site && bp_site->ValidForThisThread(this));
m_breakpoint = bp_site;
m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
}
Liiks like the PC is read from the register context and there doesn't seem to be a breakpoint site. Enable the logging before you run:
(lldb) log enable plugin.process.linux thread
(lldb) run
This should cause the PC to be logged. Then you should check that a software breakpoint was indeed set at this location. You might also want to verify that no one removed the breakpoint site after stopping?
More information about the lldb-dev
mailing list