Jump to content

Recommended Posts

index.php?app=downloads&module=display&section=screenshot&id=284

Name: DCG

Submitter: CopperD

Submitted: 16 Feb 2016

Category: *Uncertified*

LabVIEW Version: Not Applicable

License Type: Creative Commons Attribution 3.0

Allows new functions to be compiled during runtime by using libtcc. http://bellard.org/tcc/

 

Features
Full ANSI C compiler 
ISO C99 extensions (Missing only complex and imaginary numbers)
GNU C extensions (See TCC Docs)
TinyCC extensions (See TCC Docs)
GNU-like inline assembler
 32bit & 64bit opcodes depending on DLL (See TCC Docs)
Compile to memory to call as function or disk as exe
Allows for dynamic code
Pointer safe checks

 

Examples

Adding 2 numbers and using return to get the result

Using system to call cmd

Inline x86 assembly

Passing in information using argc and argv

Using pointers to pass a string in and an SHA512 hash out

 

 

Uses libtcc unmodified, so for security reasons you can download the dll from the author's website or compile your own from source. The dll is included if you wish to use it.

 

Some very basic examples that show off only a tiny subset of the features this compiler offers. Unless you are very careful, compiling functions during runtime can lead to unstable code. (Test before you deploy) All examples should run without issue but modification can and will lead to crashing. (Save often)

Click here to download this file

Link to post

OK. So it is a thin wrapper around the Tiny C Compiler.(Note that TCC  is LGPL licenced :book:)

 

It looks like the "State" is an opaque pointer to a structure so you might want to choose "Unsigned Pointer-Sized Integer" so that it is 32 and 64 bit ready. I would also suggest putting each function in a case structure and checking for 0. You can't test a pointer in C to see if it exists so the best you can do is hope that the library returns null pointers when memory is released or memory can't be allocated.

 

For your DSNewPtr, which is a LabVIEW function; there are already VIs for that and others. I forget whether they are under resources or in vi.lib but I think you should separate out LabVIEW functions and application specific functions. LabVIEW functions are reuseable and usually cross platform , whereas application specific ones are or may not be.

 

Looking forward to being able to auto-compile libbitcoin from LabVIEW :D

  • Like 2
Link to post

These are going to all become private functions in the near future. I am only going to have a few functions available to the normal user. This is my general plan for a library.

 

LV_DCG_Compile_String_Program.vi (Complete C program or Library going to disk as DLL ) (Overwrites if name is same as previous compiled code)

Inputs

Mode (Memory, Exe, Dll) required

Program name/name of exe or dll (String) required

Code (String) required

Error in

 

Outputs

Error out (Set if not compiled and string with why)

 

LV_DCG_Compile_String_Library.vi (Collection of functions) (Overwrites if name is same as previous compiled code)

Inputs

Library name (String) required

Code (String) required

Error in

 

Outputs

Error out (Set if not compiled and string with why)

 

 

LV_DCG_List.vi (List compiled programs and library functions)

Inputs

Mode (Programs, Libraries, Library Functions, All Library Functions, All) 

Library Name (String)

Error In

 

Outputs

Names (1D array of strings) (Programs names, libraries, or library functions in "Library_Name.Function_Name")

Error Out

 

 

LV_DCG_Run_Program.vi (Runs Programs using argc argv or none at all)

Inputs

name (String) required

Arguments in (1d array of strings)

Error in

 

Outputs

Program Return (int)

Error out

 

LV_DCG_Run_Function.vi (Requires the function prototype, return type, and data in)

Inputs (I am thinking about this one)

name (String) Required

Return Size (int) Required

Prototype and data (1D Array of Cluster(Data type(u8) ,value(var))

Error In

 

Outputs

Program Return (1d array of bytes of size return size)

Error out

 

LV_DCG_Manage.vi (Remove program, Remove Library, Remove All)

 

I'll add preprocessor and other functions for adding dlls and such later. But I want it simple and sweet. No libbitcoin (C++) but libccoin or picocoin.  :yes:

 

I like the check for a zero on the pointer, that could save a lot of debug time.

 

No clue why I used an int for the pointer.  :frusty:

 

I see DSNewPtr and DSDisposePtr but no MoveBlock.  :(   I remember the GetValueByPointer xnode and being burned because it wouldn't compile.  Hmmm it compiles now  :thumbup1: Still no poking unless you use moveblock. Do they have some look but don't touch policy at NI? 

 

This reminded me of Dr Cold hands at MEPS. We were told to bend down and spread em. Then Dr was going to take a peek and if the Dr didn't like what he saw he would take a poke.

 

 

I have a dream that one day Call Library Function Node will accept function pointers rather than just a path. 

Edited by CopperD
  • Like 1
Link to post

These are going to all become private functions in the near future. I am only going to have a few functions available to the normal user. This is my general plan for a library.

 

<snip>

Nice. We didn't need a spec, but since you've given us one :P - polymorphic VIs are great.

 

I see DSNewPtr and DSDisposePtr but no MoveBlock.  :(   I remember the GetValueByPointer xnode and being burned because it wouldn't compile.  Hmmm it compiles now  :thumbup1: Still no poking unless you use moveblock. Do they have some look but don't touch policy at NI?

 

They never encapsulated Moveblock. I don't know why - it's the single most useful function for CLFNs.

 

Call Library Function Node will accept function pointers rather than just a path.

Tempting to wish for callback features but I'm ambivalent. If there is one good way to crash a LabVIEW program, it is to write some of  it in another language. CLFNs are a last resort when no other options exists rather than standard coding practice. After all. If you want to write GPF ridden software, there are better languages like C and C++  :lol: 

Link to post

C++ is such an awful bastardization of C.

 

Unless you're being stupid setting the GPF interrupt is unlikely. Windows should handle this before you ever get to that level. Your program will still get killed but you don't need to worry about the CPU starting to wonder if it should halt. I was thinking about adding code to check where the page the pointer is in and its access permissions. Its extra overhead and training wheels so I don't know how I feel about it. Maybe a global flag in a list of options so it's only a jump if you don't want to perform the check.

Link to post

I was thinking about adding code to check where the page the pointer is in and its access permissions. Its extra overhead and training wheels so I don't know how I feel about it. Maybe a global flag in a list of options so it's only a jump if you don't want to perform the check.

 

Perhaps you could let the user toggle between Debug mode and Release mode? Debug mode performs checks and flashes big angry warnings if a violation is found; Release mode assumes that the developer has already combed through their code using Debug mode, so it skips the checks.

  • Like 1
Link to post

Perhaps you could let the user toggle between Debug mode and Release mode? Debug mode performs checks and flashes big angry warnings if a violation is found; Release mode assumes that the developer has already combed through their code using Debug mode, so it skips the checks.

That is a great idea, I'm going to do that.

 

Now a little extra information just so I can picture ShaunR cringle. Once TCC has compiled the program I copy the compiled code into an empty pointer from DSNewPtr of compiled function size. :yes:  I also get the starting location of main for the program. Next the memory space is set executable.  :shifty: Finally when you want to run the program we call it as a function pointer.  :D If only we had a good way of doing this inside LabVIEW without resorting to a buffer overflow. My options currently are using a small program in TCC or libffi. Libffi would be very useful in the future and for other projects.

Link to post
  • 2 weeks later...

I really want this to turn your code from a nice solid block of steel into something with the constancy of runny applesauce.

 

Feature Creep!

  • PE32/+ Analysis
  • Emulated PE32/+ loader (Why limit yourself to code you have source for?)
    • ​Performs memory allocations and base relocation
    • Run exe applications internally
    • Call dll functions internally

I'll be posting this update sometime this week.

Edited by CopperD
Link to post
  • 1 month later...

I have been mostly away on vacation and loaded with work for the last month and a half. However some progress has been made. An update showing off some of this will be put up in the next week or two.

 

PE Loader Progress

Load and execute exe from memory if ImageBase does not conflict- 95% (FInishing up some debugging on the Import Directory)

Load and execute exe from memory with conflicted ImageBase but has Relocation Table - (75% )

Load DLL from memory and call functions - (65% need to finish work with Relocation Table and add code to call DLL Entry Point)

Load and execute exe from memory with conflicted ImageBase but has no Relocation Table - (20% I have only generated a Relocation Table by hand with the help of a disassembler) May need to attach the Titan or Bea Engine for disassembly.

Load and inject exe from memory regardless of ImageBase as a new process - (60% This might raise some red flags - more of an experiment) :) 

 

Dynamic Function Calls 

Support for __stdcall __fastcall __cdecl (40% Little bit of bytecode that uses a pointer to cluster of the function prototype passed in from createThead to launch your function)

 

Function Pointers

Windows API createThread (100% IDE not aware of new threads - Wrapped so you can wait for thread to return or continue without waiting)

LabVIEW API THThreadCreate (70% Decoded function prototype and can use it to call function pointers - Need to figure out how this is being used internally so IDE can be aware of the new threads)

SmashCall (90% Works but needs some bytecode added to clean up the mess it creates - Another experiment)

 

The above items are being used to support code generated by LibTCC and the embedding of LibTCC and its supporting files. I promise this all ties together and  goes somewhere.

 

Edited by CopperD
Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By dadreamer
      I want to remind once again that all this information is just to have fun playing with LabVIEW and not intended for real projects use. I believe you all understand that. 🙂
      Not that a big opening here and even not an opening for some ones, but I found this interesting enough to make a thread. As you may already know, when some library is being called using CLF Node, LabVIEW enters ExtFuncWrapper first to do some guard checks to prevent itself from a silent crash and output some error message to the user instead. I've always considered that wrapper boring enough to study, thus never looked inside. But when once again I faced that I can't call some function through CLFN and have to write my own wrapper library, I asked myself why we cannot call some code by its pointer as in almost any well-known text language?.. Therefore I decided to know how ExtFuncWrapper calls the function. It turned out that ExtFuncWrapper receives the function's pointer (along with the parameters struct pointer) and calls that pointer later as it is (i.e., not doing any manipulations with it). So we can use it to call any function and even any code chunk directly from the diagram! After further research I found ExtFuncWrapper not very convenient to use, because to bypass some checks the parameters struct should be prepared accordingly before the call. But there are many ExtFunc... wrappers in labview.exe and ExtFuncCBWrapper is much easier to use. It has the following prototype:
      int32_t ExtFuncCBWrapper(uintptr_t CodeChunk, int32_t UseTLS, void *CodeParams); Here CodeChunk is our func / code pointer, UseTLS is 0 as we don't use LabVIEW's Thread Local Storage and CodeParams is our parameters struct. When called ExtFuncCBWrapper runs that CodeChunk, passing CodeParams to it, so we can freely use it later to do what we want. Nuff said, here are the samples.
      This one increments a Numeric.


      ExtFuncCBWrapper-Increment.vi
      As you can see, I'm passing a Numeric value as CodeParams pointer into ExtFuncCBWrapper and in the assembly I have to pull that pointer out to deal with my parameters. I'm not that excellent in asm codes, so I used one of many online x86 compilers-decompilers out there. It's even simplier in 64-bit IDE as the first parameter is already written into RCX. Okay, here goes a more advanced example - it calculates a sum of two input Numerics.


      ExtFuncCBWrapper-SumOfTwo.vi
      Here I'm passing a cluster of three parameters as CodeParams pointer (two Numerics and the resulting Sum) and in the asm I'm grabbing the first parameter, adding it to the second one and writing the result into the third one. Pretty simple operations. Now let's do some really wild asm on the diagram! 😉 The latter example calls MessageBox function from user32.dll.


      ExtFuncCBWrapper-MsgBox.vi
      This is what Rolf calls a diagram voodoo. 😃 I have to provide 4 parameters to MessageBox, 2 of which are string pointers. Thus I'm getting these pointers and writing them into my params cluster (along with the panel handle and the dialog type). When ExtFuncCBWrapper is called, in the asm code I have to use the prologue and epilogue pieces to prevent the stack corruption as I'm pushing 4 parameters later onto the stack to provide them to MessageBox. After the call I'm writing the result into the function return parameter. In 64-bit IDE the prologue/epilogue is somewhat simplier.
      Maybe you already noticed that I'm doing VirtualProtect before calling ExtFuncCBWrapper. This is done to pass through Windows Data Execution Prevention (DEP) protection. I'm setting execute and read/write access for the memory page with my code, otherwise LabVIEW refuses to run my code and throws an exception. Surprisingly it is thrown only in 64-bit IDE, but in 32-bit LV I can just wire the U8 array to ExtFuncCBWrapper, not going through that DSNewPtr-MoveBlock-VirtualProtect-DSDisposePtr chain. I did not start to figure out such a behaviour.
      Well, to be honest, I doubt that someone will find all these samples really useful for his/her tasks, because these are very low-level operations and it's much easier to use a common CLFN or a helper DLL. They are here just to show that the things described are definitely doable from an ordinary diagram, and that doesn't require writing any libraries. With a good asm skills it's even possible to realize callback functions or call some exotic functions (like C++ class methods). Some things might be improved also, e.g. embedding a generic assembly compiler to have a possibility to write the codes instead of raw bytes on the diagram. Ideally it's even possible to implement an Inline Assembly Node. Unfortunately, I have neither the time nor much desire to do it myself.
    • By CopperD
      Allows new functions to be compiled during runtime by using libtcc. http://bellard.org/tcc/
       
      Features Full ANSI C compiler  ISO C99 extensions (Missing only complex and imaginary numbers) GNU C extensions (See TCC Docs) TinyCC extensions (See TCC Docs) GNU-like inline assembler  32bit & 64bit opcodes depending on DLL (See TCC Docs) Compile to memory to call as function or disk as exe Allows for dynamic code Pointer safe checks  
      Examples
      Adding 2 numbers and using return to get the result
      Using system to call cmd
      Inline x86 assembly
      Passing in information using argc and argv
      Using pointers to pass a string in and an SHA512 hash out
       
       
      Uses libtcc unmodified, so for security reasons you can download the dll from the author's website or compile your own from source. The dll is included if you wish to use it.
       
      Some very basic examples that show off only a tiny subset of the features this compiler offers. Unless you are very careful, compiling functions during runtime can lead to unstable code. (Test before you deploy) All examples should run without issue but modification can and will lead to crashing. (Save often)
    • By Callan
      Hi all,
       
      I have been trying to use VIPM to distribute drivers that rely on a .NET framework that is unsigned (i.e not in the global assembly cache).  My issue is that after the package is installed, none of the VIs will work because LabVIEW cannot locate the .net assembly.  However, if I launch labview by opening the library VIPM installed, all of the VIs will work, and LabVIEW is able to locate the the .Net framework and it appears in the main application instance.  I need to be able to use the installed vis all the time, not just when LabVIEW is launched in this particular way.
       
      Here is a link to all the all the files I used: 
       
      https://www.dropbox.com/sh/yjt2a0t8msxhgfn/AAC4VVW-hPawwXtGMrZ6wuIra?dl=0
       
      Here are the steps I went through:
       
      1) We put all the .NET dlls and the LabVIEW.exe.config file in the Labview directory.
       

       
      2) We installed the package on our computer.  
       

       
      3)We closed everything and relaunched Labview from the start menu.  Then accessed the BioRobotics/Vicon palette.
       

       
      4)We placed the Get Ref subVI on the block diagram, opened it up, and ran it it.
       
      5) We got the following error:
       

       
      We also get a similar error for any VI that uses a method associated with the .NET dll.
       
      6) However, if we again start with everything closed and launch Labview by clicking on the VICON.lvlib located in the vi.lib
       

       
      7) Then repeat steps 3 and 4.  We do not get any errors in the VIs on the palette, and the .Net assembly loads fine.  We can even close the library and everything still works.  Somehow opening the library first makes LabVIEW know to load the ViconDataStreamSDK_DotNet assembly when using functions on the Vicon palette.
       

       
      If anyone does attempt to build a new package, it is worth noting that I included the dlls in the source files, and in the same folder as the vipb:
       

       
       
      Thanks!
       
      Callan
       
    • By rayjay
      I am trying to export a class in LabVIEW 2013 to a .NET Assembly.  According to this I can just select the members of the class that I want to export and it will generate a .NET class for them.  
       
      http://zone.ni.com/reference/en-XX/help/371361H-01/lvhowto/building_a_net_assembly/
       
      I am able to export the individual members of the class, but when I run the code in .NET it starts searching for mydllname.dll/myclassname.lvclass (the file of the class that the exported members belong to) and can't find it.  My next step was to add the class to the the Always Included list, but it seems that when I do that some of the members that I have in the Exported VI's list don't show up in the .NET assembly.  The class I'm trying to export is inhereted from another class, so I tried adding both classes to the Always Included list and all of the base class members to the Exported VI's list, but I still have members missing in the .NET classes.  Thinking it could be something releated to exporting LVOOP classes, I tried ditching the LVOOP class altogether and rewrote the labview code to use generic VI's and a cluser typedef to store the member data.  However, it seems like the labview builder doesn't recognize that the control and indicator clusers that I use to pass the member data belong to the same typedef, so it exports a different .NET class for each control and indicator cluster.  This creates a problem because I have no way of passing the output of one funtion to the next in .NET since I cannot convert between the two .NET types.
       
      Has anyone had problems like this/know how to fix it???  I couldn't find much online about building a .NET interop assembly beyond the basic configuration steps, so any help would be much appreciated!
       
      Thanks
    • By GregFreeman
      I am trying to open shell32.dll with .NET but an exception is being thrown. I'm seeing this type of exception all over when I search google but really not much related to LabVIEW (mostly vb.net, c#.net etc). I have tried loading shell32.dll from system32/shell32.dll and SysWOW64/shell32.dll and both fail. I am running 32 bit LabVIEW on Windows 7 64 bit. I'm guessing it has something to do with that. I am going to try on a coworkers 32 bit computer when I get a chance, but does anyone have suggestions?
      Thanks.
      Edit: Tried on 32 bit labview on a 32 bit machine and it still fails.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.