mxz297 / dyninst

DyninstAPI: Tools for binary instrumentation, analysis, and modification.
http://www.dyninst.org
GNU Lesser General Public License v2.1
2 stars 4 forks source link

Undefined error and crash for binary edit case #4

Closed ManojKumarChauhan closed 3 years ago

ManojKumarChauhan commented 3 years ago

case 1: Create a go binary. Create a function with arguments in go library. Instrument library function at entry point of some binary function. Using code coverage, open binary in edit mode, instrument the function and write output file. codecoverage application will crash while writing output file. (sample 1)

case 2: Create a go binary bin1 using linkshared option (go build -linkshared gobin.go). Create a function without arguments in go library and create library lib1 in shared mode (go install -buildmode=shared lib1). Instrument lib1 function at entry point of some function of bin1. Using code coverage, open bin1 in edit mode, instrument the function and write output file bin1_out. bin1_out will have the dependency on lib1. When lib1 size is large, instrumentation or wrapping will not work on bin1_out with lib1. It's required to create output library lib1_out using dyninst BPatch_binaryEdit::writeFile. When run bin1_out with lib1_out following undefined error comes symbol lookup error: /usr/lib/libtestgolib.so: undefined symbol: type.+ATcTJvw (sample 2)

case 3: From above case 2 create both using linkshared. In go library use a c library where c library handles some unix signals.Create output binary using dyninst. When I run output binary it will crash. samples.zip

mxz297 commented 3 years ago

@ManojKumarChauhan Thanks for your report. I am able to reproduce case 1. So I will start with it.

mxz297 commented 3 years ago

@ManojKumarChauhan There are several things going on here:

  1. I made several fixes regarding your report. I can only maintain one active development branch, and I am developing something else. Please start to use this branch in the future (https://github.com/mxz297/dyninst/tree/profile_support). This profile_support branch is branched from the layout_opt branch weeks ago.

  2. Your codeCoverage.C in sample1 directory needs a change: you need to move InstSpec is_init; from a local variable to a global variable. Interface appBin->insertSnippet only copies is_init's address, so if is_init is a local variable, when later it is used, it has been deallocated.

  3. Still, case 1 does not work because Dyninst currently emits function calls following SystemV ABI, which is used by C/C++. Go lang uses a different ABI. Therefore, when your instrumentation library (libtestgolib.so) is written in Go lang, the calling sequence generated by Dyninst will not work. To resolve this problem, we will need to add new functionality in Dyninst to emit calling sequences accordingly to Go lang's ABI. If you are interested, I can think about it and outline how to do it, and you can fill in the implementation.

  4. For case 2, I cannot reproduce error /usr/lib/libtestgolib.so: undefined symbol: type.+ATcTJvw. Using your libtestgolib.so in sample2, things will actually work fine for me because InstrumentedLibFunction in sample2/testgolib/test.go has no parameter. Therefore, the calling sequence generated by Dyninst will happen to work with a Go lang function

$ LD_PRELOAD=/home/xm13/projects/dyninst-dir/install/lib/libdyninstAPI_RT.so LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./goapp1_out 
inside main
inside InstrumentedLibFunction 
inside Createmainfunc
inside Createmainfunc end
inside main end
ManojKumarChauhan commented 3 years ago

I will use https://github.com/mxz297/dyninst/tree/profile_support branch. For point 3 yes. For point 4, I can still reproduce. Please make sure libtestgolib.so is copied under /usr/lib

mxz297 commented 3 years ago

For point 4, I can still reproduce. Please make sure libtestgolib.so is copied under /usr/lib

I am working on a shared machine so I cannot copy it to /usr/lib. I don't think it makes any difference where libtestgolib.so is as long as $LD_LIBRARY_PATH is set propertly.

Alternatively, you can consider creating a docker container and share it with me. In this way, I should be able to consistently see your issues.

ManojKumarChauhan commented 3 years ago

Hi @mxz297 , Using the source code of sample 2 can you please try to reproduce it once. Please create output testgolib using same function of dyninst' binary edit class which creates output binary. I will try to provide the docker image.

ManojKumarChauhan commented 3 years ago

Hi @mxz297 , Using the source code of sample 2 can you please try to reproduce it once. Please create output testgolib using same function of dyninst' binary edit class which creates output binary. I will try to provide the docker image.

I will try to reproduce it again and share the details.

ManojKumarChauhan commented 3 years ago

I got a crash in stack unwinding for binary edit case. What I did: Instrument a function and wrap a function. Crash is coming due to WrapFunction. Attached is the logs of ExtractRAMapping & DyninstRATranslation which shows the address range of RAMappingTable. The crash came due to an address passed in DyninstRATranslation which is more than max address of table. I assume that this address may belong to the wrapper function which is part of a library. Attached are the logs. wrapfunctioncrash.tar.gz

ManojKumarChauhan commented 3 years ago

Hi @mxz297 , Now I got the crash only for instrumentation. What I did: Open a binary using dyninst, instrument a function and write output binary. When I run the output binary the application got crashed. I will share all the details.

ManojKumarChauhan commented 3 years ago

app_dyninst.zip app_org.zip libandcode.zip src.zip

Hi @mxz297 ,

Please get the attached zip files. unzip libandcode and open readme file to run the application. I instrument one method and created output binary using dyninst. Output binary is crashing. Issue exists on Dyninst branches layout_opt and profile_support

mxz297 commented 3 years ago

@ManojKumarChauhan I took a look at this report, but I cannot really run it. I have two issues:

  1. As I have mentioned before, I mostly work on machines that are shared with other colleagues. So I cannot simply drop files into system paths or change password of root...
  2. My laptop runs Mac, so while I can run Linux docker images on my laptop, your example seems to require opening a web browser. I am not sure whether I can do so in a docker image.

Can you figure out a reproducer using docker and only using command lines?

ManojKumarChauhan commented 3 years ago

Hi @mxz297 , Instead of using browser you can run the commands from terminal like "wget http://localhost:port" If that does not work then please let me know. I will create a docker image.

ManojKumarChauhan commented 3 years ago

bineditcase.zip

Hi @mxz297 , Please get the attached bin & lib. Copy libs under /usr/lib.

Instrumentation is working fine but there is some issue in binary edit case.

mxz297 commented 3 years ago

@ManojKumarChauhan Do you still see the undefined symbol error?

ManojKumarChauhan commented 3 years ago

Hi @mxz297 ,

For case 1, I have created a new bug https://github.com/mxz297/dyninst/issues/5

For case 2, now I can't reproduce after your suggestion for compilation.

For case 3, it's working fine for binary edit but crashing for attachprocess without implementing stack unwinding code. If I call relocate of address space after instrumentation then codecoverage is crashing. I think inferiorMalloc & related functions need to be shift in address space.

steps: BPatch_addressSpace* app2 = bpatch.processAttach (NULL, pid); app2->loadLibrary (lib path); insertFuncEntry(); call relocate of address space via app2 //code coverage will crash here continueExecution();

mxz297 commented 3 years ago

@ManojKumarChauhan I am closing this issue as "undefined error" is no long there. Feel free to open new issues about dynamic instrumentation. Still, I will prioritize adding Go lang function call support before dynamic instrumentation.