Git Product home page Git Product logo

dyninst / dyninst Goto Github PK

View Code? Open in Web Editor NEW
691.0 40.0 147.0 205.87 MB

DyninstAPI: Tools for binary instrumentation, analysis, and modification.

Home Page: http://www.dyninst.org

License: GNU Lesser General Public License v2.1

CMake 0.55% C++ 28.11% TeX 2.71% C 67.96% Lex 0.04% Yacc 0.15% Assembly 0.07% Python 0.31% Perl 0.08% Shell 0.02% Dockerfile 0.01%
dyninst stackwalker symtab binary-analysis

dyninst's Introduction

Dyninst

Notes

  • Known issues should have open issues associated with them.
  • ARMv8 (64 bit) support for dynamic instrumentation is experimental and incomplete. For more details about current supported functionality refer to Dyninst Support for the ARMv8 (64 bit).

Build DyninstAPI and its subcomponents

Docker Containers

Containers are provided that can be used for Dyninst development (e.g., make changes to Dyninst and quickly rebuild it) or for development of your own tools (e.g., have a container ready to go with Dyninst). Links will be added here when the containers are pushed to the Dyninst associated package registries. Instructions for usage and building locally are provided in the docker directory.

Install with Spack

spack install dyninst

Build from source

  1. Configure Dyninst with CMake

    cmake /path/to/dyninst/source -DCMAKE_INSTALL_PREFIX=/path/to/installation

  2. Build and install Dyninst in parallel

    make install -jN

If this does not work for you, please refer to the Wiki for detailed instructions. If you encounter any errors, see the Building Dyninst or leave a GitHub issue.

Known Issues

  • Windows 64-bit mode is not yet supported

  • Windows rewriter mode is not yet supported

  • Exceptions in relocated code will not be caught

  • Linux rewriter mode for 32-bit, statically linked binaries does not support binaries with .plt, .rel, or .rela sections.

  • Callbacks at thread or process exit that stop the process will deadlock when a SIGSEGV occurs on a thread other than the main thread of a process

  • Stackwalker is fragile on Windows

  • Parsing a binary with no functions (typically a single object file) will crash at CodeObject destruction time.

dyninst's People

Contributors

allisonmorris avatar bbiiggppiigg avatar bigtrak avatar bwelton avatar cuviper avatar emilygemberjacobson avatar flandr avatar hainest avatar jmellorcrummey avatar jokeren avatar kupsch avatar lam2mo avatar ler0ever avatar ma-neumann avatar mcnulty avatar morehouse avatar mplegendre avatar mxz297 avatar pefoley2 avatar rafzi avatar rchyena avatar ssunny7 avatar stanfordcox avatar stevexisong avatar vsoch avatar wcohen avatar weixiao-zhan avatar wenbinf avatar wrwilliams avatar zuyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dyninst's Issues

PLT entries misparsed on ARM

Our PLT parsing mechanism on ARM is not doing the right thing, and is quite brittle. We should follow what the linker does in its generation of PLT stubs rather than relying on magic numbers/sizes/instruction sequences wherever possible.

Dyndwarf assert thrown on latest master

After pulling and rebuilding, I am getting the following assert thrown on master:

Abort message:

abort() in libdwarf. No error argument, no handler.
Aborted (core dumped)

Stack trace:

#0  0x00007ffff4a5ba28 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:55
#1  0x00007ffff4a5d62a in __GI_abort () at abort.c:89
#2  0x00007ffff3f82305 in _dwarf_error () from /lib64/libdwarf.so.1
#3  0x00007ffff3f80861 in _dwarf_next_cu_header_internal () from /lib64/libdwarf.so.1
#4  0x00007ffff3f80b90 in dwarf_next_cu_header_c () from /lib64/libdwarf.so.1
#5  0x00007ffff6ced485 in Dyninst::SymtabAPI::DwarfWalker::findAllSig8Types (
    this=0x7fffffffdad0) at /home/detter/Workspace/dyninst/symtabAPI/src/dwarfWalker.C:2443
#6  0x00007ffff6ce2f2c in Dyninst::SymtabAPI::DwarfWalker::parse (this=0x7fffffffdad0)
    at /home/detter/Workspace/dyninst/symtabAPI/src/dwarfWalker.C:115
#7  0x00007ffff6c955fd in Dyninst::SymtabAPI::Object::fix_global_symbol_modules_static_dwarf
    (this=0x65dc20) at /home/detter/Workspace/dyninst/symtabAPI/src/Object-elf.C:2438
#8  0x00007ffff6c92544 in Dyninst::SymtabAPI::Object::load_object (this=0x65dc20,
    alloc_syms=true) at /home/detter/Workspace/dyninst/symtabAPI/src/Object-elf.C:1603
#9  0x00007ffff6c96e9c in Dyninst::SymtabAPI::Object::Object (this=0x65dc20, mf_=0x6576a0,
    err_func=0x7ffff6c22963 <symtab_log_perror(char const*)>, alloc_syms=true)
    at /home/detter/Workspace/dyninst/symtabAPI/src/Object-elf.C:2837
#10 0x00007ffff6c293f8 in Dyninst::SymtabAPI::Symtab::Symtab (this=0x65c8f0,
    filename="P\341\377\377\377\177\000\000\t\000\000\000\000\000\000\000/bin/bash\000\000\000\000\000\000\000\000ge\000\000\000\000\000\300\037@\000\000\000\000\000\320\341\377\377\377\177\000\000\027Ц\367\377\177\000\000-\347\377\377\377\177\000\000p\307e\000\000\000\000\000\240\341\377\377\377\177\000\000\t\000\000\000\000\000\000\000/bin/bash\000\377\377\377\177\000\000p\307e\000\000\000\000\000\030&\336\364\377\177\000\000p\307e\000\000\000\000\000\300\037@\000\000\000\000\000\320\343\377\377\377\177\000\000\230!@\000\000\000\000\000\270\344\377\377\377\177\000\000\241\030@\000\002\000\000\000\377\377\377\377\000\000\000\000X\342\377\377\377\177\000\000h\371\242\364\377\177\000\000"..., defensive_bin=false,
    err=@0x7fffffffe11f: false)
    at /home/detter/Workspace/dyninst/symtabAPI/src/Symtab.C:1305
#11 0x00007ffff6c2cf9e in Dyninst::SymtabAPI::Symtab::openFile (obj=@0x65c800: 0x0,
    filename="/bin/bash", def_binary=Dyninst::SymtabAPI::Symtab::NotDefensive)
    at /home/detter/Workspace/dyninst/symtabAPI/src/Symtab.C:2152
#12 0x00007ffff7a6d017 in Dyninst::ParseAPI::SymtabCodeSource::SymtabCodeSource (
    this=0x65c770, file=0x7fffffffe72d "/bin/bash")
    at /home/detter/Workspace/dyninst/parseAPI/src/SymtabCodeSource.C:253
#13 0x0000000000402198 in main (argc=2, argv=0x7fffffffe4b8) at src/main.cpp:39

Problems with Instruction API parsing x86-64 binaries: xhpl executable

The current master version of dyninst has problems parsing several instructions in x86-64 binaries. These examples of problems were identified using the checkparse regression test developed at Rice and provided to Wisconsin.

Application example: xhpl

The x86-64 xhpl binary may be found here: http://www.cs.rice.edu/~johnmc/tmp/xhpl

problematic instructions:

            pop    (xed length=2, instruction api length=1) last instruction in block with DIRECT edge to sink
          kmovw    instruction length mismatch (xed length=8, instruction api length=4)
          kmovw    instruction length mismatch (xed length=9, instruction api length=4)
          vdppd    (xed length=6, instruction api length=4) last instruction in block with DIRECT edge to sink
         pinsrq    (xed length=12, instruction api length=5) last instruction in block with DIRECT edge to sink
         psrldq    (xed length=6, instruction api length=2) last instruction in block with DIRECT edge to sink
         vpsrlq    (xed length=11, instruction api length=5) last instruction in block with DIRECT edge to sink
         vpsrlq    (xed length=7, instruction api length=5) last instruction in block with DIRECT edge to sink
        vmovdqa    (xed length=5, instruction api length=4) last instruction in block with DIRECT edge to sink
        vpermpd    (xed length=7, instruction api length=5) last instruction in block with DIRECT edge to sink
       vblendpd    (xed length=6, instruction api length=4) last instruction in block with DIRECT edge to sink
       vfmaddpd    (xed length=6, instruction api length=4) last instruction in block with DIRECT edge to sink
     vgatherqpd    (xed length=10, instruction api length=4) last instruction in block with DIRECT edge to sink
   vpbroadcastd    (xed length=6, instruction api length=5) last instruction in block with DIRECT edge to sink
   vpbroadcastq    (xed length=6, instruction api length=5) last instruction in block with DIRECT edge to sink

Attached is the full report from checkparse. Unfortunately, I don't have the time to extract reports for issues for individual instruction instances. The checkparse output identifies problematic occurences. For addresses where xed claims no valid instruction at this address, the problem may be unparsing a prior instruction in a block rather than the last one.

xhpl.report.txt

InstructionAPI disassembly should match AT&T syntax

  • Addresses should be in bracket/paren form depending on architecture
  • Binary functions in SIB expressions should evaluate to commas
  • Immediates should get architecture-appropriate decorators
  • Implicit operands should be hidden from disassembly
  • Most appropriate register name should be chosen based on the instruction
  • Dereference sizes should decorate dereferences appropriately.

Build failure on windows

3c38960 broke the windows build.

C:\Users\Peter\Source\Repos\dyninst\common\src\addrtranslate-win.C(173): error C2440: 'return': cannot convert from 'HMODULE (__stdcall *)(LPCSTR,HANDLE,DWORD)' to 'Dyninst::Address'

Looks like AddressTranslateWin::getLibraryTrapAddrSysV needs to be changed, but I'm not sure what the correct fix is.

BPatch_function.C.o build failure on PPC64le

Note (builds okay on x86_64).

I am seeing the following build failure:

[ 65%] Building CXX object dyninstAPI/CMakeFiles/dyninstAPI.dir/src/BPatch_function.C.o
In file included from /g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/parse-cfg.h:49:0,
from /g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/function.h:43,
from /g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/BPatch_function.C:37:
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h:78:5: error: 'vector' does not name a type
vector _func_allocs;
^
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h:79:5: error: 'vector' does not name a type
vector _edge_allocs;
^
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h: In member function 'void DynCFGFactory::_record_func_alloc(Dyninst::ParseAPI::FuncSource)':
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h:87:11: error: '_func_allocs' was not declared in this scope
++_func_allocs[fs];
^
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h: In member function 'void DynCFGFactory::_record_edge_alloc(Dyninst::ParseAPI::EdgeTypeEnum, bool)':
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/Parsing.h:92:11: error: '_edge_allocs' was not declared in this scope
++_edge_allocs[et];
^
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/BPatch_function.C: At global scope:
/g/g0/martymcf/dyninst/dyninst/dyninstAPI/src/BPatch_function.C:1115:6: warning: unused parameter 'mods' [-Wunused-parameter]
bool BPatch_function::addMods(std::set<StackMod*> mods)
^
make[2]: *** [dyninstAPI/CMakeFiles/dyninstAPI.dir/src/BPatch_function.C.o] Error 1
make[1]: *** [dyninstAPI/CMakeFiles/dyninstAPI.dir/all] Error 2
make: *** [all] Error 2

Dyninst parsing part of function multiple times

In one of John Mellor-Crummey's binaries, there is a function that has parts that Dyninst is parsing multiple times, sort of in a loop.

Basically, the dyn_dump output looks like this:

000000000046bf40 <mkl_blas_avx512_mic_dcopy_down8x8zzai>:
        0x46bf40 48 81 ec 98 0 0 0      sub RSP, 98
        0x46bf47 48 89 5c 24 28         mov [RSP + 28], RBX
        0x46bf4c 48 8b 6                mov RAX, [RSI]
        0x46bf4f 4c 89 7c 24 20         mov [RSP + 20], R15
        0x46bf54 48 8b 3f               mov RDI, [RDI]

        // everything fine for a while...

        0x46c34c 49 83 c5 40            add R13, 40
        0x46c350 48 83 c1 40            add RCX, 40
        0x46c354 4c 3b a4 24 80 0 0 0   cmp R12, [RSP + 80]
        0x46c35c f 82 c3 fc ff ff       jb fffffcc3 + RIP + 6
>>>>>>  0x46c2a0 f1                     int1
        0x46c2a1 f5                     cmc
        0x46c2a2 48 59                  pop RCX, RSP
        0x46c2a4 db 62 f1               No_Entry
        0x46c2a3 59                     pop RCX, RSP
        0x46c2a4 db 62 f1               No_Entry
        0x46c2a5 62 f1 f5 48 59 e4      vmulpd ZMM4, ZMM1, ZMM4, {k0}

We then start parsing the area near 0x46c2a0 repeatedly. We somehow make it out of this parsing loop and get to the actual end of the function.

If you look at the addresses on the left in the full gist, it's easy to see where we enter the 'loop'.

Full gist: https://gist.github.com/jdetter/2ab4656fc75cbe26b30b56a0c5b1590a

symtabAPI fails to link on 32bit linux

Hi,

I've just noticed that symtabAPI fails to link on pure 32bit system.
It is due to recent addition of the following code

   if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS32)
3968        {
3969            Dyninst::SymtabAPI::emitElf64<Dyninst::SymtabAPI::ElfTypes32> *em =
3970                    new Dyninst::SymtabAPI::emitElf64<Dyninst::SymtabAPI::ElfTypes32>(elfHdr, isStripped, this, err_func_, obj);
3971            if( !em->createSymbolTables(allSymbols) ) return false;
3972            return em->driver(fName);
3973        }
3974        else if (elfHdr->e_ident()[EI_CLASS] == ELFCLASS64)
3975        {
3976            Dyninst::SymtabAPI::emitElf64<Dyninst::SymtabAPI::ElfTypes64> *em =
3977                    new Dyninst::SymtabAPI::emitElf64<Dyninst::SymtabAPI::ElfTypes64>(elfHdr, isStripped, this, err_func_, obj);
3978            if( !em->createSymbolTables(allSymbols) ) return false;
3979            return em->driver(fName);
3980        }
3981        return false;

In Object-Elf.C . When linking, added code now references emitElf64 object file which isn't built in 32bit build config due to this in CMakeLists.txt :

if (PLATFORM MATCHES freebsd OR 
    PLATFORM MATCHES linux OR 
    PLATFORM MATCHES bgq OR
    PLATFORM MATCHES cnl)

set (SRC_LIST ${SRC_LIST}
    src/Object-elf.C 
    src/Archive.C 
    src/Archive-elf.C 
    src/parseDwarf.C
        src/parseStab.C
        src/LinkMap.C
    src/emitElfStatic.C 
    src/dwarfWalker.C
)

if (PLATFORM MATCHES x86_64 OR PLATFORM MATCHES amd64)
set (SRC_LIST ${SRC_LIST}
    src/emitElf-64.C
    src/emitElfStatic-x86.C 
    src/relocationEntry-elf-x86.C
    )

emitElf-64.C is added to the list of sources on x86_64 build targets, yet x86 build target will require it due to above-mentioned code. My simple workaround for now was to add that source file explicitly.
I'm guessing there's a better solution , hence I'm opening an issue instead of adding a patch.

Cheers!

parseThat not outputting executable binary (Exec format error)

Mohamed is having an issue where he runs:

parseThat --binary-edit=ssh-dyn -i 0 /usr/bin/ssh

and the output binary ssh-dyn will not execute due to an exec format error. The header information looks correct to me so I'm not sure why exec won't take it:

detter@ubuntu-16:~/Mohamed$ readelf -h ./ssh-dyn
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0xdea0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          768992 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         10
  Size of section headers:           64 (bytes)
  Number of section headers:         40
  Section header string table index: 39

Ubuntu's version of /usr/bin/ssh can be found here
The ssh-dyn binary generated by parseThat can be found here

MachRegister::getReturnAddress not implemented on x86/x86_64

I'm trying to manually create a Stackwalker::Frame object by passing in ra, sp and fp.
It appears that MachRegister::getReturnAddress is the best way to get the ra register, but it's not currently implemented on x86. Is there another way to get the necessary context to create a frame object?
For reference, I'm trying to get the parent function from within a snippet inserted at the entry point of the function I'm interested in. I tried using the Walker::walkStack api, but that doesn't seem to be able to properly walk back out of an snippet, so manually creating a Frame object based on BPatch_registerExpr values from the function the snippet is inserted into seems like the best approach.
https://github.com/dyninst/dyninst/blob/master/common/src/dyn_regs.C#L259

decodeOneOperand() called with unknown addressing method 18

Via dyninst api mailing list:

Calling getProcedures() on the default module of a stripped PIE results in an assertion failure at common/src/arc-x86.C:7993. It seems that the heuristic gap parser is trying to decode the assembly as x86_32 instead of x86_64 (I may be wrong though). Exact stack trace is attached.

This is triggered by simply opening the binary, getting the default module, then calling getProcedure.

Sample offending program is /usr/bin/ssh on Ubuntu 16.04 x86_64.

test: /dyninst/common/src/arch-x86.C:7993: NS_x86::ia32_instruction& NS_x86::ia32_decode(unsigned int, const unsigned char*, NS_x86::ia32_instruction&): Assertion `0' failed.

#0  0x00007ffff6279418 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff627b01a in __GI_abort () at abort.c:89
#2  0x00007ffff6271bd7 in __assert_fail_base (fmt=<optimized out>, assertion=assertion@entry=0x7ffff6c5c396 "0", 
    file=file@entry=0x7ffff6c61f10 "/dyninst/common/src/arch-x86.C", line=line@entry=7993, 
    function=function@entry=0x7ffff6c61b80 <NS_x86::ia32_decode(unsigned int, unsigned char const*, NS_x86::ia32_instruction&)::__PRETTY_FUNCTION__> "NS_x86::ia32_instruction& NS_x86::ia32_decode(unsigned int, const unsigned char*, NS_x86::ia32_instruction&)") at assert.c:92
#3  0x00007ffff6271c82 in __GI___assert_fail (assertion=assertion@entry=0x7ffff6c5c396 "0", 
    file=file@entry=0x7ffff6c61f10 "/dyninst/common/src/arch-x86.C", line=line@entry=7993, 
    function=function@entry=0x7ffff6c61b80 <NS_x86::ia32_decode(unsigned int, unsigned char const*, NS_x86::ia32_instruction&)::__PRETTY_FUNCTION__> "NS_x86::ia32_instruction& NS_x86::ia32_decode(unsigned int, const unsigned char*, NS_x86::ia32_instruction&)") at assert.c:101
#4  0x00007ffff6c09c5a in NS_x86::ia32_decode (capa=capa@entry=1, addr=<optimized out>, instruct=...) at /dyninst/common/src/arch-x86.C:7993
#5  0x00007ffff763e826 in Dyninst::InstructionAPI::InstructionDecoder_x86::doIA32Decode (this=0x67dd60, b=...)
    at /dyninst/instructionAPI/src/InstructionDecoder-x86.C:1292
#6  0x00007ffff763f179 in Dyninst::InstructionAPI::InstructionDecoder_x86::decodeOpcode (this=<optimized out>, b=...)
    at /dyninst/instructionAPI/src/InstructionDecoder-x86.C:1352
#7  0x00007ffff7740a8a in Dyninst::InstructionAPI::InstructionDecoderImpl::decode (this=0x67dd60, b=...)
    at /dyninst/instructionAPI/src/InstructionDecoderImpl.C:56
#8  0x00007ffff763db7d in Dyninst::InstructionAPI::InstructionDecoder_x86::decode (this=<optimized out>, b=...)
    at /dyninst/instructionAPI/src/InstructionDecoder-x86.C:1406
#9  0x00007ffff763d966 in Dyninst::InstructionAPI::InstructionDecoder::decode (this=this@entry=0x7fffffffd650)
    at /dyninst/instructionAPI/src/InstructionDecoder.C:65
#10 0x00007ffff7a3b0da in hd::ProbabilityCalculator::decodeInstruction (this=this@entry=0x7fffffffd860, data=..., addr=addr@entry=151394)
    at /dyninst/parseAPI/src/ProbabilisticParser.C:493
#11 0x00007ffff7a3bdb2 in hd::ProbabilityCalculator::calcForwardWeights (this=0x7fffffffd860, cur=0, addr=151394, tree=0x7fffffffd868, valid=@0x7fffffffd78f: true)
    at /dyninst/parseAPI/src/ProbabilisticParser.C:416
#12 0x00007ffff7a3c0cb in hd::ProbabilityCalculator::calcProbByMatchingIdioms (this=this@entry=0x7fffffffd860, addr=addr@entry=151394)
    at /dyninst/parseAPI/src/ProbabilisticParser.C:331
#13 0x00007ffff79ceec0 in Dyninst::ParseAPI::Parser::probabilistic_gap_parsing (this=0x6d7780, cr=cr@entry=0x6a1f40)
    at /dyninst/parseAPI/src/Parser-speculative.C:361
#14 0x00007ffff79c3ce2 in Dyninst::ParseAPI::CodeObject::parseGaps (this=<optimized out>, cr=cr@entry=0x6a1f40, type=type@entry=Dyninst::ParseAPI::IdiomMatching)
    at /dyninst/parseAPI/src/CodeObject.C:188
#15 0x00007ffff6f93fbc in image::analyzeImage (this=this@entry=0x663cd0) at /dyninst/dyninstAPI/src/image.C:1201
#16 0x00007ffff6f940ab in image::analyzeIfNeeded (this=0x663cd0) at /dyninst/dyninstAPI/src/image.C:1165
#17 0x00007ffff6f95e37 in image::getAllFunctions (this=<optimized out>) at /dyninst/dyninstAPI/src/image.C:945
#18 pdmodule::getFunctions (this=0x677c80, funcs=std::vector of length 0, capacity 0) at /dyninst/dyninstAPI/src/image.C:1809
#19 0x00007ffff6faaec6 in mapped_module::getAllFunctions (this=0x7920d0) at /dyninst/dyninstAPI/src/mapped_module.C:48
#20 0x00007ffff6f331dd in BPatch_module::getProcedures (this=0x799750, funcs=std::vector of length 0, capacity 0, incUninstrumentable=false)
    at /dyninst/dyninstAPI/src/BPatch_module.C:350
#21 0x00007ffff6f333e7 in BPatch_module::getProcedures (this=0x799750, incUninstrumentable=incUninstrumentable@entry=false)
    at /dyninst/dyninstAPI/src/BPatch_module.C:331
#22 0x00000000004038a4 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>)

New instruction decoding problem in master branch

In the xhpl binary provided from Rice, objdump shows the following instruction at the given address:

9aeef7: 49 63 fa movslq %r10d,%rdi

Current master branch decodes the instruction as

9aeef7 : arpl R10W, DI

walkSingleFrame run against local process on WIndows crashes

This is a variation on issue #63 which I reported. My ultimate goal is to walk the stack in the local process, not in an external process. When I try my test program against the local process, the first call to walkSingleFrame dies with:

Program: StackTest.exe
File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead

My test program is:
self_stackwalk.txt

The call stack from the debugger is:

MSVCR120D!_free_dbg_nolock+0x49d
MSVCR120D!_free_dbg+0x4e
MSVCR120D!operator delete+0xbc
stackwalk!std::allocatorstd::_Container_proxy::deallocate+0x10
stackwalk!std::_String_alloc<0,std::_String_base_types<char,std::allocator > >::_Free_proxy+0x38
stackwalk!std::_String_alloc<0,std::_String_base_types<char,std::allocator > >::~_String_alloc<0,std::_String_base_types<char,std::allocator > >+0xf
stackwalk!std::basic_string<char,std::char_traits,std::allocator >::~basic_string<char,std::char_traits,std::allocator >+0x1b
stackwalk!Dyninst::Stackwalker::Walker::newWalker+0x235
StackTest!main+0xaa
StackTest!__tmainCRTStartup+0x11a
StackTest!mainCRTStartup+0xd
KERNEL32!BaseThreadInitThunk+0x24
ntdll!__RtlUserThreadStart+0x2f
ntdll!_RtlUserThreadStart+0x1b

The frame "stackwalk!Dyninst::Stackwalker::Walker::newWalker+0x235" is the return statement in "Walker* Walker::newWalker(std::string exec_name)", so it appears to be dying while deallocating the local variables in that function.

My build and test environment for DynInst is:

  • Windows 10, 64-bit
  • Visual Studio 12
  • Cmake 3.5.2 (cmake-3.5.2-win32-x86)
  • Boost 1.59 (I downloaded a pre-built Windows version, boost_1_59_0-msvc-12.0-32)
  • DynInst 9.1.0
  • I'm building exclusively 32-bit binaries, even though the OS is 64-bit
  • For most of my testing and debugging, I'm using a Debug build of DynInst. I tried a Release build first and then moved to Debug to try to figure out the problems.

Segfault when parsing binary with no functions

This is a low priority issue, however parsing crtend.o on Fedora23 causes Dyninst to segfault. It is caused by the Block deconstructor:

Block::~Block()
{
    // nothing special
    if (_obj && _obj->cs()) {
        _obj->cs()->decrementCounter(PARSE_BLOCK_COUNT);
        _obj->cs()->addCounter(PARSE_BLOCK_SIZE, -1*size());
    }
}

It would appear _obj contains junk here.

Valgrind output

[detter@localhost dyninst]$ valgrind dyn_instruct_test /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtend.o
==11250== Memcheck, a memory error detector
==11250== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==11250== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==11250== Command: dyn_instruct_test /usr/lib/gcc/x86_64-redhat-linux/5.3.1/crtend.o
==11250==
==11250== Invalid read of size 8
==11250==    at 0x5BAF793: Dyninst::ParseAPI::Block::~Block() (Block.C:63)
==11250==    by 0x5BAF84F: Dyninst::ParseAPI::Block::~Block() (Block.C:66)
==11250==    by 0x5B9B007: Dyninst::ParseAPI::CFGFactory::free_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:166)
==11250==    by 0x5B9AFD5: Dyninst::ParseAPI::CFGFactory::destroy_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:161)
==11250==    by 0x5B9B189: Dyninst::ParseAPI::CFGFactory::destroy_all() (CFGFactory.C:193)
==11250==    by 0x5B9AAE9: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:83)
==11250==    by 0x5B9AB49: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:84)
==11250==    by 0x5BB2876: Dyninst::ParseAPI::CodeObject::~CodeObject() (CodeObject.C:103)
==11250==    by 0x40257D: analyze_bin(char*) (main.C:95)
==11250==    by 0x40238B: main (main.C:56)
==11250==  Address 0x97b9400 is 0 bytes inside a block of size 184 free'd
==11250==    at 0x4C2A1A0: operator delete(void*) (vg_replace_malloc.c:576)
==11250==    by 0x5DB427F: Dyninst::ParseAPI::SymtabCodeSource::~SymtabCodeSource() (SymtabCodeSource.C:216)
==11250==    by 0x40256C: analyze_bin(char*) (main.C:94)
==11250==    by 0x40238B: main (main.C:56)
==11250==  Block was alloc'd at
==11250==    at 0x4C29216: operator new(unsigned long) (vg_replace_malloc.c:334)
==11250==    by 0x4023F7: analyze_bin(char*) (main.C:74)
==11250==    by 0x40238B: main (main.C:56)
==11250==
==11250== Jump to the invalid address stated on the next line
==11250==    at 0xA1EC9: ???
==11250==    by 0x5BAF84F: Dyninst::ParseAPI::Block::~Block() (Block.C:66)
==11250==    by 0x5B9B007: Dyninst::ParseAPI::CFGFactory::free_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:166)
==11250==    by 0x5B9AFD5: Dyninst::ParseAPI::CFGFactory::destroy_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:161)
==11250==    by 0x5B9B189: Dyninst::ParseAPI::CFGFactory::destroy_all() (CFGFactory.C:193)
==11250==    by 0x5B9AAE9: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:83)
==11250==    by 0x5B9AB49: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:84)
==11250==    by 0x5BB2876: Dyninst::ParseAPI::CodeObject::~CodeObject() (CodeObject.C:103)
==11250==    by 0x40257D: analyze_bin(char*) (main.C:95)
==11250==    by 0x40238B: main (main.C:56)
==11250==  Address 0xa1ec9 is not stack'd, malloc'd or (recently) free'd
==11250==
==11250==
==11250== Process terminating with default action of signal 11 (SIGSEGV)
==11250==  Bad permissions for mapped region at address 0xA1EC9
==11250==    at 0xA1EC9: ???
==11250==    by 0x5BAF84F: Dyninst::ParseAPI::Block::~Block() (Block.C:66)
==11250==    by 0x5B9B007: Dyninst::ParseAPI::CFGFactory::free_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:166)
==11250==    by 0x5B9AFD5: Dyninst::ParseAPI::CFGFactory::destroy_block(Dyninst::ParseAPI::Block*) (CFGFactory.C:161)
==11250==    by 0x5B9B189: Dyninst::ParseAPI::CFGFactory::destroy_all() (CFGFactory.C:193)
==11250==    by 0x5B9AAE9: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:83)
==11250==    by 0x5B9AB49: Dyninst::ParseAPI::CFGFactory::~CFGFactory() (CFGFactory.C:84)
==11250==    by 0x5BB2876: Dyninst::ParseAPI::CodeObject::~CodeObject() (CodeObject.C:103)
==11250==    by 0x40257D: analyze_bin(char*) (main.C:95)
==11250==    by 0x40238B: main (main.C:56)
==11250==
==11250== HEAP SUMMARY:
==11250==     in use at exit: 304,731 bytes in 3,429 blocks
==11250==   total heap usage: 3,764 allocs, 335 frees, 351,269 bytes allocated
==11250==
==11250== LEAK SUMMARY:
==11250==    definitely lost: 0 bytes in 0 blocks
==11250==    indirectly lost: 0 bytes in 0 blocks
==11250==      possibly lost: 1,248 bytes in 12 blocks
==11250==    still reachable: 303,483 bytes in 3,417 blocks
==11250==                       of which reachable via heuristic:
==11250==                         newarray           : 528 bytes in 1 blocks
==11250==         suppressed: 0 bytes in 0 blocks
==11250== Rerun with --leak-check=full to see details of leaked memory
==11250==
==11250== For counts of detected and suppressed errors, rerun with: -v
==11250== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

Master not building with boost 1.58.0 (undefined references)

When building master, I am now having an issue with building against boost 1.58.0. I have also merged master into VEX and I am having the same issue. Are we no longer supporting libboost 1.58.0?

[ 98%] Building CXX object dyninstAPI/CMakeFiles/dyninstAPI.dir/src/linux-x86.C.o
Linking CXX shared library libdyninstAPI.so
CMakeFiles/dyninstAPI.dir/src/ast.C.o: In function `AstSnippetNode::generateCode_phase2(codeGen&, bool, unsigned long&, unsigned int&)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/ast.C:3714: undefined reference to `boost::shared_ptr<Dyninst::PatchAPI::Snippet>::operator->() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::createProcess(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, BPatch_hybridMode, std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, int, int)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:106: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::operator!() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::attachProcess(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, BPatch_hybridMode)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:143: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::operator!() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::isStopped() const':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1098: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::shared_ptr()'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::isTerminated() const':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1103: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::shared_ptr()'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::hasExitedNormally() const':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1108: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::shared_ptr()'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::markExited()':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1145: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::operator Dyninst::ProcControlAPI::Process* boost::shared_ptr<Dyninst::ProcControlAPI::Process>::*() const'
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1145: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::shared_ptr()'
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1145: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::operator=(boost::shared_ptr<Dyninst::ProcControlAPI::Process>&&)'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::getMemoryPageSize() const':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:1495: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::operator Dyninst::ProcControlAPI::Process* boost::shared_ptr<Dyninst::ProcControlAPI::Process>::*() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::postIRPC_internal(void*, unsigned int, unsigned int, unsigned int, unsigned long, void*, bool, PCThread*, bool, bool, bool, void**)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:2085: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator=(boost::shared_ptr<Dyninst::ProcControlAPI::Thread> const&)'
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:2093: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator Dyninst::ProcControlAPI::Thread* boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::*() const'
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:2131: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator Dyninst::ProcControlAPI::Thread* boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::*() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::addSyncRPCThread(boost::shared_ptr<Dyninst::ProcControlAPI::Thread>)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:3202: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator Dyninst::ProcControlAPI::Thread* boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::*() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::removeSyncRPCThread(boost::shared_ptr<Dyninst::ProcControlAPI::Thread>)':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:3208: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator Dyninst::ProcControlAPI::Thread* boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::*() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `PCProcess::continueSyncRPCThreads()':
/u/d/e/detter/private/detter/dyninst/dyninstAPI/src/dynProcess.C:3217: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Thread>::operator!() const'
CMakeFiles/dyninstAPI.dir/src/dynProcess.C.o: In function `bool boost::operator==<Dyninst::ProcControlAPI::Process, Dyninst::ProcControlAPI::Process>(boost::shared_ptr<Dyninst::ProcControlAPI::Process> const&, boost::shared_ptr<Dyninst::ProcControlAPI::Process> const&)':
/usr/include/boost/smart_ptr/shared_ptr.hpp:483: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::get() const'
/usr/include/boost/smart_ptr/shared_ptr.hpp:483: undefined reference to `boost::shared_ptr<Dyninst::ProcControlAPI::Process>::get() const'
collect2: ld returned 1 exit status
make[2]: *** [dyninstAPI/libdyninstAPI.so.9.1.0] Error 1
make[1]: *** [dyninstAPI/CMakeFiles/dyninstAPI.dir/all] Error 2

Symtab can't find any functions without libc

I have had this issue in the past when compiling assembly files without linking against the C standard library. Compiling this source with the standard C library and changing _start to main works, however just compiling _start with no standard C library doesn't seem to work.

The program I'm using (dyn_dump) can be downloaded here

asm.S:

.globl _start
_start:
    push %rbp
    mov %rsp, %rbp

    add 8(%rax, %rax, 2), %rax
    add 8(, %rax, 2), %rax
    add 8(, %rax, ), %rax
    add 8(%rax), %rax

    mov %rbp, %rsp
    pop %rbp

    ret

compiled with (using 64 bit gcc):

gcc ./asm.S -o asm.o -nostdlib

objdump output:

../ATTVerification/objs/deref.o:     file format elf64-x86-64


Disassembly of section .note.gnu.build-id:

00000000004000b0 <.note.gnu.build-id>:
  4000b0:       04 00                   add    $0x0,%al
  4000b2:       00 00                   add    %al,(%rax)
  4000b4:       14 00                   adc    $0x0,%al
  4000b6:       00 00                   add    %al,(%rax)
  4000b8:       03 00                   add    (%rax),%eax
  4000ba:       00 00                   add    %al,(%rax)
  4000bc:       47                      rex.RXB
  4000bd:       4e 55                   rex.WRX push %rbp
  4000bf:       00 9c 87 ec 5c 9e 9a    add    %bl,-0x6561a314(%rdi,%rax,4)
  4000c6:       65 c7                   gs (bad)
  4000c8:       38 7c 46 b5             cmp    %bh,-0x4b(%rsi,%rax,2)
  4000cc:       e1 24                   loope  4000f2 <_start+0x1e>
  4000ce:       c9                      leaveq
  4000cf:       0e                      (bad)
  4000d0:       42 d6                   rex.X (bad)
  4000d2:       22                      .byte 0x22
  4000d3:       50                      push   %rax

Disassembly of section .text:

00000000004000d4 <_start>:
  4000d4:       55                      push   %rbp
  4000d5:       48 89 e5                mov    %rsp,%rbp
  4000d8:       48 03 44 40 08          add    0x8(%rax,%rax,2),%rax
  4000dd:       48 03 04 45 08 00 00    add    0x8(,%rax,2),%rax
  4000e4:       00
  4000e5:       48 03 04 05 08 00 00    add    0x8(,%rax,1),%rax
  4000ec:       00
  4000ed:       48 03 40 08             add    0x8(%rax),%rax
  4000f1:       48 89 ec                mov    %rbp,%rsp
  4000f4:       5d                      pop    %rbp
  4000f5:       c3                      retq

output of nm

[detter@localhost objs]$ nm ./asm.o
00000000006000f6 T __bss_start
00000000006000f6 T _edata
00000000006000f8 T _end
00000000004000d4 T _start

dyn_dump output:

[detter@localhost att_syntax]$ dyn_dump ../objs/asm.o
Error: couldn't get funcs.

walkSingleFrame against local process crashes on Windows

This is a variation on issue #63 which I reported. My ultimate goal is to walk the stack in the local process, not in an external process. When I try my test program against the local process, the first call to walkSingleFrame dies with:

(1fd0.38c0): Access violation - code c0000005 (first chance)

My test program is below. Base on the response on issue #63, I am calling Walker::newWalker(std::string exec_name):
self_stackwalk.txt

The call stack from the debugger is:

stackwalk!Dyninst::Stackwalker::LookupFuncStart::allocatesFrame+0x134
stackwalk!Dyninst::Stackwalker::FrameFuncStepperImpl::getCallerFrame+0x3b
stackwalk!Dyninst::Stackwalker::Walker::walkSingleFrame+0x2b4
StackTest!main+0x30f
StackTest!__tmainCRTStartup+0x199
StackTest!mainCRTStartup+0xd
KERNEL32!BaseThreadInitThunk+0x24
ntdll!__RtlUserThreadStart+0x2f
ntdll!_RtlUserThreadStart+0x1b

The failure point (allocatesFrame+0x134) points to line 287 of x86_swk.C:

result = proc->getLibraryTracker()->getLibraryAtAddr(addr, lib);

The getLibraryTracker() function is returning NULL. I can see in the debugger that the proc->library_tracker member is NULL.

My build and test environment for DynInst is:

Windows 10, 64-bit
Visual Studio 12
Cmake 3.5.2 (cmake-3.5.2-win32-x86)
Boost 1.59 (I downloaded a pre-built Windows version, boost_1_59_0-msvc-12.0-32)
DynInst 9.1.0
I'm building exclusively 32-bit binaries, even though the OS is 64-bit
For most of my testing and debugging, I'm using a Debug build of DynInst. I tried a Release build first and then moved to Debug to try to figure out the problems.

LivenessAnalyzer::isMMX assertion failure

Using the VEX branch (commit 0e9c1b1), I've triggered this assertion:

Assertion `((machReg.val() & x86::MMX) == x86::MMX) == ((machReg.val() & x86_64::MMX) == x86_64::MMX)' failed.

x86::MMX is 0x60000, x86_64::MMX is 0x90000, and that value is 0x18062001.

You can reproduce with the following C++11 program:

mutatee: stap.gz
command: ./bpatch-nop ./stap 0x161140

Here is bpatch-nop.cxx:

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <vector>

#include <BPatch.h>
#include <BPatch_addressSpace.h>
#include <BPatch_object.h>
#include <BPatch_snippet.h>

using namespace std;

int
main(int argc, char * const argv [])
{
    BPatch bp;

    if (argc < 2) {
        cerr << "usage: " << argv[0] << " <binary> [offsets...]" << endl;
        return EXIT_FAILURE;
    }

    vector<Dyninst::Offset> offsets;
    for (int i = 2; i < argc; ++i) {
        offsets.push_back(0);
        istringstream iss(argv[i]);
        iss >> setbase(0) >> offsets.back();

    }

    unique_ptr<BPatch_binaryEdit> bin(bp.openBinary(argv[1]));
    if (!bin) {
        cerr << "couldn't open: " << argv[1] << endl;
        return EXIT_FAILURE;
    }

    vector<BPatch_object *> objects;
    bin->getImage()->getObjects(objects);

    for (auto obj: objects) {
        cout << "object: " << obj->pathName() << endl;

        for (auto off: offsets) {
            auto addr = obj->fileOffsetToAddr(off);

            vector<BPatch_point *> points;
            obj->findPoints(addr, points);

            cout << hex << showbase
                << " offset " << off << " -> address " << addr
                << dec << noshowbase
                << " -> " << points.size() << " points"
                << endl;

            if (!points.empty()) {
                auto handle = bin->insertSnippet(BPatch_nullExpr(), points);
                cout << hex << showbase
                    << " snippet handle " << (intptr_t)handle
                    << dec << noshowbase << endl;
            }
        }
    }

    // NB: nothing is actually patched until we write a file
    bin->writeFile((string(argv[1]) + ".new").c_str());

    return EXIT_SUCCESS;
}
(gdb) bt
#0  0x00007ffff6d83a98 in raise () from /lib64/libc.so.6
#1  0x00007ffff6d8569a in abort () from /lib64/libc.so.6
#2  0x00007ffff6d7c227 in __assert_fail_base () from /lib64/libc.so.6
#3  0x00007ffff6d7c2d2 in __assert_fail () from /lib64/libc.so.6
#4  0x00007ffff61754ed in LivenessAnalyzer::isMMX (this=<optimized out>, machReg=...) at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:614
#5  0x00007ffff6175500 in LivenessAnalyzer::changeIfMMX (this=0x7ffff7dda9e0 <instPoint::liveRegisters()::live2>, machReg=...) at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:621
#6  0x00007ffff6175e2a in LivenessAnalyzer::calcRWSets (this=this@entry=0x7ffff7dda9e0 <instPoint::liveRegisters()::live2>, curInsn=..., blk=0x33707b8, a=a@entry=5636031) at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:471
#7  0x00007ffff61793d3 in LivenessAnalyzer::summarizeBlockLivenessInfo (this=this@entry=0x7ffff7dda9e0 <instPoint::liveRegisters()::live2>, func=func@entry=0xfdeba0, block=0x33707b8, allRegsDefined=...)
    at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:147
#8  0x00007ffff617b023 in LivenessAnalyzer::analyze (this=this@entry=0x7ffff7dda9e0 <instPoint::liveRegisters()::live2>, func=0xfdeba0) at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:233
#9  0x00007ffff617b3d0 in LivenessAnalyzer::query (this=this@entry=0x7ffff7dda9e0 <instPoint::liveRegisters()::live2>, loc=..., type=type@entry=LivenessAnalyzer::Before, bitarray=...)
    at /home/jistone/paradyn/dyninst/dataflowAPI/src/liveness.C:271
#10 0x00007ffff7a6f02d in instPoint::liveRegisters (this=this@entry=0x1283100) at /home/jistone/paradyn/dyninst/dyninstAPI/src/instPoint.C:513
#11 0x00007ffff7a65e2e in registerSpace::actualRegSpace (iP=0x1283100) at /home/jistone/paradyn/dyninst/dyninstAPI/src/registerSpace.C:166
#12 0x00007ffff7a72638 in baseTramp::generateCode (this=0x13415f0, gen=..., baseInMutatee=9443571) at /home/jistone/paradyn/dyninst/dyninstAPI/src/baseTramp.C:206
#13 0x00007ffff7af471b in Dyninst::Relocation::InstWidgetPatch::apply (this=0x339d210, gen=...) at /home/jistone/paradyn/dyninst/dyninstAPI/src/Relocation/Widgets/InstWidget.C:85
#14 0x00007ffff7b0fc29 in Dyninst::Relocation::CodeBuffer::BufferElement::generate (this=this@entry=0x1341b30, buf=buf@entry=0x3639b58, gen=..., shift=@0x3639cf4: 6387, regenerate=@0x7fffffffd15f: false)
    at /home/jistone/paradyn/dyninst/dyninstAPI/src/Relocation/CodeBuffer.C:117
#15 0x00007ffff7b0fdb7 in Dyninst::Relocation::CodeBuffer::generate (this=0x3639b58, baseAddr=baseAddr@entry=9437184) at /home/jistone/paradyn/dyninst/dyninstAPI/src/Relocation/CodeBuffer.C:274
#16 0x00007ffff7ae2d40 in Dyninst::Relocation::CodeMover::relocate (this=<optimized out>, addr=addr@entry=9437184) at /home/jistone/paradyn/dyninst/dyninstAPI/src/Relocation/CodeMover.C:180
#17 0x00007ffff7a7463d in AddressSpace::generateCode (this=this@entry=0x65bd10, cm=..., nearTo=nearTo@entry=5572486) at /home/jistone/paradyn/dyninst/dyninstAPI/src/addressSpace.C:1952
#18 0x00007ffff7a7b557 in AddressSpace::relocateInt (this=this@entry=0x65bd10, begin=, end=end@entry=, nearTo=5572486) at /home/jistone/paradyn/dyninst/dyninstAPI/src/addressSpace.C:1762
#19 0x00007ffff7a7c42c in AddressSpace::relocate (this=this@entry=0x65bd10) at /home/jistone/paradyn/dyninst/dyninstAPI/src/addressSpace.C:1718
#20 0x00007ffff7b136d9 in Dyninst::PatchAPI::DynInstrumenter::run (this=<optimized out>) at /home/jistone/paradyn/dyninst/dyninstAPI/src/Relocation/DynInstrumenter.C:54
#21 0x00007ffff6512466 in Dyninst::PatchAPI::Patcher::run (this=0x10f1610) at /home/jistone/paradyn/dyninst/patchAPI/src/Command.C:112
#22 0x00007ffff6511c4a in Dyninst::PatchAPI::Command::commit (this=0x10f1610) at /home/jistone/paradyn/dyninst/patchAPI/src/Command.C:54
#23 0x00007ffff7a4886b in BPatch_binaryEdit::writeFile (this=this@entry=0x65bc80, outFile=0x7fffffffd7f0 "./stap.new") at /home/jistone/paradyn/dyninst/dyninstAPI/src/BPatch_binaryEdit.C:215
#24 0x00000000004028eb in main (argc=<optimized out>, argv=<optimized out>) at bpatch-nop.cxx:67

Test suite does not dynamically adjust test lists based on build environment

pc_tls is our prototypical example here. The problem, in short:

  • We have a 32-bit build environment present
  • We have thread_db present
  • We lack a 32-bit thread_db

pc_tls expects that if thread_db is present, it may run, and that it may run in all valid run modes for the test/system statically. We don't want to say that thread_db is intrinsically required for all 32-bit tests, nor do we want to say that pc_tls never should run in 32-bit mode, but we do want to skip it in any mode where it can't possibly pass.

walkSingleFrame against external process crashes on Windows

I want to use DynInst to walk the stack and get better results than the Microsoft CaptureStackBackTrace() function. That function loses track of the backtrace in programs that don't have standard call frames, and other unusual situations.

I wrote a very basic test program to get used to the stackwalkAPI, but the program crashes with an infinite loop the first time I call walkSingleFrame. Looking at the two functions involved in the loop, it seems like the symbol reader has never been set up??

My test program is:
simple_stackwalk.txt

The debugger shows:

(2b84.23b4): Stack overflow - code c00000fd (first chance)

with a (partial) call stack of :

stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27
stackwalk!Dyninst::Stackwalker::Walker::getSymbolReader+0x35
stackwalk!Dyninst::Stackwalker::getDefaultSymbolReader+0x27

The two addresses map to the following source lines:

getDefaultSymbolReader+0x27: if (NULL == Walker::getSymbolReader()) {
Walker::getSymbolReader+0x35: fact = Stackwalker::getDefaultSymbolReader();

I set DYNINST_DEBUG_STACKWALK, so here is that output. The lines without filename/linenum are from my test program.
stackwalk-infloop.txt

My build and test environment for DynInst is:

  • Windows 10, 64-bit
  • Visual Studio 12
  • Cmake 3.5.2 (cmake-3.5.2-win32-x86)
  • Boost 1.59 (I downloaded a pre-built Windows version, boost_1_59_0-msvc-12.0-32)
  • DynInst 9.1.0
  • I'm building exclusively 32-bit binaries, even though the OS is 64-bit
  • For most of my testing and debugging, I'm using a Debug build of DynInst. I tried a Release build first and then moved to Debug to try to figure out the problems.

Mask register operands for 9.2.X release?

I think we should either add a MaskRegister class or add functionality to the current Register class in InstructionAPI so that we can deal with the syntactical differences between mask register operands and normal register operands. This will make it much easier for us to output our instructions in AT&T syntax. The only major changes to the Register would be adding a property (something like isMask) and adding getter/setter methods for the property.

I think it would be a cleaner implementation to have a MaskRegister class that extends the Register class.

Here is an example of the syntax for a mask register (the last operand):

     vrcp28sd %xmm0, %xmm0, %xmm0 {%k1}

@wrwilliams do you have any suggestions as to which is the better solution?

"Bad addressing mode!" in F23 libm.so

Issue from Josh Stone. There are two separate issues here, master has the commits that removed the am_VR addressing mode from instructionAPI. However, it doesn't have the commits that removed am_VR from the addressing modes enum and the instruction table. There are still around 5 instruction in the table in master that have this addressing mode, that was fixed with a commit on the VEX branch. This can be fixed by getting master up to date with VEX.

The second issue is a null pointer dereference in instructionAPI. I speculate if the master branch had the patches from VEX, master would have the same issue. This is the issue I am currently trying to resolve.

Commit:

commit 22a1e68333e2e3f296f10d311f6dae17294954f0
Author: John Detter <[email protected]>
Date:   Mon May 2 18:56:10 2016 -0500

    Fixed instruction name typo

Fedora 21 packages:

gcc-5.3.1-6.fc23.x86_64
boost-1.58.0-11.fc23.x86_64
libdwarf-20150915-1.fc23.x86_64
elfutils-libelf-0.166-1.fc23.x86_64

Multiple testsuite failures on VEX

Issue found by Xiaozhu on VEX:

I tested our current fixes against many x86 and x64 binaries. I didn't observe any wrong behavior. However, I ran dyninst testsuite our last. It failed test_instruction_farcall. Could take you a look at this failure?

ERROR: failed bind/eval

I'm seeing a lot of these errors:

$ ./runTests -test test1_1
ERROR: failed bind/eval at 7fcabd8b19ed
ERROR: failed bind/eval at 7fcabd8b1b6f
ERROR: failed bind/eval at 7fcabd8b1b80
ERROR: failed bind/eval at 407038
TEST                       COMP   OPT  ABI MODE     THREAD  LINK    PIC     RESULT
test1_1                    g++    none 64  create   NA      dynamic nonPIC  PASSED
ERROR: failed bind/eval at 407038
test1_1                    g++    none 64  rewriter NA      dynamic nonPIC  PASSED

FWIW, the two places this error is printed in Movement-adhoc.C are not new.

Using master (4b3163b + #46 + #47) on Fedora 23 x86_64.

Rewriting of binaries with GNU_RELRO segment fails on master

test5_1                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_2                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_3                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_4                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_5                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_7                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_8                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_9                    g++    none 64  create   NA      dynamic nonPIC  PASSED
test5_1                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_2                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_3                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_4                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_5                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_7                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_8                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)
test5_9                    g++    none 64  rewriter NA      dynamic nonPIC  FAILED (Group Teardown)

Gist of debugging output available here: https://gist.github.com/jdetter/03f64facb53081cd19ae9ede5a5e5657

dyninstAPI documentation typo

In the description of the BPatch class, the documentation contains the api call
void setInstrStackFrame(bool) instead of void setInstrStackFrames(bool)

Problems with Instruction API parsing x86-64 binaries: sqrtsd

The current master version of dyninst has problems parsing several instructions in x86-64 binaries. Below, I provide an example of an instruction that failed to parse (the first instruction) and the instruction following. This example was uncovere using the checkparse regression test developed at Rice and provided to Wisconsin.

Application example: soliton

problematic instructions:
sqrtsd instruction length mismatch (xed length=5, instruction api length=4)

example in context:

 404203:       f2 0f 51 04 d0          sqrtsd (%rax,%rdx,8),%xmm0 <<<----------------
 404208:       66 0f 2e c0             ucomisd %xmm0,%xmm0

Slicing does not correctly apply ABI

Currently, the ABI is used to kill registers whenever a call instruction is reached, regardless of whether users want to perform inter-procedural slicing or not.

The correct behavior is to apply ABI along with CALL_FT edges. If the user wants to perform inter-procedural slicing, the slicer should not follow CALL_FT edges.

Segfault during PIE rewriting

Submitted via the dyninstapi mailling list:

In the latest version of Dyninst, rewriting a PIE binary (not a library) results in an executable that immediately segfaults. This happens even if no instrumentation was done at all. Simply opening the binary and saving it reproduces the problem. Here's a sample backtrace:

dl_main at rtld.c:172
_dl_sysdep_start at ../elf/dl-sysdep.c:249
_dl_start_final at rtld.c:332
dl_start at rtld.c:558
_start() from /lib64/ld-linux-x86_64.so.2

I am having this issue on both Ubuntu 14.04 and Ubuntu 16, the x86_64 versions.

Line info gets misfiled into incorrect Modules

Reproducer: ask each module in libcommon.so for its line information. A tremendous number of file/line pairs that are nowhere in the include chain for serialize-xml.C nonetheless are assigned to that module.

Possible slicing/frame issue

While dissassembling stdlibc++.so on Fedora 21, I ran into an issue with an instruction (non VEX) we didn't have implemented (rdrand). I implemented that instruction and now it appears dyninst is running into a slicing issue.

The binary I am disassembling is available here.

The function that contains the issue starts at 0x8d710. Dyninst knows that this function starts at 0x8d710, however the disassembly for that function starts at 0x8d6f0, which doesn't seem right to me.

Dyninst (dyn_dump) output:

000000000008d700 <targ8d700>:
    0x8d6f0 48 8b 7         mov RAX, [RDI]
    0x8d6f3 48 85 c0        test RAX, RAX
    0x8d6f6 74 5            jz 5 + RIP + 2
    0x8d6f8 f0 83 40 80 1   add [RAX + ffffffffffffff80], 1
    0x8d6fd f3 c3           REP ret near [RSP]
    0x8d700 48 89 37        mov [RDI], RSI
    0x8d703 e9 e8 ff ff ff  jmp ffffffe8 + RIP + 5

000000000008d710 <std::__exception_ptr::exception_ptr::exception_ptr>:
    0x8d6f0 48 8b 7         mov RAX, [RDI]
    0x8d6f3 48 85 c0        test RAX, RAX
    0x8d6f6 74 5            jz 5 + RIP + 2
    0x8d6f8 f0 83 40 80 1   add [RAX + ffffffffffffff80], 1
    0x8d6fd f3 c3           REP ret near [RSP]
    0x8d710 48 8b 6         mov RAX, [RSI]
    0x8d713 48 89 7         mov [RDI], RAX
    0x8d716 e9 d5 ff ff ff  jmp ffffffd5 + RIP + 5

000000000008d760 <std::__exception_ptr::exception_ptr::~exception_ptr>:
    0x8d720 48 8b 7         mov RAX, [RDI]
    0x8d723 48 85 c0        test RAX, RAX
    0x8d726 74 29           jz 29 + RIP + 2
    0x8d728 f0 83 68 80 1   No_Entry [RAX + ffffffffffffff80], 1  (I'm working on this right now)
    0x8d751 f3 c3           REP ret near [RSP]
    0x8d760 e9 bb ff ff ff  jmp ffffffbb + RIP + 5

The objdump output is a little strange as well, because the function should only really be the first 3 lines because of the unconditional jump. Not sure what's going on here either. Objdump however does start at the correct address, 0x8d710.

objdump output:

000000000008d710 <_ZNSt15__exception_ptr13exception_ptrC1ERKS0_>:
   8d710:   48 8b 06                mov    rax,QWORD PTR [rsi]
   8d713:   48 89 07                mov    QWORD PTR [rdi],rax
   8d716:   e9 d5 ff ff ff          jmp    8d6f0 <_ZNSt15__exception_ptr13exception_ptrC1EMS0_FvvE+0x10>
   8d71b:   0f 1f 44 00 00          nop    DWORD PTR [rax+rax*1+0x0]
   8d720:   48 8b 07                mov    rax,QWORD PTR [rdi]
   8d723:   48 85 c0                test   rax,rax
   8d726:   74 29                   je     8d751 <_ZNSt15__exception_ptr13exception_ptrC1ERKS0_+0x41>
   8d728:   f0 83 68 80 01          lock sub DWORD PTR [rax-0x80],0x1
   8d72d:   75 22                   jne    8d751 <_ZNSt15__exception_ptr13exception_ptrC1ERKS0_+0x41>
   8d72f:   53                      push   rbx
   8d730:   48 8b 40 98             mov    rax,QWORD PTR [rax-0x68]
   8d734:   48 89 fb                mov    rbx,rdi
   8d737:   48 85 c0                test   rax,rax
   8d73a:   74 05                   je     8d741 <_ZNSt15__exception_ptr13exception_ptrC1ERKS0_+0x31>
   8d73c:   48 8b 3f                mov    rdi,QWORD PTR [rdi]
   8d73f:   ff d0                   call   rax
   8d741:   48 8b 3b                mov    rdi,QWORD PTR [rbx]
   8d744:   e8 57 97 ff ff          call   86ea0 <__cxa_free_exception@plt>
   8d749:   48 c7 03 00 00 00 00    mov    QWORD PTR [rbx],0x0
   8d750:   5b                      pop    rbx
   8d751:   f3 c3                   repz ret
   8d753:   66 2e 0f 1f 84 00 00    nop    WORD PTR cs:[rax+rax*1+0x0]
   8d75a:   00 00 00
   8d75d:   0f 1f 00                nop    DWORD PTR [rax]

If this is intentional behavior that I'm unaware of, this can be closed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.