Skip to content

Commit

Permalink
Handle non-returning system calls.
Browse files Browse the repository at this point in the history
  • Loading branch information
emilygemberjacobson committed Feb 13, 2015
1 parent 30b1cb3 commit 23a5a76
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 153 deletions.
1 change: 1 addition & 0 deletions common/h/dyn_regs.h
Expand Up @@ -90,6 +90,7 @@ namespace Dyninst
static MachRegister getFramePointer(Dyninst::Architecture arch);
static MachRegister getStackPointer(Dyninst::Architecture arch);
static MachRegister getSyscallNumberReg(Dyninst::Architecture arch);
static MachRegister getSyscallNumberOReg(Dyninst::Architecture arch);
static MachRegister getSyscallReturnValueReg(Dyninst::Architecture arch);
bool isPC() const;
bool isFramePointer() const;
Expand Down
18 changes: 18 additions & 0 deletions common/src/dyn_regs.C
Expand Up @@ -254,6 +254,24 @@ MachRegister MachRegister::getStackPointer(Dyninst::Architecture arch)
}

MachRegister MachRegister::getSyscallNumberReg(Dyninst::Architecture arch)
{
switch (arch)
{
case Arch_x86:
return x86::eax;
case Arch_x86_64:
return x86_64::rax;
case Arch_ppc32:
return ppc32::r0;
case Arch_ppc64:
return ppc64::r0;
case Arch_none:
return InvalidReg;
}
return InvalidReg;
}

MachRegister MachRegister::getSyscallNumberOReg(Dyninst::Architecture arch)
{
switch (arch)
{
Expand Down
1 change: 1 addition & 0 deletions instructionAPI/h/InstructionCategories.h
Expand Up @@ -46,6 +46,7 @@ namespace Dyninst
c_CompareInsn,
c_PrefetchInsn,
c_SysEnterInsn,
c_SyscallInsn,
c_NoCategory
};
INSTRUCTION_EXPORT InsnCategory entryToCategory(entryID e);
Expand Down
2 changes: 2 additions & 0 deletions instructionAPI/src/InstructionCategories.C
Expand Up @@ -98,6 +98,8 @@ namespace Dyninst
return c_BranchInsn;
case e_sysenter:
return c_SysEnterInsn;
case e_syscall:
return c_SyscallInsn;
default:
return c_NoCategory;
}
Expand Down
16 changes: 11 additions & 5 deletions parseAPI/h/CodeSource.h
Expand Up @@ -136,7 +136,14 @@ class PARSER_EXPORT CodeSource : public Dyninst::InstructionSource {
* without hints.
*/
std::vector<Hint> _hints;


/*
* Lists of known non-returning functions (by name)
* and syscalls (by number)
*/
static dyn_hash_map<std::string, bool> non_returning_funcs;
static dyn_hash_map<int, bool> non_returning_syscalls_x86;
static dyn_hash_map<int, bool> non_returning_syscalls_x86_64;

public:
/* Returns true if the function at an address is known to be
Expand All @@ -145,7 +152,8 @@ class PARSER_EXPORT CodeSource : public Dyninst::InstructionSource {
Optional.
*/
virtual bool nonReturning(Address /*func_entry*/) { return false; }
virtual bool nonReturning(std::string /* func_name */) { return false; }
bool nonReturning(std::string func_name);
virtual bool nonReturningSyscall(int /*number*/) { return false; }

/*
* If the binary file type supplies non-zero base
Expand Down Expand Up @@ -227,8 +235,6 @@ class PARSER_EXPORT SymtabCodeSource : public CodeSource {
bool owns_symtab;
mutable CodeRegion * _lookup_cache;

static dyn_hash_map<std::string, bool> non_returning_funcs;

// Stats information
StatContainer * stats_parse;
bool _have_stats;
Expand All @@ -248,7 +254,7 @@ class PARSER_EXPORT SymtabCodeSource : public CodeSource {
~SymtabCodeSource();

bool nonReturning(Address func_entry);
bool nonReturning(std::string func_name);
bool nonReturningSyscall(int num);

bool resizeRegion(SymtabAPI::Region *, Address newDiskSize);

Expand Down
4 changes: 1 addition & 3 deletions parseAPI/h/SymLiteCodeSource.h
Expand Up @@ -85,8 +85,6 @@ class SymReaderCodeSource : public CodeSource {
bool owns_symtab;
mutable CodeRegion * _lookup_cache;

static dyn_hash_map<std::string, bool> non_returning_funcs;

// Stats information
StatContainer * stats_parse;
bool _have_stats;
Expand All @@ -98,7 +96,7 @@ class SymReaderCodeSource : public CodeSource {
PARSER_EXPORT ~SymReaderCodeSource();

PARSER_EXPORT bool nonReturning(Address func_entry);
PARSER_EXPORT bool nonReturning(std::string func_name);
PARSER_EXPORT bool nonReturningSyscall(int num);

PARSER_EXPORT bool resizeRegion(SymSegment *, Address newDiskSize);

Expand Down
52 changes: 52 additions & 0 deletions parseAPI/src/CodeSource.C
Expand Up @@ -31,6 +31,8 @@
#include <vector>
#include <map>

#include <boost/assign/list_of.hpp>

#include "dyntypes.h"

#include "CodeSource.h"
Expand Down Expand Up @@ -64,5 +66,55 @@ CodeSource::findRegions(Address addr, set<CodeRegion *> & ret) const
return _region_tree.find(addr,ret);
}

dyn_hash_map<std::string, bool>
CodeSource::non_returning_funcs =
boost::assign::map_list_of
("exit",true)
("abort",true)
("__f90_stop",true)
("fancy_abort",true)
("__stack_chk_fail",true)
("__assert_fail",true)
("ExitProcess",true)
("_ZSt17__throw_bad_allocv",true)
("_ZSt20__throw_length_errorPKc",true)
("_Unwind_Resume",true)
("longjmp",true)
("siglongjmp",true)
("_ZSt16__throw_bad_castv",true)
("_ZSt19__throw_logic_errorPKc",true)
("_ZSt20__throw_out_of_rangePKc",true)
("__cxa_rethrow",true)
("__cxa_throw",true)
("_ZSt21__throw_runtime_errorPKc",true)
("_gfortran_os_error",true)
("_gfortran_runtime_error",true)
("_gfortran_stop_numeric", true)
("for_stop_core", true)
("__sys_exit", true);

dyn_hash_map<int, bool>
CodeSource::non_returning_syscalls_x86 =
boost::assign::map_list_of
(1 /*exit*/,true)
(119 /*sigreturn*/, true);

dyn_hash_map<int, bool>
CodeSource::non_returning_syscalls_x86_64 =
boost::assign::map_list_of
(60 /*exit*/,true)
(15 /*sigreturn*/, true);

bool
CodeSource::nonReturning(string name)
{
#if defined(os_windows)
// We see MSVCR<N>.exit
// Of course, it's often reached via indirect call, but hope never fails.
if ((name.compare(0, strlen("MSVCR"), "MSVCR") == 0) &&
(name.find("exit") != name.npos)) return true;
#endif
parsing_printf("Checking non-returning for %s\n", name.c_str());
return non_returning_funcs.find(name) != non_returning_funcs.end();
}

21 changes: 18 additions & 3 deletions parseAPI/src/IA_IAPI.C
Expand Up @@ -279,6 +279,10 @@ bool IA_IAPI::hasCFT() const
{
hascftstatus.second = true;
}
else if (c == c_SyscallInsn)
{
hascftstatus.second = true;
}

hascftstatus.first = true;
return hascftstatus.second;
Expand Down Expand Up @@ -459,8 +463,8 @@ bool IA_IAPI::isSyscall() const
Instruction::Ptr ci = curInsn();

return (((ci->getOperation().getID() == e_call) &&
/*(curInsn()->getOperation().isRead(gs))) ||*/
(ci->getOperand(0).format(ci->getArch()) == "16")) ||
(curInsn()->getOperation().isRead(gs)) &&
(ci->getOperand(0).format(ci->getArch()) == "16")) ||
(ci->getOperation().getID() == e_syscall) ||
(ci->getOperation().getID() == e_int) ||
(ci->getOperation().getID() == power_op_sc));
Expand All @@ -480,6 +484,14 @@ bool IA_IAPI::isSysEnter() const
return (ci->getOperation().getID() == e_sysenter);
}

void IA_IAPI::parseSyscall(std::vector<std::pair<Address, EdgeTypeEnum> >& outEdges) const
{
parsing_printf("[%s:%d] Treating syscall as call to sink w/ possible FT edge to next insn at 0x%lx\n",
FILE__, __LINE__, getAddr());
outEdges.push_back(std::make_pair((Address)-1,CALL));
outEdges.push_back(std::make_pair(getNextAddr(), CALL_FT));
}

void IA_IAPI::parseSysEnter(std::vector<std::pair<Address, EdgeTypeEnum> >& outEdges) const
{
IA_IAPI scratch(*this);
Expand All @@ -498,7 +510,7 @@ void IA_IAPI::parseSysEnter(std::vector<std::pair<Address, EdgeTypeEnum> >& outE
else
{
parsing_printf("[%s:%d] Treating sysenter as call to kernel w/normal return to next insn at 0x%lx\n",
FILE__, __LINE__, getAddr());
FILE__, __LINE__, getAddr());
outEdges.push_back(std::make_pair(getNextAddr(), CALL_FT));
}
}
Expand Down Expand Up @@ -671,6 +683,9 @@ void IA_IAPI::getNewEdges(std::vector<std::pair< Address, EdgeTypeEnum> >& outEd
{
parseSysEnter(outEdges);
return;
} else if (isSyscall()) {
parseSyscall(outEdges);
return;
}

fprintf(stderr, "Unhandled instruction %s\n", ci->format().c_str());
Expand Down
1 change: 1 addition & 0 deletions parseAPI/src/IA_IAPI.h
Expand Up @@ -118,6 +118,7 @@ class IA_IAPI : public InstructionAdapter {
bool isFakeCall() const;
bool isLinkerStub() const;
bool isSysEnter() const;
void parseSyscall(std::vector<std::pair<Address, Dyninst::ParseAPI::EdgeTypeEnum> >& outEdges) const;
void parseSysEnter(std::vector<std::pair<Address, Dyninst::ParseAPI::EdgeTypeEnum> >& outEdges) const;
std::pair<bool, Address> getFallthrough() const;

Expand Down

0 comments on commit 23a5a76

Please sign in to comment.